Skip to content

Operator scenarios

Quick map from what you want to do → the right wiki page, plus end-to-end journeys that string pages together.

Use this after Install and First login.


End-to-end journeys

These are the stories the rest of the wiki supports. Walk them on a lab host before production.

Journey A — New instance to first healthy host

Goal: PiHerder is up; one Pi is keyed and visible on the dashboard.

Step Action Why
1 Install + secrets Stack + encryption key for fleet secrets
2 First login First account becomes admin; registration locks
3 Optional HTTPS Trust for browsers and later push
4 Add a server Wizard — Identity → Trust → Connect (install key → test → clear password)
5 Wizard Features (or Edit → Features) Enable only backups / OS updates (or HA updates) / Docker you need
6 Open Dashboard Confirm the host appears; no mystery tiles yet

Done when: Server detail shows green-enough SSH/deps for enabled features; no password left stored if key auth works.

Optional polish: pin the host Overview/Docker and Network Hosts map (Pins & host jump) so the ★ menu opens the map graph (#map).


Journey B — Safe backup before you depend on it

Goal: One successful rsync backup and a dry-run restore you understand.

Step Action Why
1 Enable Backups on the server Feature flag gates UI and bulk
2 Add source paths on Backups PiHerder only copies what you list
3 Run backup now Proves Celery + rsync + path policy
4 Open Jobs See pending → running → success
5 Restore wizard → dry-run See reverse rsync without writing
6 Only then schedule cron Avoid automated failure noise

Done when: last_backup_at updates; Audit shows request → complete; you know where files land on the herder host (Volumes).


Journey C — Patch without silent upgrades

Goal: Know what needs attention; apply only when you choose.

Step Action Why
1 Enable OS patch and/or Docker Flags unlock check/apply
2 Run check only (Updates) Safe: counts packages/images, no upgrade
3 Read Dashboard “need attention” Aggregate view of the fleet
4 Manual apply on one host Live log; exclusive job per type
5 Optional: schedule checks weekly Always-on awareness
6 Optional later: schedule apply with “only if updates” Never silent default auto-upgrade

Done when: You can explain check vs apply, and Jobs shows who/what for both.


Journey C2 — HAOS appliance under PiHerder

Goal: Home Assistant OS is a managed host: keyed SSH, HA update check, System info, optional backup.

Step Action Why
1 Enable Terminal & SSH on HAOS; install rsync if you want backups Path prerequisites
2 Add a server as root (or add-on user) + deploy key Fleet record
3 Host profile HAOS (or auto-mark after check) Backend uses ha CLI
4 Enable HA updates (+ Backups if needed); leave Docker off Capability envelope
5 System info + Check HA updates Versions + component counts
6 Optional: manual HA update… in a maintenance window Same confirm/audit bar as OS patch

Full detail: HAOS hosts.

Done when: HAOS chip + real Core/OS/Supervisor versions; check job green.


Journey D — Deploy a known stack from a template

Goal: Uptime Kuma (or NPM / Pi-hole / Grafana) runs from Catalog → Templates.

Step Action Why
1 Host has Docker feature + working docker Deploy target
2 Templates overviewOOTB badge pack Versioned recipe, not a one-off paste
3 Deploy wizard Variables, host, preview; deploy runs as Job + live log (0.6+)
4 Post-deploy checklist DNS, first login, bind integrations
5 Optional: Kuma integration Status in fleet Services
6 Later: Check drift / redeploy / Accept host as desired Desired state stays authoritative; intentional host edits get adopted

Done when: Deployment page exists; Docker shows the project; secrets only via step-up if required.


Journey D2 — Capture an existing stack (from host)

Goal: Turn a running compose project (e.g. grafana-monitoring with promtail-config.yaml) into a Yours template you can redeploy elsewhere.

Step Action Why
1 Host Docker inventory shows the project Source of truth on the Pi
2 From host — pick server + project Pull over SSH
3 Review editor: compose, Additional files, variables (NODE_NAME, ports, volumes, remote URLs) Config sidecars + host labels parameterised
4 Save → badge Yours Never overwritten by OOTB pack refresh
5 Deploy to another host with a different NODE_NAME Same recipe, correct labels/endpoints

Done when: Template lists under Your templates; deploy writes compose + sidecar files; labels match the target host.


Journey Move — Compose project to another host

Goal: An unlocked stack (Grafana-class) runs on dest with its data, name, and maps. Requires PIHERDER_SERVICE_MIGRATE=true and two Docker hosts (v1.4.0, flag off by default).

Step Action Why
1 Enable the flag; recreate web Kill switch default off
2 Lock a hardware-bound stack (or HAOS) Prove Move is refused
3 Unlock a disposable stack; ⋯ → Move to another host… Wizard
4 Pick dest (wait modal) · remap dest name/ports if needed · read preflight Blocks before copy; dest name/port overrides clear name/port clashes
5 Confirm downtime → JobHold Stop → copy → dest up → name/proxy. Copy/dest-up fail: Start source stack
6 Check dest inventory, CNAME or NPM forward_host, maps, Grafana container chips Green cutover
7 Leave leftover stopped on the first run Data still on source

Full page: Move a service. Do not pick Remove source on a stack you still need. Tick Adopt into fabric only if an NPM-only name should appear on the DNS list (Pi-hole CNAMEs stay).


Journey E — Homelab map (DNS + proxy + certs)

Goal: Names, paths, and TLS are visible and mostly automated.

Step Action Why
1 Pi-hole + optional NPM DNS truth + edge proxy inventory
2 Host Edit → General FQDN + manage A A records fan out to Pi-holes
3 Network maps settings LAN/gateway so Hosts map is readable
4 Adopt / import names from Pi-hole Bring existing lab DNS into PiHerder
5 Certificates pull or upload Vault + maps → deploy to hosts
6 Dashboard network panel Cheap pulse of named/mapped/NPM counts

Done when: Hosts map shows home vs cloud; a cert map can redeploy PEMs after renew.


Journey F — Disaster recovery for PiHerder itself

Goal: You can rebuild a fully functional control plane (keys, users, maps, integrations) after losing the herder host — and you know honestly what is not in that pack.

Step Action Why
1 Offline copy of PIHERDER_MASTER_KEY Encrypted fields useless without it
2 Self-backup Full DR once (v1.2+ = pg_dump) Entire herder DB + logos — not rsync trees. Pre-1.2 “full” was JSON only.
3 Read Honest DR scenarios on that page Scenario A (min) vs C (comfort pack)
4 Schedule herder backup Regular DR hygiene
5 Know Volumes piherder_backups ≠ fleet /backups
6 Optional: copy fleet backup disk + edge ./certs File DR + herder HTTPS without re-issue
7 Practice dry-run restore on a lab stack with the same master key Confidence before a real outage

Done when: Master key + at least one Full archive live off the herder host; you can explain “v1.2 Full = whole DB / host rsync no”; restore dry-run understood.

Not done when: You only backed up the herder and expect Frigate recordings or every nmap XML to reappear — those are out of self-backup scope (see Self-backup — not included).


Journey G — Second operator with least privilege

Goal: Someone else can run fleet jobs without full admin.

Step Action Why
1 Roles viewer vs operator vs admin
2 Users create operator Invite + one-time password
3 Optional force 2FA Policy for the whole instance
4 Operator runs a backup/check Confirms RBAC allows fleet mutate
5 Confirm they cannot open herder restore Control plane stays admin-only
6 Optional: SSO + passkey Same 2FA gates after IdP

Journey I — 1.2 identity + optional console

Goal: Harden sign-in (passkey / optional SSO) and decide whether web SSH is on.

Step Action Why
1 Account → Add passkey (+ TOTP still OK) Second factor without an app-only story
2 Optional Settings → SSO BYO IdP; keep an admin password
3 Leave PIHERDER_SSH_CONSOLE=false unless you need a browser shell Default off; XSS on the herder origin is shell-equivalent when on
3b Leave PIHERDER_HOST_FILES=false until you want jailed SFTP Default off; Host Files
3c Leave PIHERDER_SERVICE_MIGRATE=false until you want host→host copy Default off; Move a service
4 If you enable it: Settings → Console for idle / max / slots; Security for 2FA grant Web SSH console · Settings
5 Then: operator + 2FA → Console → + Shell Same wiki
6 Test connection pins the host key; reset only after a rebuild TOFU — mismatch is refused
7 Smoke the v1.2 QA identity + console rows if you turn these on Optional surfaces — they stay off until you enable them

Journey H — LAN discovery (opt-in nmap)

Goal: See the whole LAN (fleet + everything else) without auto-enrolling 50 devices as managed servers.

Step Action Why
1 Build + start nmap worker (--profile nmap); fence is compose-owned (PIHERDER_NMAP_WORKER) Web never runs nmap
2 LAN Discovery integration + CIDR(s) Scope allowlist
3 Overview → Scan now modal → Discovery, then Inventory (ports); detailed/deep needs in-app confirm Trust before schedules; Cancel does not queue
4 DevicesList or Map → edit modal: map name, device type, gateway if router, Mark known Labels + kind + Router spine + inbox
5 Catalog → Network → Hosts map — radar Discovered, 1:1 fit; lock a host or cam for ports (tap callout → list); clear focus when done End-to-end view + progressive ports; no per-device link required for discovered chips
5b Optional: server detail — always-open LAN discovery card beside Network path → Edit device → Save/close returns to that server Soft-embed without Integrations detour
6 Optional: Path map — select NPM hub to light all proxied paths + connectors Access picture for via-proxy names
7 Link / promote only what you will manage Discovery ≠ fleet member
8 Optional schedules (create + Edit) Cadence you control
9 Optional Runs tab History by intensity + Job link (no run ID column)
10 Optional vuln pack update + deep scan Pack volume opt-in

Done when: Hosts map shows fleet + discovered chips; named devices read clearly; known/type/gateway are set where needed; you know how to link/promote; schedules stay off until you want them.


Scenario Doc
Compose install + secrets Install
Register first admin (no default user), then invite others First login · Users
Trusted HTTPS for PWA/push HTTPS & TLS
Light / dark theme Appearance
About PiHerder / GitHub / new version notice Avatar menu → About (/about)
Add a Pi, deploy SSH key, features (wizard) Add a server · Journey A
HAOS appliance (SSH + HA updates) HAOS hosts · Journey C2
Dashboard tiles & fleet services Dashboard & Services
Backup / patch / LAN / Docker / console history (not Grafana) Reports

Backups & patching

Scenario Doc
Configure rsync sources + schedule Backups
Restore path (dry-run then apply) Backups
Check OS / images only Updates
Apply OS or container patch Updates
Bulk check/patch/backup many hosts Updates — Bulk
Reboot without hanging the UI Updates — Reboot
See job progress / cancel Jobs
Who did what (incl. client IP) Audit

Docker on hosts

Scenario Doc
Browse projects / containers / logs Docker overview
Stop / Start / Restart all services in a project Docker overview — lifecycle
Move a compose project to another host Move a service · Journey Move
Split services across compose files (same folder) Compose sets · Compose edit
Runtime stack view groups on the map Network — view groups
First cert → map / Apply to this PiHerder Managed certificates · Trusted HTTPS
Fast open via inventory cache Inventory
Edit compose, validate, deploy version Compose edit
Stack Check updates vs Deploy Updates — Docker
Prune dangling images / exited containers Docker overview

Integrations & discovery

Scenario Doc
Opt-in LAN nmap (worker, devices, schedules) LAN Discovery · Journey H
Network maps (DNS / topology) Network maps
Stale Jobs / Audit / nmap-run purge Settings — cleanup

Service templates

Scenario Doc
Catalog badges OOTB vs Yours Templates overview
Deploy OOTB NPM / Kuma / Pi-hole / Grafana Deploy · Journey D
Redeploy, volumes, wait modal Deploy — Redeploy
Check drift / Accept host as desired / import host .env / apply last known Deploy — ops
Pull existing stack + sidecar configs (promtail, etc.) From host · Journey D2
View secrets (step-up 2FA) Secrets

Catalog: integrations & network

Scenario Doc
Catalog tabs (Integrations / Certificates / Templates / Network) Integrations overview
Connect Kuma + bind services Uptime Kuma
Grafana deep links + preferred names Grafana
Multi Pi-hole, DNS fan-out, gravity Pi-hole
Host A records, service paths, Hosts/Path maps, runtime stack expand + container order Network maps
Switch light/dark; ops-hero layout Appearance
NPM proxy hosts (read-only) + pull cert NPM
Cert vault, maps, deploy, renew Certificates

Account, users, security

Scenario Doc
Viewer / operator / admin Roles
Create users, roles Users
TOTP, passkeys, backup codes, force 2FA 2FA
SSO / OpenID Connect SSO
In-browser SSH (flag off by default) Web SSH console
Install PWA + Web Push PWA & push

Operations & DR

Scenario Doc
.env keys Env reference
Volume mounts Volumes
Settings tabs (backup, security, Alerts, status, timezone, API) Settings
Stack Status healthy? Status
Herder self-backup / restore (admin only) Self-backup · Roles
Upgrade compose / image Upgrades
v1.2 freeze QA / sign-off QA checklist (historical Hub 1.2)
More backup parallelism Multi-worker
Prometheus / env webhook fallback Metrics
Webhook + SMTP alerts / forgot password Alerts
Token REST for n8n/HA API tokens
Generic HA / Frigate / n8n links Generic links

When things go wrong

Scenario Doc
SSH / rsync / docker group / host-key pin SSH troubleshooting
Backup stuck Backup troubleshooting
Push not arriving Push troubleshooting
Template / compose editor Templates troubleshooting
Symptom table Troubleshooting index