Files
felhom.eu/REPORT-ep0-datastore-volume-2026-07-27.md
T
admin 2b24c70536 docs(ep0): hub PBS-DR capacity gauge verified correct after the volume move
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
2026-07-27 09:39:44 +02:00

93 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 | **≈713** |
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
1. **`scratch` datastore is configured at a path that does not exist** (`/srv/pbs-scratch`).
Pre-existing, not caused here, but now logs `ENOENT` on 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.
2. **The runbook's §6 acceptance test proves the wrong proposition.** `RequiresMountsFor` is 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.**
3. **§11 — storage box `u629193` is NOT simply unused.** No live backup path references it (no
datastore, no restic repo, no fstab, no `known_hosts` pin; R-17 already deleted `u629193-sub1`),
**but ep0 carries an enabled, currently-mounted sshfs unit** `mnt-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 -aHAX` **OOM-killed** ep0 (3.7 GB RAM, no swap). Cause: a PBS `.chunks/` tree pre-creates
all 65536 shard dirs → 75,341 inodes, and `-H` retains the whole inode map. `-H` was 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 -v` is not installed on ep0 → exit 127, rsync never ran, and a `| grep … || true`
wrapper swallowed it while printing a success-looking line.
- `rsync --version | head -1` reported 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
1. **Old copy retained** at `/srv/pbs-felhom` (13 GB, 9,748 chunks) as the rollback. Rollback is a
two-line `datastore.cfg` revert. Reclaim only after a new weekly offsite backup lands on the
volume, with explicit go-ahead.
2. **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.
3. ~~Hub PBS-DR capacity gauge not re-read.~~ **CLOSED — verified correct.** The 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`. 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.
4. **ep0 has no swap** (temporary 4 GB file removed; box left as found). Worth a small permanent
swapfile — outside this runbook's scope.