Back to Nanobot

Deployment

docs/deployment.md

0.2.27.9 KB
Original Source

Deployment

Use this page after nanobot agent -m "Hello!" works locally. Deployment keeps long-running surfaces online: WebUI, chat apps, heartbeat, Dream, cron jobs, and channel connections.

Before You Deploy

Check these once before Docker, systemd, or LaunchAgent:

CheckWhy it matters
nanobot status shows the expected config and workspaceConfirms the process will read the instance you meant to run
nanobot agent -m "Hello!" worksProves install, config, provider, model, and workspace writes before adding a service layer
Secrets are in environment variables or protected config filesAPI keys, bot tokens, OAuth state, and chat credentials should not be world-readable
~/.nanobot/ or your custom config/workspace path is persistentSessions, memory, channel login state, generated artifacts, and cron jobs live there
Channel access control is intentionalUse allowFrom, pairing, WebSocket token/tokenIssueSecret, or private test channels before exposing the bot
Ports are plannedGateway health defaults to 18790; WebUI/WebSocket defaults to 8765; nanobot serve defaults to 8900
Logs are easy to reachUse docker compose logs, journalctl, LaunchAgent log files, or nanobot gateway --verbose while diagnosing startup

Restart the deployed process after editing config.json. Long-running processes read config at startup.

Choose a Runtime

RuntimeUse it forState locationUseful first command
Docker ComposeRepeatable container runs on Linux servers or workstationsBind-mount ~/.nanobot to /home/nanobot/.nanobotdocker compose run --rm nanobot-cli agent -m "Hello!"
Docker CLIManual container testing or small one-off hostsBind-mount ~/.nanobot to /home/nanobot/.nanobotdocker run -v ~/.nanobot:/home/nanobot/.nanobot --rm nanobot status
systemd user serviceLinux user-level gateway that restarts automaticallyHost user's ~/.nanobot unless you pass explicit pathssystemctl --user status nanobot-gateway
macOS LaunchAgentmacOS gateway that starts after loginHost user's ~/.nanobot unless the plist passes explicit paths`launchctl list

Docker

[!TIP] The -v ~/.nanobot:/home/nanobot/.nanobot flag mounts your local config directory into the container, so your config and workspace persist across container restarts. The container runs as the non-root user nanobot (UID 1000) and reads config from /home/nanobot/.nanobot. Always mount your host config directory to /home/nanobot/.nanobot, not /root/.nanobot. If you get Permission denied, fix ownership on the host first: sudo chown -R 1000:1000 ~/.nanobot, or pass --user $(id -u):$(id -g) to match your host UID. Podman users can use --userns=keep-id instead.

[!IMPORTANT] Official Docker usage currently means building from this repository with the included Dockerfile. Docker Hub images under third-party namespaces are not maintained or verified by HKUDS/nanobot; do not mount API keys or bot tokens into them unless you trust the publisher.

[!IMPORTANT] The gateway and WebSocket channel default to host: "127.0.0.1" in config.json (set in nanobot/config/schema.py). Docker -p port forwarding cannot reach a container's loopback interface, so for the host or LAN to reach the exposed ports you must set both binds to 0.0.0.0 in ~/.nanobot/config.json before starting the container. To serve the bundled WebUI from Docker, enable the WebSocket channel and protect bootstrap with a secret:

json
{
  "gateway": { "host": "0.0.0.0" },
  "channels": {
    "websocket": {
      "enabled": true,
      "host": "0.0.0.0",
      "port": 8765,
      "tokenIssueSecret": "your-secret-here"
    }
  }
}

When the WebSocket host is 0.0.0.0, the channel refuses to start unless token or tokenIssueSecret is also configured. See webui.md#lan-access for details.

Docker Compose

bash
docker compose run --rm nanobot-cli onboard   # first-time setup
vim ~/.nanobot/config.json                     # add API keys
docker compose up -d nanobot-gateway           # start gateway
bash
docker compose run --rm nanobot-cli agent -m "Hello!"   # run CLI
docker compose logs -f nanobot-gateway                   # view logs
docker compose down                                      # stop

Docker

bash
# Build the image
docker build -t nanobot .

# Initialize config (first time only)
docker run -v ~/.nanobot:/home/nanobot/.nanobot --rm nanobot onboard

# Edit config on host to add API keys
vim ~/.nanobot/config.json

# Run gateway (connects to enabled channels, e.g. Telegram/Discord/Mochat).
# Mirrors the security caps and port mappings declared in docker-compose.yml:
#   - `--cap-drop ALL --cap-add SYS_ADMIN` + unconfined apparmor/seccomp are required
#     when `tools.exec.sandbox: "bwrap"` is enabled (bwrap needs CAP_SYS_ADMIN for
#     user namespaces). Without them, `bwrap` exits with `clone3: Operation not permitted`.
#   - `-p 8765:8765` exposes the WebSocket channel / WebUI alongside the gateway health
#     endpoint on 18790.
docker run \
  --cap-drop ALL --cap-add SYS_ADMIN \
  --security-opt apparmor=unconfined \
  --security-opt seccomp=unconfined \
  -v ~/.nanobot:/home/nanobot/.nanobot \
  -p 18790:18790 -p 8765:8765 \
  nanobot gateway

# Or run a single command
docker run -v ~/.nanobot:/home/nanobot/.nanobot --rm nanobot agent -m "Hello!"
docker run -v ~/.nanobot:/home/nanobot/.nanobot --rm nanobot status

Linux Service

Run the gateway as a systemd user service so it starts automatically and restarts on failure.

Preview the generated unit first:

bash
nanobot gateway install-service --manager systemd --dry-run

Install, enable, and start it:

bash
nanobot gateway install-service --manager systemd

For a custom instance, pass the same config/workspace selector you use to run the gateway:

bash
nanobot gateway install-service \
  --manager systemd \
  --name nanobot-telegram \
  --config ~/.nanobot-telegram/config.json \
  --workspace ~/.nanobot-telegram/workspace

Common operations:

bash
systemctl --user status nanobot-gateway        # check status
systemctl --user restart nanobot-gateway       # restart after config changes
journalctl --user -u nanobot-gateway -f        # follow logs
nanobot gateway uninstall-service --manager systemd

The installer writes ~/.config/systemd/user/nanobot-gateway.service, runs systemctl --user daemon-reload, enables the unit, and restarts it. It uses the current Python executable with python -m nanobot gateway --foreground, so the service runs in the same environment you used to install nanobot.

Note: User services only run while you are logged in. To keep the gateway running after logout, enable lingering:

bash
loginctl enable-linger $USER

macOS LaunchAgent

Use a LaunchAgent when you want nanobot gateway to stay online after you log in, without keeping a terminal open.

Preview the generated plist first:

bash
nanobot gateway install-service --manager launchd --dry-run

Install, load, enable, and start it:

bash
nanobot gateway install-service --manager launchd

For a custom instance:

bash
nanobot gateway install-service \
  --manager launchd \
  --name nanobot-telegram \
  --config ~/.nanobot-telegram/config.json \
  --workspace ~/.nanobot-telegram/workspace

Common operations:

bash
launchctl list | grep ai.nanobot.gateway
launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway
nanobot gateway uninstall-service --manager launchd

The installer writes ~/Library/LaunchAgents/ai.nanobot.gateway.plist, uses the current Python executable with python -m nanobot gateway --foreground, and writes LaunchAgent logs under ~/.nanobot/logs/.

Note: if startup fails with "address already in use", stop the manually started nanobot gateway process first.