diff --git a/flake.lock b/flake.lock index e0cf59c..5c5db42 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ ] }, "locked": { - "lastModified": 1737636397, - "narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=", + "lastModified": 1738456976, + "narHash": "sha256-cufyHbOMnSt9V4w4OVSzNcpJ+8DwzRZRJaca2Q89KVI=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "7fe006981fae53e931f513026fc754e322f13145", + "rev": "257b2050790ab3b1eb389e0f8bdc400eb9510139", "type": "github" }, "original": { @@ -57,11 +57,11 @@ ] }, "locked": { - "lastModified": 1737038063, - "narHash": "sha256-rMEuiK69MDhjz1JgbaeQ9mBDXMJ2/P8vmOYRbFndXsk=", + "lastModified": 1738148035, + "narHash": "sha256-KYOATYEwaKysL3HdHdS5kbQMXvzS4iPJzJrML+3TKAo=", "owner": "nix-community", "repo": "disko", - "rev": "bf0abfde48f469c256f2b0f481c6281ff04a5db2", + "rev": "18d0a984cc2bc82cf61df19523a34ad463aa7f54", "type": "github" }, "original": { @@ -379,11 +379,11 @@ ] }, "locked": { - "lastModified": 1737634937, - "narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=", + "lastModified": 1738178255, + "narHash": "sha256-+D6Nu2ewXbMTFzx/Q4jDOo+LAOUPr0cxQJg5k33daIE=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e", + "rev": "dcadd3398abe146d60c67e0d9ee6e27b301cae82", "type": "github" }, "original": { @@ -408,11 +408,11 @@ ] }, "locked": { - "lastModified": 1737985436, - "narHash": "sha256-zx8FdI4zr2GhNyD1YGAqa2ymodAObTSAdwuWwVucewo=", + "lastModified": 1738437059, + "narHash": "sha256-J+8ecqaP3zD9GHeN8Y4hUapoELSoggp0IZI8laTFt/0=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "23783b96036f5506fdaf8b2250a1ef849d57f0d3", + "rev": "5ac80e3686a4dfa55d2bd15c81a266b89594a295", "type": "github" }, "original": { @@ -437,11 +437,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1738107811, - "narHash": "sha256-+57jB0fv53OmAQ8QpK3eiRXfypBfKJtfdepRusNX+DM=", + "lastModified": 1738546470, + "narHash": "sha256-pyMFj2IBeiRDnYoHD9XtbFiwBzvXJCavdFoVPnZ1YB0=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "3d1dd6b5c7b90e513e86c1ad27c6c01a5c69e4f8", + "rev": "708d16636047c6a311c4e44424cf7d2090219a47", "type": "github" }, "original": { @@ -467,11 +467,11 @@ ] }, "locked": { - "lastModified": 1738011374, - "narHash": "sha256-WSgu+IWBUhUZdnrdx19yE4afevtheDV88Q6kawsJ1pE=", + "lastModified": 1738500466, + "narHash": "sha256-GAO3bpA4nk7RETw0SFN3QhDPNcTYbxiCoRZO9NudKsY=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "014003b2bd3744dfabb8c2c20a80e89f721be238", + "rev": "eefa87d099bac625234b9e89ed67624efea0d27a", "type": "github" }, "original": { @@ -492,11 +492,11 @@ ] }, "locked": { - "lastModified": 1737556638, - "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", + "lastModified": 1738422629, + "narHash": "sha256-5v+bv75wJWvahyM2xcMTSNNxmV8a7hb01Eey5zYnBJw=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", + "rev": "755aef8dab49d0fc4663c715fa4ad221b2aedaed", "type": "github" }, "original": { @@ -802,11 +802,11 @@ ] }, "locked": { - "lastModified": 1738115010, - "narHash": "sha256-Tkr0lvFIjMQ45t/Wu5qAuqn1v1wt/p3T7LBiYaOnUFU=", + "lastModified": 1738547119, + "narHash": "sha256-cc6AfR7W0AavgqA5nHUXRUus4Rr7oPWQNku5nhR4SYs=", "owner": "Infinidoge", "repo": "nix-minecraft", - "rev": "6230d8b5927108fbde8ccb8aa455ab26d7da4795", + "rev": "5b93268c80c3300dbec0fbbb2b50f674f84a474a", "type": "github" }, "original": { @@ -824,11 +824,11 @@ ] }, "locked": { - "lastModified": 1738115139, - "narHash": "sha256-oEKo2WT0JMAC3x0+CeCPNpCUutIzmHOrc6Woo4qMmIw=", + "lastModified": 1738547248, + "narHash": "sha256-ALPkA9L4G0j7piorEyeQ7zf6fW4vii4ULxRZBXmeKYM=", "owner": "nix-community", "repo": "nix-vscode-extensions", - "rev": "6d05434c798d94bf19b85a27e4f2249ab8bcd17f", + "rev": "bfacd5e2786caf61da0ad956728559dd6c1e8037", "type": "github" }, "original": { @@ -839,11 +839,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1737751639, - "narHash": "sha256-ZEbOJ9iT72iwqXsiEMbEa8wWjyFvRA9Ugx8utmYbpz4=", + "lastModified": 1738471961, + "narHash": "sha256-cgXDFrplNGs7bCVzXhRofjD8oJYqqXGcmUzXjHmip6Y=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "dfad538f751a5aa5d4436d9781ab27a6128ec9d4", + "rev": "537286c3c59b40311e5418a180b38034661d2536", "type": "github" }, "original": { @@ -855,11 +855,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1737885589, - "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", + "lastModified": 1738410390, + "narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", + "rev": "3a228057f5b619feb3186e986dbe76278d707b6e", "type": "github" }, "original": { @@ -911,11 +911,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1737885589, - "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", + "lastModified": 1738410390, + "narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", + "rev": "3a228057f5b619feb3186e986dbe76278d707b6e", "type": "github" }, "original": { @@ -927,11 +927,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1737885640, - "narHash": "sha256-GFzPxJzTd1rPIVD4IW+GwJlyGwBDV1Tj5FLYwDQQ9sM=", + "lastModified": 1738435198, + "narHash": "sha256-5+Hmo4nbqw8FrW85FlNm4IIrRnZ7bn0cmXlScNsNRLo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "4e96537f163fad24ed9eb317798a79afc85b51b7", + "rev": "f6687779bf4c396250831aa5a32cbfeb85bb07a3", "type": "github" }, "original": { @@ -943,11 +943,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1737885589, - "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", + "lastModified": 1738142207, + "narHash": "sha256-NGqpVVxNAHwIicXpgaVqJEJWeyqzoQJ9oc8lnK9+WC4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", + "rev": "9d3ae807ebd2981d593cddd0080856873139aa40", "type": "github" }, "original": { @@ -1032,11 +1032,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1738126260, - "narHash": "sha256-+E5gV8kQmf5+bTBGPovu7UGV79PfzPFnp4NHtiyOWFg=", + "lastModified": 1738362438, + "narHash": "sha256-EO2dVkMVLThWqv4hobEZEZGWBEuH2Z9SYqQDrbLSclU=", "owner": "nix-community", "repo": "NUR", - "rev": "fd6824aa672049ef000eef84100e5b3a405c9a36", + "rev": "95ddad0ff0e67c90314c6ca46324dce5f9a910d2", "type": "github" }, "original": { @@ -1222,11 +1222,11 @@ "systems": "systems_6" }, "locked": { - "lastModified": 1737955438, - "narHash": "sha256-mmggS3U1rT+N18YIAuNSBtfW+n6hQvIZ7nQ1sDFNW+g=", + "lastModified": 1738504946, + "narHash": "sha256-/btrLwD7UFgNWPxdewMdYYiI2GJxYipGnLuX7pRVAjc=", "owner": "notashelf", "repo": "nvf", - "rev": "da48a862a383026b1c7c9b0a09424af657550602", + "rev": "944327329712eda9eec8a86a972e0abd7ea368e6", "type": "github" }, "original": { @@ -2995,15 +2995,15 @@ "plugin-nvim-colorizer-lua": { "flake": false, "locked": { - "lastModified": 1735384185, - "narHash": "sha256-quqs3666vQc/4ticc/Z5BHzGxV6UUVE9jVGT07MEMQQ=", - "owner": "NvChad", + "lastModified": 1738229011, + "narHash": "sha256-IEgZnIUeNXRKZ4eV1+KknluyKZj68HBWe1EW+LueuGA=", + "owner": "catgoose", "repo": "nvim-colorizer.lua", - "rev": "8a65c448122fc8fac9c67b2e857b6e830a4afd0b", + "rev": "9b5fe0450bfb2521c6cea29391e5ec571f129136", "type": "github" }, "original": { - "owner": "NvChad", + "owner": "catgoose", "repo": "nvim-colorizer.lua", "type": "github" } @@ -3619,11 +3619,11 @@ "plugin-rustaceanvim": { "flake": false, "locked": { - "lastModified": 1735431742, - "narHash": "sha256-ucZXGbxHtbSKf5n11lL3vb6rD2BxJacIDOgcx32PLzA=", + "lastModified": 1738187731, + "narHash": "sha256-Z4aCPO4MR0Q2ZojT6YBGSa8fb7u5Nd+4Z/rekqhXqDY=", "owner": "mrcjkb", "repo": "rustaceanvim", - "rev": "51c097ebfb65d83baa71f48000b1e5c0a8dcc4fb", + "rev": "4a2f2d2cc04f5b0aa0981f98bb7d002c898318ad", "type": "github" }, "original": { @@ -4097,11 +4097,11 @@ ] }, "locked": { - "lastModified": 1737411508, - "narHash": "sha256-j9IdflJwRtqo9WpM0OfAZml47eBblUHGNQTe62OUqTw=", + "lastModified": 1738291974, + "narHash": "sha256-wkwYJc8cKmmQWUloyS9KwttBnja2ONRuJQDEsmef320=", "owner": "Mic92", "repo": "sops-nix", - "rev": "015d461c16678fc02a2f405eb453abb509d4e1d4", + "rev": "4c1251904d8a08c86ac6bc0d72cc09975e89aef7", "type": "github" }, "original": { @@ -4223,11 +4223,11 @@ ] }, "locked": { - "lastModified": 1738035934, - "narHash": "sha256-F/aKgPVGNHh2GaWByMaCy6CAG4Wj+s7jdocuUClJVQI=", + "lastModified": 1738397340, + "narHash": "sha256-Vt3y544m/w04ty8v+W/kfG3p34j+nys9rL13sNoqlcU=", "owner": "budimanjojo", "repo": "talhelper", - "rev": "0b04684857f60ebff327575ed58ace16c3c25fc5", + "rev": "5886ae9f388613dc0f3b9f17b5228c0d406b77ed", "type": "github" }, "original": { diff --git a/nixos/hosts/shadowfax/config/sops-secrets.nix b/nixos/hosts/shadowfax/config/sops-secrets.nix index f2348ec..ee22b33 100644 --- a/nixos/hosts/shadowfax/config/sops-secrets.nix +++ b/nixos/hosts/shadowfax/config/sops-secrets.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +{...}: { secrets = { # Minio "minio" = { @@ -7,51 +6,51 @@ owner = "minio"; group = "minio"; mode = "400"; - restartUnits = [ "minio.service" ]; + restartUnits = ["minio.service"]; }; # Syncthing "syncthing/publicCert" = { sopsFile = ../secrets.sops.yaml; owner = "jahanson"; mode = "400"; - restartUnits = [ "syncthing.service" ]; + restartUnits = ["syncthing.service"]; }; "syncthing/privateKey" = { sopsFile = ../secrets.sops.yaml; owner = "jahanson"; mode = "400"; - restartUnits = [ "syncthing.service" ]; + restartUnits = ["syncthing.service"]; }; # Prowlarr "arr/prowlarr/apiKey" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/dbName" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/user" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/password" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/host" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; # # Sonarr # "arr/sonarr/apiKey" = { @@ -79,29 +78,35 @@ # restartUnits = [ "sonarr.service" ]; # }; # # Radarr - # "arr/radarr/apiKey" = { - # sopsFile = ../secrets.sops.yaml; - # owner = "radarr"; - # mode = "400"; - # restartUnits = [ "radarr.service" ]; - # }; - # "arr/radarr/postgres/dbName" = { - # sopsFile = ../secrets.sops.yaml; - # owner = "radarr"; - # mode = "400"; - # restartUnits = [ "radarr.service" ]; - # }; - # "arr/radarr/postgres/user" = { - # sopsFile = ../secrets.sops.yaml; - # owner = "radarr"; - # mode = "400"; - # restartUnits = [ "radarr.service" ]; - # }; - # "arr/radarr/postgres/password" = { - # sopsFile = ../secrets.sops.yaml; - # owner = "radarr"; - # mode = "400"; - # restartUnits = [ "radarr.service" ]; - # }; + "arr/radarr/apiKey" = { + sopsFile = ../secrets.sops.yaml; + owner = "radarr"; + mode = "400"; + restartUnits = ["radarr.service"]; + }; + "arr/radarr/postgres/dbName" = { + sopsFile = ../secrets.sops.yaml; + owner = "radarr"; + mode = "400"; + restartUnits = ["radarr.service"]; + }; + "arr/radarr/postgres/user" = { + sopsFile = ../secrets.sops.yaml; + owner = "radarr"; + mode = "400"; + restartUnits = ["radarr.service"]; + }; + "arr/radarr/postgres/password" = { + sopsFile = ../secrets.sops.yaml; + owner = "radarr"; + mode = "400"; + restartUnits = ["radarr.service"]; + }; + "arr/radarr/postgres/host" = { + sopsFile = ../secrets.sops.yaml; + owner = "radarr"; + mode = "400"; + restartUnits = ["radarr.service"]; + }; }; } diff --git a/nixos/hosts/shadowfax/default.nix b/nixos/hosts/shadowfax/default.nix index 793482a..386f863 100644 --- a/nixos/hosts/shadowfax/default.nix +++ b/nixos/hosts/shadowfax/default.nix @@ -232,6 +232,26 @@ in passwordFile = config.sops.secrets."arr/prowlarr/postgres/password".path; }; }; + # Radarr + radarr = { + enable = true; + package = pkgs.unstable.radarr; + dataDir = "/nahar/radarr"; + moviesDir = "/moria/media/Movies"; + user = "radarr"; + group = "kah"; + port = 7878; + openFirewall = true; + hardening = true; + apiKeyFile = config.sops.secrets."arr/radarr/apiKey".path; + db = { + enable = true; + hostFile = config.sops.secrets."arr/radarr/postgres/host".path; + port = 5432; + userFile = config.sops.secrets."arr/radarr/postgres/user".path; + passwordFile = config.sops.secrets."arr/radarr/postgres/password".path; + }; + }; # Sabnzbd sabnzbd = { enable = true; diff --git a/nixos/hosts/shadowfax/secrets.sops.yaml b/nixos/hosts/shadowfax/secrets.sops.yaml index 56dc9e1..92fd47a 100644 --- a/nixos/hosts/shadowfax/secrets.sops.yaml +++ b/nixos/hosts/shadowfax/secrets.sops.yaml @@ -20,12 +20,14 @@ arr: sonarr: apiKey: ENC[AES256_GCM,data:TVy4L0ctHhT3gNp+WCaLCUVc0no8VIkWenroFOYk8h4z,iv:A0a6IUBeDDxPiLlrPCXhXu586QRnXha0RthuXUKkU4I=,tag:oVMS5Ys/NiDrA6YSiCjqsw==,type:str] postgres: + host: ENC[AES256_GCM,data:X0suLwp9bZE=,iv:UQXhPilmi0ix0GruDXfLeHXGUY8k+iAL03/3K/EfcCc=,tag:y3tzbv3nxbOzNEnZQCdeVg==,type:str] dbName: ENC[AES256_GCM,data:Um9YpALoU7qQfTo=,iv:q0IVjaxyaG8MWAxp43kZjHIBm6dWv37maykSfhAxe1M=,tag:NLqIikfWculCeuoRqPHc8Q==,type:str] user: ENC[AES256_GCM,data:Vd68IvZs,iv:DYT3PudE94JZZTZHzV8QgRYADtThZhxTjFJByLcZP1c=,tag:pX1ZNC+M9Jm+PlQ22BZMRw==,type:str] password: ENC[AES256_GCM,data:XOrycMom2utnefraGPoAq7xtP6yfSzTb8g==,iv:WQInK+bJuDNI9uN/GeQ2Fb1Mmlux6+lXwkGS1ZEh+kQ=,tag:DGqLerxomCVfVv15Gt3b8A==,type:str] radarr: apiKey: ENC[AES256_GCM,data:Qcfzr12aftnS+b3pDHHnfOya1+vlyVaoNCPLzJ9xv5Pv,iv:9M33sfqZPzeghxmBtYk3LgsfbInC7sPSQGuYFJiydh4=,tag:lSmi6Do64sarG15q6+yuQw==,type:str] postgres: + host: ENC[AES256_GCM,data:mYFhyUYIqp8=,iv:Cj03GOR58PWv3HWXRx0/D5tZ2oObejtIVuQcTcHGkuw=,tag:9K2asujaqi4/Qbozb18Ghg==,type:str] dbName: ENC[AES256_GCM,data:zC4j0VJJpWWT0XY=,iv:ITupnWLgvI2wAPnkD826S77BMELDqRWZKax51SVkBgA=,tag:L7YXfoxAhi94ssBoE35Aug==,type:str] user: ENC[AES256_GCM,data:jaYUWAzQ,iv:ayEutHFPyZ7CN3inTqmgPmintR8qE8HfatvzCx7VXnA=,tag:3Ou0JRzpcihL0AWcC0pC5w==,type:str] password: ENC[AES256_GCM,data:XcS9H5L+ikA2KflepKrBHVlBjKwB0Vu8mw==,iv:lSpoEiCqOpP3p1T7bBH8F9YiSf2kwQQC+FQPuaKojnE=,tag:ScV/E6JeomQlfp35NIrh1g==,type:str] @@ -107,8 +109,8 @@ sops: aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-02-01T19:17:22Z" - mac: ENC[AES256_GCM,data:yUnivIIT8LKsq+Ymc2SiI0ei1jaaESwvyNX77U2zTf70mPplzMQmRIvV10x5mxZ0RTfxQzyudpCZV1cchFxmi7Nwz/YUVcxffd8ohN5vRQDM73ONODxcVnFxBuJh9n2Hnf1jOWxOGo39p235SvxlQHl5jai+sezUN8dBqIgEzts=,iv:XC8Ra3vuNQIdbxUlLoXlCIkqANtkybuyYaS4M9hKcS8=,tag:WWPe8oFlKtsL/pA0Epo0kQ==,type:str] + lastmodified: "2025-02-03T20:15:40Z" + mac: ENC[AES256_GCM,data:V7XiBqYsWk3kEoGeM6aOfZk6DaSwZAPc2kCt25n0y5eDKeLaxp6P/gwiquNjnvKmftRAbK0IK7TXxrg4+oEaJzLccAHqc5ch+4oJpWJIC6XlcksYc4JH8K1pzzPKHCW70w0sVghUmaNE/cNaglNgj+0JG9gseC1PKx9vyxFzfAM=,iv:McVZQTSvLugOd/2OMLIDfVuNDdHETF92TCkw7+o0sQg=,tag:peILXXpBChxEa1yRXVgsJw==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.9.3 + version: 3.9.4 diff --git a/nixos/modules/nixos/services/default.nix b/nixos/modules/nixos/services/default.nix index 320dc0f..7d0cba4 100644 --- a/nixos/modules/nixos/services/default.nix +++ b/nixos/modules/nixos/services/default.nix @@ -12,6 +12,7 @@ ./podman ./prowlarr ./qbittorrent + ./radarr ./reboot-required-check.nix ./sabnzbd ./sanoid diff --git a/nixos/modules/nixos/services/radarr/default.nix b/nixos/modules/nixos/services/radarr/default.nix new file mode 100644 index 0000000..bc714d5 --- /dev/null +++ b/nixos/modules/nixos/services/radarr/default.nix @@ -0,0 +1,283 @@ +{ + config, + pkgs, + lib, + utils, + ... +}: +with lib; +let + cfg = config.mySystem.services.radarr; + dbOptions = { + options = { + enable = mkEnableOption "Database configuration for Radarr"; + host = mkOption { + type = types.str; + default = ""; + example = "127.0.0.1"; + description = "Direct database host (mutually exclusive with hostFile)"; + }; + hostFile = mkOption { + type = types.str; + default = ""; + example = "/run/secrets/radarr_db_host"; + description = "Database host from a file (mutually exclusive with host)"; + }; + port = mkOption { + type = types.port; + default = "5432"; + description = "Database port"; + }; + user = mkOption { + type = types.str; + default = "radarr"; + description = "Direct database user (mutually exclusive with userFile)"; + }; + userFile = mkOption { + type = types.str; + default = ""; + example = "/run/secrets/radarr_db_user"; + description = "Database user from a file (mutually exclusive with user)"; + }; + passwordFile = mkOption { + type = types.path; + default = "/run/secrets/radarr_db_password"; + description = "Database password from a file (always used)"; + }; + dbname = mkOption { + type = types.str; + default = "radarr_main"; + description = "Database name"; + }; + }; + }; +in +{ + options.mySystem.services.radarr = { + enable = mkEnableOption "Radarr"; + + package = mkPackageOption pkgs "Radarr" { }; + + user = mkOption { + type = types.str; + default = "radarr"; + description = "User account under which radarr runs."; + }; + + group = mkOption { + type = types.str; + default = "radarr"; + description = "Group under which radarr runs."; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/radarr"; + description = "Storage directory for radarr data"; + }; + + moviesDir = mkOption { + type = types.path; + default = "/mnt/media/movies"; + description = "Directory where movies are stored"; + }; + + port = mkOption { + type = types.port; + default = 7878; + description = "Port for radarr web interface"; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = "Open firewall ports for radarr"; + }; + + hardening = mkOption { + type = types.bool; + default = true; + description = "Enable security hardening features"; + }; + + apiKey = mkOption { + type = types.str; + default = ""; + example = "abc123"; + description = "Direct API key for radarr (mutually exclusive with apiKeyFile)"; + }; + + apiKeyFile = mkOption { + type = types.path; + default = "/run/secrets/radarr_api_key"; + description = "API key for radarr from a file (mutually exclusive with apiKey)"; + }; + + db = mkOption { + type = types.submodule dbOptions; + example = { + enable = true; + host = "10.5.0.5"; # or use hostFile + port = "5432"; + user = "radarr"; # or userFile + passwordFile = "/run/secrets/radarr_db_password"; + dbname = "radarr_main"; + }; + description = "Database settings for radarr."; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = !(cfg.db.host != "" && cfg.db.hostFile != ""); + 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 != ""); + message = "Specify either a direct database user via db.user or a file via db.userFile."; + } + { + assertion = !(cfg.apiKey != "" && cfg.apiKeyFile != ""); + message = "Specify either a direct API key via apiKey or a file via apiKeyFile (leave direct API key empty)."; + } + ]; + + systemd.tmpfiles.rules = [ + "d ${cfg.dataDir} 0775 ${cfg.user} ${cfg.group}" + ]; + + systemd.services.radarr = { + description = "Radarr"; + after = [ + "network.target" + "nss-lookup.target" + ]; + wantedBy = [ "multi-user.target" ]; + environment = lib.mkMerge [ + { + RADARR__APP__INSTANCENAME = "Radarr"; + RADARR__APP__THEME = "dark"; + RADARR__AUTH__METHOD = "External"; + RADARR__AUTH__REQUIRED = "DisabledForLocalAddresses"; + RADARR__LOG__DBENABLED = "False"; + RADARR__LOG__LEVEL = "info"; + RADARR__SERVER__PORT = toString cfg.port; + RADARR__UPDATE__BRANCH = "develop"; + } + (lib.mkIf cfg.db.enable { + RADARR__POSTGRES__PORT = toString cfg.db.port; + RADARR__POSTGRES__MAINDB = cfg.db.dbname; + }) + ]; + + serviceConfig = lib.mkMerge [ + { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + ExecStart = utils.escapeSystemdExecArgs [ + (lib.getExe cfg.package) + "-nobrowser" + "-data=${cfg.dataDir}" + "-port=${toString cfg.port}" + ]; + WorkingDirectory = cfg.dataDir; + RuntimeDirectory = "radarr"; + LogsDirectory = "radarr"; + RuntimeDirectoryMode = "0750"; + Restart = "on-failure"; + RestartSec = 5; + } + (lib.mkIf cfg.hardening { + CapabilityBoundingSet = [ "" ]; + DeviceAllow = [ "" ]; + DevicePolicy = "closed"; + LockPersonality = true; + # Needs access to .Net CLR memory space. + MemoryDenyWriteExecute = false; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectHome = "read-only"; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + ReadWritePaths = [ + cfg.dataDir + cfg.moviesDir + "/var/log/radarr" + ]; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_NETLINK" + ]; + RestrictNamespaces = [ + "uts" + "ipc" + "pid" + "user" + "cgroup" + "net" + ]; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + # .Net CLR requirement + #"~@resources" + ]; + }) + (lib.mkIf cfg.db.enable { + ExecStartPre = "+${pkgs.writeShellScript "radarr-pre-script" '' + mkdir -p /run/radarr + rm -f /run/radarr/secrets.env + + # Helper function to safely write variables + write_var() { + local var_name="$1" + local value="$2" + if [ -n "$value" ]; then + printf "%s=%s\n" "$var_name" "$value" >> /run/radarr/secrets.env + fi + } + + # API Key (direct value or file) + if [ -n "${cfg.apiKey}" ]; then + write_var "RADARR__AUTH__APIKEY" "${cfg.apiKey}" + else + write_var "RADARR__AUTH__APIKEY" "$(cat ${cfg.apiKeyFile})" + fi + + # Database Configuration + write_var "RADARR__POSTGRES__HOST" "$([ -n "${cfg.db.host}" ] && echo "${cfg.db.host}" || cat "${cfg.db.hostFile}")" + write_var "RADARR__POSTGRES__USER" "$([ -n "${cfg.db.user}" ] && echo "${cfg.db.user}" || cat "${cfg.db.userFile}")" + write_var "RADARR__POSTGRES__PASSWORD" "$(cat ${cfg.db.passwordFile})" + + # Final permissions + chmod 600 /run/radarr/secrets.env + chown ${cfg.user}:${cfg.group} /run/radarr/secrets.env + ''}"; + + EnvironmentFile = [ "-/run/radarr/secrets.env" ]; + }) + ]; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + }; + + users.groups.${cfg.group} = { }; + users.users = mkIf (cfg.user == "radarr") { + radarr = { + inherit (cfg) group; + isSystemUser = true; + home = cfg.dataDir; + }; + }; + }; +}