Skip to main content

Overview

Docker deployment provides an isolated, reproducible environment for running nanobot. The official Docker image includes all dependencies, including Node.js 20 for the WhatsApp bridge.
The -v ~/.nanobot:/root/.nanobot flag mounts your local config directory into the container, ensuring your configuration and workspace persist across container restarts.
Docker Compose is the easiest way to deploy nanobot with proper resource limits and automatic restarts.

Setup

1

Create docker-compose.yml

Create a docker-compose.yml file in your project directory:
docker-compose.yml
x-common-config: &common-config
  build:
    context: .
    dockerfile: Dockerfile
  volumes:
    - ~/.nanobot:/root/.nanobot

services:
  nanobot-gateway:
    container_name: nanobot-gateway
    <<: *common-config
    command: ["gateway"]
    restart: unless-stopped
    ports:
      - 18790:18790
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 1G
        reservations:
          cpus: '0.25'
          memory: 256M
  
  nanobot-cli:
    <<: *common-config
    profiles:
      - cli
    command: ["status"]
    stdin_open: true
    tty: true
2

Initialize configuration

Run the onboard command to create your initial configuration:
docker compose run --rm nanobot-cli onboard
This creates ~/.nanobot/config.json on your host system.
3

Configure API keys

Edit the configuration file and add your API keys:
vim ~/.nanobot/config.json
Minimal configuration:
{
  "providers": {
    "openrouter": {
      "apiKey": "sk-or-v1-xxx"
    }
  },
  "agents": {
    "defaults": {
      "model": "anthropic/claude-opus-4-5",
      "provider": "openrouter"
    }
  }
}
4

Start the gateway

Launch the gateway service in detached mode:
docker compose up -d nanobot-gateway

Common Operations

# View logs
docker compose logs -f nanobot-gateway

# Restart gateway (after config changes)
docker compose restart nanobot-gateway

# Run CLI commands
docker compose run --rm nanobot-cli agent -m "Hello!"
docker compose run --rm nanobot-cli status

# Interactive chat
docker compose run --rm nanobot-cli agent

# Stop all services
docker compose down

Docker (Standalone)

For manual Docker deployments without Compose:

Build the Image

1

Clone the repository

git clone https://github.com/HKUDS/nanobot.git
cd nanobot
2

Build the Docker image

docker build -t nanobot .
The Dockerfile uses a multi-stage build process:
  • Base: ghcr.io/astral-sh/uv:python3.12-bookworm-slim
  • Installs Node.js 20 for WhatsApp bridge
  • Installs Python dependencies with uv
  • Builds the WhatsApp bridge with npm
  • Exposes port 18790 for gateway

Initialize and Configure

1

Initialize config

docker run -v ~/.nanobot:/root/.nanobot --rm nanobot onboard
2

Edit configuration

vim ~/.nanobot/config.json
Add your provider API keys and model configuration.

Run the Gateway

# Run gateway with volume mount and port mapping
docker run -v ~/.nanobot:/root/.nanobot -p 18790:18790 nanobot gateway
Add -d flag to run in detached mode:
docker run -d -v ~/.nanobot:/root/.nanobot -p 18790:18790 --name nanobot-gateway nanobot gateway

Run CLI Commands

# One-off chat message
docker run -v ~/.nanobot:/root/.nanobot --rm nanobot agent -m "Hello!"

# Interactive chat (requires -it flags)
docker run -it -v ~/.nanobot:/root/.nanobot --rm nanobot agent

# Check status
docker run -v ~/.nanobot:/root/.nanobot --rm nanobot status

# Channel operations
docker run -v ~/.nanobot:/root/.nanobot --rm nanobot channels status

OAuth Providers (OpenAI Codex)

For providers that require OAuth login (like OpenAI Codex), you need interactive terminal access:
# Interactive OAuth login
docker run -it -v ~/.nanobot:/root/.nanobot --rm nanobot provider login openai-codex

# Or with Docker Compose
docker compose run --rm nanobot-cli provider login openai-codex
OAuth login requires an interactive terminal. Always use the -it flags with Docker or docker compose run (which enables TTY by default).

Resource Limits

The Docker Compose configuration includes sensible resource limits:
  • CPU: Up to 1 core, minimum 0.25 cores reserved
  • Memory: Up to 1GB, minimum 256MB reserved
Adjust these based on your workload:
deploy:
  resources:
    limits:
      cpus: '2'        # Increase for high-traffic deployments
      memory: 2G       # Increase if using large models or MCP servers
    reservations:
      cpus: '0.5'
      memory: 512M

Networking

Port Mapping

The gateway exposes port 18790 by default:
ports:
  - 18790:18790           # host:container
  - 8080:18790            # custom host port

Network Isolation

For production deployments with multiple services:
services:
  nanobot-gateway:
    # ... existing config ...
    networks:
      - nanobot-net

networks:
  nanobot-net:
    driver: bridge

Volumes and Persistence

Configuration Directory

The ~/.nanobot directory contains:
  • config.json - Main configuration
  • workspace/ - Agent workspace, memory, and session files
  • workspace/MEMORY.md - Persistent agent memory
  • workspace/HEARTBEAT.md - Periodic tasks
  • workspace/cron/ - Scheduled job storage
  • .whatsapp-session/ - WhatsApp session data (if using WhatsApp)
  • matrix-store/ - Matrix E2EE keys (if using Matrix)
Always mount ~/.nanobot as a volume to persist your configuration, workspace, and session data across container restarts.

Custom Volume Paths

volumes:
  - /opt/nanobot/config:/root/.nanobot    # Custom path
  - nanobot-data:/root/.nanobot           # Named volume

Environment Variables

You can override config values using environment variables:
services:
  nanobot-gateway:
    # ... existing config ...
    environment:
      - OPENROUTER_API_KEY=sk-or-v1-xxx
      - BRAVE_API_KEY=BSA-xxx
Environment variable names match the config structure:
  • Provider keys: {PROVIDER}_API_KEY (e.g., OPENROUTER_API_KEY, ANTHROPIC_API_KEY)
  • See the Configuration reference for all available variables

Multi-Instance Deployment

Run multiple isolated nanobot instances:
docker-compose.yml
services:
  nanobot-telegram:
    build: .
    command: ["gateway", "-p", "18791"]
    volumes:
      - ~/.nanobot/telegram:/root/.nanobot
    ports:
      - 18791:18791

  nanobot-discord:
    build: .
    command: ["gateway", "-p", "18792"]
    volumes:
      - ~/.nanobot/discord:/root/.nanobot
    ports:
      - 18792:18792
Each instance has its own:
  • Configuration file
  • Workspace directory
  • Session storage
  • Port binding

Health Checks

Add health checks to your Docker Compose configuration:
services:
  nanobot-gateway:
    # ... existing config ...
    healthcheck:
      test: ["CMD", "nanobot", "status"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

Troubleshooting

Container Won’t Start

# Check logs
docker compose logs nanobot-gateway

# Or for standalone
docker logs nanobot-gateway
Common issues:
  • Missing API keys in config.json
  • Invalid JSON in configuration file
  • Port 18790 already in use

Config Changes Not Applied

Restart the container after editing config.json:
docker compose restart nanobot-gateway

Permission Issues

Ensure the volume mount has correct permissions:
# On host
chmod -R 755 ~/.nanobot

Gateway Can’t Connect to Channels

  1. Check if channels are enabled in config.json
  2. Verify API tokens/credentials are correct
  3. Check network connectivity:
    docker exec nanobot-gateway ping -c 3 api.telegram.org
    

WhatsApp Bridge Issues

If using WhatsApp, the bridge runs on port 3001 inside the container:
# Check if bridge is running
docker exec nanobot-gateway ps aux | grep node

# View bridge logs
docker exec nanobot-gateway cat /app/bridge/logs/bridge.log

Memory Issues

If the container is killed due to OOM:
# Check memory usage
docker stats nanobot-gateway

# Increase memory limit in docker-compose.yml
deploy:
  resources:
    limits:
      memory: 2G

Rebuild After Source Changes

# Rebuild image and restart
docker compose build
docker compose up -d --force-recreate

Security Best Practices

Don’t store API keys in docker-compose.yml. Use Docker secrets or environment files:
# Create .env file
echo "OPENROUTER_API_KEY=sk-or-v1-xxx" > .env
docker-compose.yml
services:
  nanobot-gateway:
    # ... existing config ...
    env_file:
      - .env
Add .env to .gitignore.
Add a non-root user to the Dockerfile:
RUN useradd -m -u 1000 nanobot
USER nanobot
Update volume permissions:
sudo chown -R 1000:1000 ~/.nanobot
Use Docker networks to isolate the container:
services:
  nanobot-gateway:
    networks:
      - nanobot-internal
    # Don't expose ports externally if using reverse proxy
In config.json, enable workspace sandboxing:
{
  "tools": {
    "restrictToWorkspace": true
  }
}

Production Checklist

  • Configure proper resource limits
  • Enable health checks
  • Set up log rotation (Docker handles this by default)
  • Use secrets management for API keys
  • Enable workspace restrictions
  • Configure automatic restarts (restart: unless-stopped)
  • Set up monitoring and alerts
  • Back up ~/.nanobot directory regularly
  • Use specific image tags instead of latest
  • Test container recovery after crashes

Next Steps

Linux Service

Deploy as a systemd service for native Linux installations

Multiple Instances

Run multiple isolated nanobot instances

Channel Setup

Configure Telegram, Discord, WhatsApp, and more

Configuration

Complete configuration reference

Build docs developers (and LLMs) love