# 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) ```sh curl -fsSL https://restic.example.com/install/install.sh | \ sudo RM_SERVER=https://restic.example.com \ RM_ENROL_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) ```pwsh $env:RM_SERVER = "https://restic.example.com" $env:RM_ENROL_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: ```sh 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 (`unknown` → `ready` / `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.