Overview
swarmbot.it is an open-source Docker Swarm management platform consisting of two components that work together to provide zero-downtime cluster operations, real-time monitoring, and automatic failover.
Two components
The central API and dashboard. Stores cluster state in PostgreSQL, exposes a GraphQL API, and coordinates failover when a node goes offline.
A lightweight daemon running on each Docker node. Streams host metrics and container events to swarmbot.it every second via POST /events.
Key benefits
- Zero Downtime: Docker Swarm automatically reschedules tasks when a node fails — Swarmbot surfaces it live, it doesn't get in the way.
- No CouchDB, no Redis: Application state (users, registries, cluster config) lives in a single PostgreSQL database. Real-time metrics are stored in InfluxDB.
- Real metrics: CPU, RAM, disk, and per-container statistics updated every second.
- Kubernetes support: K3s/K8s cluster management in addition to Docker Swarm.
- Open source: MIT-licensed, self-hosted, no telemetry.
swarmbot.it requires Docker Engine 20.10+ with Swarm mode initialized. Run docker swarm init on your manager node before starting.
Architecture
The system follows a hub-and-spoke model: Swarmagent instances on each node push data to the central swarmbot.it API, which stores application state in PostgreSQL, writes real-time metrics to InfluxDB, and serves both to the Angular dashboard via GraphQL.
Express + Apollo GraphQL
Event flow
Every second, each Swarmagent instance collects the following data from the local Docker daemon and sends it as a single JSON payload to POST /events on swarmbot.it:
- Host metrics: CPU usage (%), memory usage (%), disk usage (%), disk total bytes
- Container metrics: Per-container CPU %, memory %, container name, state
- Swarm metadata: Node ID, node hostname, Docker Swarm role (manager/worker)
- Docker events: Container start/stop/die/health-status events
swarmbot.it writes host and container metrics to InfluxDB as time-series points, and records a lightweight daily count snapshot (stacks/services/tasks) to the metrics_snapshots table in PostgreSQL. Dashboard charts query InfluxDB directly through the metricsSeries GraphQL field.
Installation
Follow these steps to get swarmbot.it running in your environment. Total time: approximately 5 minutes.
Prerequisites
- Docker Engine 20.10+ with Swarm mode active
- Node.js 20+ (for swarmbot.it API and dashboard)
- PostgreSQL 14+ (or use the Docker command below)
- InfluxDB 1.8.x (required for real-time metrics — or use the Docker command below)
- Rust 1.75+ (only needed to build Swarmagent from source)
Step 1 — Initialize Docker Swarm
# Only needed if Swarm is not already initialized docker swarm init # Verify your node is a manager docker info | grep -i swarm # Swarm: active # NodeID: abc123xyz...
Step 2 — Start PostgreSQL and InfluxDB
# Using Docker (skip if you have an existing PostgreSQL) docker run -d --name swarmbot-postgres \ -e POSTGRES_USER=swarmbot \ -e POSTGRES_PASSWORD=swarmbot \ -e POSTGRES_DB=swarmbot \ -p 5432:5432 \ --restart unless-stopped \ postgres:16 # Verify it's running docker ps | grep postgres # abc123 postgres:16 ... 0.0.0.0:5432->5432/tcp swarmbot-postgres # InfluxDB (required for real-time metrics) docker run -d --name swarmbot-influxdb \ -e INFLUXDB_DB=swarmbot \ -p 8086:8086 \ --restart unless-stopped \ influxdb:1.8
Step 3 — Clone and install swarmbot.it
git clone https://github.com/swarmbot-it/swarmbot
cd swarmbot
# Install all workspace dependencies
npm install
Step 4 — Configure the environment
# PostgreSQL connection string SWARMBOT_DB=postgresql://swarmbot:swarmbot@localhost:5432/swarmbot # InfluxDB SWARMBOT_INFLUXDB=http://localhost:8086 SWARMBOT_INFLUXDB_TOKEN=swarmbot-influx-dev-token # API port SWARMBOT_PORT=8080 # Set to false to use real Docker (true = mock data) SWARMBOT_MOCK=false # CORS — comma-separated allowed origins SWARMBOT_ALLOWED_ORIGINS=http://localhost:4200,http://YOUR_IP:4200 # Optional — override the auto-generated bootstrap admin credentials SWARMBOT_BOOTSTRAP_ADMIN=admin SWARMBOT_BOOTSTRAP_PASSWORD=swarmbot
Step 5 — Start the API
npm run dev:api
# {"msg":"Starting Swarmbot","port":8080}
# {"msg":"Postgres connected"}
# {"msg":"Migration applied","migration":"001_initial"}
# {"msg":"Bootstrap admin user created","username":"admin"}
# {"msg":"InfluxDB connected"}
# {"msg":"Swarmbot listening","port":8080}
Step 6 — Start the dashboard
npm run dev:web # Angular Live Development Server is listening on localhost:4200 # Open your browser on http://localhost:4200/ # To expose on LAN (access from other machines): cd apps/web && npx ng serve --host 0.0.0.0 --port 4200
Install Swarmagent (Rust)
Swarmagent must be built and run on each Docker node you want to monitor.
git clone https://github.com/swarmbot-it/swarmagent cd swarmagent # Build (release mode) cargo build --release # Configure and run — swarmagent is push-only, it opens no listening port export SWARMBOT_URL=http://<your-swarmbot-ip>:8080 export STATS_FREQUENCY=30 # seconds ./target/release/swarmagent # INFO Starting Swarmbot # INFO Waiting for Swarmbot… # INFO Swarmbot OK # INFO Event collector started. # INFO Stats collector started.
Alpine Linux / musl: Swarmagent must be compiled natively — prebuilt glibc binaries will not work on Alpine. Ensure musl-dev and the Rust toolchain are installed via apk add rust cargo musl-dev.
Default login
Username: admin Password: swarmbot # Set via SWARMBOT_BOOTSTRAP_ADMIN / SWARMBOT_BOOTSTRAP_PASSWORD. # Change immediately after first login!
Configuration
All swarmbot.it configuration is done via environment variables, loaded from apps/api/.env.development in development or standard env vars in production.
swarmbot.it (API) variables
| Variable | Default | Description |
|---|---|---|
SWARMBOT_DB |
postgres://localhost:5432/swarmbot |
PostgreSQL connection string for application state (users, registries, cluster config). |
SWARMBOT_INFLUXDB |
unset | Base URL of the InfluxDB instance used for real-time metrics. |
SWARMBOT_INFLUXDB_TOKEN |
unset | Auth token for InfluxDB. |
SWARMBOT_PORT |
8080 |
TCP port for the HTTP/GraphQL API server. |
SWARMBOT_MOCK |
false |
When true, uses a mock Docker engine instead of the real Docker socket. Useful for UI development without a real cluster. |
SWARMBOT_ORCHESTRATOR |
auto |
Backend selection: swarm, kubernetes, or auto-detected. |
SWARMBOT_ALLOWED_ORIGINS |
http://localhost:4200, :8080, :8081 |
Comma-separated list of allowed CORS origins. Add your dashboard's LAN address here if accessing remotely. |
SWARMBOT_BOOTSTRAP_ADMIN / SWARMBOT_BOOTSTRAP_PASSWORD |
admin / swarmbot |
Credentials for the admin user created on first boot, if no users exist yet. |
SWARMAGENT_SHARED_SECRET |
unset | Opt-in shared secret required from Swarmagent as X-Agent-Token on POST /events. Unset means no auth is enforced. |
The JWT signing secret is generated automatically on first boot and stored in the app_secrets table — there is no env var to configure it.
Swarmagent variables
| Variable | Default | Description |
|---|---|---|
SWARMBOT_URL |
derived from EVENT_ENDPOINT |
Base URL of the swarmbot.it API. Swarmagent polls this on startup until it becomes available. |
AGENT_MODE |
auto |
Force docker or kubernetes mode, or auto-detect the orchestrator. |
STATS_FREQUENCY |
30 |
How often (in seconds, minimum 1) to collect and send metrics. |
SWARMAGENT_SHARED_SECRET |
unset | When set, sent as X-Agent-Token on every request to swarmbot.it. Must match the API's own SWARMAGENT_SHARED_SECRET. |
DOCKER_HOST |
unix:///var/run/docker.sock |
Docker socket path, read by the underlying Docker client library. Useful when running Swarmagent in a container. |
Swarmagent is push-only — it opens no listening port and has no HTTP health-check endpoint of its own.
API Reference
swarmbot.it exposes a GraphQL API at POST /graphql. Use the GraphQL Playground at http://localhost:8080/graphql (in development) for interactive exploration.
Authentication
All API requests require a Bearer token in the Authorization header. Obtain a token by POSTing to the REST auth endpoint with HTTP Basic credentials:
# POST /login (HTTP Basic auth) curl -X POST http://localhost:8080/login \ -u admin:swarmbot # {"token":"eyJhbGciOiJIUzI1NiIsInR5..."} # Use the token in GraphQL requests curl -X POST http://localhost:8080/graphql \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"query":"{ nodes { id hostname role cpu mem disk } }"}'
Queries
# Get all Swarm nodes with current metrics query { nodes { id hostname role # "manager" | "worker" availability # "active" | "pause" | "drain" cpu # current CPU usage % mem # current memory usage % disk # current disk usage % } }
# List all Swarm services; tasks are queried separately query { services { id name image replicasRunning replicasTotal status stack } tasks { id serviceName nodeHostname status # "running" | "failed" | "shutdown" | "starting" } }
# Time-series metrics for the whole cluster (backed by InfluxDB) query ClusterMetrics($input: MetricsSeriesInput!) { metricsSeries(input: $input) { labels # ["15m ago", "14m ago", ...] cpu # [42.1, 43.5, ...] mem disk } } # Variables: { "input": { "range": "1h", "resolution": "medium" } } # range: any duration string · resolution: "low" | "medium" | "high" # add "nodeId" to input to scope the series to a single node
Mutations
# Deploy a new service (registry must reference an existing Registry id) mutation { createService(input: { name: "myapp", image: "nginx:latest", registry: "docker-hub", replicas: 3 }) { id name replicasTotal } } # Scale a service mutation { scaleService(id: "abc123", replicas: 5) } # Remove a service mutation { removeService(id: "abc123") }
Swarmagent
Swarmagent is a Rust daemon built with bollard (Docker API) and tokio (async runtime). It runs on each Docker node and streams data to swarmbot.it.
What it monitors
- Host CPU: System-wide CPU usage percentage via
/proc/stator Docker stats API - Host memory: Total, used, and available RAM from Docker info
- Disk: Total and used disk space for the Docker root directory
- Containers: Per-container CPU and memory from the Docker stats stream
- Events: Real-time Docker event stream (start/stop/die/health events)
- Swarm info: Node ID, hostname, Swarm role and state
POST /events payload
// Envelope: { "type": "stats" | "event", "message": <payload> } { "type": "stats", "message": { "id": "mqyml912ulvx2m7nyijmdmuf3", "hostname": "Legion", "orchestrator": "swarm", "cpu": { "usedPercentage": 12.4, "cores": 16 }, "memory": { "total": 17179869184, "used": 6644629504, "usedPercentage": 38.7, "free": 10535239680 }, "disk": { "total": 512110190592, "used": 266770219008, "usedPercentage": 52.1, "free": 245339971584 }, "containers": [ { "name": "nginx.1.abc123", "id": "a1b2c3d4e5f6", "cpuPercentage": 0.8, "memory": 128.4, "memoryLimit": 512, "memoryPercentage": 25.1, "pids": 3 } ], "engineVersion": "27.3.1", "apiVersion": "1.44", "agentVersion": "0.1.2" } }
Swarmagent is push-only — it has no HTTP server, no health endpoint, and opens no listening port. It only makes outbound requests to swarmbot.it.
Security
Authentication
swarmbot.it uses JWT tokens. The signing secret is generated automatically on first boot and stored in the app_secrets database table — there is nothing to configure. Revoked tokens are recorded in the revoked_jti table and rejected on every subsequent request until they would have expired anyway.
Password hashing
Passwords are hashed with PBKDF2. Legacy SHA-256 digests are automatically upgraded on next login.
CORS
The API only accepts requests from origins listed in SWARMBOT_ALLOWED_ORIGINS. Set this to your exact dashboard URL — wildcard origins are not supported.
Encryption at rest
Sensitive values (registry passwords, API tokens) are encrypted with AES-256-GCM before being stored in PostgreSQL. The encryption key is derived from the auto-generated JWT secret.
Production checklist: Change the default admin password (SWARMBOT_BOOTSTRAP_PASSWORD), run behind a reverse proxy with TLS, and restrict SWARMBOT_ALLOWED_ORIGINS to your exact dashboard domain.
Network security
- Swarmagent → swarmbot.it communication should be on a private/overlay network
- The swarmbot.it API port (8080) should not be publicly exposed — use a reverse proxy
- All short-lived tokens (SLTs) expire in 5 minutes
Troubleshooting
Common issues and their solutions.
| Symptom | Cause | Fix |
|---|---|---|
| Login fails with 401 | Wrong credentials or expired token | Use admin / swarmbot on first boot. Check API logs for JWT error details. |
| API returns "Connecting to PostgreSQL" then exits | PostgreSQL not reachable | Check SWARMBOT_DB in .env and verify PostgreSQL is running on port 5432. |
| Dashboard shows "0 nodes" | Docker Swarm not initialized or MOCK=true | Run docker swarm init and set SWARMBOT_MOCK=false. |
| Swarmagent: "node_id = unknown" | Docker Swarm not initialized on this node | Run docker swarm init (manager) or docker swarm join (worker). |
| CORS error in browser console | Dashboard origin not whitelisted | Add your exact dashboard URL to SWARMBOT_ALLOWED_ORIGINS, restart API. |
| Port 8080 already in use on restart | Stale Node.js process | kill -9 $(lsof -t -i:8080) then restart. |
| Swarmagent binary fails on Alpine | Prebuilt binary uses glibc, Alpine uses musl | Build from source: apk add rust cargo musl-dev && cargo build --release |
| Metrics not appearing in charts | Swarmagent not connected, wrong SWARMBOT_URL, or InfluxDB unreachable | Check SWARMBOT_URL in Swarmagent env and SWARMBOT_INFLUXDB on the API. Verify the API can reach InfluxDB: curl $SWARMBOT_INFLUXDB/ping |
Getting logs
# API logs (structured JSON) npm run dev:api 2>&1 | tee /tmp/swarmbot-api.log # Swarmagent logs (human-readable tracing) RUST_LOG=info ./target/release/swarmagent 2>&1 | tee /tmp/swarmagent.log # Check application state in PostgreSQL psql postgresql://swarmbot:swarmbot@localhost:5432/swarmbot \ -c "SELECT username, role, last_login_at FROM users;" # Check the last hour of CPU metrics for a node in InfluxDB curl -G http://localhost:8086/query \ --data-urlencode "db=swarmbot" \ --data-urlencode "q=SELECT * FROM cpu WHERE time > now() - 1h"
For bug reports and feature requests, open an issue on GitHub. Include the API log output and your environment (OS, Docker version, Node.js version).