Deployment

Deploy SwarmClaw to a VPS so it's always online — your agents, connectors, and schedules run 24/7.

Hosted Platforms

If you want an always-on SwarmClaw without managing your own reverse proxy first, start here. The app repo now includes provider-ready deploy configs for the published ghcr.io/swarmclawai/swarmclaw:latest image plus a small unauthenticated health endpoint at /api/healthz.

All hosted deployments should keep these principles:

  • mount persistent storage at /app/data
  • manage secrets with the provider, not a mounted .env.local
  • set both ACCESS_KEY and CREDENTIAL_SECRET
  • optionally add OTLP env vars if you want traces exported to Langfuse, Jaeger, Grafana, Datadog, or another OTLP consumer

Render

Render is the cleanest hosted path right now because its Deploy button can consume the repo-root render.yaml.

Deploy on Render

The included blueprint does the following:

  • pulls ghcr.io/swarmclawai/swarmclaw:latest
  • exposes port 3456
  • mounts a persistent disk at /app/data
  • health-checks /api/healthz
  • prompts for ACCESS_KEY
  • prompts for CREDENTIAL_SECRET

After Render provisions the service, open the generated .onrender.com URL, enter the access key you supplied, and complete the setup flow.

Fly.io Using the GHCR Image

The repo ships a ready-to-edit fly.toml that points at the published GHCR image.

Typical flow:

git clone https://github.com/swarmclawai/swarmclaw.git
cd swarmclaw

# Update the app name in fly.toml first
fly launch --copy-config --no-deploy
fly volumes create swarmclaw_data --size 10 --region iad
fly secrets set ACCESS_KEY=replace-me CREDENTIAL_SECRET=replace-me
fly deploy

Notes:

  • keep the volume mounted at /app/data
  • the bundled config expects internal port 3456
  • OTLP export is optional; if you want traces, add secrets such as OTEL_ENABLED=true and OTEL_EXPORTER_OTLP_ENDPOINT=...

Railway Using the GHCR Image

Railway supports deployment from public Docker images, but its first-create flow for image-backed services is still dashboard-driven instead of repo-button-driven.

Use this setup in the Railway dashboard:

  1. Create a new service from a Docker image.
  2. Use ghcr.io/swarmclawai/swarmclaw:latest.
  3. Add a persistent volume mounted at /app/data.
  4. Set the health check path to /api/healthz.
  5. Add these environment variables:
PORT=3456
ACCESS_KEY=replace-me
CREDENTIAL_SECRET=replace-me
OTEL_SERVICE_NAME=swarmclaw

Optional OTLP env vars:

OTEL_ENABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=https://your-collector:4318
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer your-token

The repo-root railway.json captures the intended restart and health policy for Railway-aligned deployments.

Deploying OpenClaw from SwarmClaw

If you are using SwarmClaw as the control plane for a swarm of OpenClaw instances, you do not need a separate third-party deployment service. SwarmClaw now ships an in-app Smart Deploy flow that only uses official OpenClaw sources:

  • Local deploy — start a managed OpenClaw gateway on the same host as SwarmClaw with a generated token and copyable service-install command
  • VPS smart deploy — generate preconfigured Docker + cloud-init bundles for Hetzner, DigitalOcean, Vultr, Linode, Lightsail, Google Cloud, Azure, OCI, or any Ubuntu VPS
  • In-house SSH deploy — push the official OpenClaw Docker bundle from SwarmClaw to your own VPS and bootstrap it there over SSH
  • Hosted repo-backed deploys — generate official repo-oriented templates for Render, Fly.io, and Railway

For VPS deployments, SwarmClaw emits cloud-init.yaml, .env, docker-compose.yml, and bootstrap.sh with smart defaults already filled in. That means a user can often create a fresh VPS, paste the cloud-init payload, wait for first boot, and then save the generated endpoint/token back into SwarmClaw without manually assembling Docker commands.

Those controls are available during onboarding, in Providers -> OpenClaw Gateways, and in the gateway editor itself. SSH-managed gateways also expose remote lifecycle controls for start, stop, restart, upgrade, backup, restore, and token rotation. For the full OpenClaw-specific flow, see OpenClaw Setup.

Operational guidance:

  • prefer private exposure paths such as Tailscale or SSH tunnels for gateway access
  • if you publish a remote gateway, front it with TLS and keep the generated token private
  • avoid unofficial OpenClaw deployment services; the built-in SwarmClaw bundles intentionally stay on the official OpenClaw Docker image or official OpenClaw repo

The simplest approach. SSH into your VPS and run SwarmClaw with pm2 behind a reverse proxy.

Prerequisites

  • Ubuntu 22.04+ or Debian 12+ (any Linux works, commands may differ)
  • Node.js 22.6+ and one of npm 10+, pnpm, Yarn, or Bun
  • A domain name (optional, for TLS)

Install Node.js

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -
sudo apt install -y nodejs git build-essential

build-essential is needed for better-sqlite3 native compilation.

Install and Build

SwarmClaw is published to the npm registry once, so the same package is consumable from npm, pnpm, yarn, and bun. The examples below use npm, but you can swap in your preferred package manager.

git clone https://github.com/swarmclawai/swarmclaw.git
cd swarmclaw

# Pick one
npm install && npm run build
pnpm install && pnpm build
yarn install && yarn build
bun install && bun run build

Or via the install script:

curl -fsSL https://swarmclaw.ai/install.sh | bash
cd ~/swarmclaw
npm run build

Run with pm2

pm2 keeps SwarmClaw running and restarts it on crashes or reboots.

sudo npm install -g pm2
pm2 start npm --name swarmclaw -- start
pm2 save
pm2 startup

Equivalent process-launch commands if you prefer a different package manager:

pm2 start pnpm --name swarmclaw -- start
pm2 start yarn --name swarmclaw -- start
pm2 start bun --name swarmclaw -- run start

SwarmClaw is now running on port 3456. Check the logs for your access key:

pm2 logs swarmclaw --lines 20

Reverse Proxy with Caddy

Caddy auto-provisions TLS certificates. Install it and create a config:

sudo apt install -y caddy

Edit /etc/caddy/Caddyfile:

swarmclaw.yourdomain.com {
    reverse_proxy localhost:3456
}
sudo systemctl restart caddy

Your instance is now live at https://swarmclaw.yourdomain.com with automatic HTTPS.

Reverse Proxy with nginx (Alternative)

sudo apt install -y nginx certbot python3-certbot-nginx

Create /etc/nginx/sites-available/swarmclaw:

server {
    listen 80;
    server_name swarmclaw.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3456;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_read_timeout 86400;
    }
}
sudo ln -s /etc/nginx/sites-available/swarmclaw /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl restart nginx
sudo certbot --nginx -d swarmclaw.yourdomain.com

Firewall

Only expose ports 80/443 publicly. Never expose 3456 directly.

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable

Updating

SwarmClaw has a built-in update checker. When updates are available, a banner appears in the sidebar with a one-click update button.

To update manually:

cd ~/swarmclaw
npm run update:easy
pm2 restart swarmclaw

Your data in data/ and .env.local is untouched — only source code is updated.


Option 2: Docker

Prerequisites

  • Docker and Docker Compose installed on your VPS

Quick Start

git clone https://github.com/swarmclawai/swarmclaw.git
cd swarmclaw
docker compose up -d

This builds the image, mounts data/ and .env.local as volumes, and runs on port 3456. Inside this deployment mode, local shell, browser, and sandbox_exec execution fall back to host execution inside the app container unless you separately provide Docker access to that container.

Check Logs

docker compose logs -f

Look for the access key on first launch.

Updating

cd swarmclaw
LATEST_TAG=$(git tag --list 'v*' --sort=-v:refname | head -n1)
git checkout -B stable "$LATEST_TAG"
docker compose up -d --build

With a Reverse Proxy

Same Caddy or nginx config as Option 1 — point it at localhost:3456.

Custom Port

Edit docker-compose.yml:

ports:
  - "8080:3456"

Option 3: Systemd Service

If you prefer systemd over pm2:

Create /etc/systemd/system/swarmclaw.service:

[Unit]
Description=SwarmClaw
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/swarmclaw
ExecStart=/usr/bin/npm start
Restart=always
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3456

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable swarmclaw
sudo systemctl start swarmclaw

Data Safety

These files are not tracked by git and are preserved across updates:

  • data/*.db — SQLite databases (swarmclaw.db, memory.db, logs.db, checkpoints)
  • data/uploads/ — uploaded files and generated artifacts
  • .env.local — access key and encryption secret

Back up data/ and .env.local regularly. Without .env.local, encrypted credentials cannot be decrypted.

Security Checklist

  • Never expose port 3456 directly — always use a reverse proxy with TLS
  • Use the auto-generated access key (check .env.local)
  • Keep your VPS updated (sudo apt update && sudo apt upgrade)
  • Review agent system prompts before enabling shell or browser tools
  • Back up data/ and .env.local regularly