Files
homelab/services/media/sabnzbd.nix
darmanandClaude Sonnet 5 6f24ab69ad docs: condense comments across the repo
Comments had drifted into multi-paragraph narrative (git commit
lineage, debugging stories, restated code) in several hot spots
(scripts/deploy, hermes-agent.nix, flake.nix, gitea.nix, headscale.nix).
Trim every comment to its load-bearing "why" — gotchas, safety
warnings, and non-obvious rationale survive verbatim in substance,
just tightened to 1-2 sentences; historical narrative and anything
already covered in CLAUDE.md is cut. No code/logic changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJqEmY1y3AYX3JoX4Y6b21
2026-09-18 21:36:30 +02:00

102 lines
5.0 KiB
Nix

{ config, ... }:
# SABnzbd — usenet downloader, migrated off a hand-authored ini (imported from
# the old ZimaOS docker stack) onto NixOS-managed `settings`. Only values that
# differ from SABnzbd's own defaults are declared here.
#
# `admin_dir`/`log_dir` must stay absolute: the module writes the merged ini to
# /var/lib/sabnzbd/sabnzbd.ini (eMMC), so a relative default would resolve
# there instead of the original /mnt/data location — silently "resetting"
# SABnzbd to an empty queue/history on first switch, without deleting anything.
{
services.sabnzbd = {
enable = true;
allowConfigWrite = true; # let sabnzbd keep saving state (queue, wizard flags, ...)
settings = {
misc = {
host = "::";
port = 8085;
web_color = "Night";
enable_https = false;
url_base = "/sabnzbd";
cache_limit = "1G";
download_dir = "/mnt/data/HighSeas/Downloads/Incomplete";
complete_dir = "/mnt/data/HighSeas/Downloads";
admin_dir = "/mnt/data/AppData/sabnzbd/config/admin";
log_dir = "/mnt/data/AppData/sabnzbd/config/logs";
# Verbatim from the migrated ini — includes a pre-existing "izma ace"
# (missing comma) left as-is rather than silently "fixed" here.
unwanted_extensions = "exe, com, bat, ink, js, vbs, ps1, sh, py, php, pl, rb, jar, class, swf, scr, hta, msi, msp, msu, pif, ink, chm, vb, vba, ws, wsf, wsh, xll, docm, dotm, xlsm, xltm, pptm, potm, ppsm, sldm, thmx, xlam, ppam, docb, dotb, xltb, mht, mhtml, url, iqylink, deamon, elf, dmg, iso, cue, nrg, img, udf, wim, vhd, vhdx, vmdk, ova, tf, pb, savedmodel, h5, ckpt, meta, index, data-00000-of-00001, vocab, config, model, pt, tgz, tar.gz, bz2, xz, izma ace, arc, cab, jar, izh, pea, sit, sitx, sqx, zoo, pak, upk, bsa, dat, nzb, nzbs, nzb.gz, nzb.bz2";
host_whitelist = "cd1a98d07ece, helium, sabnzbd.jupiter.sol, localhost, jupiter, jupiter.sol";
username = "@sabnzbd_web_username@";
password = "@sabnzbd_web_password@";
api_key = "@sabnzbd_api_key@";
nzb_key = "@sabnzbd_nzb_key@";
};
servers."news.eweka.nl" = {
name = "news.eweka.nl";
displayname = "news.eweka.nl";
host = "news.eweka.nl";
port = 563;
connections = 8;
ssl = true;
ssl_verify = "strict";
username = "@sabnzbd_eweka_username@";
password = "@sabnzbd_eweka_password@";
};
categories = {
"*" = { name = "*"; order = 0; pp = 3; };
movies = { name = "movies"; order = 1; script = "Default"; priority = -100; };
tv = { name = "tv"; order = 2; script = "Default"; priority = -100; };
audio = { name = "audio"; order = 3; script = "Default"; priority = -100; };
software = { name = "software"; order = 4; script = "Default"; priority = -100; };
prowlarr = { name = "prowlarr"; order = 5; script = "Default"; priority = -100; };
xxx = { name = "xxx"; order = 6; script = "Default"; priority = -100; };
readarr = { name = "readarr"; order = 7; script = "Default"; priority = -100; };
};
};
secretValues = {
"@sabnzbd_web_username@" = config.sops.secrets.sabnzbd_web_username.path;
"@sabnzbd_web_password@" = config.sops.secrets.sabnzbd_web_password.path;
"@sabnzbd_api_key@" = config.sops.secrets.sabnzbd_api_key.path;
"@sabnzbd_nzb_key@" = config.sops.secrets.sabnzbd_nzb_key.path;
"@sabnzbd_eweka_username@" = config.sops.secrets.sabnzbd_eweka_username.path;
"@sabnzbd_eweka_password@" = config.sops.secrets.sabnzbd_eweka_password.path;
};
};
# Write access to the shared downloads dir (owned darman:users on disk).
users.users.sabnzbd.extraGroups = [ "users" ];
# download/complete/admin dirs live on the array, but systemd only derives
# RequiresMountsFor from /var/lib/sabnzbd (eMMC) — without this, a missing
# array lets sabnzbd start and download onto the 29G OS disk instead.
systemd.services.sabnzbd.unitConfig.RequiresMountsFor = [ "/mnt/data" ];
systemd.services.fix-downloads-perms.unitConfig.RequiresMountsFor = [ "/mnt/data" ];
# SABnzbd hardcodes completed job folders to 0700, ignoring the ini's `umask`
# (unpack-only) — setgid keeps the group but perm bits still zero out and
# lock out cinephage/mediamanager, so sweep it clean on a timer instead.
systemd.services.fix-downloads-perms = {
description = "Fix group perms SABnzbd resets on completed downloads";
serviceConfig.Type = "oneshot";
script = ''
find /mnt/data/HighSeas/Downloads \
! -group users -exec chgrp users {} + 2>/dev/null || true
find /mnt/data/HighSeas/Downloads -type d ! -perm -g+rwx \
-exec chmod g+rwx {} + 2>/dev/null || true
find /mnt/data/HighSeas/Downloads -type f ! -perm -g+rw \
-exec chmod g+rw {} + 2>/dev/null || true
'';
};
systemd.timers.fix-downloads-perms = {
description = "Periodically fix group perms under HighSeas/Downloads";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "1m";
OnUnitActiveSec = "2m";
};
};
}