# End-to-end smoke test (P1-34) A runbook for verifying the Phase 1 happy path against a real `restic/rest-server`. Run this on any Linux host with Docker; nothing here touches your real Proxmox cluster or Unraid storage. The test exercises: 1. Operator mints an enrollment token **with repo creds** (P1-32). 2. Agent enrols, server burns the token, host_credentials row lands. 3. Agent connects over WS, server pushes `config.update` containing the decrypted creds **before** the agent sees any command. 4. Agent persists creds into `secrets.enc` (P1-33). 5. Run-now backup against the live `restic/rest-server`. 6. `snapshots.report` updates the per-host projection. 7. `GET /api/hosts/{id}/snapshots` returns the new snapshot. Total time: ~5 minutes on a warm machine. --- ## Prereqs - Docker + Docker Compose - `restic` v0.16+ on the host running the agent (the agent does **not** install it; that's a deliberate design choice — see spec §4.2) - `curl`, `jq` ## Layout Everything lives under `/tmp/rm-smoke/`. Nothing escapes it; remove the directory to clean up. ``` /tmp/rm-smoke/ ├── compose.yaml # rest-server + control-plane ├── data/ # control-plane SQLite + secret key │ └── agent-binaries/ # built agent binaries served by /agent/binary ├── rest/ # rest-server data volume │ └── htpasswd └── agent/ # this host plays the part of an endpoint ├── etc/ # → bind-mounted as /etc/restic-manager └── var-lib/ # → bind-mounted as /var/lib/restic-manager ``` ## 1. Build the binaries ```sh mkdir -p /tmp/rm-smoke/data/agent-binaries cd ~/src/restic-manager make build cp bin/restic-manager-agent /tmp/rm-smoke/data/agent-binaries/restic-manager-agent-linux-amd64 ``` The server's `/agent/binary?os=linux&arch=amd64` resolves to that path. ## 2. Compose the stack `/tmp/rm-smoke/compose.yaml`: ```yaml services: rest-server: image: restic/rest-server:latest restart: unless-stopped environment: - OPTIONS=--no-auth # smoke-test only; real deploys use --append-only + htpasswd ports: # Mapped to 8100 because most dev boxes already have something # on 8000. Use any free port; just keep the URLs below in sync. - "127.0.0.1:8100:8000" volumes: - ./rest:/data control-plane: image: ghcr.io/dcglab/restic-manager:dev # or build locally; see §1 restart: unless-stopped ports: - "127.0.0.1:8080:8080" volumes: - ./data:/data environment: - RM_LISTEN=:8080 - RM_DATA_DIR=/data - RM_BASE_URL=http://127.0.0.1:8080 - RM_SECRET_KEY_FILE=/data/secret.key - RM_COOKIE_SECURE=false # smoke-test only — we're on plain HTTP ``` For local-only smoke: skip the image and run the server straight from the binary instead, pointing at `/tmp/rm-smoke/data`: ```sh RM_LISTEN=:8080 RM_DATA_DIR=/tmp/rm-smoke/data \ RM_SECRET_KEY_FILE=/tmp/rm-smoke/data/secret.key \ RM_COOKIE_SECURE=false \ ./bin/restic-manager-server ``` Either way, watch stderr for the **bootstrap token** — printed on first run, used in the next step. ## 3. Bootstrap the admin account ```sh BOOTSTRAP_TOKEN='' curl -s -X POST http://127.0.0.1:8080/api/bootstrap \ -H 'content-type: application/json' \ -d "{\"token\":\"$BOOTSTRAP_TOKEN\",\"username\":\"admin\",\"password\":\"correct horse battery staple\"}" ``` ## 4. Mint an enrollment token (with repo creds) ```sh curl -s -c /tmp/rm-smoke/cookies -X POST http://127.0.0.1:8080/api/auth/login \ -H 'content-type: application/json' \ -d '{"username":"admin","password":"correct horse battery staple"}' ENROLL=$(curl -s -b /tmp/rm-smoke/cookies -X POST http://127.0.0.1:8080/api/enrollment-tokens \ -H 'content-type: application/json' \ -d '{ "hostname":"smoke-host", "repo_url":"rest:http://127.0.0.1:8100/smoke/", "repo_username":"", "repo_password":"smoke-pw" }') TOKEN=$(echo "$ENROLL" | jq -r .token) echo "token: $TOKEN" ``` If the server rejects with `missing_field`, you forgot `repo_url`/`repo_password` — both are required (P1-32). ## 5. Initialise the rest-server repo `restic/rest-server` will lazy-create the path on first write, but restic itself wants the repo initialised: ```sh RESTIC_PASSWORD=smoke-pw \ restic -r rest:http://127.0.0.1:8100/smoke/ init ``` ## 6. Pretend to be a fresh endpoint The agent will write `agent.yaml` + `secrets.enc` under `/tmp/rm-smoke/agent/etc` and `/tmp/rm-smoke/agent/var-lib`. We point both at those dirs to keep the smoke run isolated from your real `/etc/restic-manager`. ```sh mkdir -p /tmp/rm-smoke/agent/etc /tmp/rm-smoke/agent/var-lib CONFIG=/tmp/rm-smoke/agent/etc/agent.yaml # Pre-write the secrets path so we don't hit the system default. cat > "$CONFIG" <