nix.gc (common.nix) is weekly, too slow to catch a switch pinning the old generation's closure on a 29G eMMC — add a full nix-collect-garbage on every boot instead. Also set boot.swraid.mdadmConf so eval stops warning that mdmon will crash (dormant here: the RAID0 array uses native superblocks, so mdmon never actually runs). sabnzbd.configFile is deprecated by the module; move to services.sabnzbd.settings with credentials (web login, api/nzb keys, eweka.nl server) sourced from sops via secretValues instead of living in a plaintext ini. admin_dir/log_dir are pinned absolute at their original /mnt/data location so the existing download queue/history isn't reset by the ini moving to /var/lib/sabnzbd. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
109 lines
5.5 KiB
Nix
109 lines
5.5 KiB
Nix
{ config, ... }:
|
|
|
|
# SABnzbd — usenet downloader. Migrated off a reused hand-authored ini
|
|
# (servers/API key/history originally imported from the old ZimaOS docker
|
|
# stack) onto NixOS-managed `settings`, per the module's own deprecation
|
|
# notice for `configFile`. Only the values that differ from SABnzbd's own
|
|
# built-in defaults are declared here — everything else falls back to the
|
|
# same defaults SABnzbd was already using.
|
|
#
|
|
# `admin_dir`/`log_dir` MUST stay absolute: the module writes the merged ini
|
|
# to /var/lib/sabnzbd/sabnzbd.ini (eMMC), and both dirs are otherwise
|
|
# relative to wherever the ini lives. Pointing them back at the ORIGINAL
|
|
# /mnt/data location keeps the existing download queue/history database
|
|
# (admin_dir) intact — a relative default here would silently "reset"
|
|
# SABnzbd to an empty queue on first switch, even though nothing was deleted.
|
|
{
|
|
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 all live on the array, but systemd only
|
|
# derives RequiresMountsFor from /var/lib/sabnzbd (eMMC) — so with the array
|
|
# absent sabnzbd would start and download onto the 29G OS disk.
|
|
systemd.services.sabnzbd.unitConfig.RequiresMountsFor = [ "/mnt/data" ];
|
|
systemd.services.fix-downloads-perms.unitConfig.RequiresMountsFor = [ "/mnt/data" ];
|
|
|
|
# SABnzbd hardcodes completed job folders to 0700 on every job, ignoring
|
|
# the ini's `umask` (that only covers files during unpack, not the job
|
|
# dir itself). setgid on Downloads keeps the group as "users" but perm
|
|
# bits still come back zeroed, locking out cinephage/mediamanager — sweep
|
|
# it clean instead of fighting SABnzbd.
|
|
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";
|
|
};
|
|
};
|
|
}
|