{ ... }: # Prowlarr — indexer manager (usenet + torrent), feeds SABnzbd/MediaManager. # dataDir is left at the module default: a *custom* dataDir makes the # upstream module force-reset it to 0700 root:root on every boot, stomping # DynamicUser's access ("unable to open database file"). Instead bind-mount # the real (migrated-from-ZimaOS) config dir onto the default path, so # DynamicUser+StateDirectory chowns it on first activation like a fresh # install — no manual chown needed. # # Mount onto /var/lib/private/prowlarr, NOT the public /var/lib/prowlarr: # StateDirectory symlinks the public path to .../private/; binding # onto the public path itself blocks systemd's migrate-on-start rename # ("Device or resource busy", exit 238/STATE_DIRECTORY). { services.prowlarr.enable = true; # `nofail` is NOT optional here: without it this bind is RequiredBy # local-fs.target, so an unassembled RAID array fails that target and drops # jupiter into emergency mode — which is a dead end, since root is locked and # sulogin has nothing to offer on a headless box. It defeats the `nofail` on # /mnt/data itself (a mount layered on the array is what actually took the # target down). Let this bind fail alone instead. fileSystems."/var/lib/private/prowlarr" = { device = "/mnt/data/AppData/prowlarr/config"; fsType = "none"; options = [ "bind" "nofail" ]; }; # systemd derives RequiresMountsFor from the unit's own paths, which here is # only /var/lib/prowlarr on the eMMC — so without this prowlarr starts happily # with the array absent and writes its state onto the 29G OS disk. Pin it to # the array so it fails loudly instead. systemd.services.prowlarr.unitConfig.RequiresMountsFor = [ "/mnt/data" ]; }