{ config, pkgs, lib, ... }: with lib; let cfg = config.nas-apps.arrs; settings = import ../settings.nix; radarrDataDir = "/var/lib/radarr"; downloadDir = "/downloads"; incompleteDir = "/downloads-incomplete"; sonarrDataDir = "/var/lib/sonarr"; sabnzbdConfig = "/var/lib/sabnzbd"; jackettDir = "/var/lib/jackett/.config/Jackett"; mediaDir = "/media"; arrUserId = config.users.users.nix-apps.uid; arrGroupId = config.users.groups.jallen-nas.gid; radarrPkg = pkgs.radarr; sonarrPkg = pkgs.sonarr; delugePkg = pkgs.deluge; jackettPkg = pkgs.jackett; sabnzbdPkg = pkgs.sabnzbd; in { imports = [ ./options.nix ]; config = mkIf cfg.enable { containers.arrs = { autoStart = true; privateNetwork = true; hostAddress = settings.hostAddress; localAddress = cfg.localAddress; config = { pkgs, lib, ... }: { nixpkgs.config.allowUnfree = true; # Enable radarr service services.radarr = { enable = cfg.radarr.enable; openFirewall = true; user = "arrs"; group = "media"; dataDir = radarrDataDir; package = radarrPkg; }; # Enable Sonarr service services.sonarr = { enable = cfg.sonarr.enable; openFirewall = true; user = "arrs"; group = "media"; dataDir = sonarrDataDir; package = sonarrPkg; }; # Enable Sabnzbd service services.sabnzbd = { enable = cfg.sabnzbd.enable; openFirewall = true; user = "arrs"; group = "media"; configFile = "${sabnzbdConfig}/sabnzbd.ini"; package = sabnzbdPkg; }; services.deluge = { enable = cfg.deluge.enable; user = "arrs"; group = "media"; openFirewall = true; dataDir = "/media"; package = delugePkg; web = { enable = true; port = cfg.deluge.port; openFirewall = true; }; }; services.jackett = { enable = cfg.jackett.enable; user = "arrs"; group = "media"; openFirewall = true; package = jackettPkg; }; # Create required users and groups users.users.arrs = { isSystemUser = true; uid = lib.mkForce arrUserId; group = "media"; extraGroups = [ "downloads" ]; }; users.groups = { media = { gid = lib.mkForce arrGroupId; }; downloads = { }; }; # System packages environment.systemPackages = with pkgs; [ glib sqlite mono mediainfo protonvpn-cli_2 ]; # Create and set permissions for required directories system.activationScripts.arr-dirs = '' mkdir -p ${radarrDataDir} mkdir -p ${sonarrDataDir} mkdir -p ${sabnzbdConfig} mkdir -p ${downloadDir} mkdir -p ${incompleteDir} mkdir -p ${mediaDir} chown -R arrs:media ${radarrDataDir} chown -R arrs:media ${sonarrDataDir} chown -R arrs:media ${sabnzbdConfig} chown -R arrs:media ${downloadDir} chown -R arrs:media ${incompleteDir} chown -R arrs:media ${mediaDir} chmod -R 775 ${radarrDataDir} chmod -R 775 ${sonarrDataDir} chmod -R 775 ${sabnzbdConfig} chmod -R 775 ${downloadDir} chmod -R 775 ${incompleteDir} chmod -R 775 ${mediaDir} ''; networking = { firewall = { enable = true; allowedTCPPorts = [ cfg.radarr.port cfg.sonarr.port cfg.sabnzbd.port 8080 ]; }; # Use systemd-resolved inside the container # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686 useHostResolvConf = lib.mkForce false; }; services.resolved.enable = true; system.stateVersion = "23.11"; }; # Bind mount directories from host bindMounts = { "${radarrDataDir}" = { hostPath = cfg.radarr.dataDir; isReadOnly = false; }; "${sonarrDataDir}" = { hostPath = cfg.sonarr.dataDir; isReadOnly = false; }; "${sabnzbdConfig}" = { hostPath = cfg.sabnzbd.dataDir; isReadOnly = false; }; "${downloadDir}" = { hostPath = cfg.downloadsDir; isReadOnly = false; }; "${incompleteDir}" = { hostPath = cfg.incompleteDownloadsDir; isReadOnly = false; }; "${jackettDir}" = { hostPath = cfg.jackett.dataDir; isReadOnly = false; }; "/media/movies" = { hostPath = cfg.moviesDir; isReadOnly = false; }; "/media/tv" = { hostPath = cfg.tvDir; isReadOnly = false; }; "/media/isos" = { hostPath = cfg.isosDir; isReadOnly = false; }; }; }; networking = { nat = { forwardPorts = [ { destination = "${cfg.localAddress}:${toString cfg.radarr.port}"; sourcePort = cfg.radarr.port; } { destination = "${cfg.localAddress}:${toString cfg.sonarr.port}"; sourcePort = cfg.sonarr.port; } { destination = "${cfg.localAddress}:8080"; sourcePort = cfg.sabnzbd.port; } { destination = "${cfg.localAddress}:${toString cfg.deluge.port}"; sourcePort = cfg.deluge.port; } { destination = "${cfg.localAddress}:${toString cfg.jackett.port}"; sourcePort = cfg.jackett.port; } ]; }; firewall = { allowedTCPPorts = [ cfg.radarr.port cfg.sonarr.port cfg.sabnzbd.port 8080 cfg.deluge.port cfg.jackett.port ]; allowedUDPPorts = [ cfg.radarr.port cfg.sonarr.port cfg.sabnzbd.port 8080 cfg.deluge.port cfg.jackett.port ]; }; }; }; }