Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Docker Deployment

What you’ll learn

  • How to run NabaOS in Docker with a single command
  • How to configure docker-compose.yml for persistent, production-ready deployments
  • How to set up volumes, environment variables, and health checks
  • How to run with the web dashboard
  • Where cloud deployment is headed (and what works today)

Quick Start

Run the agent with a single docker run command:

docker run -d \
  --name nabaos \
  --restart unless-stopped \
  -e NABA_LLM_PROVIDER=anthropic \
  -e NABA_LLM_API_KEY="$NABA_LLM_API_KEY" \
  -e NABA_TELEGRAM_BOT_TOKEN="$NABA_TELEGRAM_BOT_TOKEN" \
  -e NABA_DAILY_BUDGET_USD=10.0 \
  -v nabaos-data:/data \
  -v nabaos-models:/models \
  ghcr.io/nabaos/nabaos:latest

Verify the container is running:

docker ps --filter name=nabaos

Check the logs to confirm startup:

docker logs nabaos

Expected output:

2026-02-24T10:00:01Z  INFO  NabaOS starting...
2026-02-24T10:00:01Z  INFO  Loading configuration from /data/config
2026-02-24T10:00:02Z  INFO  Security layer initialized
2026-02-24T10:00:02Z  INFO  Ready.

docker-compose.yml Walkthrough

For production deployments, use docker-compose.yml. Here is the full file with annotations:

version: '3.8'

services:
  nabaos:
    # Build from local source, or use the published image:
    #   image: ghcr.io/nabaos/nabaos:latest
    build: .

    environment:
      # --- LLM Provider ---
      - NABA_LLM_PROVIDER=${NABA_LLM_PROVIDER:-anthropic}

      # --- API Key ---
      - NABA_LLM_API_KEY=${NABA_LLM_API_KEY}

      # --- Telegram ---
      - NABA_TELEGRAM_BOT_TOKEN=${NABA_TELEGRAM_BOT_TOKEN}

      # --- Web Dashboard ---
      - NABA_WEB_PASSWORD=${NABA_WEB_PASSWORD}

      # --- Data paths ---
      - NABA_DATA_DIR=/data
      - NABA_MODEL_PATH=/models

      # --- Cost control ---
      - NABA_DAILY_BUDGET_USD=${NABA_DAILY_BUDGET_USD:-10.0}

      # --- Logging ---
      - RUST_LOG=${RUST_LOG:-info}

    volumes:
      # Persistent data: agents, plugins, catalog, cache DBs, config, logs
      - nabaos-data:/data
      # ML models: ONNX files for BERT classifier, embeddings
      - nabaos-models:/models

    # Expose the web dashboard port
    ports:
      - "8919:8919"

    # Restart automatically unless you explicitly stop the container
    restart: unless-stopped

volumes:
  nabaos-data:
  nabaos-models:

Start the stack:

docker compose up -d

Stop the stack:

docker compose down

Volume Configuration

The container uses two volumes for persistent storage:

VolumeContainer pathContents
nabaos-data/dataAgents, plugins, catalog, SQLite databases (nyaya.db, vault.db, cache.db, cost.db), constitution files, logs
nabaos-models/modelsONNX model files (BERT, SetFit, embedding models)

Bind mounts (alternative)

If you prefer host-directory bind mounts instead of named volumes, replace the volumes section:

    volumes:
      - ./data:/data
      - ./models:/models

Environment Variables

Pass these to the container via -e flags or the environment: block in Compose:

VariableRequiredDefaultDescription
NABA_LLM_PROVIDERNoanthropicLLM provider: anthropic, openai, gemini
NABA_LLM_API_KEYYesAPI key for your chosen LLM provider
NABA_TELEGRAM_BOT_TOKENNoTelegram bot token for messaging interface
NABA_WEB_PASSWORDNoPassword for the web dashboard
NABA_DAILY_BUDGET_USDNo10.0Daily spending cap for LLM API calls (USD)
RUST_LOGNoinfoLog verbosity: debug, info, warn, error
NABA_DATA_DIRNo/dataData directory inside the container
NABA_MODEL_PATHNo/modelsModel directory inside the container
NABA_SECURITY_BOT_TOKENNoSeparate Telegram bot for security alerts
NABA_ALERT_CHAT_IDNoTelegram chat ID for security alert delivery

Using a .env file

Create a .env file next to your docker-compose.yml:

NABA_LLM_PROVIDER=anthropic
NABA_LLM_API_KEY=sk-ant-api03-xxxxx
NABA_TELEGRAM_BOT_TOKEN=123456:ABC-DEF
NABA_WEB_PASSWORD=secure-dashboard-pw
NABA_DAILY_BUDGET_USD=10.0
RUST_LOG=info

Docker Compose reads .env automatically. Do not commit this file to version control.


Health Checks

Add a health check to your docker-compose.yml so Docker monitors the process:

services:
  nabaos:
    # ... (other configuration) ...
    healthcheck:
      test: ["CMD", "nabaos", "admin", "cache", "stats"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 15s

Check health status:

docker inspect --format='{{.State.Health.Status}}' nabaos

If you are running the web dashboard, you can also check the HTTP endpoint:

docker compose exec nabaos curl -sf http://localhost:8919/api/health || echo "unhealthy"

Security Notes

The Docker image follows security best practices:

  • Non-root user: The container runs as a non-root user.
  • Minimal base image: debian:bookworm-slim with only ca-certificates installed.
  • Multi-stage build: The Rust toolchain is not present in the final image.
  • Read-only filesystem (optional): Add read_only: true and a tmpfs for /tmp:
services:
  nabaos:
    # ... (other configuration) ...
    read_only: true
    tmpfs:
      - /tmp

Cloud Deployment

Coming soon: First-class deployment guides for GCP Cloud Run, AWS ECS, and Azure Container Apps are planned.

In the meantime, the standard Docker image works on any platform that runs containers. Here are the manual steps that work today:

GCP Cloud Run

# Tag and push the image to Google Artifact Registry
docker tag ghcr.io/nabaos/nabaos:latest \
  us-docker.pkg.dev/YOUR_PROJECT/nabaos/nabaos:latest
docker push us-docker.pkg.dev/YOUR_PROJECT/nabaos/nabaos:latest

# Deploy
gcloud run deploy nabaos \
  --image us-docker.pkg.dev/YOUR_PROJECT/nabaos/nabaos:latest \
  --set-env-vars "NABA_LLM_PROVIDER=anthropic,NABA_LLM_API_KEY=$NABA_LLM_API_KEY" \
  --memory 1Gi \
  --cpu 1 \
  --no-allow-unauthenticated

Caveat: Cloud Run is stateless. You need to mount a persistent volume (e.g., GCS FUSE or Cloud SQL) for /data.

AWS ECS

# Push to ECR
aws ecr get-login-password | docker login --username AWS --password-stdin YOUR_ACCOUNT.dkr.ecr.REGION.amazonaws.com
docker tag ghcr.io/nabaos/nabaos:latest YOUR_ACCOUNT.dkr.ecr.REGION.amazonaws.com/nabaos:latest
docker push YOUR_ACCOUNT.dkr.ecr.REGION.amazonaws.com/nabaos:latest

# Create task definition and service via the AWS Console or CLI
# Mount an EFS volume at /data for persistence

All cloud platforms require you to handle persistent storage for /data separately, since the agent stores SQLite databases and configuration there.