Skip to content

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
# .env
PIHERDER_HOSTNAME=piherder.example.com
PIHERDER_PUBLIC_URL=https://piherder.example.com:8443

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 compose up -d

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 stop before reboot: containers stay stopped (unless-stopped).
  • docker compose down: containers are removed; you must up -d again.
  • Existing installs created web without this policy: run docker compose up -d once so Docker recreates it. Confirm with docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' piherder-webunless-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:

PIHERDER_IMAGE=bjorngluck/piherder:1.4.0 docker compose up -d

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 loginregister 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

docker compose ps
docker compose logs -f web --tail=100

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

git fetch --tags
git checkout v1.4.0    # or later 1.4.x
docker compose pull
docker compose up -d

Always keep a self-backup and the same PIHERDER_MASTER_KEY before major upgrades.