From 2440d52e1e65aceef5e34ef6fe8151316b5ab488 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 11 Jul 2026 07:21:19 +0200 Subject: [PATCH] =?UTF-8?q?runbook:=20Peti=20PBS=20DR=20enable=20(supervis?= =?UTF-8?q?ed=20phase)=20=E2=80=94=20box=20prep,=20signed=200.80.0=20updat?= =?UTF-8?q?e,=20tier=20enable,=20ceremony?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6 --- .../pilot/RUNBOOK-peti-pbsdr-2026-07-11.md | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 documentation/pilot/RUNBOOK-peti-pbsdr-2026-07-11.md diff --git a/documentation/pilot/RUNBOOK-peti-pbsdr-2026-07-11.md b/documentation/pilot/RUNBOOK-peti-pbsdr-2026-07-11.md new file mode 100644 index 0000000..46647eb --- /dev/null +++ b/documentation/pilot/RUNBOOK-peti-pbsdr-2026-07-11.md @@ -0,0 +1,94 @@ +# RUNBOOK — Peti PBS DR tier enable (the epic's payoff) — 2026-07-11 + +> **State when written:** agent **0.80.0 published** (sha `f2ba62ca6aca6e24a8d08706ea0dc3ae43940a63e9bdf57d4606ad1756cf06d2`, +> anon round-trip verified; the demo runs the IDENTICAL bytes, adoption-proven). Hub v0.44.0 live; +> ep0 tenantsync surface live. Peti's box: `peti-felhom-86d37d`, agent 0.79.0, **wg_tunnel DISABLED +> (no WG peer registered), OOB DISABLED** — the box-side steps below need root ON the box +> (Peti's hands, supervised, per the tester agreement; there is no OOB path to it today). +> +> Roles: **[PETI-root]** = paste-block run as root on his box (Viktor supervising), +> **[VIKTOR]** = operator secrets (opsign key, hub global key, hub UI), **[CC]** = watches/asserts. + +## 1. [PETI-root] Box prep: new sudoers + wrapper + tunnel enable (BEFORE the self-update) + +The self-update ships ONLY the binary — the slice-2 sudoers alias (`FELHOM_PBSDR`) + the +`felhom-pbs-apply` wrapper must land beside it. Order sudoers/wrapper FIRST (inert under 0.79.0). + +```sh +# 1a. fetch the two files from the felhom-agent repo at main (raw), install guarded: +cd /root +for f in configs/felhom-agent.sudoers configs/felhom-pbs-apply; do + curl -fsSL "https://gitea.dooplex.hu/admin/felhom-agent/raw/branch/main/$f" -o "/root/$(basename $f).staged" \ + || echo "FETCH FAILED — repo not public; use the paste-block Viktor provides instead" +done +tr -d '\r' < /root/felhom-pbs-apply.staged > /root/felhom-pbs-apply.clean +bash -n /root/felhom-pbs-apply.clean +install -o root -g root -m 0755 /root/felhom-pbs-apply.clean /usr/local/sbin/felhom-pbs-apply +tr -d '\r' < /root/felhom-agent.sudoers.staged > /root/felhom-agent.sudoers.clean +visudo -cf /root/felhom-agent.sudoers.clean # MUST print "parsed OK" before install +install -o root -g root -m 0440 /root/felhom-agent.sudoers.clean /etc/sudoers.d/felhom-agent +rm -f /root/felhom-pbs-apply.* /root/felhom-agent.sudoers.* +# 1b. enable the offsite tunnel (wgtunnel is default-off; the bridge needs it): +python3 - <<'EOF' +import json +p="/etc/felhom-agent/agent.json"; c=json.load(open(p)) +c.setdefault("wg_tunnel",{})["enabled"]=True +json.dump(c,open(p,"w"),indent=2) +EOF +chown felhom-agent:felhom-agent /etc/felhom-agent/agent.json && chmod 0600 /etc/felhom-agent/agent.json +systemctl restart felhom-agent +``` + +**[CC] asserts after 1:** hub `wg_peers` gains a row bound to `peti-felhom-86d37d` (the agent +self-registers); peersync pushes it to ep0 (`wg show wg0` there lists the new peer); the box's +report grows the `wireguard` stanza; `wg-handshake-read` capability goes green once +wireguard-tools is installed by the bring-up (this is the degradation the tier clears). + +## 2. [VIKTOR] Signed self-update 0.79.0 → 0.80.0 (the GL-6-proven one-command shape) + +```sh +felhom-opsign -op agent_update -host peti-felhom-86d37d -key-id felhom-op-1 \ + -agent-version 0.80.0 \ + -sha256 f2ba62ca6aca6e24a8d08706ea0dc3ae43940a63e9bdf57d4606ad1756cf06d2 \ + -key -upload https://hub.felhom.eu -hub-key +``` +(`-hub-key` = the hub's `report_api_key` — the global/operator key, NOT the web login; GL-6 note.) + +**[CC] asserts after 2:** box journal: gate `allowed=true` → anon Gitea download → sha re-verify → +A/B flip → dwell → `update committed version=0.80.0`; report shows agent 0.80.0 and the pbsdr +capabilities (62 total expected) green; `pbsdr: bridge enabled` in the journal. + +## 3. [VIKTOR, hub UI] Enable the tier: Customers → peti-felhom → PBS DR tier (ep0) + +Enable checkbox ON, storage id **felhom-pbs** (the default — his box has no prior entry). Save. + +**What must happen, in order (the fresh path — [CC] watches every link):** +1. hub: `tenantsync: provision ok for peti-felhom (ns=peti-felhom, …)` — ep0 namespace + token + born over the SSH surface; secret staged consume-once for `peti-felhom-86d37d`; generation bump. +2. box (≤60s after its next envelope): bridge fetches the descriptor → **verify-pin BEFORE + consume** (PBS fingerprint over the tunnel, 10.77.0.1:8007) → consume (hub marks `consumed_at`) + → `felhom-pbs-apply create` (secret on stdin) → **K born at /etc/pve/priv/storage/felhom-pbs.enc** + → dual-grant → post-probe active → `escrow.pbs_storage_id=felhom-pbs` seeded → + `pbsdr: converged state=applied`. +3. report stanza `pbs_dr: {state: applied}`; `pvesm status --storage felhom-pbs` active on his box. + +## 4. [PETI-root] THE CEREMONY (RUNBOOK-escrow-ceremony; the bare one-liner — no flags needed) + +```sh +felhom-agent --selftest=escrow-create --upload +``` +Fresh **R** printed EXACTLY ONCE — **Peti keeps it** (paper; it supersedes his go-live R). The +upload triggers the hub's auto-confirm chain (slice 3 precedent): offsite `pending → escrowed`, +then the first offsite run. + +**[CC] asserts after 4:** hub `host_escrow` row updated for `peti-felhom-86d37d` (fresh +key_fingerprint + created_at); escrow/auto-confirm state green; first offsite/DR-tier artifacts +visible. **Nobody but Peti sees or stores R.** + +## Abort/rollback notes + +- Any failure BEFORE step-3's consume: retry-safe (nothing burned). A `consumed_failed` report + state after it = the hub "Re-issue PBS credentials" button (fresh secret; the bridge recovers). +- The self-update has crash-rollback armed (`.prev` retained; GL-6 proven both directions). +- NO deletion path exists anywhere in the new surface (set-only law) — a misconfigured entry is + `pvesm set`-corrected, never removed.