Compare commits

...

4 Commits

9 changed files with 400 additions and 0 deletions

View File

@@ -32,6 +32,13 @@
./services/jellyfin-qbittorrent-monitor.nix ./services/jellyfin-qbittorrent-monitor.nix
./services/bitmagnet.nix ./services/bitmagnet.nix
./services/prowlarr.nix
./services/sonarr.nix
./services/radarr.nix
./services/bazarr.nix
./services/jellyseerr.nix
./services/recyclarr.nix
./services/soulseek.nix ./services/soulseek.nix
./services/ups.nix ./services/ups.nix
@@ -192,6 +199,7 @@
hostName = hostname; hostName = hostname;
hostId = "0f712d56"; hostId = "0f712d56";
firewall.enable = true; firewall.enable = true;
firewall.trustedInterfaces = [ "wg-br" ];
useDHCP = false; useDHCP = false;
enableIPv6 = false; enableIPv6 = false;

View File

@@ -125,6 +125,11 @@
ntfy = 2586; ntfy = 2586;
livekit = 7880; livekit = 7880;
lk_jwt = 8081; lk_jwt = 8081;
prowlarr = 9696;
sonarr = 8989;
radarr = 7878;
bazarr = 6767;
jellyseerr = 5055;
}; };
https = { https = {
@@ -193,6 +198,35 @@
signalBackupDir = "/${zpool_ssds}/bak/signal"; signalBackupDir = "/${zpool_ssds}/bak/signal";
grayjayBackupDir = "/${zpool_ssds}/bak/grayjay"; grayjayBackupDir = "/${zpool_ssds}/bak/grayjay";
}; };
sonarr = {
dataDir = services_dir + "/sonarr";
};
radarr = {
dataDir = services_dir + "/radarr";
};
prowlarr = {
dataDir = services_dir + "/prowlarr";
};
bazarr = {
dataDir = services_dir + "/bazarr";
};
jellyseerr = {
configDir = services_dir + "/jellyseerr";
};
recyclarr = {
dataDir = services_dir + "/recyclarr";
};
media = {
moviesDir = torrents_path + "/media/movies";
tvDir = torrents_path + "/media/tv";
};
}; };
pkgs = import nixpkgs { pkgs = import nixpkgs {

34
services/bazarr.nix Normal file
View File

@@ -0,0 +1,34 @@
{
pkgs,
config,
service_configs,
lib,
...
}:
{
imports = [
(lib.serviceMountWithZpool "bazarr" service_configs.zpool_ssds [
service_configs.bazarr.dataDir
])
(lib.serviceMountWithZpool "bazarr" service_configs.zpool_hdds [
service_configs.torrents_path
])
(lib.serviceFilePerms "bazarr" [
"Z ${service_configs.bazarr.dataDir} 0700 ${config.services.bazarr.user} ${config.services.bazarr.group}"
])
];
services.bazarr = {
enable = true;
listenPort = service_configs.ports.bazarr;
};
services.caddy.virtualHosts."bazarr.${service_configs.https.domain}".extraConfig = ''
import ${config.age.secrets.caddy_auth.path}
reverse_proxy :${builtins.toString service_configs.ports.bazarr}
'';
users.users.${config.services.bazarr.user}.extraGroups = [
service_configs.media_group
];
}

43
services/jellyseerr.nix Normal file
View File

@@ -0,0 +1,43 @@
{
pkgs,
config,
service_configs,
lib,
...
}:
{
imports = [
(lib.serviceMountWithZpool "jellyseerr" service_configs.zpool_ssds [
service_configs.jellyseerr.configDir
])
(lib.serviceFilePerms "jellyseerr" [
"Z ${service_configs.jellyseerr.configDir} 0700 jellyseerr jellyseerr"
])
];
services.jellyseerr = {
enable = true;
port = service_configs.ports.jellyseerr;
configDir = service_configs.jellyseerr.configDir;
};
systemd.services.jellyseerr.serviceConfig = {
DynamicUser = lib.mkForce false;
User = "jellyseerr";
Group = "jellyseerr";
ReadWritePaths = [ service_configs.jellyseerr.configDir ];
};
users.users.jellyseerr = {
isSystemUser = true;
group = "jellyseerr";
home = service_configs.jellyseerr.configDir;
};
users.groups.jellyseerr = { };
services.caddy.virtualHosts."jellyseerr.${service_configs.https.domain}".extraConfig = ''
# import ${config.age.secrets.caddy_auth.path}
reverse_proxy :${builtins.toString service_configs.ports.jellyseerr}
'';
}

26
services/prowlarr.nix Normal file
View File

@@ -0,0 +1,26 @@
{
pkgs,
service_configs,
config,
lib,
...
}:
{
imports = [
(lib.serviceMountWithZpool "prowlarr" service_configs.zpool_ssds [
service_configs.prowlarr.dataDir
])
(lib.vpnNamespaceOpenPort service_configs.ports.prowlarr "prowlarr")
];
services.prowlarr = {
enable = true;
dataDir = service_configs.prowlarr.dataDir;
settings.server.port = service_configs.ports.prowlarr;
};
services.caddy.virtualHosts."prowlarr.${service_configs.https.domain}".extraConfig = ''
import ${config.age.secrets.caddy_auth.path}
reverse_proxy ${config.vpnNamespaces.wg.namespaceAddress}:${builtins.toString service_configs.ports.prowlarr}
'';
}

View File

@@ -86,6 +86,11 @@
# how many connections per sec # how many connections per sec
ConnectionSpeed = 300; ConnectionSpeed = 300;
# Automatic Torrent Management: use category save paths for new torrents
DisableAutoTMMByDefault = false;
DisableAutoTMMTriggers.CategorySavePathChanged = false;
DisableAutoTMMTriggers.DefaultSavePathChanged = false;
ChokingAlgorithm = "RateBased"; ChokingAlgorithm = "RateBased";
PieceExtentAffinity = true; PieceExtentAffinity = true;
SuggestMode = true; SuggestMode = true;

36
services/radarr.nix Normal file
View File

@@ -0,0 +1,36 @@
{
pkgs,
config,
service_configs,
lib,
...
}:
{
imports = [
(lib.serviceMountWithZpool "radarr" service_configs.zpool_ssds [
service_configs.radarr.dataDir
])
(lib.serviceMountWithZpool "radarr" service_configs.zpool_hdds [
service_configs.torrents_path
])
(lib.serviceFilePerms "radarr" [
"Z ${service_configs.radarr.dataDir} 0700 ${config.services.radarr.user} ${config.services.radarr.group}"
])
];
services.radarr = {
enable = true;
dataDir = service_configs.radarr.dataDir;
settings.server.port = service_configs.ports.radarr;
settings.update.mechanism = "external";
};
services.caddy.virtualHosts."radarr.${service_configs.https.domain}".extraConfig = ''
import ${config.age.secrets.caddy_auth.path}
reverse_proxy :${builtins.toString service_configs.ports.radarr}
'';
users.users.${config.services.radarr.user}.extraGroups = [
service_configs.media_group
];
}

172
services/recyclarr.nix Normal file
View File

@@ -0,0 +1,172 @@
{
pkgs,
config,
service_configs,
lib,
...
}:
let
configTemplate = (pkgs.formats.yaml {}).generate "recyclarr.yml" {
radarr.movies = {
base_url = "http://localhost:${builtins.toString service_configs.ports.radarr}";
api_key = "RADARR_API_KEY_PLACEHOLDER";
include = [
{ template = "radarr-quality-definition-movie"; }
{ template = "radarr-quality-profile-remux-web-2160p"; }
{ template = "radarr-custom-formats-remux-web-2160p"; }
];
quality_profiles = [{
name = "Remux + WEB 2160p";
upgrade = {
allowed = true;
until_quality = "Remux-2160p";
};
qualities = [
{ name = "Remux-2160p"; }
{
name = "WEB 2160p";
qualities = [ "WEBDL-2160p" "WEBRip-2160p" ];
}
{ name = "Remux-1080p"; }
{ name = "Bluray-1080p"; }
{
name = "WEB 1080p";
qualities = [ "WEBDL-1080p" "WEBRip-1080p" ];
}
{ name = "HDTV-1080p"; }
];
}];
custom_formats = [
# Upscaled
{
trash_ids = [ "bfd8eb01832d646a0a89c4deb46f8564" ];
assign_scores_to = [{ name = "Remux + WEB 2160p"; score = -10000; }];
}
# x265 (HD) - override template -10000 penalty
{
trash_ids = [ "dc98083864ea246d05a42df0d05f81cc" ];
assign_scores_to = [{ name = "Remux + WEB 2160p"; score = 0; }];
}
# x265 (no HDR/DV) - override template -10000 penalty
{
trash_ids = [ "839bea857ed2c0a8e084f3cbdbd65ecb" ];
assign_scores_to = [{ name = "Remux + WEB 2160p"; score = 0; }];
}
];
};
sonarr.series = {
base_url = "http://localhost:${builtins.toString service_configs.ports.sonarr}";
api_key = "SONARR_API_KEY_PLACEHOLDER";
include = [
{ template = "sonarr-quality-definition-series"; }
{ template = "sonarr-v4-quality-profile-web-2160p"; }
{ template = "sonarr-v4-custom-formats-web-2160p"; }
];
quality_profiles = [{
name = "WEB-2160p";
upgrade = {
allowed = true;
until_quality = "WEB 2160p";
};
qualities = [
{
name = "WEB 2160p";
qualities = [ "WEBDL-2160p" "WEBRip-2160p" ];
}
{ name = "Bluray-1080p Remux"; }
{ name = "Bluray-1080p"; }
{
name = "WEB 1080p";
qualities = [ "WEBDL-1080p" "WEBRip-1080p" ];
}
{ name = "HDTV-1080p"; }
];
}];
custom_formats = [
# Upscaled
{
trash_ids = [ "23297a736ca77c0fc8e70f8edd7ee56c" ];
assign_scores_to = [{ name = "WEB-2160p"; score = -10000; }];
}
# x265 (HD) - override template -10000 penalty
{
trash_ids = [ "47435ece6b99a0b477caf360e79ba0bb" ];
assign_scores_to = [{ name = "WEB-2160p"; score = 0; }];
}
# x265 (no HDR/DV) - override template -10000 penalty
{
trash_ids = [ "9b64dff695c2115facf1b6ea59c9bd07" ];
assign_scores_to = [{ name = "WEB-2160p"; score = 0; }];
}
];
};
};
dataDir = service_configs.recyclarr.dataDir;
radarrConfig = "${service_configs.radarr.dataDir}/config.xml";
sonarrConfig = "${service_configs.sonarr.dataDir}/config.xml";
user = "recyclarr";
group = "recyclarr";
# Runs as root (via + prefix) to read API keys from config.xml, then chowns output
generateConfig = pkgs.writeShellScript "recyclarr-generate-config" ''
RADARR_KEY=$(${pkgs.gnugrep}/bin/grep -oP '(?<=<ApiKey>)[^<]+' ${radarrConfig})
SONARR_KEY=$(${pkgs.gnugrep}/bin/grep -oP '(?<=<ApiKey>)[^<]+' ${sonarrConfig})
${pkgs.gnused}/bin/sed \
-e "s/RADARR_API_KEY_PLACEHOLDER/$RADARR_KEY/" \
-e "s/SONARR_API_KEY_PLACEHOLDER/$SONARR_KEY/" \
${configTemplate} > ${dataDir}/recyclarr.yml
chown ${user}:${group} ${dataDir}/recyclarr.yml
'';
in
{
imports = [
(lib.serviceMountWithZpool "recyclarr" service_configs.zpool_ssds [
dataDir
])
];
systemd.tmpfiles.rules = [
"d ${dataDir} 0755 ${user} ${group} -"
"d ${dataDir}/data 0755 ${user} ${group} -"
];
systemd.services.recyclarr = {
description = "Recyclarr TRaSH Guides Sync";
after = [ "network-online.target" "radarr.service" "sonarr.service" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
User = user;
Group = group;
ExecStartPre = "+${generateConfig}";
ExecStart = "${lib.getExe pkgs.recyclarr} sync --config ${dataDir}/recyclarr.yml --app-data ${dataDir}/data";
};
};
users.users.${user} = {
isSystemUser = true;
group = group;
home = dataDir;
};
users.groups.${group} = {};
systemd.timers.recyclarr = {
description = "Run Recyclarr daily";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "1h";
};
};
}

42
services/sonarr.nix Normal file
View File

@@ -0,0 +1,42 @@
{
pkgs,
config,
service_configs,
lib,
...
}:
{
imports = [
(lib.serviceMountWithZpool "sonarr" service_configs.zpool_ssds [
service_configs.sonarr.dataDir
])
(lib.serviceMountWithZpool "sonarr" service_configs.zpool_hdds [
service_configs.torrents_path
])
(lib.serviceFilePerms "sonarr" [
"Z ${service_configs.sonarr.dataDir} 0700 ${config.services.sonarr.user} ${config.services.sonarr.group}"
])
];
systemd.tmpfiles.rules = [
"d /torrents/media 2775 root ${service_configs.media_group} -"
"d ${service_configs.media.tvDir} 2775 root ${service_configs.media_group} -"
"d ${service_configs.media.moviesDir} 2775 root ${service_configs.media_group} -"
];
services.sonarr = {
enable = true;
dataDir = service_configs.sonarr.dataDir;
settings.server.port = service_configs.ports.sonarr;
settings.update.mechanism = "external";
};
services.caddy.virtualHosts."sonarr.${service_configs.https.domain}".extraConfig = ''
import ${config.age.secrets.caddy_auth.path}
reverse_proxy :${builtins.toString service_configs.ports.sonarr}
'';
users.users.${config.services.sonarr.user}.extraGroups = [
service_configs.media_group
];
}