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_KEYandCREDENTIAL_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.
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=trueandOTEL_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:
- Create a new service from a Docker image.
- Use
ghcr.io/swarmclawai/swarmclaw:latest. - Add a persistent volume mounted at
/app/data. - Set the health check path to
/api/healthz. - 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
Option 1: Direct (Recommended)
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.localregularly