Docker Setup Guide¶
WireBuddy's supported container deployment uses Docker host networking on a Linux host. The repository contains the master Compose file at docker/docker-compose.yml and the node Compose file at docker/docker-compose.node.yml.
Prerequisites¶
- Linux host (amd64 or arm64)
- Docker Engine and Docker Compose
- WireGuard support in the host kernel (Linux 5.6+ or a compatible module)
/dev/net/tun- IP forwarding enabled on the host
Containers share the host kernel. The image therefore supplies wg and wg-quick, but it cannot supply the WireGuard kernel implementation.
Docker Compose¶
Clone the repository and create the environment file:
Generate a key and store it as WIREBUDDY_SECRET_KEY in .env:
The key must contain at least 32 UTF-8 bytes. Keep it unchanged across container recreations; changing or losing it makes encrypted WireGuard and OTP secrets unreadable.
Start WireBuddy from the repository root:
View the startup output, which contains the bootstrap password:
WireBuddy prints the generated temporary password once to the console, outside the normal log handlers, and never stores it. Find it in the output above.
Open http://<server-ip>:8000 and sign in as admin with that temporary password. The first login requires a password change.
First sign-in is plain HTTP
Until HTTPS is enabled, the bootstrap password and session travel in clear text. Sign in from the host itself, over an SSH tunnel (ssh -L 8000:127.0.0.1:8000 <server>) or from a trusted network.
Why the full Compose command?
The Compose file lives in docker/, while .env lives in the repository root. Passing both paths explicitly makes configuration resolution independent of the current working directory.
Included Compose Security¶
The supplied Compose service uses:
network_mode: host- all capabilities dropped, then re-added individually:
NET_ADMINfor WireGuard, plusNET_BIND_SERVICE,SETUID,SETGID,CHOWN, andDAC_OVERRIDEfor the bundled Unbound resolver no-new-privileges:true/dev/net/tun- a 40-second stop grace period
- bounded JSON-file log rotation
- a readiness health check against
/ready
Do not switch the service to bridge or macvlan networking. WireBuddy verifies host networking at startup because interface management and conntrack statistics require the host network namespace.
WIREBUDDY_SKIP_NETWORK_CHECK=1 is a development/CI escape hatch, not a production setting.
Persistent Data¶
The Compose file mounts docker/data/ at /app/data in the container.
| Path | Content |
|---|---|
wirebuddy.db | Users, interfaces, peers, settings, and node state |
certs/ | ACME certificates and account material |
dns/ | Generated Unbound configuration and DNS query data |
tsdb/ | Traffic, DNS trend, network, and speed-test metrics |
geolite2/ | Downloaded GeoLite2 City and ASN databases |
Back up both docker/data/ and the secret key. The application also provides backup and restore controls under Settings → Backup.
Custom Web Port or Bind Address¶
The GUI port and localhost-only setting are normally managed under Settings → General → Server Settings and take effect after restart.
Docker deployments can override them in .env. WIREBUDDY_PORT always takes precedence, and the supplied Compose file always sets it (default 8000), so under Compose change the port here rather than in the Settings:
Because host networking is used, no Docker ports: mapping is required. The selected port must be free on the host.
Reverse Proxy¶
The Docker entrypoint trusts forwarded headers from loopback by default. For a same-host Caddy or nginx proxy, this needs no configuration. If the proxy connects from another address, set WIREBUDDY_TRUSTED_PROXIES to the exact proxy IP or CIDR — this single variable covers both Uvicorn's forwarded-header trust and the application-level client-IP/HTTPS-cookie detection. A wildcard (*) is rejected.
See Environment Variables and the Installation Guide for complete proxy examples.
Docker Run¶
Compose is recommended. An equivalent basic container can be started with:
docker run -d \
--name wirebuddy \
--network host \
--cap-drop ALL \
--cap-add NET_ADMIN \
--cap-add NET_BIND_SERVICE \
--cap-add SETUID \
--cap-add SETGID \
--cap-add CHOWN \
--cap-add DAC_OVERRIDE \
--security-opt no-new-privileges:true \
--stop-timeout 40 \
--device /dev/net/tun:/dev/net/tun \
-e TZ=Etc/UTC \
-e WIREBUDDY_SECRET_KEY="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')" \
-e WIREBUDDY_DATA_DIR=/app/data \
-v wirebuddy-data:/app/data \
--restart always \
giiibates/wirebuddy:latest
Persist the generated secret separately before relying on this example for a production installation.
Health Checks¶
Two unauthenticated probes are available:
/health: lightweight liveness check/ready: readiness including database, scheduler, and expected DNS ingestion state
The supplied Compose file and the image health check use /ready, so the container is reported unhealthy when the database, the scheduler or the DNS log ingestion stops working. Use /health where you only need to know that the process answers.
Updating¶
docker compose --env-file .env -f docker/docker-compose.yml pull
docker compose --env-file .env -f docker/docker-compose.yml up -d
Use latest for the current stable release or pin an existing full release tag from Docker Hub.
Managing the Container¶
# Status
docker compose --env-file .env -f docker/docker-compose.yml ps
# Restart
docker compose --env-file .env -f docker/docker-compose.yml restart wirebuddy
# Shell
docker compose --env-file .env -f docker/docker-compose.yml exec wirebuddy bash
# WireGuard status
docker compose --env-file .env -f docker/docker-compose.yml exec wirebuddy wg show
Remote Node¶
Remote nodes use docker/docker-compose.node.yml and an enrollment token plus verification key created by the master. Follow the Multi-Node Deployment guide rather than adapting the master Compose service.
Troubleshooting¶
If the container exits during startup:
docker compose --env-file .env -f docker/docker-compose.yml logs wirebuddy
docker compose --env-file .env -f docker/docker-compose.yml config
docker inspect wirebuddy --format '{{.HostConfig.NetworkMode}}'
The final command must print host. Also verify that /dev/net/tun exists, the configured GUI port is free, and the secret key has at least 32 bytes.