Deployment
Bub can be used interactively in a local terminal (see Terminal interaction), or deployed to a server to run as a long-lived process:
- Persistent gateway (Gateway): listen on channels such as Telegram and Feishu around the clock and respond to messages.
- Cloud isolated sandbox (Remote Workspace): provide a complete development toolchain inside an isolated container, accessed through the terminal with
bub chat, keeping the host machine safe.
There are two main deployment approaches:
| Approach | Scenario | Advantages |
|---|---|---|
| Docker Compose (recommended) | Cloud servers, VPS, NAS, local containers | Works out of the box with Node/pnpm/Python/Git and other toolchains included; isolated environment, easy to back up and upgrade |
| Daemon mode | Linux / Windows hosts that already have a Python environment | Low resource usage; register as a system background service in one step with bub gateway --install |
Before you start
Section titled “Before you start”Complete the following preparation before deploying:
- Model configuration: specify
BUB_MODELandBUB_API_KEYin.env. See Configuration for details. - Channel credentials and allowlist: when connecting channels such as Telegram, always configure an allowlist (for example
BUB_TELEGRAM_ALLOW_USERS) to prevent unauthorized access from consuming tokens. - Data persistence: session state (Tape), history, and plugins are stored in the data directory (host
~/.bub, container/data). Make sure persistent storage is in place when deploying.
Docker Compose
Section titled “Docker Compose”The official image (ghcr.io/bubbuild/bub) bundles Python 3.12, uv, Git, Node.js, pnpm, and common command-line tools. The host only needs to provide configuration files and storage volumes.
1. Configure the environment
Section titled “1. Configure the environment”Fetch docker-compose.yml and env.example into the deployment directory:
mkdir -p bub-deploy && cd bub-deploy
curl -O https://raw.githubusercontent.com/bubbuild/bub/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/bubbuild/bub/main/env.example
cp env.example .env
Fill in the core parameters in .env:
# Model
BUB_MODEL=openrouter:openrouter/free
BUB_API_KEY=sk-or-...
# Channel (Telegram as an example)
BUB_TELEGRAM_TOKEN=123456789:your-telegram-bot-token
BUB_TELEGRAM_ALLOW_USERS=123456789,your_telegram_username
# Host data directory and workspace (optional)
# BUB_HOME_HOST=~/.bub
# BUB_WORKSPACE_PATH=.
docker compose reads .env from the current directory automatically. Never commit an .env containing tokens to a public repository.
2. Mount directories
Section titled “2. Mount directories”By default, docker-compose.yml contains three volume mounts:
volumes:
- ${BUB_WORKSPACE_PATH:-.}:/workspace
- ${BUB_HOME_HOST:-${HOME}/.bub}:/data
- ${BUB_AGENT_HOME:-${HOME}/.agents}:/root/.agents
| Container path | Corresponding host path | Description |
|---|---|---|
/workspace |
BUB_WORKSPACE_PATH (default current directory) |
Workspace: the directory where the Agent executes commands and reads/writes files |
/data |
BUB_HOME_HOST (default ~/.bub) |
Data directory: stores Tape, history, and managed plugins (/data/bub-project) |
/root/.agents |
BUB_AGENT_HOME (default ~/.agents) |
Global skills: Agent skills directory reused across projects |
BUB_HOME=/data is set inside the container, so session data and plugins survive container destruction and recreation.
3. Start
Section titled “3. Start”Pull the image and start it in the background:
docker compose pull
docker compose up -d
docker compose logs -f appIn production, pin a specific tag in .env (for example BUB_IMAGE=ghcr.io/bubbuild/bub:0.6.0).
Build from source and start:
docker compose up -d --build The equivalent command when you do not use Compose:
docker run -d --name bub --restart unless-stopped \
--env-file .env \
-e BUB_HOME=/data \
-v "$PWD":/workspace \
-v "$HOME/.bub":/data \
-v "$HOME/.agents":/root/.agents \
ghcr.io/bubbuild/bub:latest
docker logs -f bub 4. Verify
Section titled “4. Verify”Check the container status and gateway logs:
docker compose ps
docker compose logs -f app
When the Telegram gateway starts normally, it outputs:
telegram.start allow_users_count=1 allow_chats_count=0 proxy_enabled=False
telegram.start polling
Check that an environment variable was injected (without printing its value):
docker compose exec app sh -c 'test -n "$BUB_TELEGRAM_TOKEN" && echo token-present'
5. Interactive chat
Section titled “5. Interactive chat”Compose enables stdin_open and tty by default. Even if the container runs the gateway in the background, you can enter the container at any time and start an interactive conversation:
docker compose exec -it app bub chat
This lets you pair-program directly with the Agent using the preinstalled toolchain in a fully isolated cloud sandbox.
6. Customize startup and dependencies
Section titled “6. Customize startup and dependencies”On container startup, entrypoint.sh runs the following in order:
-
Install Python dependencies: if
/workspace/bub-reqs.txtexists, install them automatically withuv pip install. -
Sync plugins: activate the virtual environment and run
bub installto sync the managed plugins in/data/bub-project. -
Run the entrypoint: if
/workspace/startup.shexists, run it withbash; otherwise runbub gateway.
Override the startup command example
Section titled “Override the startup command example”Create startup.sh in the workspace and make it executable:
#!/bin/bash
# /workspace/startup.sh
set -euo pipefail
# You must use exec to replace the process so that system signals are delivered to the gateway correctly
exec /app/.venv/bin/bub gateway --enable-channel telegram
7. Plugin management
Section titled “7. Plugin management”Managed plugins live in the persistent volume /data/bub-project. Install them directly inside the container without rebuilding the image:
# Install a plugin
docker compose exec app bub install https://github.com/owner/repo.git@v1.2.0
# Update plugins
docker compose exec app bub update
# Restart to activate the new plugins
docker compose restart app
8. Backup and upgrade
Section titled “8. Backup and upgrade”Tape is an append-only JSONL file. Before upgrading, pause writes and make a backup:
# 1. Stop writes and back up
docker compose stop app
tar -czf "bub-data-$(date +%Y%m%d-%H%M%S).tar.gz" "$HOME/.bub"
cp .env ".env.bak-$(date +%Y%m%d-%H%M%S)"
# 2. Pull the new image and start
docker compose pull
docker compose up -d
To roll back, simply switch back to the old tag in .env (for example BUB_IMAGE=ghcr.io/bubbuild/bub:0.6.0) and restart.
Daemon mode
Section titled “Daemon mode”On a host that already has a Python environment, you can use the built-in --install command of bub gateway to register it directly as a system background service:
- Linux: registers as a systemd user service at
~/.config/systemd/user/bub-gateway.service. - Windows: registers as a scheduled task for the current user (auto-start at login, automatic restart on failure).
- macOS:
--installis not supported yet; use launchd, tmux, or the Docker approach above.
1. Install the service
Section titled “1. Install the service”Run the following in the workspace directory that contains .env:
# Create the environment and install the app
uv venv && source .venv/bin/activate
uv pip install 'bub[app]'
# Install and start the background service in one step
bub gateway --install
The installer automatically records the current Python interpreter path, workspace directory, and environment variables.
2. Keep alive and manage
Section titled “2. Keep alive and manage”After a Linux user logs out of SSH, user-level services are suspended by default. To keep running around the clock, enable linger:
loginctl enable-linger $USER
Common management commands:
# Check status
systemctl --user status bub-gateway
# Follow logs in real time
journalctl --user -u bub-gateway -f
# Restart and stop
systemctl --user restart bub-gateway
systemctl --user stop bub-gateway
3. Uninstall the service
Section titled “3. Uninstall the service”To remove the background service:
bub gateway --uninstall
Security recommendations
Section titled “Security recommendations”- Strict allowlist: configure
BUB_TELEGRAM_ALLOW_USERSorBUB_TELEGRAM_ALLOW_CHATS; messages that fail validation are rejected or silently dropped. - Minimize the workspace: mount only the project directories you need into the workspace, and do not let the Agent access directories containing host keys or critical system paths.
- Step limit: cap the steps per task with
BUB_MAX_STEPSto guard against infinite loops and API quota consumption. It is unlimited by default (sys.maxsize), so production deployments should set it explicitly, for example to 50. - Credential security: inject secrets through
.envor environment variables, and never commit tokens to version control. - Regular backups: periodically archive and back up the Tape files in
~/.bub(or the container’s/data).