nanobot/docs/deployment.md
2026-04-25 19:36:20 +08:00

5.1 KiB

Deployment

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 user nanobot (UID 1000). 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.

Docker Compose

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
docker compose run --rm nanobot-cli agent -m "Hello!"   # run CLI
docker compose logs -f nanobot-gateway                   # view logs
docker compose down                                      # stop

Docker

# 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)
docker run -v ~/.nanobot:/home/nanobot/.nanobot -p 18790:18790 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.

1. Find the nanobot binary path:

which nanobot   # e.g. /home/user/.local/bin/nanobot

2. Create the service file at ~/.config/systemd/user/nanobot-gateway.service (replace ExecStart path if needed):

[Unit]
Description=Nanobot Gateway
After=network.target

[Service]
Type=simple
ExecStart=%h/.local/bin/nanobot gateway
Restart=always
RestartSec=10
NoNewPrivileges=yes
ProtectSystem=strict
ReadWritePaths=%h

[Install]
WantedBy=default.target

3. Enable and start:

systemctl --user daemon-reload
systemctl --user enable --now nanobot-gateway

Common operations:

systemctl --user status nanobot-gateway        # check status
systemctl --user restart nanobot-gateway       # restart after config changes
journalctl --user -u nanobot-gateway -f        # follow logs

If you edit the .service file itself, run systemctl --user daemon-reload before restarting.

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

loginctl enable-linger $USER

macOS LaunchAgent

On macOS, run the gateway as a launchd user agent so it starts automatically after login and restarts if it exits unexpectedly.

1. Find the nanobot binary path:

which nanobot   # e.g. /Users/youruser/.local/bin/nanobot

If you installed nanobot with uv tool, you may also want the Python path for ProgramArguments:

which python

2. Create the LaunchAgent plist at ~/Library/LaunchAgents/ai.nanobot.gateway.plist (replace paths if needed):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>ai.nanobot.gateway</string>

  <key>ProgramArguments</key>
  <array>
    <string>/Users/youruser/.local/share/uv/tools/nanobot-ai/bin/python</string>
    <string>/Users/youruser/.local/bin/nanobot</string>
    <string>gateway</string>
    <string>--workspace</string>
    <string>/Users/youruser/.nanobot/workspace</string>
  </array>

  <key>WorkingDirectory</key>
  <string>/Users/youruser/.nanobot/workspace</string>

  <key>RunAtLoad</key>
  <true/>

  <key>KeepAlive</key>
  <dict>
    <key>SuccessfulExit</key>
    <false/>
  </dict>

  <key>StandardOutPath</key>
  <string>/Users/youruser/.nanobot/logs/gateway.log</string>

  <key>StandardErrorPath</key>
  <string>/Users/youruser/.nanobot/logs/gateway.error.log</string>

  <key>EnvironmentVariables</key>
  <dict>
    <key>PATH</key>
    <string>/Users/youruser/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    <key>PYTHONUNBUFFERED</key>
    <string>1</string>
  </dict>
</dict>
</plist>

3. Load and start it:

mkdir -p ~/.nanobot/logs
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.nanobot.gateway.plist
launchctl enable gui/$(id -u)/ai.nanobot.gateway
launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway

Common operations:

launchctl list | grep ai.nanobot.gateway
launchctl kickstart -k gui/$(id -u)/ai.nanobot.gateway
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.nanobot.gateway.plist
log stream --process nanobot

If you edit the plist itself, run launchctl bootout ... and launchctl bootstrap ... again so launchd reloads the updated definition.

Note: if launchctl kickstart fails with an "address already in use" error, you probably still have a manually started nanobot gateway process running on the same port. Stop the manual process first, then kickstart the LaunchAgent again.