Storage and recovery¶
Put downloads and libraries under one filesystem, for example
/mnt/homelab/media/downloads and /mnt/homelab/media/library. Separate
datasets, subvolumes or mounts can prevent hardlinks even when they share one
disk. An import then becomes a copy, consuming extra I/O and space while
torrents seed.
TRaSH hardlink guidance
Declare the existing disk in the consuming host and set
homelab.storage.requiredMounts = [ "/mnt/homelab" ];. The storage preparation
unit checks the actual mount before creating directories. Service dependencies
order startup behind it. The project does not partition or format disks. A
disappearing or failing disk still requires operator recovery; startup guards
are not a substitute for monitoring or a hot-unplug guarantee.
Media directories use mode 2770 and the shared media group. Services retain their own primary identities for state. Downloads default to group-writable files; players receive a read-only library mount. Existing files may need an attended permission migration. No recursive ownership or permission rewrite is performed.
A 4 TB drive shared between media and backups needs a capacity budget before automatic downloads begin. Use sibling directories with separate ownership. Do not place a backup repository under its own source tree. Directory separation is not a quota. Leave headroom for download/unpack/import and backup retention; SABnzbd's initial free-space guard is 20 GB and must be tuned to the workload. A drive that is normally online for media is not an offline backup copy.
Keep SQLite databases and service state on the system SSD. Schedule library
scans, subtitle jobs, Usenet repair and backups away from interactive use.
homelab.profiles.desktop.enable gives downloads and library managers lower CPU
and I/O priority. Benchmark before selecting worker counts, cache sizes or GPU
transcoding. Enable the actual GPU through native Jellyfin and host driver
options after testing codec support and power use.
Recovery procedure¶
Inventory the evaluated paths before defining the host's backup job. These are the defaults at the checked-in package revision; host overrides take precedence. Application state can contain API credentials even when the original credentials came from nix-seal. Use encrypted backups with restricted access.
| Application | Persistent state to include | Native option |
|---|---|---|
| Sonarr | /var/lib/sonarr/.config/NzbDrone |
services.sonarr.dataDir |
| Radarr | /var/lib/radarr/.config/Radarr |
services.radarr.dataDir |
| Lidarr | /var/lib/lidarr/.config/Lidarr |
services.lidarr.dataDir |
| Bazarr | /var/lib/bazarr |
services.bazarr.dataDir |
| Prowlarr | /var/lib/prowlarr |
services.prowlarr.dataDir |
| Seerr | /var/lib/seerr, backed by /var/lib/private/seerr for its dynamic user |
services.seerr.configDir and stateRevision |
| qBittorrent | /var/lib/qBittorrent, including torrent resume data |
services.qbittorrent.profileDir |
| SABnzbd | /var/lib/sabnzbd, plus separately configured queue paths |
services.sabnzbd.stateDir, relative to /var/lib |
| NZBGet | /var/lib/nzbget, plus queue and NZB directories under downloads |
services.nzbget.settings |
| Jellyfin | /var/lib/jellyfin, including its config directory |
services.jellyfin.dataDir and configDir |
| Plex | /var/lib/plex |
services.plex.dataDir |
| Navidrome | /var/lib/navidrome, excluding replaceable cache if desired |
services.navidrome.settings.DataFolder |
| Audiobookshelf | /var/lib/audiobookshelf |
services.audiobookshelf.dataDir, relative to /var/lib |
Older Seerr state revisions use /var/lib/private/jellyseerr/config. Resolve
dynamic-user symlinks when selecting backup sources; copying only the symlink
does not preserve the database. Back up the host's encrypted nix-seal catalog
and its recovery material through its existing procedure, not disposable /run
outputs. Library files are a separate backup decision from application state.
These paths come from the
pinned NixOS modules.
- Export application settings or stop writers during a maintenance window. A live copy of a database directory does not establish consistency.
- Back up state, metadata and user-provided secret recovery material to an independent destination. Exclude disposable downloads and transcode caches.
- Keep media according to its replacement cost. Backups on the same media disk do not protect against that disk failing.
- Restore into a separate directory or VM, check ownership and application startup, then record the restore date and the recovered data.
- Before package upgrades, retain both a usable state backup and the previous lockfile. Roll back data and software together when a schema migration prevents an ordinary NixOS generation rollback.
During a restore, establish mounts and service identities first, restore data with the expected ownership, and provision nix-seal outputs. Start the VPN and downloaders, library managers and Prowlarr, then players and Seerr. Pause automatic acquisition until API connections, library paths and sample playback have been checked. A restored download queue without its matching payload may restart downloads or require a client recheck.
The consuming nix-conf host owns Restic destinations and existing backup checks. This flake does not silently create a second backup scheduler or prune policy.