diff --git a/modules/nixos/services/arr.nix b/modules/nixos/services/arr.nix index de4aac8..293dfd6 100644 --- a/modules/nixos/services/arr.nix +++ b/modules/nixos/services/arr.nix @@ -1,4 +1,31 @@ -{ config, lib, ... }: { +{ config, pkgs, lib, ... }: + +let + + arrConfig = { + radarr = { + exportarrPort = "9707"; + url = "localhost:7878"; + apiKey = config.secrets.radarrApiKey.dest; + }; + sonarr = { + exportarrPort = "9708"; + url = "localhost:8989"; + apiKey = config.secrets.sonarrApiKey.dest; + }; + prowlarr = { + exportarrPort = "9709"; + url = "localhost:9696"; + apiKey = config.secrets.prowlarrApiKey.dest; + }; + sabnzbd = { + exportarrPort = "9710"; + url = "localhost:8085"; + apiKey = config.secrets.sabnzbdApiKey.dest; + }; + }; + +in { options = { arrs.enable = lib.mkEnableOption "Arr services"; }; @@ -43,7 +70,7 @@ }]; handle = [{ handler = "reverse_proxy"; - upstreams = [{ dial = "localhost:8989"; }]; + upstreams = [{ dial = arrConfig.sonarr.url; }]; }]; } { @@ -54,7 +81,7 @@ }]; handle = [{ handler = "reverse_proxy"; - upstreams = [{ dial = "localhost:7878"; }]; + upstreams = [{ dial = arrConfig.radarr.url; }]; }]; } { @@ -76,7 +103,11 @@ }]; handle = [{ handler = "reverse_proxy"; - upstreams = [{ dial = "localhost:6767"; }]; + upstreams = [{ + dial = "localhost:${ + builtins.toString config.services.bazarr.listenPort + }"; + }]; }]; } { @@ -87,7 +118,7 @@ }]; handle = [{ handler = "reverse_proxy"; - upstreams = [{ dial = "localhost:8085"; }]; + upstreams = [{ dial = arrConfig.sabnzbd.url; }]; }]; } { @@ -95,11 +126,83 @@ match = [{ host = [ config.hostnames.download ]; }]; handle = [{ handler = "reverse_proxy"; - upstreams = [{ dial = "localhost:5055"; }]; + upstreams = [{ + dial = + "localhost:${builtins.toString config.services.jellyseerr.port}"; + }]; }]; } ]; + # Enable Prometheus exporters + systemd.services = lib.mapAttrs' (name: attrs: { + name = "prometheus-${name}-exporter"; + value = { + description = "Export Prometheus metrics for ${name}"; + after = [ "network.target" ]; + wantedBy = [ "${name}.service" ]; + serviceConfig = { + Type = "simple"; + DynamicUser = true; + ExecStart = let + url = if name != "sabnzbd" then + "http://${attrs.url}/${name}" + else + "http://${attrs.url}"; + in '' + ${pkgs.exportarr}/bin/exportarr ${name} \ + --url ${url} \ + --port ${attrs.exportarrPort}''; + EnvironmentFile = + lib.mkIf (builtins.hasAttr "apiKey" attrs) attrs.apiKey; + Restart = "on-failure"; + ProtectHome = true; + ProtectSystem = "strict"; + PrivateTmp = true; + PrivateDevices = true; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + NoNewPrivileges = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + PrivateMounts = true; + }; + }; + }) arrConfig; + + # Secrets for Prometheus exporters + secrets.radarrApiKey = { + source = ../../../private/radarr-api-key.age; + dest = "/var/private/radarr-api"; + prefix = "API_KEY="; + }; + secrets.sonarrApiKey = { + source = ../../../private/sonarr-api-key.age; + dest = "/var/private/sonarr-api"; + prefix = "API_KEY="; + }; + secrets.prowlarrApiKey = { + source = ../../../private/prowlarr-api-key.age; + dest = "/var/private/prowlarr-api"; + prefix = "API_KEY="; + }; + secrets.sabnzbdApiKey = { + source = ../../../private/sabnzbd-api-key.age; + dest = "/var/private/sabnzbd-api"; + prefix = "API_KEY="; + }; + + # Prometheus scrape targets + prometheus.scrapeTargets = map (key: + "127.0.0.1:${ + lib.attrsets.getAttrFromPath [ key "exportarrPort" ] arrConfig + }") (builtins.attrNames arrConfig); + }; } diff --git a/private/prowlarr-api-key.age b/private/prowlarr-api-key.age new file mode 100644 index 0000000..dfb0284 --- /dev/null +++ b/private/prowlarr-api-key.age @@ -0,0 +1,12 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyAyVkNR +d1lsUmJWVmlxb3NnNTJNN052ckRPOURYR3VCWUFpd25aQTBPVldJCnBNRTdlOTNP +SkhHZkZVU2VrV1hVcGczUVVZVHBtRTNoNUliZHNpeXltZW8KLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIGJCWktmWDE1Z1Q4M0RDKytaZndtZmlCeU5paXUxTld4d2FNV3dT +Nyt3aWsKTUlqTys0Q1RiTERlMnZRUDJMZHJheStYak0rY01jWVM3STF2QjExZzFm +UQotPiBzc2gtZWQyNTUxOSBuanZYNUEgcm9wVTlCKzFEejdlNVp0ZVpnRUxDUmpo +YmRlZWVpSGJocUtNN05KS0cwTQpYUmdpYVNVemZXWUd1ZUlQTks4VUdmaEZPZ2x2 +YVdqWG0ySkt2dDNSQzJvCi0tLSBaN0gwclJpcUFvT0pHcUhyVERnZ1Nralg5bGxZ +b0hyaVB6OStpczQxclFJCmHfg8XI+AzbijptcC6Zhqigp8D3CvB8mSF5H6kPFmJU +odbXmgzihXxWjnG6tH4LgEiEI2dWfbELIwqLs4BIiLlt +-----END AGE ENCRYPTED FILE----- diff --git a/private/radarr-api-key.age b/private/radarr-api-key.age new file mode 100644 index 0000000..8bf3a2a --- /dev/null +++ b/private/radarr-api-key.age @@ -0,0 +1,12 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBuRldh +Um5iYmpEZlZHMmFTMTQ0WVdUUllBeE9MNFFWdXlwNmoxUU1VdUQ4Clk3aXJMYlFM +dFFWODlIamNoc0xGVUdSRktVUllhSHpXR2plbmNkcFR0VW8KLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIEp6RktOMFVLTi9NRTF3MHg0Uk4xRzRlNTlIajVKeWtxN3huNnZN +bDdwRzQKMTUvQ21BWXliOFdNRVFUNjMyS0tyeEt1bURRM2JVMXFIV2cwZDA5WldC +dwotPiBzc2gtZWQyNTUxOSBuanZYNUEgNWlWYUV5SXdCbUJjbnd4UjVqSllyNGZX +bUtIenJJanZCNUdtZkIwQUZYdwowUUE3cHpTRW5zdy9MUlg5VlZGWlNiZ2pVbmUy +c1V0WkZJckJUY25KWmowCi0tLSBxTWg3VHN4MHlVdWpLZzRtaXRYeGEvOFlLR00w +bkVzRkltY0lON0FBYXpjChPtxNyevNnkMHYc7xbsZo/7ThtPB4uOqHfF8swX1efg +AHsWemHnBEfsMBEmCtmczOhFwCNOtgc+q3rQCvmuU9tX +-----END AGE ENCRYPTED FILE----- diff --git a/private/sabnzbd-api-key.age b/private/sabnzbd-api-key.age new file mode 100644 index 0000000..b86dd71 --- /dev/null +++ b/private/sabnzbd-api-key.age @@ -0,0 +1,12 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBDbFRU +RjZFN0Jtd3o4eWthZ09BRUIvNXFZOHVLdVIvRTJCd09ULzJpcjI4CmVjb2szMmtI +N3I5a0FKQ2RpeHJ2NjhwbWM0OFZwUFUzZnV2QWI3VDEvZ2sKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIHNEd1d6bGY3WVVVdVV6TFQ2V3NhN2xubWhwQVBIVVBmKzRBWStX +eVpzaW8Ka0o2a3ArSjdsTEZSa1cyVGdzZThGcUVFKys2UURaRUxwd0FjdDI0VmVJ +QQotPiBzc2gtZWQyNTUxOSBuanZYNUEgc243YjBiOFdrQlV3SDEwWjc1TVB1cita +WVk4bk0wbUk3elBJMkg0Qy9DSQoyVnNWQTJzU1laZ0pGZVlsTEVWV2o2bEVpaVNh +QVNaNXVMaUpKTzVlQW1zCi0tLSB6SG5LWng0OVFGd2NvODVXclgycXFpSVFrMnFk +VlhaL0h2MnBZZDJrN0ZFCtbPQRVZWx65T3DGVY8yG9D2tj1R9ccMcPyJNxJsmfsx +hcINJq2zJKLP2mtvADH95uoaQylwpQQiVd8s6fwMH5cX +-----END AGE ENCRYPTED FILE----- diff --git a/private/sonarr-api-key.age b/private/sonarr-api-key.age new file mode 100644 index 0000000..85a69f0 --- /dev/null +++ b/private/sonarr-api-key.age @@ -0,0 +1,12 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBtV2FM +U09jOUsxNVVLQmFkOWxubGdlZGpGMlh0YjFqbTA5TG53SW9DRGt3CjNQeWRac3Ey +YlRkRnN3YXFnSkxjOTd3eXZLVHRmK3BIdTlJL0ZQNUhHaGsKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIHJaUE0rc0dXaXkvNlErTmd0R016aWZ4eFM2bVh4T1pMa1Z6NEpC +aE14Z28KS2FpU2NCclBDMDJVVC9UMWJibmlsc3hnZE9GVUl5NUxBdVMwYXJXWXhz +QQotPiBzc2gtZWQyNTUxOSBuanZYNUEgaS8zRkg4MWpLT3UwSWVBSmRUSW9KdXZ1 +c2Ywcy94YXdKSTZlcG5PSkF6UQpLMWpoaTZ6cjA5dFlZbXp5dm92U25EWnFKODJN +MHM1RGtDTyt0UEdVZHEwCi0tLSA1LzRHMTN4S1ozd2FIN1g4aTR1Skx3SE0yanNM +aUpZU2tkR2xaN0ZDa3NJCjuPq+1BQBbHCbJAiTBI9EiJ9ddYrJxEt7yxjnbRx5s+ +YsA15LKloxgnK+KU9TMLCFUIlgq0nheyeysMSnqgxhDv +-----END AGE ENCRYPTED FILE-----