Skip to content

Commit 553e7a6

Browse files
committed
configure recyclarr with sane defaults
1 parent ec24f9d commit 553e7a6

2 files changed

Lines changed: 236 additions & 0 deletions

File tree

modules/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
./postgres.nix
88
./prowlarr
99
./radarr
10+
./recyclarr
1011
./sabnzbd
1112
./sonarr
1213
];

modules/recyclarr/default.nix

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
{
2+
config,
3+
lib,
4+
...
5+
}:
6+
with lib; let
7+
inherit (config) nixflix;
8+
inherit (config.nixflix) globals;
9+
cfg = config.nixflix.recyclarr;
10+
11+
sonarrConfig = optionalAttrs cfg.sonarr.enable {
12+
sonarr = [
13+
{
14+
instance_name = "main";
15+
base_url = "http://127.0.0.1:${toString config.nixflix.sonarr.config.hostConfig.port}";
16+
api_key._secret = "/run/credentials/recyclarr.service/sonarr-api_key";
17+
18+
quality_profiles = [
19+
{
20+
name = cfg.sonarr.qualityProfile;
21+
upgrade = {
22+
allowed = true;
23+
until_quality = cfg.sonarr.upgradeUntilQuality;
24+
};
25+
qualities =
26+
[
27+
{name = cfg.sonarr.qualityProfile;}
28+
]
29+
++ optional (cfg.sonarr.qualityProfile != cfg.sonarr.upgradeUntilQuality) {
30+
name = cfg.sonarr.upgradeUntilQuality;
31+
};
32+
}
33+
];
34+
35+
include =
36+
[
37+
{template = "sonarr-quality-definition-series";}
38+
{template = "sonarr-v4-quality-profile-web-1080p";}
39+
{template = "sonarr-v4-custom-formats-web-1080p";}
40+
]
41+
++ optionals cfg.sonarr.anime.enable [
42+
{template = "sonarr-v4-quality-profile-anime";}
43+
{template = "sonarr-v4-custom-formats-anime";}
44+
];
45+
}
46+
];
47+
};
48+
49+
radarrConfig = optionalAttrs cfg.radarr.enable {
50+
radarr = [
51+
{
52+
instance_name = "main";
53+
base_url = "http://127.0.0.1:${toString config.nixflix.radarr.config.hostConfig.port}";
54+
api_key._secret = "/run/credentials/recyclarr.service/radarr-api_key";
55+
56+
quality_profiles = [
57+
{
58+
name = cfg.radarr.qualityProfile;
59+
upgrade = {
60+
allowed = true;
61+
until_quality = cfg.radarr.upgradeUntilQuality;
62+
};
63+
qualities =
64+
[
65+
{name = cfg.radarr.qualityProfile;}
66+
]
67+
++ optional (cfg.radarr.qualityProfile != cfg.radarr.upgradeUntilQuality) {
68+
name = cfg.radarr.upgradeUntilQuality;
69+
};
70+
}
71+
];
72+
73+
include =
74+
[
75+
{template = "radarr-quality-definition-movie";}
76+
{template = "radarr-quality-profile-uhd-bluray-web";}
77+
{template = "radarr-custom-formats-uhd-bluray-web";}
78+
]
79+
++ optionals cfg.radarr.anime.enable [
80+
{template = "radarr-quality-profile-anime";}
81+
{template = "radarr-custom-formats-anime";}
82+
];
83+
}
84+
];
85+
};
86+
87+
recyclarrConfiguration = sonarrConfig // radarrConfig;
88+
in {
89+
options.nixflix.recyclarr = {
90+
enable = mkOption {
91+
type = types.bool;
92+
default = false;
93+
description = "Whether to enable Recyclarr for automated TRaSH guide syncing";
94+
};
95+
96+
user = mkOption {
97+
type = types.str;
98+
default = "recyclarr";
99+
description = "User under which Recyclarr runs";
100+
};
101+
102+
group = mkOption {
103+
type = types.str;
104+
default = "recyclarr";
105+
description = "Group under which Recyclarr runs";
106+
};
107+
108+
config = mkOption {
109+
type = types.nullOr types.attrs;
110+
default = null;
111+
description = ''
112+
Recyclarr configuration as a Nix attribute set.
113+
When set, this completely replaces the auto-generated configuration,
114+
giving you full control over the Recyclarr setup.
115+
'';
116+
};
117+
118+
sonarr = {
119+
enable = mkOption {
120+
type = types.bool;
121+
default = config.nixflix.sonarr.enable;
122+
defaultText = literalExpression "config.nixflix.sonarr.enable";
123+
description = "Whether to sync Sonarr configuration via Recyclarr";
124+
};
125+
126+
qualityProfile = mkOption {
127+
type = types.str;
128+
default = "UHD-4K";
129+
description = "Quality profile to use for Sonarr";
130+
};
131+
132+
upgradeUntilQuality = mkOption {
133+
type = types.str;
134+
default = "HD-1080p";
135+
description = "Quality level to stop upgrading at for Sonarr";
136+
};
137+
138+
anime = {
139+
enable = mkOption {
140+
type = types.bool;
141+
default = false;
142+
description = ''
143+
Whether to enable anime-specific profiles for Sonarr.
144+
When enabled, BOTH normal and anime quality profiles will be configured,
145+
following TRaSH Guides' recommendation for single-instance setups.
146+
'';
147+
};
148+
};
149+
};
150+
151+
radarr = {
152+
enable = mkOption {
153+
type = types.bool;
154+
default = config.nixflix.radarr.enable;
155+
defaultText = literalExpression "config.nixflix.radarr.enable";
156+
description = "Whether to sync Radarr configuration via Recyclarr";
157+
};
158+
159+
qualityProfile = mkOption {
160+
type = types.str;
161+
default = "UHD-4K";
162+
description = "Quality profile to use for Radarr";
163+
};
164+
165+
upgradeUntilQuality = mkOption {
166+
type = types.str;
167+
default = "UHD-4K";
168+
description = "Quality level to stop upgrading at for Radarr";
169+
};
170+
171+
anime = {
172+
enable = mkOption {
173+
type = types.bool;
174+
default = false;
175+
description = ''
176+
Whether to enable anime-specific profiles for Radarr.
177+
When enabled, BOTH normal and anime quality profiles will be configured,
178+
following TRaSH Guides' recommendation for single-instance setups.
179+
'';
180+
};
181+
};
182+
};
183+
};
184+
185+
config = mkIf (nixflix.enable && cfg.enable) {
186+
assertions = [
187+
{
188+
assertion = cfg.sonarr.enable || cfg.radarr.enable;
189+
message = "Recyclarr requires at least one of nixflix.recyclarr.sonarr.enable or nixflix.recyclarr.radarr.enable to be true";
190+
}
191+
{
192+
assertion = cfg.sonarr.enable -> config.nixflix.sonarr.config.apiKeyPath != null;
193+
message = "Recyclarr Sonarr sync requires nixflix.sonarr.config.apiKeyPath to be set";
194+
}
195+
{
196+
assertion = cfg.radarr.enable -> config.nixflix.radarr.config.apiKeyPath != null;
197+
message = "Recyclarr Radarr sync requires nixflix.radarr.config.apiKeyPath to be set";
198+
}
199+
];
200+
201+
users.users.${cfg.user} = optionalAttrs (globals.uids ? ${cfg.user}) {
202+
uid = mkForce globals.uids.${cfg.user};
203+
};
204+
205+
users.groups.${cfg.group} = optionalAttrs (globals.gids ? ${cfg.group}) {
206+
gid = mkForce globals.gids.${cfg.group};
207+
};
208+
209+
services.recyclarr = {
210+
enable = true;
211+
inherit (cfg) user group;
212+
configuration =
213+
if cfg.config == null
214+
then recyclarrConfiguration
215+
else cfg.config;
216+
schedule = "daily";
217+
};
218+
219+
systemd.services.recyclarr = {
220+
after =
221+
["nixflix-setup-dirs.service" "network-online.target"]
222+
++ optional cfg.radarr.enable "radarr-config.service"
223+
++ optional cfg.sonarr.enable "sonarr-config.service";
224+
requires =
225+
optional cfg.radarr.enable "radarr-config.service"
226+
++ optional cfg.sonarr.enable "sonarr-config.service";
227+
wants = ["network-online.target"];
228+
wantedBy = mkForce ["multi-user.target"]; # Run on startup
229+
230+
serviceConfig.LoadCredential =
231+
optional cfg.radarr.enable "radarr-api_key:${config.nixflix.radarr.config.apiKeyPath}"
232+
++ optional cfg.sonarr.enable "sonarr-api_key:${config.nixflix.sonarr.config.apiKeyPath}";
233+
};
234+
};
235+
}

0 commit comments

Comments
 (0)