Files
restic-manager/docs/book/src/getting-started/enrolling-hosts.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

3.9 KiB

Enrolling your first host

The control plane only knows about hosts you've explicitly enrolled. Two paths exist:

  1. Token-based enrolment — admin generates a token, pastes it into an install command on the host. The host appears immediately, already mapped to the desired repo.
  2. Announce-and-approve — the agent runs without a token, "announces" itself to the server, and a human in the UI accepts the announcement.

Token-based is the default and what most operators want; the announce flow exists for the case where you can't easily paste a secret onto the host (auto-imaged endpoints, scripted bring-ups from a config repo).

Token-based enrolment

From the UI

  1. Click + Add host on the dashboard.
  2. Fill in the hostname, the restic repo URL, and the repo credentials. The credentials are AEAD-encrypted at the server immediately; what you paste is what the agent receives.
  3. Optionally pick the initial source paths — these become the first source group on the host.
  4. Submit. The server mints a one-time token and shows you a copy- pasteable install snippet.

On the host (Linux)

curl -fsSL https://restic.example.com/install/install.sh | \
    sudo RM_SERVER=https://restic.example.com \
         RM_ENROL_TOKEN=<token> \
         bash

The script:

  1. Detects architecture (amd64 or arm64).
  2. Downloads the agent binary from /agent/binary?os=…&arch=….
  3. Drops the systemd unit at /etc/systemd/system/restic-manager-agent.service.
  4. Runs the agent in -enrol mode, which posts the token and stores the persistent bearer it gets back.
  5. Enables and starts the unit.

Within seconds the host should appear on the dashboard as online.

On the host (Windows)

$env:RM_SERVER  = "https://restic.example.com"
$env:RM_ENROL_TOKEN = "<token>"
iwr -useb $env:RM_SERVER/install/install.ps1 | iex

Equivalent shape: registers a Windows service via the SCM (see P2-16 for details), runs -enrol, starts the service.

Recovering a lost token

Tokens are single-use and short-lived (1h). If you closed the tab before pasting the install command, head to the Add host page — outstanding tokens are listed there with a Regenerate button. Regenerating revokes the old token's hash and mints a fresh raw token while preserving the original repo credentials and initial paths. (NS-02 in tasks.md if you want the design rationale.)

Announce-and-approve

If the host can reach the server but you don't want to paste a secret on it, run the agent in -announce mode:

restic-manager-agent -announce \
                     -server https://restic.example.com \
                     -hostname myhost

The host appears in the Pending hosts panel on the dashboard with its hostname, OS, arch, and the source IP that announced it. Click Accept, fill in the repo URL + credentials, and the server pushes the bearer over the still-open WebSocket. No back-and-forth round trip.

If you don't accept within an hour the announcement is swept.

What happens on the agent

After enrolment, the agent:

  1. Connects via WebSocket to /ws/agent with its bearer token.
  2. Sends a hello envelope with its OS, arch, agent version, restic version, and protocol version.
  3. Receives a config.update carrying its encrypted repo credentials and any source-group paths.
  4. Sits idle, sending a heartbeat every 30s. Operator-driven "Run now" actions arrive as command.run envelopes; scheduled jobs are driven by the agent's local cron.

Auto-init of the repository

The first time a backup runs, the agent invokes restic init against the repo you configured at enrolment. If the repo already exists (config file already exists) the agent treats it as a success and proceeds. The host's repo status (unknownready / init_failed) is surfaced under the vitals strip on the host detail page; if init fails, save fresh credentials in the Repo tab to retry.