feat: multi-radarr #74

Merged
jahanson merged 6 commits from multi-radarr into main 2025-02-10 11:49:52 -06:00
5 changed files with 503 additions and 318 deletions

View file

@ -57,11 +57,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1738148035, "lastModified": 1738765162,
"narHash": "sha256-KYOATYEwaKysL3HdHdS5kbQMXvzS4iPJzJrML+3TKAo=", "narHash": "sha256-3Z40qHaFScWUCVQrGc4Y+RdoPsh1R/wIh+AN4cTXP0I=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "18d0a984cc2bc82cf61df19523a34ad463aa7f54", "rev": "ff3568858c54bd306e9e1f2886f0f781df307dff",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -437,11 +437,11 @@
"xdph": "xdph" "xdph": "xdph"
}, },
"locked": { "locked": {
"lastModified": 1738546470, "lastModified": 1739123889,
"narHash": "sha256-pyMFj2IBeiRDnYoHD9XtbFiwBzvXJCavdFoVPnZ1YB0=", "narHash": "sha256-TinJJD88Y2EY0eoThanqN8Zr8I25JVhr1CeRS2LUeOc=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "Hyprland", "repo": "Hyprland",
"rev": "708d16636047c6a311c4e44424cf7d2090219a47", "rev": "f261fb6fe028a1427cfd672eee6e7d5705cd696f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -467,11 +467,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1738500466, "lastModified": 1738966025,
"narHash": "sha256-GAO3bpA4nk7RETw0SFN3QhDPNcTYbxiCoRZO9NudKsY=", "narHash": "sha256-MzgrF0jKlTNnNS33D8PwI5z2MJ1Tzf5MQVf/oms2pdw=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-plugins", "repo": "hyprland-plugins",
"rev": "eefa87d099bac625234b9e89ed67624efea0d27a", "rev": "4f48dbe12f3cbbeb4d31c91c67b21edbc5b4b451",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -802,11 +802,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1738547119, "lastModified": 1739152024,
"narHash": "sha256-cc6AfR7W0AavgqA5nHUXRUus4Rr7oPWQNku5nhR4SYs=", "narHash": "sha256-9lPbbaZfltXnkATkqBETzonhW8T4zQKgCs+BqLWt1n4=",
"owner": "Infinidoge", "owner": "Infinidoge",
"repo": "nix-minecraft", "repo": "nix-minecraft",
"rev": "5b93268c80c3300dbec0fbbb2b50f674f84a474a", "rev": "a5890fd3546723e386f2e485bc37e1bd56c4f623",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -824,11 +824,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1738547248, "lastModified": 1739152168,
"narHash": "sha256-ALPkA9L4G0j7piorEyeQ7zf6fW4vii4ULxRZBXmeKYM=", "narHash": "sha256-Zv6eGe+c5f9Chyw6O3ePJ4hbscetuzZxYShwjn3ACEs=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-vscode-extensions", "repo": "nix-vscode-extensions",
"rev": "bfacd5e2786caf61da0ad956728559dd6c1e8037", "rev": "bd6b70f681b2561f53c9522be64330c7ff9d08d8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -839,11 +839,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1738471961, "lastModified": 1738816619,
"narHash": "sha256-cgXDFrplNGs7bCVzXhRofjD8oJYqqXGcmUzXjHmip6Y=", "narHash": "sha256-5yRlg48XmpcX5b5HesdGMOte+YuCy9rzQkJz+imcu6I=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "537286c3c59b40311e5418a180b38034661d2536", "rev": "2eccff41bab80839b1d25b303b53d339fbb07087",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -911,11 +911,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1738410390, "lastModified": 1739020877,
"narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", "narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "3a228057f5b619feb3186e986dbe76278d707b6e", "rev": "a79cfe0ebd24952b580b1cf08cd906354996d547",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -927,11 +927,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1738435198, "lastModified": 1739055578,
"narHash": "sha256-5+Hmo4nbqw8FrW85FlNm4IIrRnZ7bn0cmXlScNsNRLo=", "narHash": "sha256-2MhC2Bgd06uI1A0vkdNUyDYsMD0SLNGKtD8600mZ69A=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f6687779bf4c396250831aa5a32cbfeb85bb07a3", "rev": "a45fa362d887f4d4a7157d95c28ca9ce2899b70e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -943,11 +943,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1738142207, "lastModified": 1739020877,
"narHash": "sha256-NGqpVVxNAHwIicXpgaVqJEJWeyqzoQJ9oc8lnK9+WC4=", "narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9d3ae807ebd2981d593cddd0080856873139aa40", "rev": "a79cfe0ebd24952b580b1cf08cd906354996d547",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1032,11 +1032,11 @@
"treefmt-nix": "treefmt-nix" "treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1738362438, "lastModified": 1739155557,
"narHash": "sha256-EO2dVkMVLThWqv4hobEZEZGWBEuH2Z9SYqQDrbLSclU=", "narHash": "sha256-LKagpHr2dxARgTSZDEXdpN6AX0moNzUhvjtmb+3+GrM=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NUR", "repo": "NUR",
"rev": "95ddad0ff0e67c90314c6ca46324dce5f9a910d2", "rev": "38696e05e8c52a8e1db5e045fe857eb0f65cdbf7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1056,6 +1056,8 @@
"plugin-aerial-nvim": "plugin-aerial-nvim", "plugin-aerial-nvim": "plugin-aerial-nvim",
"plugin-alpha-nvim": "plugin-alpha-nvim", "plugin-alpha-nvim": "plugin-alpha-nvim",
"plugin-base16": "plugin-base16", "plugin-base16": "plugin-base16",
"plugin-blink-cmp": "plugin-blink-cmp",
"plugin-blink-compat": "plugin-blink-compat",
"plugin-bufdelete-nvim": "plugin-bufdelete-nvim", "plugin-bufdelete-nvim": "plugin-bufdelete-nvim",
"plugin-catppuccin": "plugin-catppuccin", "plugin-catppuccin": "plugin-catppuccin",
"plugin-ccc": "plugin-ccc", "plugin-ccc": "plugin-ccc",
@ -1222,11 +1224,11 @@
"systems": "systems_6" "systems": "systems_6"
}, },
"locked": { "locked": {
"lastModified": 1738504946, "lastModified": 1739089639,
"narHash": "sha256-/btrLwD7UFgNWPxdewMdYYiI2GJxYipGnLuX7pRVAjc=", "narHash": "sha256-MCkgsVTAtoVUthorcCeit1oBuFyG7XktYdeMzyHL2uE=",
"owner": "notashelf", "owner": "notashelf",
"repo": "nvf", "repo": "nvf",
"rev": "944327329712eda9eec8a86a972e0abd7ea368e6", "rev": "a78026438cc8e280a696bcadb60f5c8f93b96a12",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1326,6 +1328,38 @@
"type": "github" "type": "github"
} }
}, },
"plugin-blink-cmp": {
"flake": false,
"locked": {
"lastModified": 1736295934,
"narHash": "sha256-MfHI4efAdaoCU8si6YFdznZmSTprthDq3YKuF91z7ss=",
"owner": "saghen",
"repo": "blink.cmp",
"rev": "1cc3b1a908fbcfd15451c4772759549724f38524",
"type": "github"
},
"original": {
"owner": "saghen",
"repo": "blink.cmp",
"type": "github"
}
},
"plugin-blink-compat": {
"flake": false,
"locked": {
"lastModified": 1734896240,
"narHash": "sha256-Rrrh+O3FbBnaAnCHwPuQyfhH+XueSkQp6ipEkn6esGY=",
"owner": "saghen",
"repo": "blink.compat",
"rev": "74b251a1e9478c4fa6d7c6bc2921d7124e6f6cbb",
"type": "github"
},
"original": {
"owner": "saghen",
"repo": "blink.compat",
"type": "github"
}
},
"plugin-bufdelete-nvim": { "plugin-bufdelete-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
@ -4223,11 +4257,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1738397340, "lastModified": 1739084700,
"narHash": "sha256-Vt3y544m/w04ty8v+W/kfG3p34j+nys9rL13sNoqlcU=", "narHash": "sha256-8WzaXHu81bcAgFNC/VnnlDFAchH7B8UNlust1oyOZqA=",
"owner": "budimanjojo", "owner": "budimanjojo",
"repo": "talhelper", "repo": "talhelper",
"rev": "5886ae9f388613dc0f3b9f17b5228c0d406b77ed", "rev": "3802fa0b656a1eb585280b88895b1f7339336694",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -91,41 +91,77 @@
restartUnits = [ "sonarr.service" ]; restartUnits = [ "sonarr.service" ];
}; };
# Radarr # Radarr
"arr/radarr/apiKey" = { "arr/radarr/1080p/apiKey" = {
sopsFile = ../secrets.sops.yaml; sopsFile = ../secrets.sops.yaml;
owner = "radarr"; owner = "radarr";
mode = "400"; mode = "400";
restartUnits = [ "radarr.service" ]; restartUnits = [ "radarr-movies1080p.service" ];
}; };
"arr/radarr/postgres/dbName" = { "arr/radarr/1080p/postgres/dbName" = {
sopsFile = ../secrets.sops.yaml; sopsFile = ../secrets.sops.yaml;
owner = "radarr"; owner = "radarr";
mode = "400"; mode = "400";
restartUnits = [ "radarr.service" ]; restartUnits = [ "radarr-movies1080p.service" ];
}; };
"arr/radarr/postgres/user" = { "arr/radarr/1080p/postgres/user" = {
sopsFile = ../secrets.sops.yaml; sopsFile = ../secrets.sops.yaml;
owner = "radarr"; owner = "radarr";
mode = "400"; mode = "400";
restartUnits = [ "radarr.service" ]; restartUnits = [ "radarr-movies1080p.service" ];
}; };
"arr/radarr/postgres/password" = { "arr/radarr/1080p/postgres/password" = {
sopsFile = ../secrets.sops.yaml; sopsFile = ../secrets.sops.yaml;
owner = "radarr"; owner = "radarr";
mode = "400"; mode = "400";
restartUnits = [ "radarr.service" ]; restartUnits = [ "radarr-movies1080p.service" ];
}; };
"arr/radarr/postgres/host" = { "arr/radarr/1080p/postgres/host" = {
sopsFile = ../secrets.sops.yaml; sopsFile = ../secrets.sops.yaml;
owner = "radarr"; owner = "radarr";
mode = "400"; mode = "400";
restartUnits = [ "radarr.service" ]; restartUnits = [ "radarr-movies1080p.service" ];
}; };
"arr/radarr/extraEnvVars" = { "arr/radarr/1080p/extraEnvVars" = {
sopsFile = ../secrets.sops.yaml; sopsFile = ../secrets.sops.yaml;
owner = "radarr"; owner = "radarr";
mode = "400"; mode = "400";
restartUnits = [ "radarr.service" ]; restartUnits = [ "radarr-movies1080p.service" ];
};
"arr/radarr/anime/apiKey" = {
sopsFile = ../secrets.sops.yaml;
owner = "radarr";
mode = "400";
restartUnits = [ "radarr-anime.service" ];
};
"arr/radarr/anime/postgres/dbName" = {
sopsFile = ../secrets.sops.yaml;
owner = "radarr";
mode = "400";
restartUnits = [ "radarr-anime.service" ];
};
"arr/radarr/anime/postgres/user" = {
sopsFile = ../secrets.sops.yaml;
owner = "radarr";
mode = "400";
restartUnits = [ "radarr-anime.service" ];
};
"arr/radarr/anime/postgres/password" = {
sopsFile = ../secrets.sops.yaml;
owner = "radarr";
mode = "400";
restartUnits = [ "radarr-anime.service" ];
};
"arr/radarr/anime/postgres/host" = {
sopsFile = ../secrets.sops.yaml;
owner = "radarr";
mode = "400";
restartUnits = [ "radarr-anime.service" ];
};
"arr/radarr/anime/extraEnvVars" = {
sopsFile = ../secrets.sops.yaml;
owner = "radarr";
mode = "400";
restartUnits = [ "radarr-anime.service" ];
}; };
# Unpackerr # Unpackerr
"arr/unpackerr/extraEnvVars" = { "arr/unpackerr/extraEnvVars" = {

View file

@ -4,10 +4,11 @@
inputs, inputs,
pkgs, pkgs,
... ...
}: let }:
sanoidConfig = import ./config/sanoid.nix {}; let
sanoidConfig = import ./config/sanoid.nix { };
disks = import ./config/disks.nix; disks = import ./config/disks.nix;
smartdDevices = map (device: {inherit device;}) disks; smartdDevices = map (device: { inherit device; }) disks;
pushoverNotify = pkgs.writeShellApplication { pushoverNotify = pkgs.writeShellApplication {
name = "pushover-notify"; name = "pushover-notify";
@ -17,7 +18,7 @@
jq jq
]; ];
excludeShellChecks = ["SC2154"]; excludeShellChecks = [ "SC2154" ];
text = '' text = ''
${builtins.readFile ./scripts/pushover-notify.sh} ${builtins.readFile ./scripts/pushover-notify.sh}
@ -31,28 +32,29 @@
jq jq
]; ];
excludeShellChecks = ["SC2154"]; excludeShellChecks = [ "SC2154" ];
text = '' text = ''
${builtins.readFile ./scripts/refresh-series.sh} ${builtins.readFile ./scripts/refresh-series.sh}
''; '';
}; };
in { in
{
imports = [ imports = [
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
(import ../../profiles/disko-nixos.nix { (import ../../profiles/disko-nixos.nix {
disks = ["/dev/sda|/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_500GB_S58SNM0W406409E"]; disks = [ "/dev/sda|/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_500GB_S58SNM0W406409E" ];
}) })
inputs.nix-minecraft.nixosModules.minecraft-servers inputs.nix-minecraft.nixosModules.minecraft-servers
]; ];
boot = { boot = {
initrd = { initrd = {
kernelModules = ["nfs"]; kernelModules = [ "nfs" ];
supportedFilesystems = ["nfs"]; supportedFilesystems = [ "nfs" ];
}; };
binfmt.emulatedSystems = ["aarch64-linux"]; # Enabled for arm compilation binfmt.emulatedSystems = [ "aarch64-linux" ]; # Enabled for arm compilation
kernelModules = [ kernelModules = [
"vfio" "vfio"
@ -60,11 +62,11 @@ in {
"vfio_pci" "vfio_pci"
"vfio_virqfd" "vfio_virqfd"
]; ];
extraModulePackages = []; extraModulePackages = [ ];
kernelParams = ["zfs.zfs_arc_max=107374182400"]; # 100GB kernelParams = [ "zfs.zfs_arc_max=107374182400" ]; # 100GB
}; };
swapDevices = []; swapDevices = [ ];
hardware = { hardware = {
cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
@ -74,7 +76,7 @@ in {
nvidia-container-toolkit.enable = true; nvidia-container-toolkit.enable = true;
}; };
users.users.root.openssh.authorizedKeys.keys = []; users.users.root.openssh.authorizedKeys.keys = [ ];
# Network settings # Network settings
networking = { networking = {
hostName = "shadowfax"; hostName = "shadowfax";
@ -167,7 +169,7 @@ in {
# Minio # Minio
minio = { minio = {
enable = true; enable = true;
dataDir = ["/eru/minio"]; dataDir = [ "/eru/minio" ];
rootCredentialsFile = config.sops.secrets."minio".path; rootCredentialsFile = config.sops.secrets."minio".path;
}; };
@ -194,7 +196,7 @@ in {
# Soft Serve - SSH git server # Soft Serve - SSH git server
soft-serve = { soft-serve = {
enable = true; enable = true;
settings = import ./config/soft-serve.nix {}; settings = import ./config/soft-serve.nix { };
}; };
sunshine = { sunshine = {
@ -214,7 +216,7 @@ in {
# VSCode Compatibility Settings # VSCode Compatibility Settings
vscode-server.enable = true; vscode-server.enable = true;
xserver.videoDrivers = ["nvidia"]; xserver.videoDrivers = [ "nvidia" ];
greetd = { greetd = {
enable = true; enable = true;
vt = 3; vt = 3;
@ -228,7 +230,7 @@ in {
}; };
# sops # sops
sops = import ./config/sops-secrets.nix {}; sops = import ./config/sops-secrets.nix { };
# System settings and services. # System settings and services.
mySystem = { mySystem = {
@ -266,23 +268,50 @@ in {
}; };
# Radarr # Radarr
radarr = { radarr = {
enable = true;
instances = {
movies1080p = {
enable = true; enable = true;
package = pkgs.unstable.radarr; package = pkgs.unstable.radarr;
dataDir = "/nahar/radarr"; dataDir = "/nahar/radarr/1080p";
extraEnvVarFile = config.sops.secrets."arr/radarr/extraEnvVars".path; extraEnvVarFile = config.sops.secrets."arr/radarr/1080p/extraEnvVars".path;
moviesDir = "/moria/media/Movies"; moviesDir = "/moria/media/Movies";
user = "radarr"; user = "radarr";
group = "kah"; group = "kah";
port = 7878; port = 7878;
openFirewall = true; openFirewall = true;
hardening = true; hardening = true;
apiKeyFile = config.sops.secrets."arr/radarr/apiKey".path; apiKeyFile = config.sops.secrets."arr/radarr/1080p/apiKey".path;
db = { db = {
enable = true; enable = true;
hostFile = config.sops.secrets."arr/radarr/postgres/host".path; hostFile = config.sops.secrets."arr/radarr/1080p/postgres/host".path;
port = 5432; port = 5432;
userFile = config.sops.secrets."arr/radarr/postgres/user".path; dbname = "radarr_main";
passwordFile = config.sops.secrets."arr/radarr/postgres/password".path; userFile = config.sops.secrets."arr/radarr/1080p/postgres/user".path;
passwordFile = config.sops.secrets."arr/radarr/1080p/postgres/password".path;
};
};
moviesAnime = {
enable = true;
package = pkgs.unstable.radarr;
dataDir = "/nahar/radarr/anime";
extraEnvVarFile = config.sops.secrets."arr/radarr/anime/extraEnvVars".path;
moviesDir = "/moria/media/Anime/Movies";
user = "radarr";
group = "kah";
port = 7879;
openFirewall = true;
hardening = true;
apiKeyFile = config.sops.secrets."arr/radarr/anime/apiKey".path;
db = {
enable = true;
hostFile = config.sops.secrets."arr/radarr/anime/postgres/host".path;
port = 5432;
dbname = "radarr_anime";
userFile = config.sops.secrets."arr/radarr/anime/postgres/user".path;
passwordFile = config.sops.secrets."arr/radarr/anime/postgres/password".path;
};
};
}; };
}; };
# Sonarr # Sonarr
@ -354,7 +383,7 @@ in {
# qBittorrent # qBittorrent
qbittorrent = { qbittorrent = {
enable = true; enable = true;
package = pkgs.unstable.qbittorrent.override {guiSupport = false;}; package = pkgs.unstable.qbittorrent.override { guiSupport = false; };
user = "qbittorrent"; user = "qbittorrent";
group = "kah"; group = "kah";
dataDir = "/nahar/qbittorrent"; dataDir = "/nahar/qbittorrent";
@ -378,9 +407,9 @@ in {
system = { system = {
incus = { incus = {
enable = true; enable = true;
preseed = import ./config/incus-preseed.nix {}; preseed = import ./config/incus-preseed.nix { };
}; };
motd.networkInterfaces = ["bond0"]; motd.networkInterfaces = [ "bond0" ];
nfs.enable = true; nfs.enable = true;
zfs.enable = true; zfs.enable = true;
zfs.mountPoolsAtBoot = [ zfs.mountPoolsAtBoot = [

View file

@ -28,13 +28,22 @@ arr:
password: ENC[AES256_GCM,data:XOrycMom2utnefraGPoAq7xtP6yfSzTb8g==,iv:WQInK+bJuDNI9uN/GeQ2Fb1Mmlux6+lXwkGS1ZEh+kQ=,tag:DGqLerxomCVfVv15Gt3b8A==,type:str] password: ENC[AES256_GCM,data:XOrycMom2utnefraGPoAq7xtP6yfSzTb8g==,iv:WQInK+bJuDNI9uN/GeQ2Fb1Mmlux6+lXwkGS1ZEh+kQ=,tag:DGqLerxomCVfVv15Gt3b8A==,type:str]
extraEnvVars: ENC[AES256_GCM,data:KnZSJ2YbNLawSzrj7syx0cfAFseHbgjGvjpB7yWajXfCIy+CV800z9YU2SVO2kV6b+9OrmyKKFFbM5ac4cWnc5Pcx8TUxfiAuL5RSi6ZTmUrZUA7Zqx5UDTHwXgvhDI=,iv:TX8sFk7uc1TYG/gkuA9plGZlhP25WuczEXd+QKsPi4c=,tag:zhVeZxrTgcv+Y2OP8I+k5g==,type:str] extraEnvVars: ENC[AES256_GCM,data:KnZSJ2YbNLawSzrj7syx0cfAFseHbgjGvjpB7yWajXfCIy+CV800z9YU2SVO2kV6b+9OrmyKKFFbM5ac4cWnc5Pcx8TUxfiAuL5RSi6ZTmUrZUA7Zqx5UDTHwXgvhDI=,iv:TX8sFk7uc1TYG/gkuA9plGZlhP25WuczEXd+QKsPi4c=,tag:zhVeZxrTgcv+Y2OP8I+k5g==,type:str]
radarr: radarr:
apiKey: ENC[AES256_GCM,data:Qcfzr12aftnS+b3pDHHnfOya1+vlyVaoNCPLzJ9xv5Pv,iv:9M33sfqZPzeghxmBtYk3LgsfbInC7sPSQGuYFJiydh4=,tag:lSmi6Do64sarG15q6+yuQw==,type:str] 1080p:
apiKey: ENC[AES256_GCM,data:NVIa3nK4/QxZF1/peKei9Qsxn2AjRiBnBdr2N08QiXhi,iv:h/Rb38FCF8auMCTT+Cuj/i8YAeavntwbbJEA9LwDYUY=,tag:OwAQy76GjIrY9/126zExdA==,type:str]
postgres: postgres:
host: ENC[AES256_GCM,data:mYFhyUYIqp8=,iv:Cj03GOR58PWv3HWXRx0/D5tZ2oObejtIVuQcTcHGkuw=,tag:9K2asujaqi4/Qbozb18Ghg==,type:str] host: ENC[AES256_GCM,data:bycrytLkcdI=,iv:zfsSP+uoVpvG2HXydCXT+yfMc5GadjG8qo+4ld+rdjk=,tag:cXtYTFg27hS9Idn3UjUn1A==,type:str]
dbName: ENC[AES256_GCM,data:zC4j0VJJpWWT0XY=,iv:ITupnWLgvI2wAPnkD826S77BMELDqRWZKax51SVkBgA=,tag:L7YXfoxAhi94ssBoE35Aug==,type:str] dbName: ENC[AES256_GCM,data:pjvSoLQ/TUdd6Y0=,iv:TsThUHuF9Mm1fuGYcEh/GanaDGuoSJxPt7LVRJHSFAo=,tag:tMIdTPSaNE4hOh97lck6DQ==,type:str]
user: ENC[AES256_GCM,data:jaYUWAzQ,iv:ayEutHFPyZ7CN3inTqmgPmintR8qE8HfatvzCx7VXnA=,tag:3Ou0JRzpcihL0AWcC0pC5w==,type:str] user: ENC[AES256_GCM,data:0QFQsAfq,iv:+qtq/BhC26fdW9rXlbZFf6fQCOV+UsP1Y9cNMUtn5+w=,tag:WBg4ruYa7t+8d8iHjjPJ1g==,type:str]
password: ENC[AES256_GCM,data:XcS9H5L+ikA2KflepKrBHVlBjKwB0Vu8mw==,iv:lSpoEiCqOpP3p1T7bBH8F9YiSf2kwQQC+FQPuaKojnE=,tag:ScV/E6JeomQlfp35NIrh1g==,type:str] password: ENC[AES256_GCM,data:TvGQsShraVE70JoHkk4PWkoeElu+dn882w==,iv:oQ15XrRCLUZ6XWSifB9hGF+wYActgDE9NEqly+LTTFA=,tag:kUbn5dKq9jU4Xl1+mRI2Zw==,type:str]
extraEnvVars: ENC[AES256_GCM,data:hQlXQD4Zb3HnXfOZsX5PpxxyIzpYjqFletRiGRUWpICCEIcbsEK6WN8VtCaH+lpVqcVOpLUSSX1jILEwn4H483JyPk9EI04tIGBgq+svUOg7PZhc7zLllczMKN+BcdY=,iv:OyeAYXln8Dm1WvrrySkYXk+XC7kcwHFUSamIBdCTHRY=,tag:OGsR6IfBJF5Ki6VG15iyUw==,type:str] extraEnvVars: ENC[AES256_GCM,data:4E1NFQZOrH7sBGnJus7+VZLTWnzif1Asr+mCeaXorsfO8nJpA14HjQ9diAqPuabTlUsl4vMznFmKjdAFCvuRz9p7xfq96qmJKN3oTKuVaz6SlQbXKcfCeldn2E2EA2k=,iv:CVaiTGR0WpcCNvDpD202P4dHqEjX9xqJEVz0usEeANY=,tag:FRz7t5wV2TePakxmyBkb1Q==,type:str]
anime:
apiKey: ENC[AES256_GCM,data:7Z59sJCKBmayd1J71+C72IdoeNlU71jcJS885bUwc+g8,iv:0Uav84UAanmZvvZfJJNoDmvyKY068L8+ONnVGWmldSI=,tag:WYQvccwlm/Y8S2ynPkEPjA==,type:str]
postgres:
host: ENC[AES256_GCM,data:EL6Qzm8r/XQ=,iv:Gz099lg7zDRrIf7i2kOb+MSXGwHazTtcnBbCmciVCHE=,tag:l2Lqd7dDeRZYzflhK9/Kdg==,type:str]
dbName: ENC[AES256_GCM,data:9MJ6UcVlLPN+hI4=,iv:AwCdIJ1KwThbUVGM759m0GVWh3yf3anBHdsfdIjVWP4=,tag:7kUUSTNpt/rOtYHkDRlKxA==,type:str]
user: ENC[AES256_GCM,data:QE+Lr0L0ad3oufG4,iv:WCTkwhN9FjibXlyPqY7oDjSByXn6Exma/VDsE3ju/FE=,tag:orFBsxd/ETSaiFC1KNsO0A==,type:str]
password: ENC[AES256_GCM,data:3rYBq3cosu962m/FZIc/WZogr+BZxQ==,iv:dK/IDKYz3NKeAE7PV/f+qRtSu3veg20B6+6gZmaD/eg=,tag:9k0+zrcWC6i6YjwJkMYkzA==,type:str]
extraEnvVars: ENC[AES256_GCM,data:HAGHXI14CFx/CXbpHGn1MQQeRmMO9zzsnHEJrgTfho96XPtoKJQj+b3h7VNVkkHAifjuMzbKb0BM8qrtAIjssWuQUrWChxgHBg3OWodsJkstYplB0RYIun5RorzHaNY=,iv:3nW9806ciMdblFphEi9zK8kkIB8r01eF/167vYq177w=,tag:7aPJ63Wl+SGzWCBXuitgmA==,type:str]
unpackerr: unpackerr:
extraEnvVars: ENC[AES256_GCM,data:UT6HLaEKGEHggZx8Ict23OOLlRppErCnIDA16CleMFe33/IHyyp8El8aBNCq5A/1+NIGN5aZat2El562QAcZBVITa9ffmmtXqnDsheaRo+nDSPR5mGqh39uoKWIy2eSO5nv3rD0jN08MFYjxZNti/k0p0JIDMYN5shnVLiwO7krLs3Z6m+sZntg6euCWnHJMM2p3v38bffUzbZWrD1hEKaOUofOhTL0rDUiiysCawMZvJx6zXgfyO6DeUdwlYIxlg0mZ8SkmDRoFDPYrI40tIA+oSScJhJkDgoNPPJVEuGu6vVMPgqkAWUSucVGeiYVati2PsBJHn9wori2GWRTY0n7mjQKe8cz3nPIKQFWYLRWDZ9UBBvh05bYLa54+C4mGczFFPZra/DDoR2i9gzCXxjhRmt2Qs+g0RqefJTq5W2qQKRLj9PKFr02GuOY=,iv:pmOkkfFd4eGRCburRz6rgqqAFQJhPgjuUKn23ipLg3E=,tag:heZtewMOnnMxE5qSVEiI0Q==,type:str] extraEnvVars: ENC[AES256_GCM,data:UT6HLaEKGEHggZx8Ict23OOLlRppErCnIDA16CleMFe33/IHyyp8El8aBNCq5A/1+NIGN5aZat2El562QAcZBVITa9ffmmtXqnDsheaRo+nDSPR5mGqh39uoKWIy2eSO5nv3rD0jN08MFYjxZNti/k0p0JIDMYN5shnVLiwO7krLs3Z6m+sZntg6euCWnHJMM2p3v38bffUzbZWrD1hEKaOUofOhTL0rDUiiysCawMZvJx6zXgfyO6DeUdwlYIxlg0mZ8SkmDRoFDPYrI40tIA+oSScJhJkDgoNPPJVEuGu6vVMPgqkAWUSucVGeiYVati2PsBJHn9wori2GWRTY0n7mjQKe8cz3nPIKQFWYLRWDZ9UBBvh05bYLa54+C4mGczFFPZra/DDoR2i9gzCXxjhRmt2Qs+g0RqefJTq5W2qQKRLj9PKFr02GuOY=,iv:pmOkkfFd4eGRCburRz6rgqqAFQJhPgjuUKn23ipLg3E=,tag:heZtewMOnnMxE5qSVEiI0Q==,type:str]
sops: sops:
@ -115,8 +124,8 @@ sops:
aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M
vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA== vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-04T04:28:14Z" lastmodified: "2025-02-10T04:49:46Z"
mac: ENC[AES256_GCM,data:7y38SzT51EOTx83lEJugW5XmsgGa00yemYIE5IRLasqwiSGSWHTt3iZy/2FLNXbFIqiz+O1K3xajstOF4ijvpYmP6Tu3rCh/4gxChqcokP6kxsI6b4nKp6ZkC/eZpoevFQmYHYqJU4b9iOQT9QZqdzwCIxOVRNZDAAc8u1SeBsg=,iv:7ni7qo6Xojs5MlOZBMLnnEKnDqdNDp9Ms/D9JMoRnm0=,tag:1/wqZh0igzhFyqdBxemntA==,type:str] mac: ENC[AES256_GCM,data:wT82lve5wNbxXUgcw3EZkOrsLFOmtriJtSNtpcfcH2KYkFEZTyzYCO10EBMrm1FjJxJFmhtde9f+CkSkT5ypjP6Ou4TGn9nP0jOlCyLxYyQkv7Lr31aEF8d2Q0NDjSHePW4YUiY88YrOX8shWYFVtNoZSonyCv8G6lwGVIsZzi4=,iv:MkHiwV5qRBE3LfTt0WHV56LWAeTEcRlux4xIf90R3AU=,tag:qUgCaPLa+W/pZ8uM1Gw7Xw==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.9.4 version: 3.9.4

View file

@ -5,7 +5,8 @@
utils, utils,
... ...
}: }:
with lib; let with lib;
let
cfg = config.mySystem.services.radarr; cfg = config.mySystem.services.radarr;
dbOptions = { dbOptions = {
options = { options = {
@ -50,11 +51,42 @@ with lib; let
}; };
}; };
}; };
in {
options.mySystem.services.radarr = {
enable = mkEnableOption "Radarr";
package = mkPackageOption pkgs "Radarr" {}; # Function to create instance-specific configuration
mkRadarrInstance = name: instanceCfg: {
systemd.services."radarr-${name}" = {
description = "Radarr (${name})";
};
networking.firewall = mkIf instanceCfg.openFirewall {
allowedTCPPorts = [ instanceCfg.port ];
};
users.groups.${instanceCfg.group} = { };
users.users = mkIf (instanceCfg.user == "radarr") {
radarr = {
inherit (instanceCfg) group;
isSystemUser = true;
home = instanceCfg.dataDir;
};
};
};
in
{
options.mySystem.services.radarr = {
enable = mkEnableOption "Radarr (global)";
instances = mkOption {
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
options = {
enable = mkEnableOption "Radarr (instance)";
package = mkPackageOption pkgs "Radarr" { };
user = mkOption { user = mkOption {
type = types.str; type = types.str;
@ -70,7 +102,7 @@ in {
dataDir = mkOption { dataDir = mkOption {
type = types.path; type = types.path;
default = "/var/lib/radarr"; default = "/var/lib/radarr/${name}";
description = "Storage directory for radarr data"; description = "Storage directory for radarr data";
}; };
@ -126,7 +158,7 @@ in {
extraEnvVars = mkOption { extraEnvVars = mkOption {
type = types.attrs; type = types.attrs;
default = {}; default = { };
example = { example = {
MY_VAR = "my value"; MY_VAR = "my value";
}; };
@ -140,76 +172,104 @@ in {
description = "Extra environment file for Radarr."; description = "Extra environment file for Radarr.";
}; };
}; };
}
)
);
default = { };
description = "Radarr instance configurations.";
};
};
config = mkIf cfg.enable { config = mkIf cfg.enable {
assertions = [ # Add assertions for all instances
assertions = flatten (
mapAttrsToList (
name: instanceCfg:
if instanceCfg.enable then
[
{ {
assertion = !(cfg.db.host != "" && cfg.db.hostFile != ""); assertion = !(instanceCfg.db.host != "" && instanceCfg.db.hostFile != "");
message = "Specify either a direct database host via db.host or a file via db.hostFile (leave direct host empty)."; message = "Specify either a direct database host via db.host or a file via db.hostFile (leave direct host empty).";
} }
{ {
assertion = !(cfg.db.user != "radarr" && cfg.db.userFile != ""); assertion = !(instanceCfg.db.user != "radarr" && instanceCfg.db.userFile != "");
message = "Specify either a direct database user via db.user or a file via db.userFile."; message = "Specify either a direct database user via db.user or a file via db.userFile.";
} }
{ {
assertion = !(cfg.apiKey != "" && cfg.apiKeyFile != ""); assertion = !(instanceCfg.apiKey != "" && instanceCfg.apiKeyFile != "");
message = "Specify either a direct API key via apiKey or a file via apiKeyFile (leave direct API key empty)."; message = "Specify either a direct API key via apiKey or a file via apiKeyFile (leave direct API key empty).";
} }
]; ]
else
[ ]
) cfg.instances
);
systemd.tmpfiles.rules = [ # Create systemd tmpfiles rules for each enabled instance
"d ${cfg.dataDir} 0775 ${cfg.user} ${cfg.group}" systemd.tmpfiles.rules = flatten (
]; mapAttrsToList (
name: instanceCfg:
if instanceCfg.enable then
[
"d ${instanceCfg.dataDir} 0775 ${instanceCfg.user} ${instanceCfg.group}"
]
else
[ ]
) cfg.instances
);
systemd.services.radarr = { # Create services for each enabled instance
description = "Radarr"; systemd.services = mapAttrs' (
name: instanceCfg:
nameValuePair "radarr-${name}" (
mkIf instanceCfg.enable {
description = "Radarr (${name})";
after = [ after = [
"network.target" "network.target"
"nss-lookup.target" "nss-lookup.target"
]; ];
wantedBy = ["multi-user.target"]; wantedBy = [ "multi-user.target" ];
environment = lib.mkMerge [ environment = lib.mkMerge [
{ {
RADARR__APP__INSTANCENAME = "Radarr"; RADARR__APP__INSTANCENAME = name;
RADARR__APP__THEME = "dark"; RADARR__APP__THEME = "dark";
RADARR__AUTH__METHOD = "External"; RADARR__AUTH__METHOD = "External";
RADARR__AUTH__REQUIRED = "DisabledForLocalAddresses"; RADARR__AUTH__REQUIRED = "DisabledForLocalAddresses";
RADARR__LOG__DBENABLED = "False"; RADARR__LOG__DBENABLED = "False";
RADARR__LOG__LEVEL = "info"; RADARR__LOG__LEVEL = "info";
RADARR__SERVER__PORT = toString cfg.port; RADARR__SERVER__PORT = toString instanceCfg.port;
RADARR__UPDATE__BRANCH = "develop"; RADARR__UPDATE__BRANCH = "develop";
} }
(lib.mkIf cfg.db.enable { (lib.mkIf instanceCfg.db.enable {
RADARR__POSTGRES__PORT = toString cfg.db.port; RADARR__POSTGRES__PORT = toString instanceCfg.db.port;
RADARR__POSTGRES__MAINDB = cfg.db.dbname; RADARR__POSTGRES__MAINDB = instanceCfg.db.dbname;
}) })
cfg.extraEnvVars instanceCfg.extraEnvVars
]; ];
serviceConfig = lib.mkMerge [ serviceConfig = lib.mkMerge [
{ {
Type = "simple"; Type = "simple";
User = cfg.user; User = instanceCfg.user;
Group = cfg.group; Group = instanceCfg.group;
ExecStart = utils.escapeSystemdExecArgs [ ExecStart = utils.escapeSystemdExecArgs [
(lib.getExe cfg.package) (lib.getExe instanceCfg.package)
"-nobrowser" "-nobrowser"
"-data=${cfg.dataDir}" "-data=${instanceCfg.dataDir}"
"-port=${toString cfg.port}" "-port=${toString instanceCfg.port}"
]; ];
WorkingDirectory = cfg.dataDir; WorkingDirectory = instanceCfg.dataDir;
RuntimeDirectory = "radarr"; RuntimeDirectory = "radarr-${name}";
LogsDirectory = "radarr"; LogsDirectory = "radarr-${name}";
RuntimeDirectoryMode = "0750"; RuntimeDirectoryMode = "0750";
Restart = "on-failure"; Restart = "on-failure";
RestartSec = 5; RestartSec = 5;
} }
(lib.mkIf cfg.hardening { (lib.mkIf instanceCfg.hardening {
CapabilityBoundingSet = [""]; CapabilityBoundingSet = [ "" ];
DeviceAllow = [""]; DeviceAllow = [ "" ];
DevicePolicy = "closed"; DevicePolicy = "closed";
LockPersonality = true; LockPersonality = true;
# Needs access to .Net CLR memory space.
MemoryDenyWriteExecute = false; MemoryDenyWriteExecute = false;
NoNewPrivileges = true; NoNewPrivileges = true;
PrivateDevices = true; PrivateDevices = true;
@ -220,9 +280,9 @@ in {
ProtectKernelTunables = true; ProtectKernelTunables = true;
ProtectSystem = "strict"; ProtectSystem = "strict";
ReadWritePaths = [ ReadWritePaths = [
cfg.dataDir instanceCfg.dataDir
cfg.moviesDir instanceCfg.moviesDir
"/var/log/radarr" "/var/log/radarr-${name}"
"/eru/media" "/eru/media"
]; ];
RestrictAddressFamilies = [ RestrictAddressFamilies = [
@ -242,61 +302,78 @@ in {
SystemCallArchitectures = "native"; SystemCallArchitectures = "native";
SystemCallFilter = [ SystemCallFilter = [
"@system-service" "@system-service"
#"~@privileged"
# .Net CLR requirement
#"~@resources"
]; ];
}) })
(lib.mkIf cfg.db.enable { (lib.mkIf instanceCfg.db.enable {
ExecStartPre = "+${pkgs.writeShellScript "radarr-pre-script" '' ExecStartPre = "+${pkgs.writeShellScript "radarr-${name}-pre-script" ''
mkdir -p /run/radarr mkdir -p /run/radarr-${name}
rm -f /run/radarr/secrets.env rm -f /run/radarr-${name}/secrets.env
# Helper function to safely write variables # Helper function to safely write variables
write_var() { write_var() {
local var_name="$1" local var_name="$1"
local value="$2" local value="$2"
if [ -n "$value" ]; then if [ -n "$value" ]; then
printf "%s=%s\n" "$var_name" "$value" >> /run/radarr/secrets.env printf "%s=%s\n" "$var_name" "$value" >> /run/radarr-${name}/secrets.env
fi fi
} }
# API Key (direct value or file) # API Key (direct value or file)
if [ -n "${cfg.apiKey}" ]; then if [ -n "${instanceCfg.apiKey}" ]; then
write_var "RADARR__AUTH__APIKEY" "${cfg.apiKey}" write_var "RADARR__AUTH__APIKEY" "${instanceCfg.apiKey}"
else else
write_var "RADARR__AUTH__APIKEY" "$(cat ${cfg.apiKeyFile})" write_var "RADARR__AUTH__APIKEY" "$(cat ${instanceCfg.apiKeyFile})"
fi fi
# Database Configuration # Database Configuration
write_var "RADARR__POSTGRES__HOST" "$([ -n "${cfg.db.host}" ] && echo "${cfg.db.host}" || cat "${cfg.db.hostFile}")" write_var "RADARR__POSTGRES__HOST" "$([ -n "${instanceCfg.db.host}" ] && echo "${instanceCfg.db.host}" || cat "${instanceCfg.db.hostFile}")"
write_var "RADARR__POSTGRES__USER" "$([ -n "${cfg.db.user}" ] && echo "${cfg.db.user}" || cat "${cfg.db.userFile}")" write_var "RADARR__POSTGRES__USER" "$([ -n "${instanceCfg.db.userFile}" ] && cat "${instanceCfg.db.userFile}" || echo "${instanceCfg.db.user}")"
write_var "RADARR__POSTGRES__PASSWORD" "$(cat ${cfg.db.passwordFile})" write_var "RADARR__POSTGRES__PASSWORD" "$(cat ${instanceCfg.db.passwordFile})"
# Final permissions # Final permissions
chmod 600 /run/radarr/secrets.env chmod 600 /run/radarr-${name}/secrets.env
chown ${cfg.user}:${cfg.group} /run/radarr/secrets.env chown ${instanceCfg.user}:${instanceCfg.group} /run/radarr-${name}/secrets.env
''}"; ''}";
EnvironmentFile = ( EnvironmentFile = (
["-/run/radarr/secrets.env"] [ "-/run/radarr-${name}/secrets.env" ]
++ lib.optional (cfg.extraEnvVarFile != null && cfg.extraEnvVarFile != "") cfg.extraEnvVarFile ++ lib.optional (
instanceCfg.extraEnvVarFile != null && instanceCfg.extraEnvVarFile != ""
) instanceCfg.extraEnvVarFile
); );
}) })
]; ];
}; }
)
) cfg.instances;
networking.firewall = mkIf cfg.openFirewall { # Firewall configurations
allowedTCPPorts = [cfg.port]; networking.firewall = mkMerge (
}; mapAttrsToList (
name: instanceCfg:
mkIf (instanceCfg.enable && instanceCfg.openFirewall) {
allowedTCPPorts = [ instanceCfg.port ];
}
) cfg.instances
);
users.groups.${cfg.group} = {}; # Users and groups
users.users = mkIf (cfg.user == "radarr") { users = mkMerge (
mapAttrsToList (
name: instanceCfg:
mkIf instanceCfg.enable {
groups.${instanceCfg.group} = { };
users = mkIf (instanceCfg.user == "radarr") {
radarr = { radarr = {
inherit (cfg) group; inherit (instanceCfg) group;
isSystemUser = true; isSystemUser = true;
home = cfg.dataDir; # home = instanceCfg.dataDir;
home = "/nahar/radarr";
}; };
}; };
}
) cfg.instances
);
}; };
} }