/srv/media is now a single btrfs subvolume on the media disk holding the
libraries and both staging trees, so imports are same-filesystem renames.
426 torrents were re-pointed through the deluge UI and are seeding without
a recheck, and the M.2 went from 164G to 39G used.
The layout is described by hardware-configuration.nix, deluge.nix and
sabnzbd.nix better than prose could, so the plan has nothing left to say.
Two follow-ups it was carrying, recorded here rather than kept as a file:
copying across filesystems flattened every reflink between the music
library and the torrent payloads, so those trees hold 170 GiB where they
held ~124 and duperemove would reclaim it; and the media filesystem has
still never been scrubbed.
Assisted-by: pi (claude-opus-5)
Both documents had accreted a running commentary -- findings, then
corrections to those findings, then corrections to the corrections. That
is a changelog, and it is the wrong shape for something read mid-migration
at 2am.
Rewritten to carry only current state and what remains to be done. The
boot-chain work, the swap incident, the USB 2.0 discovery and the
successive revisions of the throughput numbers are all gone; git holds
that history if anyone wants it.
The migration is now a runbook rather than a description: what can be done
in advance without downtime, what needs the media stack stopped and
roughly how long each step takes, and what must wait until the result is
proven.
Documents the reflink structure between music and torrents, measured
rather than assumed. Both trees cost ~124 GiB today and ~170 GiB once
copied, because reflinks cannot cross filesystems. Sharing is whole-file
and strictly bimodal -- no file is fragmentarily shared, and the 23% that
sit at 90-99% differ only by a ~115 KiB tag block Lidarr rewrote after
importing -- so duperemove recovers nearly all of it afterwards. Warns
against file-level duplicate finders, which compare content rather than
extents and would trade 564 seeds for zero bytes. Replaces a fabricated
claim that music was heavily hardlinked: it has none.
Drops host SSH keys from the backup set, where they were listed as tier 1
on the false premise that sops needs them. Every creation rule already
lists the GPG key as a recipient beside the per-host age keys.
Corrects the claim that alcyone needs no dumps: firefly and headscale are
both sqlite there, and only its postgres (roundcube) is excluded.
Assisted-by: pi (claude-opus-5)
Device letters on merope follow USB enumeration order and are not stable;
they changed three times on 2026-08-08/09 as drives were re-plugged. Both
documents now address disks by label throughout.
Corrections to the migration plan:
- The ~28 MiB/s attributed to the media disk was a saturated USB 2.0 link,
not a seek-bound spindle. On USB 3 it sustains 183 MB/s, 6.5x faster.
Sizing arguments were built on the wrong number.
- The 04:42 reset was a UAS device reset on the M.2 bridge (174c:2362),
not swap: swap stayed flat at 2.27 GiB with 4.4 GiB available. The
watchdog held it to 105s against 48min the previous day.
- Both drives now sit on the VL805 SuperSpeed side, so they share one
PCIe lane rather than having independent paths.
Boot, resolved 2026-08-09 in two stages, both firmware-level and
therefore invisible to nixos-rebuild:
- EEPROM walks USB in port order and looped when the drive in 2-1 had no
bootable partition. Excluded both data drives by VID:PID. Note
'rpi-eeprom-config --apply' is unusable on NixOS, since the wrapper
points FIRMWARE_ROOT at a nonexistent path; build the image with
--config and stage pieeprom.upd/.sig by hand.
- U-Boot 2021.04 predates bootstd and declares USB as a single instance,
so boot_targets held one usb0 and only devnum=0 was ever tried.
Replaced with 2026.04, which enumerates every bootdev. Old binary kept
as u-boot-rpi4.bin.bak.
Backups doc records that the M.2 has 2233 corruption errors and has never
been scrubbed, so they were found passively rather than by verification.
Music (92 GB, the only irreplaceable data there) has been copied to the
backups disk; a scrub is now the open item.
Assisted-by: pi (claude-opus-5)
No backup tooling exists anywhere in the flake today, and sdc1 is a
932GB disk holding 5.9MB.
Covers what is actually irreplaceable -- firefly, radicale, deluge
state, mail, git, immich, music -- rather than the 4.6TB of re-acquirable
video, and specifies database dumps rather than live file copies, which
would otherwise produce backups that silently will not restore.
Mail and calendars are already replicated across three hosts, so they are
included for history rather than redundancy: sync propagates deletion,
and the useful protection there is retention depth, not another copy.
Assisted-by: pi (claude-opus-5)
Consolidates all media onto sdb in a single btrfs subvolume mounted at
/srv, so every import becomes a rename or hardlink rather than a
cross-device copy, and the disk holding the swapfile sees no media I/O.
Written up after the 2026-08-07 stall, whose root cause was swap
contending with a Radarr import on the same device.
Assisted-by: pi (claude-opus-5)