dotfiles/modules/nixos/services/arr.nix

227 lines
6.5 KiB
Nix
Raw Normal View History

2023-07-25 02:55:30 +00:00
{ config, pkgs, lib, ... }:
let
2024-01-10 04:11:11 +00:00
# This config specifies ports for Prometheus to scrape information
2023-07-25 02:55:30 +00:00
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 {
2023-03-12 13:24:16 +00:00
2023-07-07 16:16:07 +00:00
options = { arrs.enable = lib.mkEnableOption "Arr services"; };
2023-03-12 13:24:16 +00:00
config = lib.mkIf config.arrs.enable {
2023-03-12 13:24:16 +00:00
2023-06-06 00:56:52 +00:00
services = {
bazarr = {
enable = true;
group = "media";
};
jellyseerr.enable = true;
prowlarr.enable = true;
sabnzbd = {
enable = true;
group = "media";
2024-01-10 04:11:11 +00:00
# The config file must be editable within the application
# It contains server configs and credentials
2023-06-06 00:56:52 +00:00
configFile = "/data/downloads/sabnzbd/sabnzbd.ini";
};
sonarr = {
enable = true;
group = "media";
};
radarr = {
enable = true;
group = "media";
};
};
2023-03-12 13:24:16 +00:00
2024-01-10 04:11:11 +00:00
# Create a media group to be shared between services
2023-06-06 00:56:52 +00:00
users.groups.media = { };
2024-01-10 04:11:11 +00:00
# Give the human user access to the media group
2023-06-06 00:56:52 +00:00
users.users.${config.user}.extraGroups = [ "media" ];
2024-01-10 04:11:11 +00:00
# Allows media group to read/write the sabnzbd directory
2023-06-04 14:19:56 +00:00
users.users.sabnzbd.homeMode = "0770";
2023-06-06 00:56:52 +00:00
2024-01-10 04:11:11 +00:00
unfreePackages = [ "unrar" ]; # Required as a dependency for sabnzbd
2023-03-12 13:24:16 +00:00
# Requires updating the base_url config value in each service
# If you try to rewrite the URL, the service won't redirect properly
caddy.routes = [
{
2024-01-10 04:11:11 +00:00
# Group means that routes with the same name are mutually exclusive,
# so they are split between the appropriate services.
2023-03-12 13:24:16 +00:00
group = "download";
match = [{
2023-07-07 16:16:07 +00:00
host = [ config.hostnames.download ];
2023-03-12 13:24:16 +00:00
path = [ "/sonarr*" ];
}];
handle = [{
handler = "reverse_proxy";
2024-01-10 04:11:11 +00:00
# We're able to reference the url and port of the service dynamically
2023-07-25 02:55:30 +00:00
upstreams = [{ dial = arrConfig.sonarr.url; }];
2023-03-12 13:24:16 +00:00
}];
}
{
group = "download";
match = [{
2023-07-07 16:16:07 +00:00
host = [ config.hostnames.download ];
2023-03-12 13:24:16 +00:00
path = [ "/radarr*" ];
}];
handle = [{
handler = "reverse_proxy";
2023-07-25 02:55:30 +00:00
upstreams = [{ dial = arrConfig.radarr.url; }];
2023-03-12 13:24:16 +00:00
}];
}
{
group = "download";
match = [{
2023-07-07 16:16:07 +00:00
host = [ config.hostnames.download ];
2023-03-12 13:24:16 +00:00
path = [ "/prowlarr*" ];
}];
handle = [{
handler = "reverse_proxy";
2024-01-10 04:11:11 +00:00
# Prowlarr doesn't offer a dynamic config, so we have to hardcode it
2023-03-12 13:24:16 +00:00
upstreams = [{ dial = "localhost:9696"; }];
}];
}
{
group = "download";
match = [{
2023-07-07 16:16:07 +00:00
host = [ config.hostnames.download ];
2023-03-12 13:24:16 +00:00
path = [ "/bazarr*" ];
}];
handle = [{
handler = "reverse_proxy";
2023-07-25 02:55:30 +00:00
upstreams = [{
2024-01-10 04:11:11 +00:00
# Bazarr only dynamically sets the port, not the host
2023-07-25 02:55:30 +00:00
dial = "localhost:${
builtins.toString config.services.bazarr.listenPort
}";
}];
2023-03-12 13:24:16 +00:00
}];
}
2023-06-03 23:00:18 +00:00
{
group = "download";
match = [{
2023-07-07 16:16:07 +00:00
host = [ config.hostnames.download ];
2023-06-03 23:00:18 +00:00
path = [ "/sabnzbd*" ];
}];
handle = [{
handler = "reverse_proxy";
2023-07-25 02:55:30 +00:00
upstreams = [{ dial = arrConfig.sabnzbd.url; }];
2023-06-03 23:00:18 +00:00
}];
}
2023-06-04 01:10:23 +00:00
{
group = "download";
2023-07-07 16:16:07 +00:00
match = [{ host = [ config.hostnames.download ]; }];
2023-06-04 01:10:23 +00:00
handle = [{
handler = "reverse_proxy";
2023-07-25 02:55:30 +00:00
upstreams = [{
dial =
"localhost:${builtins.toString config.services.jellyseerr.port}";
}];
2023-06-04 01:10:23 +00:00
}];
}
2023-03-12 13:24:16 +00:00
];
# Configure Cloudflare DNS to point to this machine
services.cloudflare-dyndns.domains = [ config.hostnames.download ];
2023-07-25 02:55:30 +00:00
# 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
2024-01-10 04:11:11 +00:00
# Sabnzbd doesn't accept the URI path, unlike the others
2023-07-25 02:55:30 +00:00
url = if name != "sabnzbd" then
"http://${attrs.url}/${name}"
else
"http://${attrs.url}";
2024-01-10 04:11:11 +00:00
# Exportarr is trained to pull from the arr services
2023-07-25 02:55:30 +00:00
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=";
};
2024-01-10 04:11:11 +00:00
# Prometheus scrape targets (expose Exportarr to Prometheus)
2023-07-25 02:55:30 +00:00
prometheus.scrapeTargets = map (key:
"127.0.0.1:${
lib.attrsets.getAttrFromPath [ key "exportarrPort" ] arrConfig
}") (builtins.attrNames arrConfig);
2023-03-12 13:24:16 +00:00
};
}