alpha
Login
or
Join now
seanaye.bsky.social
/
nixos-config
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
me like nix
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
Sync SABnzbd API key to Arr clients
author
Sean Aye
date
1 week ago
(Jun 14, 2026, 10:18 PM -0400)
commit
1520f0cb
1520f0cbfb0b548f56844138323957c9895c8c4f
parent
d88ddcd4
d88ddcd48d1758b0203c2c630aeecd24b42dd857
change-id
ozkqvnyk
ozkqvnyktssxsmrzmztztwmmqtxtzlzw
+66
1 changed file
Expand all
Collapse all
Unified
Split
modules
media-server.nix
+66
modules/media-server.nix
Reviewed
···
50
50
after = [ "transmission-media-dirs.service" ];
51
51
};
52
52
53
53
+
# Keep manually-created Sonarr/Radarr SABnzbd download clients in sync with
54
54
+
# SABnzbd's generated API key. This avoids storing the SABnzbd API key in Nix
55
55
+
# while repairing clients after the settings-backed SABnzbd config rewrite.
56
56
+
systemd.services.sync-sabnzbd-download-client-keys = {
57
57
+
description = "Sync SABnzbd API key into Arr download clients";
58
58
+
after = [ "sabnzbd.service" "sonarr.service" "radarr.service" ];
59
59
+
wants = [ "sabnzbd.service" "sonarr.service" "radarr.service" ];
60
60
+
wantedBy = [ "multi-user.target" ];
61
61
+
serviceConfig = {
62
62
+
Type = "oneshot";
63
63
+
User = "root";
64
64
+
};
65
65
+
path = [ pkgs.python3 ];
66
66
+
script = ''
67
67
+
python3 ${pkgs.writeText "sync-sabnzbd-download-client-keys.py" ''
68
68
+
import json
69
69
+
import urllib.error
70
70
+
import urllib.request
71
71
+
from pathlib import Path
72
72
+
73
73
+
def read_key(path):
74
74
+
for line in Path(path).read_text().splitlines():
75
75
+
if line.strip().startswith("api_key"):
76
76
+
return line.split("=", 1)[1].strip()
77
77
+
raise RuntimeError(f"api_key not found in {path}")
78
78
+
79
79
+
sab_key = read_key("/var/lib/sabnzbd/sabnzbd.ini")
80
80
+
81
81
+
services = [
82
82
+
("Sonarr", "http://127.0.0.1:8989", "/data/.state/nixarr/secrets/sonarr.api-key"),
83
83
+
("Radarr", "http://127.0.0.1:7878", "/data/.state/nixarr/secrets/radarr.api-key"),
84
84
+
]
85
85
+
86
86
+
def request(base, api_key, method, path, data=None):
87
87
+
body = None if data is None else json.dumps(data).encode()
88
88
+
req = urllib.request.Request(
89
89
+
base + path,
90
90
+
data=body,
91
91
+
method=method,
92
92
+
headers={"X-Api-Key": api_key, "Content-Type": "application/json"},
93
93
+
)
94
94
+
with urllib.request.urlopen(req, timeout=10) as resp:
95
95
+
raw = resp.read()
96
96
+
return None if not raw else json.loads(raw)
97
97
+
98
98
+
for name, base, key_file in services:
99
99
+
try:
100
100
+
api_key = Path(key_file).read_text().strip()
101
101
+
clients = request(base, api_key, "GET", "/api/v3/downloadclient")
102
102
+
changed = 0
103
103
+
for client in clients:
104
104
+
if (client.get("implementation") or "").lower() != "sabnzbd" and (client.get("name") or "").lower() != "sabnzbd":
105
105
+
continue
106
106
+
for field in client.get("fields", []):
107
107
+
if field.get("name") == "apiKey" and field.get("value") != sab_key:
108
108
+
field["value"] = sab_key
109
109
+
changed += 1
110
110
+
request(base, api_key, "PUT", f"/api/v3/downloadclient/{client['id']}", client)
111
111
+
print(f"{name}: updated {changed} SABnzbd apiKey field(s)")
112
112
+
except Exception as e:
113
113
+
print(f"{name}: failed to sync SABnzbd API key: {e}")
114
114
+
raise
115
115
+
''}
116
116
+
'';
117
117
+
};
118
118
+
53
119
# nixarr configures SABnzbd through services.sabnzbd.settings on newer nixpkgs,
54
120
# but NixOS keeps the legacy configFile default when system.stateVersion < 26.05,
55
121
# causing those settings to be ignored. Force the new settings-backed path.