bb4ed3502d
P5-01 — Documentation site under docs/book/ rendered with mdBook
(downloaded via Makefile, same static-binary pattern as Tailwind).
Structured chapters: getting started, concepts, operations,
security, reference. `make docs` / `make docs-watch`. Generated
output gitignored.
P5-02 — CONTRIBUTING.md rewritten from placeholder to a full
guide. CODE_OF_CONDUCT.md adapted from Contributor Covenant for a
single-maintainer project. .gitea/issue_template/{bug,feature}.md
and PULL_REQUEST_TEMPLATE.md.
P5-04 — Six README screenshots captured live from a fresh server
bootstrap (login, empty dashboard, add-host, alerts, settings,
audit log). README rewritten to centre the screenshot grid and
link out to the docs site.
P5-05 — SECURITY.md with disclosure policy (3-day ack, 30-day
default window), scope in/out, threat-model summary, operator
hardening checklist. Mirrored as a docs-site chapter.
P5-06 — End-to-end test harness. e2e/compose.e2e.yml brings up
server + sibling Linux agent (alpine + restic) + restic/rest-server.
Agent uses announce-and-approve so Playwright can drive the full
operator flow: bootstrap → login → accept pending → backup →
verify terminal status. Second spec scrapes /metrics to assert
the P6-04 endpoint surface. .gitea/workflows/e2e.yml runs on every
PR; local how-to in docs/e2e.md.
2.7 KiB
2.7 KiB
Hardening checklist
A baseline for new deployments. Most of these are defaults; the list is here to make audit easy.
Server
- Reverse proxy in front, TLS terminating at the proxy (Caddy/nginx/Traefik).
RM_TRUSTED_PROXYset to the proxy's CIDR.RM_BASE_URLmatches the public hostname and the cookie scope you want.RM_COOKIE_SECURE=true(the default; only setfalsefor local HTTP testing).- HTTP listener bound to localhost in the compose file,
not
0.0.0.0. The reverse proxy is the only thing that should reach it. secret.keybacked up separately from the database.- Bootstrap token consumed and the printed log line scrubbed from any log archive.
Authentication
- Admin user has a password ≥ 12 characters (the floor).
- OIDC enabled if you have an IdP — local password auth stays as a break-glass.
- Disabled (not deleted) any users who change roles or leave so their session is invalidated immediately.
- The last-admin guard isn't tripped — there's always at least one enabled admin user.
Repo credentials
- Append-only credential set as the everyday cred for every host.
- Admin credential set only where prune cadence is enabled.
- No credentials reused across hosts. Each host should have its own credential pair so a single host compromise has a single blast radius.
- If using rest-server,
--append-onlyflag is on for the everyday user; the prune user is a separate identity.
Agent
- Agent runs as
root(Linux) orLocalSystem(Windows) only when the source paths require it. Otherwise pin a service user that has read access to what's backed up and nothing else. - systemd unit's sandboxing flags are intact
(
NoNewPrivileges,Protect*,MemoryDenyWriteExecute). - Agent's config file
/etc/restic-manager/agent.yamlis mode0600and owned by the service user. The bearer token lives in there.
Operations
- Alerts wired to a real channel (webhook into Slack, ntfy topic, SMTP) — not just sitting in the UI.
- Test-fire each notification channel after configuring.
- Audit-log retention is long enough to cover the operator's incident-response window.
- Prometheus endpoint, if enabled, gated by token AND CIDR where practical (default is opt-in / off).
Recovery
- A documented procedure for rotating a leaked agent bearer (delete + re-enrol the host).
- A test-restore done at least once, end-to-end, before relying on the system in anger.
secret.keyand the SQLite database covered by separate backup paths so neither alone reconstitutes the other.