Skip to content

Commit 3ac3a47

Browse files
authored
nixos/sonarr: add settings option (#373576)
2 parents d62d5be + 203d5d9 commit 3ac3a47

File tree

2 files changed

+117
-26
lines changed

2 files changed

+117
-26
lines changed

nixos/modules/services/misc/sonarr.nix

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@
77
}:
88
let
99
cfg = config.services.sonarr;
10+
11+
settingsEnvVars = lib.pipe cfg.settings [
12+
(lib.mapAttrsRecursive (
13+
path: value:
14+
lib.optionalAttrs (value != null) {
15+
name = lib.toUpper "SONARR__${lib.concatStringsSep "__" path}";
16+
value = toString (if lib.isBool value then lib.boolToString value else value);
17+
}
18+
))
19+
(lib.collect (x: lib.isString x.name or false && lib.isString x.value or false))
20+
lib.listToAttrs
21+
];
1022
in
1123
{
1224
options = {
@@ -27,6 +39,85 @@ in
2739
'';
2840
};
2941

42+
apiKeyFile = lib.mkOption {
43+
type = lib.types.nullOr lib.types.path;
44+
description = ''
45+
Path to the file containing the API key for Sonarr (32 chars).
46+
This will overwrite the API key in the config file.
47+
'';
48+
example = "/run/secrets/sonarr-apikey";
49+
default = null;
50+
};
51+
52+
environmentFiles = lib.mkOption {
53+
type = lib.types.listOf lib.types.path;
54+
default = [ ];
55+
description = ''
56+
Environment file to pass secret configuration values.
57+
58+
Each line must follow the `SONARR__SECTION__KEY=value` pattern.
59+
Please consult the documentation at the [wiki](https://wiki.servarr.com/useful-tools#using-environment-variables-for-config).
60+
'';
61+
};
62+
63+
settings = lib.mkOption {
64+
type = lib.types.submodule {
65+
freeformType = (pkgs.formats.ini { }).type;
66+
options = {
67+
update = {
68+
mechanism = lib.mkOption {
69+
type =
70+
with lib.types;
71+
nullOr (enum [
72+
"external"
73+
"builtIn"
74+
"script"
75+
]);
76+
description = "which update mechanism to use";
77+
default = "external";
78+
};
79+
automatically = lib.mkOption {
80+
type = lib.types.bool;
81+
description = "Automatically download and install updates.";
82+
default = false;
83+
};
84+
};
85+
server = {
86+
port = lib.mkOption {
87+
type = lib.types.int;
88+
description = "Port Number";
89+
default = 8989;
90+
};
91+
};
92+
log = {
93+
analyticsEnabled = lib.mkOption {
94+
type = lib.types.bool;
95+
description = "Send Anonymous Usage Data";
96+
default = false;
97+
};
98+
};
99+
};
100+
};
101+
example = lib.options.literalExpression ''
102+
{
103+
update.mechanism = "internal";
104+
server = {
105+
urlbase = "localhost";
106+
port = 8989;
107+
bindaddress = "*";
108+
};
109+
}
110+
'';
111+
default = { };
112+
description = ''
113+
Attribute set of arbitrary config options.
114+
Please consult the documentation at the [wiki](https://wiki.servarr.com/useful-tools#using-environment-variables-for-config).
115+
116+
WARNING: this configuration is stored in the world-readable Nix store!
117+
Use [](#opt-services.sonarr.environmentFiles) if it contains a secret.
118+
'';
119+
};
120+
30121
user = lib.mkOption {
31122
type = lib.types.str;
32123
default = "sonarr";
@@ -44,6 +135,15 @@ in
44135
};
45136

46137
config = lib.mkIf cfg.enable {
138+
assertions = [
139+
{
140+
assertion = !(cfg.settings ? auth && cfg.settings.auth ? apikey);
141+
message = ''
142+
The `services.sonarr.settings` attribute set must not contain `ApiKey`, you should instead use `services.sonarr.apiKeyFile` to avoid storing secrets in the Nix store.
143+
'';
144+
}
145+
];
146+
47147
systemd.tmpfiles.rules = [
48148
"d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -"
49149
];
@@ -52,11 +152,20 @@ in
52152
description = "Sonarr";
53153
after = [ "network.target" ];
54154
wantedBy = [ "multi-user.target" ];
55-
155+
environment = settingsEnvVars;
56156
serviceConfig = {
57157
Type = "simple";
58158
User = cfg.user;
59159
Group = cfg.group;
160+
EnvironmentFile = cfg.environmentFiles;
161+
LoadCredential = lib.optional (cfg.apiKeyFile != null) "SONARR__AUTH__APIKEY:${cfg.apiKeyFile}";
162+
ExecStartPre = lib.optionalString (cfg.apiKeyFile != null) pkgs.writeShellScript "sonarr-apikey" ''
163+
if [ ! -s config.xml ]; then
164+
echo '<?xml version="1.0" encoding="UTF-8"?><Config><ApiKey></ApiKey></Config>' > "${cfg.dataDir}/config.xml"
165+
fi
166+
${lib.getExe pkgs.xmlstarlet} ed -L -u "/Config/ApiKey" -v "@API_KEY@" "${cfg.dataDir}/config.xml"
167+
${lib.getExe pkgs.replace-secret} '@API_KEY@' ''${CREDENTIALS_DIRECTORY}/SONARR__AUTH__APIKEY "${cfg.dataDir}/config.xml"
168+
'';
60169
ExecStart = utils.escapeSystemdExecArgs [
61170
(lib.getExe cfg.package)
62171
"-nobrowser"
@@ -67,7 +176,7 @@ in
67176
};
68177

69178
networking.firewall = lib.mkIf cfg.openFirewall {
70-
allowedTCPPorts = [ 8989 ];
179+
allowedTCPPorts = [ cfg.settings.server.port ];
71180
};
72181

73182
users.users = lib.mkIf (cfg.user == "sonarr") {

nixos/tests/prometheus-exporters.nix

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -356,36 +356,18 @@ let
356356
'';
357357
};
358358

359-
exportarr-sonarr = let apikey = "eccff6a992bc2e4b88e46d064b26bb4e"; in {
359+
exportarr-sonarr = let apiKeyFile = pkgs.writeText "dummy-api-key" "eccff6a992bc2e4b88e46d064b26bb4e"; in {
360360
nodeName = "exportarr_sonarr";
361361
exporterConfig = {
362362
enable = true;
363363
url = "http://127.0.0.1:8989";
364-
apiKeyFile = pkgs.writeText "dummy-api-key" apikey;
364+
inherit apiKeyFile;
365365
};
366366
metricProvider = {
367-
services.sonarr.enable = true;
368-
systemd.services.sonarr.serviceConfig.ExecStartPre =
369-
let
370-
sonarr_config = pkgs.writeText "config.xml" ''
371-
<Config>
372-
<LogLevel>info</LogLevel>
373-
<EnableSsl>False</EnableSsl>
374-
<Port>8989</Port>
375-
<SslPort>9898</SslPort>
376-
<UrlBase></UrlBase>
377-
<BindAddress>*</BindAddress>
378-
<ApiKey>${apikey}</ApiKey>
379-
<AuthenticationMethod>None</AuthenticationMethod>
380-
<UpdateMechanism>BuiltIn</UpdateMechanism>
381-
<Branch>main</Branch>
382-
<InstanceName>Sonarr</InstanceName>
383-
</Config>
384-
'';
385-
in
386-
[
387-
''${pkgs.coreutils}/bin/install -D -m 777 ${sonarr_config} -T /var/lib/sonarr/.config/NzbDrone/config.xml''
388-
];
367+
services.sonarr = {
368+
enable = true;
369+
inherit apiKeyFile;
370+
};
389371
};
390372
exporterTest = ''
391373
wait_for_unit("sonarr.service")

0 commit comments

Comments
 (0)