Getting Started
WatchWarden is in early-adopter / beta stage. The core features are implemented, tested (380+ automated tests), and security-reviewed — but the project has not yet seen extensive large-scale production use in diverse environments. Please test in your own staging environment before relying on it for critical workloads. See Design Decisions for background on development approach.
WatchWarden runs in two modes. Pick the one that fits your setup.
- Solo Mode (Standalone)
- Managed Mode (Full UI)
No controller, no database, no UI. Just mount the Docker socket and go.
docker run -d \
--name watchwarden \
-v /var/run/docker.sock:/var/run/docker.sock \
-e WW_SCHEDULE="@every 6h" \
-e WW_AUTO_UPDATE=true \
--restart unless-stopped \
ghcr.io/watchwarden-labs/watchwarden-agent:latest
Add Telegram notifications:
docker run -d \
--name watchwarden \
-v /var/run/docker.sock:/var/run/docker.sock \
-e WW_SCHEDULE="@every 6h" \
-e WW_AUTO_UPDATE=true \
-e WW_TELEGRAM_TOKEN=123456:ABC-DEF \
-e WW_TELEGRAM_CHAT_ID=-100123456 \
--restart unless-stopped \
ghcr.io/watchwarden-labs/watchwarden-agent:latest
With ntfy notifications:
docker run -d \
--name watchwarden \
-v /var/run/docker.sock:/var/run/docker.sock \
-e WW_SCHEDULE="@every 6h" \
-e WW_AUTO_UPDATE=true \
-e WW_NTFY_URL=https://ntfy.sh \
-e WW_NTFY_TOPIC=my-updates \
--restart unless-stopped \
ghcr.io/watchwarden-labs/watchwarden-agent:latest
Key Solo Mode variables:
| Variable | Default | Description |
|---|---|---|
WW_SCHEDULE | @every 24h | Check interval (@every 6h) or cron (0 4 * * *) |
WW_AUTO_UPDATE | false | Automatically apply updates |
WW_UPDATE_STRATEGY | recreate | recreate or start-first (blue-green, auto-falls back for port conflicts) |
WW_PRUNE | false | Remove old images after update |
See Agent Configuration for the full reference.
Multi-host management with a central controller, real-time dashboard, and per-agent configuration.
services:
postgres:
image: postgres:18-alpine
environment:
POSTGRES_DB: watchwarden
POSTGRES_USER: watchwarden
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
controller:
image: ghcr.io/watchwarden-labs/watchwarden-controller:latest
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://watchwarden:${POSTGRES_PASSWORD}@postgres:5432/watchwarden
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
depends_on:
postgres:
condition: service_healthy
ui:
image: ghcr.io/watchwarden-labs/watchwarden-ui:latest
ports:
- "8080:8080"
depends_on:
- controller
agent:
image: ghcr.io/watchwarden-labs/watchwarden-agent:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
CONTROLLER_URL: ws://controller:3000
AGENT_TOKEN: ${LOCAL_AGENT_TOKEN}
AGENT_NAME: local
volumes:
postgres_data:
Generate secrets and start:
export POSTGRES_PASSWORD=$(openssl rand -base64 32)
export ADMIN_PASSWORD=$(openssl rand -base64 16)
export JWT_SECRET=$(openssl rand -base64 32)
export ENCRYPTION_KEY=$(openssl rand -base64 32)
export LOCAL_AGENT_TOKEN=$(openssl rand -base64 32)
docker compose up -d
Open http://localhost:8080 and log in.
Adding Remote Agents
- Go to Agents > Add Agent in the dashboard
- Copy the generated token
- On the remote host:
docker run -d \
--name watchwarden-agent \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONTROLLER_URL=ws://YOUR_CONTROLLER_IP:3000 \
-e AGENT_TOKEN=your-generated-token \
-e AGENT_NAME=production-server \
--restart unless-stopped \
ghcr.io/watchwarden-labs/watchwarden-agent:latest
What's Next?
- Configuration Reference — all environment variables
- Architecture — how the components work together
- WatchWarden vs Watchtower — feature comparison