From fb970c56351ac4e370d68340ea70ed217ff2c73d Mon Sep 17 00:00:00 2001 From: C4 Patino Date: Tue, 23 Jun 2026 23:10:20 -0500 Subject: [PATCH] feat: add unpackerr module and configuration to servarr --- lib/module/default.nix | 9 +++ .../apps/servarr/unpackerr/default.nix | 76 ++++++++++++++++++ secrets/crypt/unpackerr.toml | Bin 0 -> 12040 bytes 3 files changed, 85 insertions(+) create mode 100644 modules/nixos/services/apps/servarr/unpackerr/default.nix create mode 100644 secrets/crypt/unpackerr.toml diff --git a/lib/module/default.nix b/lib/module/default.nix index 975fc2d..3f8b4f3 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -88,6 +88,15 @@ with lib; rec { #@ Type -> Any -> String mkOptAttrset' = type: default: mkOptAttrset type default null; + ## Create a store path that symlinks to a path outside the Nix store. + ## + ## This is useful for mutable/decrypted files that should not be copied into + ## the store, matching Home Manager's mkOutOfStoreSymlink behavior. + mkOutOfStoreSymlink = pkgs: path: + pkgs.runCommandLocal "${baseNameOf path}" {} '' + ln -s ${lib.escapeShellArg path} $out + ''; + ## Create a listOf NixOS module option. ## ## ```nix diff --git a/modules/nixos/services/apps/servarr/unpackerr/default.nix b/modules/nixos/services/apps/servarr/unpackerr/default.nix new file mode 100644 index 0000000..eb4c240 --- /dev/null +++ b/modules/nixos/services/apps/servarr/unpackerr/default.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + namespace, + pkgs, + ... +}: let + inherit (lib) filter mkIf optional; + inherit (lib.${namespace}) getAttrByNamespace hostHasService mkOutOfStoreSymlink; + inherit (config.networking) hostName; + + networkCfg = getAttrByNamespace config "${namespace}.services.networking"; + + starrServices = ["radarr" "sonarr" "lidarr"]; + enabledStarrServices = filter (service: hostHasService networkCfg.network-services hostName service) starrServices; + isEnabled = enabledStarrServices != []; +in { + config = mkIf isEnabled { + systemd.services.unpackerr = let + unpackerrUser = config.users.users.unpackerr; + systemdDependencies = + enabledStarrServices + |> map (service: "${service}.service"); + in { + description = "Extract downloads for Starr apps"; + + wantedBy = ["multi-user.target"]; + wants = ["network-online.target"] ++ systemdDependencies; + after = ["network-online.target"] ++ systemdDependencies; + + serviceConfig = let + cfg = + "${config.users.users.c4patino.home}/dotfiles/secrets/crypt/unpackerr.toml" + |> mkOutOfStoreSymlink pkgs; + in { + Type = "simple"; + User = unpackerrUser.name; + Group = unpackerrUser.group; + UMask = "0002"; + + StateDirectory = "unpackerr"; + + LoadCredential = ["unpackerr.toml:${cfg}"]; + + ExecStart = "${pkgs.unpackerr}/bin/unpackerr --config %d/unpackerr.toml"; + Restart = "always"; + RestartSec = 30; + }; + }; + + users = { + users.unpackerr = { + isSystemUser = true; + group = "unpackerr"; + extraGroups = ["qbittorrent"] ++ enabledStarrServices; + }; + + groups.unpackerr = {}; + }; + + ${namespace}.services.storage.impermanence.folders = let + unpackerrUser = config.users.users.unpackerr; + in [ + { + directory = "/var/lib/unpackerr"; + user = unpackerrUser.name; + group = unpackerrUser.group; + mode = "700"; + } + ]; + + systemd.services.radarr.upholds = optional (builtins.elem "radarr" enabledStarrServices) "unpackerr.service"; + systemd.services.sonarr.upholds = optional (builtins.elem "sonarr" enabledStarrServices) "unpackerr.service"; + systemd.services.lidarr.upholds = optional (builtins.elem "lidarr" enabledStarrServices) "unpackerr.service"; + }; +} diff --git a/secrets/crypt/unpackerr.toml b/secrets/crypt/unpackerr.toml new file mode 100644 index 0000000000000000000000000000000000000000..3b936a997eee6492a592c76316f892c0a0946d1c GIT binary patch literal 12040 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 Rdi_7$g