Self-Host Guide

Deploy ClawButler on Your Own Machine

Run ClawButler on your own server or local machine to govern your OpenClaw Agents. Your data stays fully private. Supports Windows, macOS, and Linux natively — no WSL required on Windows.

One-Click Install (Recommended)#

A single command handles environment detection, dependency installation, secret generation, and service startup. Supports Linux and macOS.

bash
curl -fsSL https://raw.githubusercontent.com/Octo-o-o-o/clawbutler/main/scripts/install.sh | bash

Zero-Config Local Trial

Don't want to answer configuration prompts? QUICK mode skips all interaction and starts with safe defaults:

bash
curl -fsSL https://raw.githubusercontent.com/Octo-o-o-o/clawbutler/main/scripts/install.sh | QUICK=1 bash

Windows users: install WSL2 first (Ubuntu recommended), then run the commands above in a WSL2 terminal.

The install script automates: system check → Docker verification → clone repo → auto-detect local OpenClaw → generate secrets → port conflict detection → build & start services → run migrations → health check → install management CLI

Management CLI (clawbutlerctl)#

The installer automatically places clawbutlerctl in /usr/local/bin. Common management commands:

CommandDescription
clawbutlerctl startStart all services
clawbutlerctl stopStop all services
clawbutlerctl restartRestart all services
clawbutlerctl statusCheck service health & status
clawbutlerctl logs [service]View logs (all or specific service)
clawbutlerctl updatePull latest version & rebuild
clawbutlerctl configShow current configuration
clawbutlerctl rollback <sha>Rollback to a specific commit

Manual Setup (Developers)#

For finer-grained control or development mode, follow these manual steps.

Prerequisites#

You need four tools: Docker (for databases), Node.js 22+ (for Web frontend), pnpm (package manager), and uv (Python environment manager). Install instructions for each platform below.

Docker
Node.js 22+
pnpm
uv

Windows

Download Docker Desktop and Node.js from their official websites. Install pnpm and uv via PowerShell.

powershell
# 1. Docker Desktop → docker.com/products/docker-desktop/ (download & install)
# 2. Node.js 22 LTS → nodejs.org (download & install)
# 3. pnpm
npm install -g pnpm
# 4. uv (Python package manager — auto-installs Python 3.12)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Restart PowerShell after install, or refresh PATH:
$env:Path = "$env:USERPROFILE\.local\bin;$env:Path"

macOS

Install Homebrew first, then use it for Node.js. Docker Desktop or OrbStack for containers. uv via curl.

bash
# 1. Docker Desktop → docker.com/products/docker-desktop/ (Apple Silicon / Intel)
#    Alternative: OrbStack (orbstack.dev) — lighter resource usage
# 2. Homebrew (if not installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 3. Node.js 22+
brew install node@22
# 4. pnpm
npm install -g pnpm
# 5. uv (Python package manager — auto-installs Python 3.12)
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env   # refresh PATH

Linux

Install Docker Engine via the official script. Node.js via NodeSource (Ubuntu/Debian) or your distro's package manager. uv via curl.

bash
# 1. Docker Engine
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER && newgrp docker
# 2. Node.js 22+ (Ubuntu/Debian)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
# Fedora: sudo dnf install -y nodejs
# Arch:   sudo pacman -S nodejs npm
# 3. pnpm
npm install -g pnpm
# 4. uv (Python package manager — auto-installs Python 3.12)
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/env   # refresh PATH

Verify Environment#

Run these commands to confirm all tools are ready:

bash
docker --version          # Docker 20+
docker info 2>&1 | grep "Server Version"   # confirms daemon is running
node --version            # v22.x.x+
pnpm --version            # 10.x.x+
uv --version              # 0.6.x+

If uv is not found: Windows — restart PowerShell or run $env:Path refresh; macOS/Linux — run source $HOME/.local/bin/env or restart your terminal.

Installation Steps#

1

Clone the repo

bash
git clone https://github.com/Octo-o-o-o/clawbutler.git
cd clawbutler
2

Start databases

Start PostgreSQL 17 and Valkey 8 (Redis-compatible cache) via Docker. First run downloads ~100-150 MB of images.

bash
docker compose -f deploy/docker-compose.dev.yml up -d

Verify both containers are running:

bash
docker compose -f deploy/docker-compose.dev.yml ps
# Both deploy-db-1 (port 5432) and deploy-valkey-1 (port 6379) should be "Up"
3

Deploy API backend

Copy environment config

The .env.example contains all defaults for local development. No edits needed.

macOS / Linux

bash
cp .env.example apps/api/.env

Windows (PowerShell)

powershell
Copy-Item ".env.example" "apps\api\.env"

Install Python 3.12 and dependencies

bash
cd apps/api
uv python install 3.12
uv sync --all-extras

Initialize the database

bash
uv run alembic upgrade head

Start the API service

bash
cd ../..   # back to project root
cd apps    # MUST be in apps/ directory
uv run --project api uvicorn api.main:app --reload --host 0.0.0.0 --port 8000

Common pitfall — relative import error

The API uses Python relative imports (from .config import ...). You MUST run uvicorn from the apps/ directory using the module path api.main:app. Running 'uvicorn main:app' from apps/api/ will fail with: ImportError: attempted relative import with no known parent package.

If port 8000 is occupied, use --port 8001 and update the Web frontend's .env.local accordingly. Keep this terminal open and open a new one for Step 4.

Check if port 8000 is in use

macOS / Linux

bash
lsof -i :8000

Windows (PowerShell)

powershell
Get-NetTCPConnection -LocalPort 8000 -ErrorAction SilentlyContinue
4

Deploy Web frontend

Open a new terminal tab/window for the Web frontend.

Install frontend dependencies

bash
cd apps/web    # from project root
pnpm install

Create frontend environment config

If your API runs on a different port (e.g., 8001), replace 8000 with the actual port number.

macOS / Linux

bash
cat > .env.local << 'EOF'
AUTH_SECRET=local-dev-secret-change-in-prod
AUTH_TRUST_HOST=true
AUTH_URL=http://localhost:3000
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
API_BASE_URL_INTERNAL=http://localhost:8000
EOF

Windows (PowerShell)

powershell
@"
AUTH_SECRET=local-dev-secret-change-in-prod
AUTH_TRUST_HOST=true
AUTH_URL=http://localhost:3000
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
API_BASE_URL_INTERNAL=http://localhost:8000
"@ | Out-File -Encoding utf8 .env.local

Start the Web service

bash
pnpm dev
5

Verify deployment

ServiceAddress
Web Dashboardhttp://localhost:3000
API Docs (Swagger)http://localhost:8000/docs
Health Checkhttp://localhost:8000/health

macOS / Linux

bash
curl http://localhost:8000/health
# Expected: JSON with status="ok" and a non-empty version field

Windows (PowerShell)

powershell
Invoke-RestMethod -Uri "http://localhost:8000/health"
# Expected: status: ok, plus a non-empty version field

Daily Usage#

After rebooting, start services in 3 separate terminals:

bash
# Terminal 1: Start databases (if not running)
docker compose -f deploy/docker-compose.dev.yml up -d

# Terminal 2: Start API (from project-root/apps/)
cd apps
uv run --project api uvicorn api.main:app --reload --host 0.0.0.0 --port 8000

# Terminal 3: Start Web (from project-root/apps/web/)
cd apps/web
pnpm dev

To stop: press Ctrl+C in the API and Web terminals. For databases: docker compose -f deploy/docker-compose.dev.yml down (data is preserved in Docker Volumes).

Production Configuration#

For production deployment, generate secure secrets and configure these environment variables in your .env file:

VariableHow to generate
DB_PASSWORDopenssl rand -base64 24
JWT_SECRET_KEYopenssl rand -hex 32
AUTH_SECRETopenssl rand -base64 32
ENCRYPTION_KEYopenssl rand -hex 32
SMTP_HOSTFrom email provider
SMTP_PASSWORDFrom email provider
CORS_ORIGINSSet manually
AUTH_URLSet manually

SMTP_HOST is required in production mode. Recommended: Resend (free 100 emails/day).

Production HTTPS (Caddy)#

Recommended: use Caddy for automatic Let's Encrypt certificates. Install via apt/yum on Linux, brew on macOS.

bash
# Install Caddy
# Linux (Debian/Ubuntu): sudo apt install caddy
# Linux (RHEL/Fedora):   sudo dnf install caddy
# macOS:                 brew install caddy
# Windows:               choco install caddy (or scoop install caddy)

# Edit Caddyfile
# Linux:  sudo nano /etc/caddy/Caddyfile
# macOS:  nano /opt/homebrew/etc/Caddyfile
caddyfile
your-domain.com {
    handle /api/auth/* { reverse_proxy localhost:3000 }
    handle /api/*      { reverse_proxy localhost:8000 }
    handle /health     { reverse_proxy localhost:8000 }
    handle /docs       { reverse_proxy localhost:8000 }
    handle             { reverse_proxy localhost:3000 }
}
bash
# Production: bind ports to 127.0.0.1
docker compose -f docker-compose.yml \
  -f deploy/docker-compose.production.yml up -d --build

sudo systemctl enable caddy && sudo systemctl start caddy

System Requirements#

Minimum

  • 2 vCPU / 4 GB RAM / 20 GB SSD
  • Docker Engine 24+ / Docker Desktop
  • Linux / macOS / Windows
  • amd64 / arm64

Recommended

  • 4 vCPU / 8 GB RAM / 40 GB SSD
  • Static public IP + domain
  • SMTP email service
Cloud estimates: GCP e2-medium ~$25/mo | AWS t3.medium ~$30/mo | Hetzner CX22 ~$6/mo | DigitalOcean ~$24/mo

Operations#

Upgrade

bash
# Recommended: use management CLI
clawbutlerctl update

# Or manually:
cd ~/clawbutler && git pull
docker compose build && docker compose up -d

Backup

bash
docker compose exec -T postgres \
  pg_dump -U postgres agentplanet \
  | gzip > backup_$(date +%Y%m%d).sql.gz

Cloud Connection#

Connect your self-hosted OpenClaw to ClawButler Cloud (clawbutler.cc) for remote management, chat, and monitoring — without exposing any local ports to the internet.

Architecture: Edge Agent Tunnel

Cloud (clawbutler.cc)              Your Machine
┌──────────────────┐               ┌──────────────────┐
│  ClawButler API  │   WSS (443)   │  Edge Agent      │
│  ◄════════════════════════════►  │    ↕              │
│  Dashboard / Chat│   outbound    │  OpenClaw Gateway │
└──────────────────┘   tunnel      │  (127.0.0.1:18789) │
                                   └──────────────────┘
1

Install the Edge Agent

The install script auto-detects your local OpenClaw gateway and downloads the Edge Agent.

bash
curl -fsSL https://clawbutler.cc/install | bash -s -- --edge-only

macOS / Linux Desktop

Run the command above in your local terminal. The script will automatically open your browser to complete pairing.

Windows (WSL2)

Open your WSL2 terminal (Ubuntu) and run the command above. The pairing URL will open automatically in your Windows browser.

Prerequisite: wsl --install in PowerShell (Admin)

Linux Server (SSH)

SSH into your server, then run the command above. The script will display a pairing URL — open it in your local browser.

2

Pair with Cloud

Run the pairing command. The Edge Agent will display a short-lived code.

bash
cd ~/.clawbutler/edge-agent
python3 clawbutler_edge.py pair \
  --cloud-url https://clawbutler.cc \
  --openclaw-url ws://127.0.0.1:18789

The --openclaw-token flag is auto-detected if OpenClaw is configured with gateway authentication. You can also pass it explicitly.

3

Approve in Browser

Open the URL displayed by the Edge Agent in your browser (you'll need to be logged in to clawbutler.cc). Enter a connector name and click Approve. The Edge Agent receives its credentials automatically.

4

Start the Edge Agent

Run the Edge Agent. It establishes an outbound WSS tunnel to the cloud. Your local agents are now accessible from clawbutler.cc.

bash
python3 clawbutler_edge.py

The Edge Agent reconnects automatically if the connection drops. Consider running it as a background service (systemd, launchd, or nohup).

Connection Security#

The Edge Agent is designed with a zero-inbound-port architecture. Your OpenClaw gateway never needs to be reachable from the internet.

Exposing ports directly (insecure)

Opening port 18789 to the internet exposes your OpenClaw gateway to port scanners, brute-force attacks, and unauthorized access. Default ports like 18789 are actively scanned by automated tools within minutes of exposure.

Edge Agent tunnel (recommended)

The Edge Agent makes outbound-only connections via WSS (port 443). OpenClaw stays bound to 127.0.0.1. No firewall rules or port forwarding needed. The tunnel is encrypted end-to-end with TLS.

Security Layers

1
Outbound-only connection

The Edge Agent initiates the WSS connection to the cloud. No inbound ports are opened on your machine. OpenClaw only listens on localhost (127.0.0.1), completely invisible to external networks.

2
TLS-encrypted tunnel

All traffic between the Edge Agent and ClawButler Cloud travels over WSS (WebSocket Secure), using the same TLS encryption as HTTPS. Frame data cannot be intercepted or tampered with in transit.

3
Token-based authentication

The Edge Agent authenticates to the cloud using a cryptographically random 48-byte token issued during pairing. The cloud verifies the token on every WebSocket connection.

4
Ed25519 device authentication

The Edge Agent authenticates to the local OpenClaw gateway using Ed25519 challenge-response signing, the same cryptographic protocol used by SSH. No passwords are stored or transmitted.

Data stays local

Your agent configurations, conversation history, and OpenClaw data remain on your machine. The cloud only sees the API requests and responses that flow through the tunnel during active use. The Edge Agent does not sync or upload your data.

Default Ports#

ServicePortDescription
PostgreSQL5432Primary database
Valkey6379Cache and session store
FastAPI Backend8000REST API and Server-Sent Events (SSE)
Next.js Frontend3000Web dashboard UI

FAQ#

Ready to go?

Check the source code or use the managed cloud service.

Self-Host Guide — ClawButler