Files
restic-manager/docs/book/src/operations/backups-and-restores.md
T
steve bb4ed3502d P5: OSS readiness — docs site, contributor onboarding, e2e harness
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.
2026-05-08 20:08:23 +01:00

2.8 KiB

Backups and restores

Running a backup

Three ways to trigger one:

  1. Scheduled — the agent's local cron fires at the time set on the schedule.
  2. Run-now — operator clicks Run now on the host detail right rail. Posts to /hosts/{id}/run-backup (defaults to all source groups) or to a per-group form for finer control.
  3. APIPOST /api/hosts/{id}/jobs with the appropriate payload. Same audit + dispatch path.

In every case the server creates a jobs row, broadcasts a command.run to the host, and lands the operator on the live job log page (HTMX HX-Redirect).

Cancelling a job

Any running job — backup, forget, prune, restore, anything — exposes a Cancel button on its detail page. The server broadcasts command.cancel, and the agent kills the running restic subprocess via context cancel: SIGTERM first, SIGKILL after a 5s grace (cmd.Cancel + cmd.WaitDelay). On Windows the SIGTERM step is replaced with os.Kill because Windows can't deliver SIGTERM. Result: a cancelled job lands as cancelled within a couple of hundred milliseconds.

Restore wizard

Restoring a file or path goes through a four-step wizard at /hosts/{id}/restore:

  1. Pick a snapshot. Search by id or by date; the page is pre-populated when you launched the wizard from a snapshot row.
  2. Browse the snapshot tree. Lazy-loaded children via the MsgTreeList synchronous WS RPC; results are cached per-wizard-session for 30 minutes. Pick the absolute paths you want.
  3. Choose a target. Either In place (overwrites the live filesystem; requires you to type the hostname to confirm) or New directory (default $HOME/rm-restore/<job-id>/; agent expands $HOME / ${HOME} / ~/ and creates the directory chain).
  4. Review and submit. Server mints a job, dispatches command.run with a RestorePayload, and HX-Redirects to the live job log.

--no-ownership is gated on restic ≥ 0.17 (the flag was added in that release). Hosts running 0.16 don't get the flag and restore as the running user instead.

Snapshot diff

Two snapshot ids in the Diff form on the host detail page → a JobDiff job that runs restic diff <a> <b>. Output streams to the standard live job log. Useful when investigating a suspiciously-sized backup.

Job log artefacts

Every job's log is persisted in job_logs (one row per line), not just streamed in-memory. That gives you:

  • A live view at /jobs/{id} while the job runs.
  • Two download formats from the same page header dropdown:
    • txt — one line per row, HH:MM:SS.mmm TAG payload.
    • ndjson — one self-contained JSON object per line ({seq, ts, stream, payload}), perfect for jq.

Downloads work whether the job is running or finished — the source is the DB, not the live socket.