Install (Docker Compose)¶
What this is¶
The supported way to run PiHerder: Docker Compose stack (web, db, redis, celery-worker, caddy) with secrets in .env and data on host volumes.
Why Compose¶
One command brings up the whole control plane with migrations, workers for backups, and optional TLS termination. Other topologies (Kubernetes, bare metal) are not documented as supported.
Production install
Prefer a tagged image (1.4.0 / 1.4 / latest). Release notes: RELEASE_v1.4.0.md.
Steps¶
1. Clone and enter the repo¶
git clone https://github.com/bjorngluck/piherder.git
cd piherder
git checkout v1.4.0
cp .env.example .env
2. Generate secrets¶
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
openssl rand -hex 32 # SECRET_KEY
Paste into .env:
PIHERDER_MASTER_KEY=... # Fernet key from above — never lose this
SECRET_KEY=... # long random; not the compose default
3. (Recommended) Set public hostname¶
Place trusted PEMs in certs/ — full steps: Trusted HTTPS & TLS.
Local only / no certs yet
Mount Caddyfile.dev instead of Caddyfile for self-signed TLS. Fine for desktop testing; not reliable for phone Web Push.
4. Start the stack¶
Docker itself must start at boot (systemctl enable docker — already true on most Pi OS / Ubuntu Docker installs). Every core service, including web, uses restart: unless-stopped, so a host reboot brings the UI back without a manual compose up.
docker compose stop/docker stopbefore reboot: containers stay stopped (unless-stopped).docker compose down: containers are removed; you mustup -dagain.- Existing installs created web without this policy: run
docker compose up -donce so Docker recreates it. Confirm withdocker inspect -f '{{.HostConfig.RestartPolicy.Name}}' piherder-web→unless-stopped.
Compose pulls multi-arch bjorngluck/piherder:latest from Docker Hub (linux/amd64 + linux/arm64). Schema migrations run on web startup via Alembic.
To pin a release tag:
5. Open the UI¶
| Access | URL |
|---|---|
| With Caddy + certs | https://your.host:8443 (or your PIHERDER_PUBLIC_URL) |
| Caddy HTTP | http://your.host:8888 |
| Direct to web (no Caddy) | http://127.0.0.1:8000 (loopback only — not published on the LAN) |
Continue: First login — register the first admin (no default password user).
6. (Optional) LAN Discovery nmap worker¶
Default docker compose up does not start nmap. Web never runs scans: it only enqueues to queue nmap.
Worker fence (compose hard-codes — no .env required):
| Process | PIHERDER_NMAP_WORKER |
|---|---|
| web + main celery-worker | 0 — tasks refuse to scan |
celery-worker-nmap (+ Dockerfile.nmap) | 1 — only allowed executor |
Documented in .env.example and Environment reference.
docker build -f Dockerfile.nmap -t piherder:nmap-local .
docker compose --profile nmap up -d celery-worker-nmap
Ensure stock compose still publishes Postgres/Redis on host loopback (nmap worker uses host networking). Vuln pack dir defaults to ./piherder_nmap_vuln (PIHERDER_NMAP_VULN_PATH). Never add -Q nmap to the main celery-worker. Operator guide: LAN Discovery.
7. Production security checklist¶
| Item | Why |
|---|---|
Strong PIHERDER_MASTER_KEY + SECRET_KEY | Encrypts fleet secrets / signs sessions. Weak SECRET_KEY refuses boot unless PIHERDER_ALLOW_INSECURE (lab) |
PIHERDER_PUBLIC_URL=https://… (or COOKIE_SECURE=true) | Session cookies get the Secure flag; password-reset links and OIDC redirects use this origin only |
| Prefer Caddy 8888/8443 — app :8000 is loopback only | Correct client IP for audit + TLS termination (PIHERDER_TRUSTED_PROXY_CIDRS) |
METRICS_TOKEN=… if scrapers can reach /metrics | Empty token = open metrics on the app port |
Leave ALLOW_OPEN_REGISTRATION=false | Only first admin self-registers; others via Users |
| Settings → PiHerder backup → Full DR once | Offline archive + keep master key with it (1.2 Full = real pg_dump) |
| After first Test connection | SSH host key is pinned; reset the pin only after a rebuild |
Full env catalog: Environment reference.
Verify containers¶
Healthy web should accept HTTP; logs may show Web Push VAPID ready after first start.
Volumes created on the host¶
| Host path | Purpose |
|---|---|
./backups (or PIHERDER_BACKUP_HOST_PATH) | Per-server rsync destinations |
./piherder_backups | PiHerder self-backup archives |
./piherder_data | Avatars / logos |
./certs | TLS PEMs for Caddy |
Details: Volumes.
Image tags¶
Official image: bjorngluck/piherder. Default compose tag is latest. See Publish image.
To develop against local source, restore build: . for web / celery-worker or build and set PIHERDER_IMAGE to a local tag.
Upgrade later¶
Always keep a self-backup and the same PIHERDER_MASTER_KEY before major upgrades.