# Felhom pilot — tester agreement (Peti) > The terms of the first external pilot: what Peti runs, what Felhom can and cannot do on his > hardware, the honest limitations of the pilot, and his exit rights. Lives at > `felhom.eu/documentation/pilot/PETI-tester-agreement.md`. > Created 2026-07-09 (GL-7). Operator: Viktor. Tester: Peti. > > This is the operator-side record of the bargain. The points in §3, §4 and §5 are what Peti is told > and asked to acknowledge at onboarding; that conversation happens in Hungarian — this document is > the English source of truth those points are drawn from. --- ## 1. What the pilot is Peti runs **Felhom as a guest on his own Proxmox server** — the **BYO-host** model. He stays root on his hardware; Felhom is one LXC guest plus a narrow, non-root management footprint. This is not the appliance model (Felhom-owned hardware); the whole point of the pilot is to prove the BYO trust boundary on someone else's box. **Peti's box:** an 80-core / 128 GB rack server already running his own workloads. The Felhom guest is capped at **12 cores / 32768 MiB** (noisy-neighbour containment — the only thing standing between Felhom and his other guests, since we do not control the host). **Name:** `sajatfelhom.hu`. The existing Cloudflare tunnel for that domain must be re-pointed at the new guest as part of onboarding (§7). --- ## 2. What runs on Peti's box | Component | Footprint | Privilege | |-----------|-----------|-----------| | Felhom guest (LXC) | one container in the `felhom` pool, capped 12c/32 GB | unprivileged LXC | | Host agent | one binary + systemd unit on the host | **non-root** (`felhom-agent` user) | | Sudoers allowlist | `/etc/sudoers.d/felhom-agent` | narrow, `pct`/`vzdump`/mount verbs only | | PVE API token | scoped to the `felhom` pool + named storages only | `Pool.*`/`VM.*`/`Datastore.*` on those objects | | Local API | binds `vmbr0:8443` on his LAN | TLS + per-guest bearer token | Nothing else. In particular, on a BYO host the installer **does not** touch these appliance-only mechanisms: - **Break-glass is OFF.** Felhom never runs `chpasswd` on `root@pam` and never vaults a host root credential to the hub. Peti's root password is his own and is never seen or changed. - **Out-of-band operator SSH is OFF** (`oob.enabled=false`). Felhom opens no operator tunnel into his box. - **The offsite WireGuard tunnel is OFF** (`wg_tunnel.enabled=false`). No Felhom-side connection reaches back into his network. These are asserted at install time (the byo config-write asserts `oob`/`wg_tunnel`/`lan_resolver` are all off before the install is marked complete) and were live-validated on the demo host during the GL-6 drill. --- ## 3. What Felhom can and cannot do (the trust boundary) **Can:** provision and manage its own guest, run backups of its own guest to the storages named in its ACL, report guest/host health to the hub, and — only with an operator signing key that Peti's box has pinned — apply a signed agent self-update. Every host action goes through the narrow sudoers allowlist, scoped to the `felhom` pool. **Cannot:** read or modify Peti's other guests (the pool-scoped token is refused outside `felhom`); change his root password; open an inbound operator session; touch his DNS service (see F6 below); or reach storages outside its named ACL. The local API authorises every request strictly against the calling token's own guest — a token minted for one guest is refused for any other (`localapi/server.go`; spot-verified). --- ## 4. Honest limitations of the pilot This is the data-sovereignty pitch stated plainly, not hidden: - **No offsite backup yet (local-only).** Backups stay on Peti's own hardware. **A dead or stolen box, or a dead backup drive with no second local target, loses data.** The offsite tier (Tier-1/Tier-2 split + production WG endpoint) is a fast-follow, not part of this pilot. Local backups being green is asserted at onboarding (§7). - **Backups live on a physically removable drive on his own hardware (F2).** This is the flip side of "no offsite" and is the sovereignty guarantee: his data never leaves his premises, and he can physically remove the drive. It also means the resilience of the backup is exactly the resilience of that one local drive/pool. - **The `felhom` pool membership is asserted at bring-up only, not continuously healed (F7).** If something outside Felhom moves the guest out of the pool while it runs, Felhom won't silently re-grab it; a re-run (or `--adopt-pool`) repairs it. No autonomous host-level reassertion. - **Port 53 must be free on his host (F6).** Felhom's guest DNS wants `:53`. If Peti already runs a DNS service there, the installer **refuses and tells him** — it will not stop, mask, or reconfigure a DNS service on a host Felhom does not own. He resolves the conflict; Felhom mutates nothing. This is checked before anything is written (§7 pre-flight). --- ## 5. Exit rights (data sovereignty) Peti can leave at any time and keep his data. The uninstaller: - **Keeps** all drive data under `/mnt/felhom-drives/*`, the backup storage contents, the hub record, and any vaulted recovery credential — and prints a KEPT-vs-WIPED statement naming each, in both modes. Drives are unmounted (plain `umount`; a busy drive is warned, never force-unmounted). - **Removes** only Felhom's own footprint: its guest, agent, sudoers, self-update artifacts, and config (including `.bak*` siblings that could hold a hub API key). - Refuses to touch any guest that is not a Felhom guest (it targets only guests carrying the `/etc/felhom-bootstrap` bind mount). Result: Peti walks away with his hardware untouched and his data on his own removable drives. This was live-validated twice on the demo host (two real uninstalls, drive data intact each time, host audit clean) during the GL-6 drill. --- ## 6. Pre-install checklist (confirm with Peti before day-0) - [ ] **PVE major version 9.x** (the byo preflight refuses non-9.x unless forced). - [ ] **Port 53 is free** on the host — no existing DNS service bound there (F6; preflight refuses otherwise). - [ ] **The `felhom` pool** either does not exist or is Felhom's to use. - [ ] **VMID 9201 is free** (or pick another; the installer auto-selects a free one if 9201 is taken). - [ ] **⚠ OPEN — the backup target.** `felhom-pbs` (the demo offsite datastore) is unreachable from Peti's LAN, so the default `--acl-storages "local local-lvm felhom-pbs"` is wrong for him. We must know **whether Peti's server has a second disk/pool** to use as the local backup target: - If **yes** → name it in `--acl-storages` (e.g. `"local local-lvm "`) so backups land on a *different* physical drive than the live guest — real local resilience. - If **no** (single pool) → backups land on the same pool as the guest; this is a degraded posture (one drive failure loses both live and backup) and must be stated to Peti explicitly. **Resolve this before finalising the install command below.** - [ ] **`sajatfelhom.hu` Cloudflare tunnel** — confirm we can re-point it at the new guest (§7). - [ ] **Customer `peti-felhom` exists in the hub** with real Gitea read creds filled in (`git.username`/`git.token`) — the artifact fetch needs them, or relies on the anonymous path. --- ## 7. The install command Built from the hub's customer page (`peti-felhom` → **Setup Command** → BYO). The BYO shape is deliberately minimal — a fresh box auto-fetches the golden template from Gitea, so no `--force-gitea-golden` is needed: ``` sudo ./felhom-host-install.sh \ --customer-id peti-felhom \ --mode byo \ --cores 12 \ --memory 32768 \ --acl-storages "local local-lvm " ``` `` is resolved by the §6 open question. Add `--vmid`/`--node` only if 9201 is taken or the host is multi-node. The command is **download-then-run** (the script is fetched and inspected, never piped straight into a shell). **Onboarding sequence:** 1. Run pre-flight first: same command with `--preflight-only` — prints PASS/FAIL, writes no state. Confirms 9.x, `:53` free, ACL storages exist, pool membership. 2. Run the install. Peti sees the host-mutation disclosure and types his hostname to acknowledge. 3. **Set the dashboard password (G9).** The customer dashboard is open until the operator sets the password via the hub config; set it at onboarding, along with the geo-restriction. Until then the dashboard is publicly reachable — do not consider onboarding complete without it. 4. **Re-point the `sajatfelhom.hu` Cloudflare tunnel** at the new guest. 5. **Verify local backups are green** on his box (§4 — the honesty gate). Confirm a backup completes to `` and a restore-test passes mount-parity. --- ## 8. Acknowledgement At onboarding, Peti is asked to acknowledge (in Hungarian): 1. Felhom runs as a guest on his hardware; he stays root and Felhom never changes his root password or opens an inbound operator session. 2. **There is no offsite backup in the pilot.** His data stays on his premises on a removable drive; a lost box or a failed backup drive without a second local copy loses data. 3. He can uninstall at any time and keep his data and hardware; Felhom removes only its own footprint. 4. This is a pilot: rough edges are expected, and the honest limitations above are the trade for full data sovereignty.