diff --git a/docs/deploy/digitalocean.md b/docs/deploy/digitalocean.md new file mode 100644 index 0000000..c4c5b0e --- /dev/null +++ b/docs/deploy/digitalocean.md @@ -0,0 +1,300 @@ +# Deploy Baudbot on DigitalOcean + +This guide walks through deploying baudbot on a DigitalOcean Droplet — a Linux virtual machine with dedicated resources and a static IP. Droplets are a good fit for baudbot because they give you a full Linux server with root access, persistent storage, and straightforward networking. + +## Prerequisites + +- A [DigitalOcean account](https://cloud.digitalocean.com/registrations/new) with a payment method on file +- An SSH key pair on your local machine (`ssh-keygen -t ed25519` if you don't have one) +- Your SSH public key uploaded to DigitalOcean: **Settings → Security → SSH Keys → Add SSH Key** +- API keys ready for configuration (see [CONFIGURATION.md](../../CONFIGURATION.md)): + - At least one LLM API key (Anthropic, OpenAI, Gemini, or OpenCode Zen) + - Slack app tokens (bot token + app-level token) + - GitHub account for the agent + +## System requirements + +| Resource | Minimum | Recommended | +|----------|---------|-------------| +| OS | Ubuntu 24.04 LTS | Ubuntu 24.04 LTS | +| RAM | 4 GB | 8 GB | +| CPU | 2 vCPU | 4 vCPU | +| Disk | 20 GB SSD | 40 GB+ SSD | + +## Step 1: Create the Droplet + +### Option A: DigitalOcean Console + +1. Log in to [cloud.digitalocean.com](https://cloud.digitalocean.com) +2. Click **Create → Droplets** +3. **Region**: Choose the datacenter nearest to you (e.g. `nyc1`, `sfo3`, `ams3`) +4. **Image**: Ubuntu 24.04 (LTS) x64 +5. **Size**: Basic → Regular → **4 GB / 2 vCPUs / 80 GB SSD ($24/mo)** or **8 GB / 4 vCPUs / 160 GB SSD ($48/mo)** +6. **Authentication**: Select your SSH key +7. **Hostname**: `baudbot` (or whatever you prefer) +8. Click **Create Droplet** + +### Option B: `doctl` CLI + +Install the DigitalOcean CLI: + +```bash +# macOS +brew install doctl + +# Linux (snap) +sudo snap install doctl + +# Or download from https://docs.digitalocean.com/reference/doctl/how-to/install/ +``` + +Authenticate: + +```bash +doctl auth init +# Paste your API token from https://cloud.digitalocean.com/account/api/tokens +``` + +Create the Droplet: + +```bash +# List your SSH key fingerprints +doctl compute ssh-key list + +# Create a 4 GB / 2 vCPU Droplet (Basic, Regular) +doctl compute droplet create baudbot \ + --image ubuntu-24-04-x64 \ + --size s-2vcpu-4gb \ + --region nyc1 \ + --ssh-keys \ + --wait + +# Or 8 GB / 4 vCPU for heavier workloads +doctl compute droplet create baudbot \ + --image ubuntu-24-04-x64 \ + --size s-4vcpu-8gb \ + --region nyc1 \ + --ssh-keys \ + --wait +``` + +Get the IP address: + +```bash +doctl compute droplet list --format Name,PublicIPv4 +``` + +## Step 2: Connect and install baudbot + +SSH into the Droplet: + +```bash +ssh root@ +``` + +Clone and install: + +```bash +git clone https://github.com/modem-dev/baudbot.git ~/baudbot +sudo ~/baudbot/install.sh +``` + +The installer handles everything: +- Installs prerequisites (git, curl, tmux, iptables, Docker, gh) +- Creates the `baudbot_agent` user +- Installs Node.js and the pi agent +- Generates an SSH key for GitHub +- Sets up the firewall and process isolation +- Walks you through secrets configuration + +After the installer finishes, complete the manual steps it prints: + +```bash +# 1. Add the agent's SSH key to your GitHub account +cat /home/baudbot_agent/.ssh/id_ed25519.pub +# Copy this and add it at https://github.com/settings/keys + +# 2. Authenticate the GitHub CLI +sudo -u baudbot_agent gh auth login +# Follow the device code flow +``` + +## Step 3: Configure secrets + +If you skipped secrets during install, or need to update them: + +```bash +sudo baudbot config +sudo baudbot deploy +``` + +Or edit the secrets file directly: + +```bash +sudo nano /home/baudbot_agent/.config/.env +sudo baudbot deploy +``` + +See [CONFIGURATION.md](../../CONFIGURATION.md) for the full list of environment variables. + +## Step 4: Networking and firewall + +### Baudbot's built-in firewall + +Baudbot's installer sets up `iptables` rules that restrict the `baudbot_agent` user's network access to an allowlist of ports: + +- **Outbound internet**: HTTP/S (80/443), SSH (22), DNS (53), cloud databases (3306, 5432, 6379, 27017) +- **Localhost**: dev server ports (3000–5999), databases, the Slack bridge (7890) +- **Everything else**: blocked and logged + +These rules persist across reboots via a systemd unit (`baudbot-firewall.service`). + +### DigitalOcean Cloud Firewall (optional, recommended) + +Add a DigitalOcean Cloud Firewall for defense-in-depth. Since baudbot communicates outbound only (via Slack Socket Mode and SSH for git), you need very few inbound rules: + +```bash +doctl compute firewall create \ + --name baudbot-fw \ + --droplet-ids \ + --inbound-rules "protocol:tcp,ports:22,address:0.0.0.0/0,address:::/0" \ + --outbound-rules "protocol:tcp,ports:all,address:0.0.0.0/0,address:::/0 protocol:udp,ports:all,address:0.0.0.0/0,address:::/0" +``` + +**Inbound rules**: +| Protocol | Port | Source | Purpose | +|----------|------|--------|---------| +| TCP | 22 | Your IP (or `0.0.0.0/0`) | SSH access for admin | + +> **Tip**: Restrict SSH to your IP address for better security. Update the firewall when your IP changes. + +**Outbound rules**: Allow all (baudbot's iptables handles per-user egress filtering). + +No other inbound ports are needed — baudbot uses Slack's Socket Mode (outbound WebSocket on port 443), not incoming webhooks. + +### Console alternative + +1. Go to **Networking → Firewalls → Create Firewall** +2. Add an inbound rule for SSH (TCP 22) +3. Keep all outbound rules (or allow all) +4. Under **Apply to Droplets**, select your baudbot Droplet + +## Step 5: Start baudbot + +```bash +# Start the agent (uses systemd) +sudo baudbot start + +# Check status +sudo baudbot status + +# View logs +sudo baudbot logs +``` + +## Step 6: Verify it's working + +```bash +# Run the health check +sudo baudbot doctor + +# Check the systemd service +systemctl status baudbot + +# Check the firewall is active +sudo iptables -L BAUDBOT_OUTPUT -n -v --line-numbers +``` + +If you configured Slack, send a message mentioning @baudbot in an allowed channel — it should respond. + +## Monitoring + +### Logs + +```bash +# Tail live logs +sudo baudbot logs + +# View systemd journal +journalctl -u baudbot -f + +# Check firewall blocked connections +journalctl -k | grep BAUDBOT_BLOCKED +``` + +### DigitalOcean Monitoring + +Enable DigitalOcean's built-in monitoring for CPU, memory, and disk alerts: + +```bash +doctl compute droplet create baudbot \ + ... \ + --enable-monitoring +``` + +Or enable it on an existing Droplet from the **Monitoring** tab in the console. Set up alert policies under **Monitoring → Create Alert Policy** for: +- CPU usage > 80% sustained +- Memory usage > 90% +- Disk usage > 80% + +### Automatic backups + +Enable weekly backups when creating the Droplet (`--enable-backups` with doctl), or enable them later from the **Backups** tab. Backups cost 20% of the Droplet price (e.g. $4.80/mo for a $24/mo Droplet). + +## Cost estimate + +| Component | Spec | Monthly cost | +|-----------|------|-------------| +| **Droplet (minimum)** | 4 GB / 2 vCPU Basic | $24/mo | +| **Droplet (recommended)** | 8 GB / 4 vCPU Basic | $48/mo | +| Backups (optional) | Weekly | +20% of Droplet | +| Cloud Firewall | — | Free | +| Snapshots (optional) | Per GB | $0.06/GB/mo | +| **Total (minimum)** | | **~$24/mo** | +| **Total (recommended)** | | **~$48–58/mo** | + +Pricing as of January 2026. Effective January 1, 2026, DigitalOcean uses per-second billing with a minimum charge of 60 seconds or $0.01. Check [digitalocean.com/pricing/droplets](https://www.digitalocean.com/pricing/droplets) for current rates. + +## Platform-specific tips + +- **Snapshots before updates**: Take a snapshot before running `baudbot update` — it's cheap insurance. From the console: **Droplet → Snapshots → Take Snapshot**, or via CLI: `doctl compute droplet-action snapshot --snapshot-name baudbot-pre-update`. +- **Resize without downtime**: If the agent needs more RAM, power off and resize the Droplet from the console. CPU/RAM-only resizes (no disk increase) are reversible. +- **Droplet Console**: If you lose SSH access, use the **Access → Droplet Console** in the DigitalOcean web UI for emergency access. +- **User data for automation**: For repeatable installs, use `--user-data-file` to pass a cloud-init script that clones and runs the installer automatically: + ```bash + doctl compute droplet create baudbot \ + --image ubuntu-24-04-x64 \ + --size s-2vcpu-4gb \ + --region nyc1 \ + --ssh-keys \ + --user-data-file baudbot-init.sh \ + --wait + ``` +- **VPC networking**: Droplets are automatically placed in a default VPC. If you run other services (databases, etc.) on DigitalOcean, they can communicate over the private network without traversing the public internet. +- **IPv6**: Enable IPv6 on the Droplet if your team needs it (`--enable-ipv6` with doctl). + +## Updating baudbot + +```bash +ssh root@ + +# Pull latest and redeploy +sudo baudbot update + +# Or rollback if something breaks +sudo baudbot rollback previous +``` + +## Destroying the Droplet + +```bash +# Via CLI +doctl compute droplet delete baudbot --force + +# Don't forget to clean up the firewall too +doctl compute firewall delete +``` + +Or from the console: **Droplet → Destroy → Destroy this Droplet**. + +> **Warning**: Destroying a Droplet deletes all data. Take a snapshot first if you want to preserve anything. diff --git a/docs/deploy/fly-io.md b/docs/deploy/fly-io.md new file mode 100644 index 0000000..bc6171c --- /dev/null +++ b/docs/deploy/fly-io.md @@ -0,0 +1,326 @@ +# Deploy Baudbot on Fly.io + +This guide walks through deploying baudbot on Fly.io using Fly Machines — fast-launching VMs with persistent volume storage. Fly.io is a good fit for baudbot if you want per-second billing, global region options, and infrastructure-as-code style management through the `fly` CLI. + +## Important: Fly.io is not a traditional VPS + +Fly.io runs your workloads as Docker containers inside Firecracker microVMs. This means: + +- You need a **Dockerfile** to define the Machine image +- Persistent data must live on a **Fly Volume** (the root filesystem is ephemeral and resets on redeploy) +- The Machine can be stopped/started, but redeploys replace the root filesystem +- You manage everything through the `fly` CLI or the Machines REST API + +Baudbot's installer expects a standard Linux server with `apt`, `systemd`, and full root access. To make this work on Fly.io, you'll run a long-lived Machine with an attached volume for persistent state. + +## Prerequisites + +- A [Fly.io account](https://fly.io/app/sign-up) with a credit card on file +- The `flyctl` CLI installed: + ```bash + # macOS + brew install flyctl + + # Linux + curl -L https://fly.io/install.sh | sh + ``` +- Authenticated with Fly.io: + ```bash + fly auth login + ``` +- API keys ready for configuration (see [CONFIGURATION.md](../../CONFIGURATION.md)): + - At least one LLM API key (Anthropic, OpenAI, Gemini, or OpenCode Zen) + - Slack app tokens (bot token + app-level token) + - GitHub account for the agent + +## System requirements + +| Resource | Minimum | Recommended | +|----------|---------|-------------| +| CPU | 2 shared vCPU | 4 shared vCPU or 2 performance vCPU | +| RAM | 4 GB | 8 GB | +| Volume | 20 GB | 40 GB | + +## Step 1: Create the app and volume + +Create a Fly app (this is a logical container — no Machine is running yet): + +```bash +fly apps create baudbot --org personal +``` + +> Replace `personal` with your Fly.io organization name if applicable. + +Create a persistent volume in your preferred region: + +```bash +# List available regions +fly platform regions + +# Create a 40 GB volume (adjust size as needed) +fly volumes create baudbot_data --region iad --size 40 --app baudbot +``` + +> **Important**: The volume and Machine must be in the same region. Choose one close to you. Common regions: `iad` (Virginia), `ord` (Chicago), `lax` (LA), `lhr` (London), `fra` (Frankfurt), `nrt` (Tokyo). + +## Step 2: Create the Dockerfile + +Baudbot needs a full Ubuntu environment with systemd support. Create a `Dockerfile` for the Machine: + +```dockerfile +FROM ubuntu:24.04 + +# Prevent interactive prompts during package install +ENV DEBIAN_FRONTEND=noninteractive + +# Install base dependencies that baudbot's setup needs +RUN apt-get update && apt-get install -y \ + git curl tmux iptables sudo docker.io gh \ + openssh-client ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Clone baudbot source +RUN git clone https://github.com/modem-dev/baudbot.git /root/baudbot + +# Create a startup script that handles volume-backed persistent state +COPY start.sh /start.sh +RUN chmod +x /start.sh + +CMD ["/start.sh"] +``` + +Create the `start.sh` entrypoint script: + +```bash +#!/bin/bash +set -euo pipefail + +VOLUME="/data" +BAUDBOT_HOME="/home/baudbot_agent" + +# First-run: run baudbot setup (non-interactive core installer) +# Note: setup.sh is used here instead of install.sh because prerequisites +# are already installed via the Dockerfile and we need non-interactive setup. +if [ ! -f "$VOLUME/.baudbot-installed" ]; then + echo "=== First run: setting up baudbot ===" + /root/baudbot/setup.sh root + touch "$VOLUME/.baudbot-installed" + + # Move agent home to the volume so state persists across redeploys + if [ -d "$BAUDBOT_HOME" ] && [ ! -L "$BAUDBOT_HOME" ]; then + cp -a "$BAUDBOT_HOME" "$VOLUME/baudbot_agent_home" + fi +fi + +# Symlink agent home to volume (survives root filesystem replacement) +if [ -d "$VOLUME/baudbot_agent_home" ] && [ ! -L "$BAUDBOT_HOME" ]; then + rm -rf "$BAUDBOT_HOME" + ln -sf "$VOLUME/baudbot_agent_home" "$BAUDBOT_HOME" +fi + +# Symlink source repo to volume for persistence +if [ ! -d "$VOLUME/baudbot-source" ]; then + cp -a /root/baudbot "$VOLUME/baudbot-source" +fi +rm -rf /root/baudbot +ln -sf "$VOLUME/baudbot-source" /root/baudbot + +# Re-run hardening and firewall on each boot +"$BAUDBOT_HOME/runtime/bin/harden-permissions.sh" 2>/dev/null || true +/root/baudbot/bin/setup-firewall.sh 2>/dev/null || true + +# Start the agent in the foreground (keeps the Machine alive) +exec sudo -u baudbot_agent "$BAUDBOT_HOME/runtime/start.sh" +``` + +## Step 3: Configure the fly.toml + +Create `fly.toml` in the same directory as your Dockerfile: + +```toml +app = "baudbot" + +[build] + dockerfile = "Dockerfile" + +[mounts] + source = "baudbot_data" + destination = "/data" + +[[vm]] + size = "shared-cpu-4x" + memory = 4096 # 4 GB — increase to 8192 for heavier workloads + +# No HTTP services needed — baudbot communicates outbound only +# (Slack Socket Mode, SSH for git, HTTPS for APIs) +``` + +> **Note**: Baudbot does not need any `[[services]]` or `[[http_service]]` blocks. It connects outbound to Slack via WebSocket and to GitHub via SSH/HTTPS. No inbound ports are required. + +## Step 4: Set secrets + +Store sensitive configuration as Fly.io secrets (available as environment variables inside the Machine): + +```bash +# LLM API key (set at least one) +fly secrets set ANTHROPIC_API_KEY=sk-ant-... --app baudbot + +# Slack +fly secrets set SLACK_BOT_TOKEN=xoxb-... --app baudbot +fly secrets set SLACK_APP_TOKEN=xapp-... --app baudbot +fly secrets set SLACK_ALLOWED_USERS=U01ABCDEF,U02GHIJKL --app baudbot + +# Email (optional) +fly secrets set AGENTMAIL_API_KEY=... --app baudbot +fly secrets set BAUDBOT_EMAIL=my-agent@agentmail.to --app baudbot +fly secrets set BAUDBOT_SECRET=$(openssl rand -hex 32) --app baudbot + +# List configured secrets (values are hidden) +fly secrets list --app baudbot +``` + +> **Important**: Fly.io secrets are injected as environment variables at Machine boot. Baudbot's installer also writes secrets to `~/.config/.env`. For the Fly.io deployment, you should populate both — the Fly secrets for the Machine environment and the `.env` file for the agent processes that read it directly. After first boot, SSH in and run `sudo baudbot config` to populate the `.env` file. + +## Step 5: Deploy + +```bash +fly deploy --app baudbot +``` + +This builds the Docker image, pushes it to Fly.io's registry, creates a Machine with the attached volume, and starts it. + +Watch the deploy: + +```bash +fly logs --app baudbot +``` + +## Step 6: Post-deploy setup + +SSH into the running Machine to complete setup: + +```bash +fly ssh console --app baudbot +``` + +Inside the Machine: + +```bash +# Add the agent's SSH key to your GitHub account +cat /home/baudbot_agent/.ssh/id_ed25519.pub +# Copy and add at https://github.com/settings/keys + +# Authenticate the GitHub CLI +sudo -u baudbot_agent gh auth login + +# Populate the .env file (if not done during install) +sudo baudbot config +sudo baudbot deploy + +# Verify everything is running +sudo baudbot doctor +sudo baudbot status +``` + +## Monitoring + +### Logs + +```bash +# Stream live logs +fly logs --app baudbot + +# SSH in and check directly +fly ssh console --app baudbot +journalctl -u baudbot -f +sudo baudbot logs +``` + +### Machine status + +```bash +# Check Machine state +fly machine list --app baudbot + +# Get detailed Machine info +fly machine status --app baudbot +``` + +### Fly.io Metrics + +Fly.io provides built-in metrics in the dashboard at [fly.io/apps/baudbot/monitoring](https://fly.io/apps/baudbot/monitoring), covering CPU, memory, and network usage. + +## Networking + +Baudbot on Fly.io communicates entirely outbound: + +- **Slack**: Socket Mode WebSocket over port 443 (outbound) +- **GitHub**: SSH (port 22) and HTTPS (port 443) outbound +- **LLM APIs**: HTTPS (port 443) outbound +- **No inbound ports needed**: No `[[services]]` required in fly.toml + +Fly Machines have unrestricted outbound networking by default. Baudbot's built-in iptables firewall adds per-user egress restrictions for the `baudbot_agent` user once set up. + +### Private networking + +If you run other services on Fly.io (databases, etc.), they can communicate over Fly's private WireGuard network (`.flycast` addresses, `fly-local-6pn` for IPv6) without traversing the public internet. + +## Cost estimate + +| Component | Spec | Monthly cost | +|-----------|------|-------------| +| **Machine (minimum)** | `shared-cpu-2x` / 4 GB | ~$21/mo | +| **Machine (recommended)** | `shared-cpu-4x` / 4 GB | ~$23/mo | +| **Machine (performance)** | `performance-2x` / 4 GB | ~$62/mo | +| Volume (40 GB) | Persistent storage | $6/mo | +| Volume snapshots | First 10 GB free | ~$0.08/GB/mo | +| Dedicated IPv4 (if needed) | Static IP | $2/mo | +| **Total (shared, minimum)** | | **~$27/mo** | +| **Total (shared, recommended)** | | **~$29/mo** | +| **Total (performance)** | | **~$68/mo** | + +Billing is per-second. If you stop the Machine, you pay only for stopped rootfs storage ($0.15/GB/mo) plus the volume. Check [fly.io/docs/about/pricing](https://fly.io/docs/about/pricing/) for current rates. + +> **Tip**: Fly.io offers reservation blocks for 40% savings on committed compute. A $36/year shared Machines block gives $5/mo in credits. + +## Platform-specific tips + +- **Volume backups**: Fly Volumes get automatic daily snapshots with 5-day retention by default. Check snapshots with `fly volumes snapshots list --app baudbot`. +- **Don't use autostop**: Baudbot is an always-on agent. Make sure your fly.toml does not configure `auto_stop_machines` or `auto_start_machines` — the Machine should run continuously. +- **Redeployment replaces root filesystem**: When you `fly deploy`, the root filesystem is rebuilt from the Docker image. All persistent state must live on the volume (`/data`). The `start.sh` script handles this by symlinking the agent home to the volume. +- **Scale vertically**: Change Machine size without redeploying: + ```bash + fly machine update --vm-size shared-cpu-4x --vm-memory 8192 --app baudbot + ``` +- **Region selection matters**: Pick a region close to you for lower latency when SSHing in. Baudbot's API calls go to external services, so the region has minimal impact on agent performance. +- **WireGuard tunnels**: For secure access without SSH, set up a Fly.io WireGuard tunnel: `fly wireguard create`. This lets you access the Machine's private IPv6 address directly. + +## Updating baudbot + +```bash +# SSH into the Machine +fly ssh console --app baudbot + +# Update from git +sudo baudbot update + +# Or rollback +sudo baudbot rollback previous +``` + +Alternatively, update the Dockerfile to pull a newer version and redeploy with `fly deploy`. The volume preserves agent state across redeploys. + +## Stopping and destroying + +```bash +# Stop the Machine (keeps volume, stops compute billing) +fly machine stop --app baudbot + +# Start it back up +fly machine start --app baudbot + +# Destroy everything (irreversible) +fly apps destroy baudbot +``` + +> **Warning**: `fly apps destroy` deletes the app, all Machines, and all volumes. All data is lost. diff --git a/docs/deploy/sprites.md b/docs/deploy/sprites.md new file mode 100644 index 0000000..8a78e55 --- /dev/null +++ b/docs/deploy/sprites.md @@ -0,0 +1,374 @@ +# Deploy Baudbot on Sprites.dev + +This guide walks through deploying baudbot on [Sprites.dev](https://sprites.dev) — persistent, hardware-isolated Linux microVMs from the team behind Fly.io. Sprites are a good fit for baudbot because they provide a full, persistent Ubuntu environment with automatic idle/wake behavior and granular per-second billing. + +## What is Sprites? + +Sprites are stateful sandbox environments — essentially persistent Linux computers that hibernate when idle and wake on demand. Key properties: + +- **Full Ubuntu 24.04 LTS** with Node.js, Python, Go, Git, and common dev tools preinstalled +- **Persistent ext4 filesystem**: files, installed packages, and data survive across sessions (unlike containers) +- **Hardware isolation**: each Sprite runs in a Firecracker microVM +- **Automatic idle behavior**: Sprites sleep when inactive and wake on the next command or HTTP request (~100–500ms warm, 1–2s cold) +- **Up to 8 CPUs and 16 GB RAM** dynamically available per Sprite +- **100 GB persistent storage** per Sprite +- **Checkpoint and restore**: snapshot your entire filesystem and roll back if needed + +Sprites use your Fly.io account for authentication. + +## Prerequisites + +- A [Fly.io account](https://fly.io/app/sign-up) (Sprites uses Fly.io authentication) +- The `sprite` CLI installed: + ```bash + curl -fsSL https://sprites.dev/install.sh | sh + ``` + This auto-detects your platform and installs to `~/.local/bin`. +- Authenticated: + ```bash + sprite org auth + # Opens a browser to authenticate via Fly.io + ``` +- API keys ready for configuration (see [CONFIGURATION.md](../../CONFIGURATION.md)): + - At least one LLM API key (Anthropic, OpenAI, Gemini, or OpenCode Zen) + - Slack app tokens (bot token + app-level token) + - GitHub account for the agent + +## System requirements + +Sprites provide up to 8 CPUs and 16 GB RAM dynamically — you don't choose a fixed plan. Baudbot will use what it needs: + +| Resource | Baudbot needs | Sprites provides | +|----------|--------------|-----------------| +| OS | Ubuntu 24.04 | ✅ Preinstalled | +| RAM | 4–8 GB | Up to 16 GB | +| CPU | 2–4 vCPU | Up to 8 vCPU | +| Disk | 20–40 GB | 100 GB | +| Node.js | v22+ | ✅ Preinstalled | +| Git | Any | ✅ Preinstalled | + +> **Note on always-on behavior**: Sprites automatically hibernate when idle to save costs. For an always-on agent like baudbot, you'll need a mechanism to keep the Sprite awake or accept that it may sleep between tasks. See [Keeping baudbot alive](#keeping-baudbot-alive) below. + +## Step 1: Create the Sprite + +```bash +sprite create baudbot +``` + +Set it as your active Sprite to avoid passing `-s baudbot` to every command: + +```bash +sprite use baudbot +``` + +Verify it's running: + +```bash +sprite list +``` + +## Step 2: Install system prerequisites + +Sprites come with Node.js, Python, Go, and Git preinstalled. You need to install the remaining dependencies that baudbot's installer expects: + +```bash +sprite exec sudo apt-get update +sprite exec sudo apt-get install -y tmux iptables docker.io gh sudo curl +``` + +## Step 3: Clone and install baudbot + +```bash +# Clone the repo +sprite exec git clone https://github.com/modem-dev/baudbot.git /root/baudbot + +# Run the installer +# Note: install.sh is interactive, so use a console session +sprite console +``` + +Inside the console: + +```bash +sudo /root/baudbot/install.sh +``` + +The installer will: +- Detect Ubuntu 24.04 +- Create the `baudbot_agent` user +- Install Node.js (baudbot's own version, separate from the preinstalled one) +- Generate an SSH key for GitHub +- Set up the firewall and process isolation +- Walk you through secrets configuration +- Deploy the agent runtime + +When it finishes, complete the manual steps: + +```bash +# 1. Copy the agent's SSH public key +cat /home/baudbot_agent/.ssh/id_ed25519.pub +# Add it at https://github.com/settings/keys + +# 2. Authenticate the GitHub CLI +sudo -u baudbot_agent gh auth login +# Follow the device code flow + +# Exit the console when done +exit +``` + +## Step 4: Configure secrets + +If you skipped secrets during install: + +```bash +sprite console +``` + +Inside: + +```bash +sudo baudbot config +sudo baudbot deploy +``` + +Or edit the `.env` file directly: + +```bash +sudo nano /home/baudbot_agent/.config/.env +sudo baudbot deploy +``` + +See [CONFIGURATION.md](../../CONFIGURATION.md) for all environment variables. + +## Step 5: Start baudbot + +```bash +sprite console +``` + +Inside: + +```bash +sudo baudbot start +sudo baudbot status +sudo baudbot doctor +``` + +### Keeping baudbot alive + +Sprites hibernate when there's no active process or connection. Since baudbot is an always-on agent, you need the Sprite to stay awake while baudbot is running. Two approaches: + +#### Option A: Use Sprites Services (recommended) + +Sprites has a built-in service manager that auto-restarts processes when the Sprite wakes: + +```bash +sprite exec sprite-env services create baudbot-agent \ + --cmd sudo \ + --args "-u baudbot_agent /home/baudbot_agent/runtime/start.sh" +``` + +This ensures baudbot restarts automatically whenever the Sprite wakes from hibernation (e.g., when a Slack message triggers outbound activity). The Sprite will still hibernate when idle — baudbot's Slack connection will drop — but it will restart quickly when woken. + +> **Trade-off**: With this approach, there will be a brief delay (seconds) when the Sprite wakes from hibernation before baudbot reconnects to Slack. For most teams this is acceptable. If you need instant response times, see Option B. + +#### Option B: Keep a persistent session + +Start baudbot in a detachable TTY session: + +```bash +sprite exec -tty bash -c "sudo -u baudbot_agent /home/baudbot_agent/runtime/start.sh" +# The Sprite stays awake as long as this session is active +# Press Ctrl+\ to detach (keeps running) +``` + +List and reattach to sessions: + +```bash +sprite sessions list +sprite sessions attach +``` + +> **Note**: TTY sessions keep the Sprite awake and billing active. This gives you always-on behavior but at continuous compute cost. + +## Networking + +### Outbound (what baudbot needs) + +Baudbot communicates entirely outbound: + +- **Slack**: Socket Mode WebSocket over port 443 +- **GitHub**: SSH (22) and HTTPS (443) +- **LLM APIs**: HTTPS (443) + +Sprites have outbound internet access by default. Baudbot's built-in iptables firewall restricts the `baudbot_agent` user's egress to an allowlist. + +### Inbound (not needed) + +Baudbot does not need inbound connections. Sprites provide a public URL (`https://baudbot.sprites.app`) per Sprite, but you don't need to use it for baudbot. + +If you do want to expose the control plane or any debug interface, Sprites route HTTP traffic to port 8080 by default: + +```bash +# Check your Sprite's URL +sprite url + +# Make it public (only if needed) +sprite url update --auth public +``` + +### Port forwarding for debugging + +Forward ports from the Sprite to your local machine: + +```bash +# Forward the Slack bridge port for debugging +sprite proxy 7890 + +# Forward multiple ports +sprite proxy 7890 9229 +``` + +## Monitoring + +### Check agent status + +```bash +# Quick status check +sprite exec sudo baudbot status + +# Full health check +sprite exec sudo baudbot doctor + +# View recent logs +sprite exec sudo baudbot logs +``` + +### Interactive debugging + +```bash +# Open a console +sprite console + +# Inside, check processes and resources +ps aux | grep baudbot +df -h +free -h +journalctl -u baudbot --no-pager -n 50 +``` + +### Sprite resource usage + +```bash +sprite exec df -h # disk space +sprite exec free -h # memory +sprite exec ps aux # processes +``` + +## Checkpoints (backups) + +Sprites support filesystem checkpoints — full snapshots you can restore to: + +```bash +# Create a checkpoint before updates +sprite checkpoint create --comment "before baudbot update" + +# List checkpoints +sprite checkpoint list + +# Restore to a checkpoint (replaces entire filesystem) +sprite restore +``` + +> **Tip**: Always create a checkpoint before running `baudbot update` or making significant changes. + +## Cost estimate + +Sprites bill per-second for actual resource usage — you pay for CPU cycles, resident memory, and storage. Costs depend heavily on how active the agent is. + +### Estimate: Moderate usage (handles ~10–20 tasks/day) + +Assuming baudbot is awake ~12 hours/day, averaging 30% of 2 CPUs and 2 GB RAM, with idle time between tasks: + +| Resource | Usage | Monthly cost | +|----------|-------|-------------| +| CPU | ~7.2 CPU-hrs/day × 30 days | ~$15.12 | +| Memory | ~24 GB-hrs/day × 30 days | ~$31.50 | +| Hot storage | 20 GB × ~360 hrs | ~$4.92 | +| Cold storage | 20 GB × ~372 hrs | ~$0.20 | +| **Total** | | **~$52/mo** | + +### Estimate: Light usage (handles ~3–5 tasks/day) + +Assuming baudbot is awake ~4 hours/day with the Sprite sleeping the rest: + +| Resource | Usage | Monthly cost | +|----------|-------|-------------| +| CPU | ~2.4 CPU-hrs/day × 30 days | ~$5.04 | +| Memory | ~6 GB-hrs/day × 30 days | ~$7.88 | +| Hot storage | 20 GB × ~120 hrs | ~$1.64 | +| Cold storage | 20 GB × ~612 hrs | ~$0.33 | +| **Total** | | **~$15/mo** | + +### Estimate: Always-on (persistent session) + +If you keep a persistent session so the Sprite never sleeps, averaging 20% of 2 CPUs and 2 GB RAM continuously: + +| Resource | Usage | Monthly cost | +|----------|-------|-------------| +| CPU | ~288 CPU-hrs/mo | ~$20.16 | +| Memory | ~1,464 GB-hrs/mo | ~$64.05 | +| Hot storage | 20 GB × 732 hrs | ~$10.00 | +| **Total** | | **~$94/mo** | + +Pricing is usage-based. New accounts get $30 in trial credits. Check [sprites.dev](https://sprites.dev) for current rates. + +> **Tip**: The idle/wake model can save significant money if your team doesn't need 24/7 instant response. Sprites wake in 100ms–2s, so the delay is minimal. + +## Platform-specific tips + +- **Sprites are persistent by default**: Unlike containers, everything you install or create stays. No need for Dockerfiles or volume management. This makes Sprites the simplest deployment option for baudbot. +- **Use checkpoints before risky changes**: `sprite checkpoint create --comment "pre-update"` gives you a one-command rollback path. +- **Services for auto-restart**: Use `sprite-env services create` to register baudbot as a service that starts automatically on wake. This is the recommended way to keep baudbot running across hibernate cycles. +- **SSHFS for local editing**: Mount the Sprite's filesystem locally for editing config files with your local editor. See the [Sprites docs on SSHFS](https://docs.sprites.dev/working-with-sprites/#mounting-filesystem-locally). +- **Storage is generous**: Each Sprite has 100 GB. You have plenty of room for repos, build artifacts, and Docker images. +- **Sprites run Ubuntu 24.04**: This matches baudbot's recommended OS exactly. No image selection or configuration needed. +- **TTY detach/reattach**: Press `Ctrl+\` to detach from a running session. Use `sprite sessions list` and `sprite sessions attach ` to reconnect. +- **Docker**: Sprites support Docker inside the VM. baudbot's guarded Docker wrapper (`baudbot-docker`) works as expected. + +## Updating baudbot + +```bash +sprite console +``` + +Inside: + +```bash +# Create a checkpoint first +# (run this from your local machine) +# sprite checkpoint create --comment "before update" + +sudo baudbot update + +# Verify +sudo baudbot status +sudo baudbot doctor +``` + +Or from outside the Sprite: + +```bash +sprite checkpoint create --comment "before update" +sprite exec sudo baudbot update +sprite exec sudo baudbot status +``` + +## Destroying the Sprite + +```bash +sprite destroy -s baudbot +``` + +> **Warning**: Destruction is irreversible. All data, files, packages, and checkpoints are permanently deleted. Create a checkpoint first if you want to preserve anything.