The last open item from the datastore relocation. Hub operator UI (Offsite -> PBS DR) reports felhom-offsite (ep0) at 97.9 GB capacity, 12.6 GB used, 13% full - agreeing with the on-box df (98 G / 13 G / 13%). The gauge follows the datastore's CONFIGURED PATH, so the relocation required no hub-side change. RUNBOOK section 10.3 warned that a stale 37.2 GB reading would mean the gauge reads the wrong filesystem and would be a real bug worth a roadmap item - it does not, and there is no bug. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ARoadHBf8rHoscfiqeVZn
5.4 KiB
REPORT — ep0 PBS datastore relocated onto the 100 GB volume (2026-07-27)
Class: supervised operational run (RUNBOOK execution). No code changed. No version bump.
Written as REPORT-<topic>.md per the parallel-session rule — the shared REPORT.md was not touched.
Full record with all evidence: documentation/runbooks/RUNBOOK-ep0-datastore-volume-2026-07-27.md
Outcome: DONE and verified
felhom-offsite now lives on a dedicated 100 GB Hetzner Cloud Volume instead of ep0's 40 GB root disk.
| Before | After | |
|---|---|---|
| Path | /srv/pbs-felhom (root disk) |
/mnt/pbs-datastore (volume) |
| Datastore total | 37.2 GB | 98 GB (hub gauge: 97.9 GB) |
| Used | 28.9 % | 13 % (hub gauge: 12.6 GB, 13 %) |
| Headroom to the 80 % warn | 19 GB | ≈65 GB |
| Additional customers before warn | ≈2 | ≈7–13 |
Datastore name unchanged — the PBS-DR descriptors, per-box storage ids, ACLs and namespace layout that R-39/R-82 made self-healing are untouched.
Window: 06:58 → 07:19 UTC (PBS down 07:00 → 07:17). Nothing was deleted.
Acceptance evidence
| Gate | Result |
|---|---|
| Copy integrity | 13,242,207,822 = 13,242,207,822 B · 9,748 = 9,748 chunks · 7 = 7 snapshots · backup:backup · itemised dry-run 0 lines |
| Snapshot counts per ns | demo-felhom 2=2, demo-felhom-01 3=3, demo-hp 2=2 |
| atime semantics | rw,relatime,discard — relatime present, noatime absent (GC correctness) |
| Verify job | TASK OK, 3/3 groups, forced re-verification of every snapshot, 0 errors |
| §6 mount guard | refusal observed — Job … failed with result 'dependency'; mountpoint stayed empty |
| §8 restore round-trip | source_tier: pbs, pass: true, mount_parity: ok, clean teardown, 12m1s |
Three findings the operator should act on
-
scratchdatastore is configured at a path that does not exist (/srv/pbs-scratch). Pre-existing, not caused here, but now logsENOENTon every PBS start. This is the PRIME RISK shape ("reports fine, is not there") already live in the config. Decision needed: remove the stanza or create the directory. -
The runbook's §6 acceptance test proves the wrong proposition.
RequiresMountsForis a mount-first ordering guarantee, not a refusal — systemd silently re-mounts an unmounted volume and PBS then starts safely. The test only bites when the device is genuinely unavailable, which is how it was re-run and passed. Amendment recommended in the runbook record. -
§11 — storage box
u629193is NOT simply unused. No live backup path references it (no datastore, no restic repo, no fstab, noknown_hostspin; R-17 already deletedu629193-sub1), but ep0 carries an enabled, currently-mounted sshfs unitmnt-pbs\x2dstoragebox.mount→/mnt/pbs-storagebox, holding spike leftovers. Disable and remove that unit before deleting the box, or ep0 logs a failed mount every boot. The deletion is the operator's console click.
Deviations from the runbook as written
- The volume arrived already formatted and mounted by Hetzner at
/mnt/HC_Volume_106469259(§2 assumed neither). Operator ruled: reformat + repath. The 5 % reserve was reclaimed (-m 0). - §8 ran on demo-felhom, not demo-hp — DooPlex holds no SSH key for demo-hp (the G1 gap). Same tier, same relocated datastore, larger archive.
- The window was contended by a stale 10-minute restore-test cadence on demo-felhom: the config
had already been reverted to 3.5 days on disk, but the cadence is read once at daemon start and
NRestarts=0. Restarting the agent applied it (cadence=84h0m0s). The in-flight test was allowed to finish rather than aborted.
Process errors made during this run (recorded deliberately)
rsync -aHAXOOM-killed ep0 (3.7 GB RAM, no swap). Cause: a PBS.chunks/tree pre-creates all 65536 shard dirs → 75,341 inodes, and-Hretains the whole inode map.-Hwas dropped only after proving no hardlinks exist (-links +1→ 0; max link count → 1); PBS references chunks by digest, never by hardlink./usr/bin/time -vis not installed on ep0 → exit 127, rsync never ran, and a| grep … || truewrapper swallowed it while printing a success-looking line.rsync --version | head -1reported a working rsync 3.4.1 as "missing" — the §12 pipe-into-head trap, fourth recorded instance in this project. Both fixed by capturing the command's own$?.
Deferred
- Old copy retained at
/srv/pbs-felhom(13 GB, 9,748 chunks) as the rollback. Rollback is a two-linedatastore.cfgrevert. Reclaim only after a new weekly offsite backup lands on the volume, with explicit go-ahead. - GC not run — now unblocked by the round-trip, but left for a separate deliberate run. No GC schedule is configured on this PBS at all.
Hub PBS-DR capacity gauge not re-read.CLOSED — verified correct. The hub operator UI (Offsite → PBS DR) reportsfelhom-offsite (ep0)at 97.9 GB capacity, 12.6 GB used, 13 % full, agreeing with the on-boxdf. The gauge follows the datastore's configured path, so the move needed no hub-side change and the suspected "wrong filesystem" bug does not exist.- ep0 has no swap (temporary 4 GB file removed; box left as found). Worth a small permanent swapfile — outside this runbook's scope.