build-the-nas.md
§4 splits the pool into two datasets and calls the split "the backup decision
made deliberately rather than drifted into":
| Dataset |
What it holds |
Backed up |
erebor/media |
films, music, the library |
no |
erebor/apps |
Jellyfin's database and config |
yes |
The reasoning is sound and already settled by ADR-0008: the library is
replaceable and its loss is "annoying rather than catastrophic", but the
metadata is not — watch history, resume positions, accounts, how the library is
organised. "Re-acquiring a series does not restore which episode you were on,
and that is measured in megabytes."
Nothing implements the yes. §8 of the same runbook says so: "The off-host
copy of erebor/apps, which §4 decided should exist and this runbook does not
build."
It is claimed in a second place too
stacks/media/compose.yaml:184
says of the jellyfin-config volume: "Backed up. See the mount comment above,
and §4 of build-the-nas.md for why this is the half of the tier that is."
scripts/backup-volumes.sh contains no jellyfin entry and no sentinel for it.
So two files assert a backup that no script performs, which is worse than
having no backup: the next person to read either one has no reason to look.
This is the shape #428 found in
the sensitive tier — volumes with no sentinels — arriving a second time, and it
is cheaper to fix before the data exists than after.
Why it is not simply "add it to backup-volumes.sh"
That script runs on the monitoring host, against volumes on the Docker daemon
it can see, and it verifies by decrypting — which needs the private key present.
smaug is on CasaBonita, it initiates nothing upward, and the whole estate's
relationship with it is pull. So the mechanism is a design question, not a
table entry, and it has at least three candidate answers with different costs:
- A pull over the existing
99 → 40:9100 path. That rule is scoped to the
scrape port; anything else needs another rule.
- The inert port-22 rule.
10.0.99.20 → 10.0.40.30:22 exists and does
nothing, because TrueNAS ships SSH disabled. ADR-0016 wrote that rule for
"prometheus pulling the metadata backup" — which is exactly this job.
Switching SSH on is then a deliberate act with a written reason.
- TrueNAS's own replication or cloud-sync tasks, which would put a second
backup mechanism in the estate, outside backup-volumes.sh's verification and
outside CI's reach — the same boundary ADR-0040 accepted for the pool layout,
and worth accepting or rejecting on purpose.
What it needs
Blocked on the pool — build-the-nas.md §3–§4, which waits on the two Exos
drives. Tracked under #413.
Found reconciling the tracker against the smaug build.
Corrected 2026-09-19
"Blocked on the pool" — no longer. Unblocked, still entirely true, and worse than filed: per the comment above, jellyfin-config is a Docker named volume on erebor/ix-apps/docker, not on erebor/apps, so the dataset §4 calls "backed up" holds the compose file and its .env and nothing Jellyfin writes. Meanwhile scripts/backup-volumes.sh names no media volume in SENTINEL, COMPANIONS or DISPOSABLE, and stacks/media/compose.yaml still labels jellyfin-config "Backed up".
Fourth checklist item, promoted from the comment: bind /config to a path under erebor/apps, or back up ix-apps as-is — decide which, then the copy off-host. Re-sequenced to seq/1: the highest-value unblocked item in this milestone, and one of the two things it closes on.
build-the-nas.md§4 splits the pool into two datasets and calls the split "the backup decision
made deliberately rather than drifted into":
erebor/mediaerebor/appsThe reasoning is sound and already settled by ADR-0008: the library is
replaceable and its loss is "annoying rather than catastrophic", but the
metadata is not — watch history, resume positions, accounts, how the library is
organised. "Re-acquiring a series does not restore which episode you were on,
and that is measured in megabytes."
Nothing implements the yes. §8 of the same runbook says so: "The off-host
copy of
erebor/apps, which §4 decided should exist and this runbook does notbuild."
It is claimed in a second place too
stacks/media/compose.yaml:184says of the
jellyfin-configvolume: "Backed up. See the mount comment above,and §4 of build-the-nas.md for why this is the half of the tier that is."
scripts/backup-volumes.shcontains nojellyfinentry and no sentinel for it.So two files assert a backup that no script performs, which is worse than
having no backup: the next person to read either one has no reason to look.
This is the shape #428 found in
the sensitive tier — volumes with no sentinels — arriving a second time, and it
is cheaper to fix before the data exists than after.
Why it is not simply "add it to backup-volumes.sh"
That script runs on the monitoring host, against volumes on the Docker daemon
it can see, and it verifies by decrypting — which needs the private key present.
smaugis on CasaBonita, it initiates nothing upward, and the whole estate'srelationship with it is pull. So the mechanism is a design question, not a
table entry, and it has at least three candidate answers with different costs:
99 → 40:9100path. That rule is scoped to thescrape port; anything else needs another rule.
10.0.99.20 → 10.0.40.30:22exists and doesnothing, because TrueNAS ships SSH disabled. ADR-0016 wrote that rule for
"
prometheuspulling the metadata backup" — which is exactly this job.Switching SSH on is then a deliberate act with a written reason.
backup mechanism in the estate, outside
backup-volumes.sh's verification andoutside CI's reach — the same boundary ADR-0040 accepted for the pool layout,
and worth accepting or rejecting on purpose.
What it needs
jellyfin-configa sentinel, so the claim in the compose file ischeckable rather than decorative.
beyond
oracle's shelf, and this is a small amount of data, so it maysimply join what already exists rather than needing somewhere new.
erebor/mediais not backed up, onpurpose, and that should be as legible on the host as it is in §4.
Blocked on the pool —
build-the-nas.md§3–§4, which waits on the two Exosdrives. Tracked under #413.
Found reconciling the tracker against the
smaugbuild.Corrected 2026-09-19
"Blocked on the pool" — no longer. Unblocked, still entirely true, and worse than filed: per the comment above,
jellyfin-configis a Docker named volume onerebor/ix-apps/docker, not onerebor/apps, so the dataset §4 calls "backed up" holds the compose file and its.envand nothing Jellyfin writes. Meanwhilescripts/backup-volumes.shnames no media volume inSENTINEL,COMPANIONSorDISPOSABLE, andstacks/media/compose.yamlstill labelsjellyfin-config"Backed up".Fourth checklist item, promoted from the comment: bind
/configto a path undererebor/apps, or back upix-appsas-is — decide which, then the copy off-host. Re-sequenced toseq/1: the highest-value unblocked item in this milestone, and one of the two things it closes on.