# Media writes are allowed only after the pool and all its branches mount. # Keep these directory rules out of global tmpfiles: nofail mounts may be # absent when global tmpfiles runs, and creating paths then fills the root disk. { config, pkgs, lib, utils, ... }: let pool = "/mnt/storage"; branches = config.fileSystems.${pool}.depends or [ ]; mounts = map (p: "${utils.escapeSystemdPath p}.mount") ([ pool ] ++ branches); consumers = [ "jellyfin" "sonarr" "radarr" "bazarr" "qbittorrent-nox" "sabnzbd" "docker-shelfarr" "arr-interconnect" "bazarr-sync" "bazarr-sync-full" ]; directories = pkgs.writeText "media-directories.conf" '' d /mnt/storage/torrents/downloads 2775 qbittorrent media - Z /mnt/storage/torrents/downloads 2775 qbittorrent media - d /mnt/storage/torrents/shows 2775 sonarr media - Z /mnt/storage/torrents/shows 2775 sonarr media - d /mnt/storage/torrents/movies 2775 radarr media - Z /mnt/storage/torrents/movies 2775 radarr media - d /mnt/storage/torrents/audiobooks 2775 fred media - Z /mnt/storage/torrents/audiobooks 2775 fred media - d /mnt/storage/usenet/downloads 2775 sabnzbd media - Z /mnt/storage/usenet/downloads 2775 sabnzbd media - d /mnt/storage/usenet/incomplete 2775 sabnzbd media - Z /mnt/storage/usenet/incomplete 2775 sabnzbd media - ''; in { config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") { systemd.services = { media-storage-ready = { description = "Prepare media directories on the mounted pool"; requires = mounts; bindsTo = mounts; after = mounts; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' set -euo pipefail ${lib.concatMapStringsSep "\n" (p: '' ${pkgs.util-linux}/bin/mountpoint -q ${lib.escapeShellArg p} || { echo "Required media mount missing: ${p}" >&2 exit 1 } '') ([ pool ] ++ branches)} ${pkgs.systemd}/bin/systemd-tmpfiles --create ${directories} ''; }; } // lib.genAttrs consumers (_: { requires = [ "media-storage-ready.service" ]; after = [ "media-storage-ready.service" ]; bindsTo = [ "media-storage-ready.service" ]; }); }; }