feat: recyclarr

Add the recyclarr service.
This commit is contained in:
Simon Elsbrock
2025-03-08 11:57:14 +01:00
parent 29b7be20d4
commit 593984901f
2 changed files with 242 additions and 0 deletions
+6
View File
@@ -75,6 +75,10 @@ with lib; let
+ strings.optionalString cfg.jellyseerr.enable ''
chown -R jellyseerr:root "${cfg.jellyseerr.stateDir}"
find "${cfg.jellyseerr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \)
''
+ strings.optionalString cfg.recyclarr.enable ''
chown -R recyclarr:root "${cfg.recyclarr.stateDir}"
find "${cfg.recyclarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \)
'';
};
in {
@@ -91,6 +95,7 @@ in {
./prowlarr
./transmission
./sabnzbd
./recyclarr
../util
];
@@ -125,6 +130,7 @@ in {
- [Prowlarr](#nixarr.prowlarr.enable)
- [Radarr](#nixarr.radarr.enable)
- [Readarr](#nixarr.readarr.enable)
- [Recyclarr](#nixarr.recyclarr.enable)
- [Sonarr](#nixarr.sonarr.enable)
- [Transmission](#nixarr.transmission.enable)
- [SABnzbd](#nixarr.sabnzbd.enable)
+236
View File
@@ -0,0 +1,236 @@
{
config,
lib,
pkgs,
inputs,
...
}:
with lib; let
cfg = config.nixarr.recyclarr;
nixarr = config.nixarr;
format = pkgs.formats.yaml {};
# Helper function to extract API keys
extractApiKeys = pkgs.writeShellApplication {
name = "extract-recyclarr-api-keys";
runtimeInputs = with pkgs; [yq];
text = ''
# Ensure state directory exists with proper permissions
mkdir -p "${cfg.stateDir}"
chown ${config.services.recyclarr.user}:${config.services.recyclarr.group} "${cfg.stateDir}"
chmod 755 "${cfg.stateDir}"
${optionalString nixarr.radarr.enable ''
# Extract Radarr API key
API_KEY_FILE="${cfg.stateDir}/radarr-api-key"
xq -r '.Config.ApiKey' "${nixarr.radarr.stateDir}/config.xml" > "$API_KEY_FILE"
chmod 400 "$API_KEY_FILE"
chown ${config.services.recyclarr.user}:${config.services.recyclarr.group} "$API_KEY_FILE"
echo "RADARR_API_KEY=$(tr -d '\n' < "$API_KEY_FILE")" >> "${cfg.stateDir}/env"
''}
${optionalString nixarr.sonarr.enable ''
# Extract Sonarr API key
API_KEY_FILE="${cfg.stateDir}/sonarr-api-key"
xq -r '.Config.ApiKey' "${nixarr.sonarr.stateDir}/config.xml" > "$API_KEY_FILE"
chmod 400 "$API_KEY_FILE"
chown ${config.services.recyclarr.user}:${config.services.recyclarr.group} "$API_KEY_FILE"
echo "SONARR_API_KEY=$(tr -d '\n' < "$API_KEY_FILE")" >> "${cfg.stateDir}/env"
''}
chmod 400 "${cfg.stateDir}/env"
chown ${config.services.recyclarr.user}:${config.services.recyclarr.group} "${cfg.stateDir}/env"
'';
};
# Generate configuration file from Nix attribute set if provided
generatedConfigFile = format.generate "recyclarr-config.yml" cfg.configuration;
# Determine which config file to use
effectiveConfigFile =
if cfg.configFile != null
then cfg.configFile
else generatedConfigFile;
in {
options.nixarr.recyclarr = {
enable = mkOption {
type = types.bool;
default = false;
example = true;
description = ''
Whether or not to enable the Recyclarr service. This service does not need to be run behind a VPN.
**Required options:** [`nixarr.enable`](#nixarr.enable)
'';
};
package = mkPackageOption pkgs "recyclarr" {};
schedule = lib.mkOption {
type = lib.types.str;
default = "daily";
description = "When to run recyclarr in systemd calendar format.";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/recyclarr";
defaultText = literalExpression ''"''${nixarr.stateDir}/recyclarr"'';
example = "/nixarr/.state/recyclarr";
description = "The location of the state directory for the Recyclarr service.";
};
configFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
Path to the recyclarr YAML configuration file. See [Recyclarr's
documentation](https://recyclarr.dev/wiki/yaml/config-reference)
for more information.
The API keys for Radarr and Sonarr can be referenced in the config
file using the `RADARR_API_KEY` and `SONARR_API_KEY` environment
variables (with macro `!env_var`).
Note: You cannot set both `configFile` and `configuration` options.
'';
example = "./recyclarr.yaml";
};
configuration = mkOption {
type = types.nullOr format.type;
default = null;
example = literalExpression ''
{
sonarr = {
series = {
base_url = "http://localhost:8989";
api_key = "!env_var SONARR_API_KEY";
quality_definition = {
type = "series";
};
delete_old_custom_formats = true;
custom_formats = [
{
trash_ids = [
"85c61753df5da1fb2aab6f2a47426b09" # BR-DISK
"9c11cd3f07101cdba90a2d81cf0e56b4" # LQ
];
assign_scores_to = [
{
name = "WEB-DL (1080p)";
score = -10000;
}
];
}
];
};
};
radarr = {
movies = {
base_url = "http://localhost:7878";
api_key = "!env_var RADARR_API_KEY";
quality_definition = {
type = "movie";
};
delete_old_custom_formats = true;
custom_formats = [
{
trash_ids = [
"570bc9ebecd92723d2d21500f4be314c" # Remaster
"eca37840c13c6ef2dd0262b141a5482f" # 4K Remaster
];
assign_scores_to = [
{
name = "HD Bluray + WEB";
score = 25;
}
];
}
];
};
};
}
'';
description = ''
Recyclarr YAML configuration as a Nix attribute set. For detailed configuration options and examples,
see the [official configuration reference](https://recyclarr.dev/wiki/yaml/config-reference/).
The API keys for Radarr and Sonarr can be referenced using the `RADARR_API_KEY` and `SONARR_API_KEY`
environment variables (with the string "!env_var RADARR_API_KEY").
Note: You cannot set both `configFile` and `configuration` options.
'';
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = cfg.enable -> nixarr.enable;
message = ''
The nixarr.recyclarr.enable option requires the nixarr.enable
option to be set, but it was not.
'';
}
{
assertion = cfg.enable -> (nixarr.radarr.enable || nixarr.sonarr.enable);
message = ''
The nixarr.recyclarr.enable option requires at least one of nixarr.radarr.enable
or nixarr.sonarr.enable to be set, but neither was enabled.
'';
}
{
assertion = !(cfg.configFile != null && cfg.configuration != null);
message = ''
You cannot set both nixarr.recyclarr.configFile and nixarr.recyclarr.configuration.
Please choose one method to configure Recyclarr.
'';
}
{
assertion = cfg.configFile != null || cfg.configuration != null;
message = ''
You must set either nixarr.recyclarr.configFile or nixarr.recyclarr.configuration.
'';
}
];
services.recyclarr = {
enable = true;
package = cfg.package;
schedule = cfg.schedule;
};
systemd.services.recyclarr-setup = {
description = "Setup Recyclarr environment";
requiredBy = ["recyclarr.service"];
before = ["recyclarr.service"];
requires =
(optionals nixarr.radarr.enable ["radarr.service"])
++ (optionals nixarr.sonarr.enable ["sonarr.service"]);
after =
(optionals nixarr.radarr.enable ["radarr.service"])
++ (optionals nixarr.sonarr.enable ["sonarr.service"]);
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${extractApiKeys}/bin/extract-recyclarr-api-keys";
};
};
systemd.services.recyclarr = {
requires = ["recyclarr-setup.service"];
after = ["recyclarr-setup.service"];
serviceConfig = {
ExecStart = lib.mkForce "${cfg.package}/bin/recyclarr sync --app-data ${cfg.stateDir} --config ${effectiveConfigFile}";
EnvironmentFile = "${cfg.stateDir}/env";
ReadWritePaths = [cfg.stateDir];
};
};
systemd.tmpfiles.rules = [
"d '${cfg.stateDir}' 0750 ${config.services.recyclarr.user} root - -"
];
};
}