*arr: fix (?)
All checks were successful
Build and Deploy / mreow (push) Successful in 1m7s
Build and Deploy / yarn (push) Successful in 52s
Build and Deploy / muffin (push) Successful in 1m16s

This commit is contained in:
2026-05-04 20:25:04 -04:00
parent a95f614dd9
commit 9ef9389672
3 changed files with 99 additions and 0 deletions

View File

@@ -285,5 +285,84 @@ lib.extend (
# Returns a string suitable for $() command substitution in shell scripts. # Returns a string suitable for $() command substitution in shell scripts.
extractArrApiKey = extractArrApiKey =
configXmlPath: "${lib.getExe pkgs.gnugrep} -oP '(?<=<ApiKey>)[^<]+' ${configXmlPath}"; configXmlPath: "${lib.getExe pkgs.gnugrep} -oP '(?<=<ApiKey>)[^<]+' ${configXmlPath}";
# Creates a NixOS-managed *arr settings sync service.
# Spawns a oneshot systemd unit that PUTs the requested values into the *arr API
# whenever the *arr service starts (or when the desired settings change). The
# API key is read from the *arr's own config.xml at runtime.
#
# `settings` is keyed by API endpoint under /api/v3/config/, with one nested
# attrset of field-name -> value pairs per endpoint. Idempotent: it skips the
# PUT when the live config already matches.
mkArrSettingsService =
{
name,
port,
dataDir,
settings,
}:
{ pkgs, config, ... }:
let
configXml = "${dataDir}/config.xml";
endpoints = lib.attrNames settings;
applyOne =
endpoint:
let
jqFilter = lib.concatStringsSep " | " (
lib.mapAttrsToList (k: v: ".${k} = ${builtins.toJSON v}") settings.${endpoint}
);
in
''
echo ":: ${name} config/${endpoint}"
CFG=$(curl -fsS -H "X-Api-Key: $KEY" "$BASE/config/${endpoint}")
NEW=$(jq '${jqFilter}' <<<"$CFG")
if [ "$CFG" = "$NEW" ]; then
echo " unchanged"
else
ID=$(jq -r .id <<<"$NEW")
curl -fsS -X PUT \
-H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
--data "$NEW" "$BASE/config/${endpoint}/$ID" >/dev/null
echo ${final.escapeShellArg " applied: ${jqFilter}"}
fi
'';
applyScript = pkgs.writeShellApplication {
name = "${name}-apply-settings";
runtimeInputs = with pkgs; [
curl
jq
gnugrep
];
text = ''
set -euo pipefail
KEY=$(grep -oP '(?<=<ApiKey>)[^<]+' ${configXml})
BASE="http://localhost:${toString port}/api/v3"
# Wait up to 60s for the API to come online.
for _ in $(seq 1 30); do
if curl -fsS --max-time 2 -H "X-Api-Key: $KEY" "$BASE/system/status" >/dev/null 2>&1; then
break
fi
sleep 2
done
${lib.concatStringsSep "\n" (map applyOne endpoints)}
'';
};
in
{
systemd.services."${name}-apply-settings" = {
description = "Apply NixOS-managed ${name} settings via API";
after = [ "${name}.service" ];
wantedBy = [ "${name}.service" ];
restartTriggers = [ applyScript ];
serviceConfig = {
Type = "oneshot";
User = config.services.${name}.user;
Group = config.services.${name}.group;
ExecStart = lib.getExe applyScript;
};
};
};
} }
) )

View File

@@ -21,6 +21,15 @@
port = service_configs.ports.private.radarr.port; port = service_configs.ports.private.radarr.port;
auth = true; auth = true;
}) })
(lib.mkArrSettingsService {
name = "radarr";
port = service_configs.ports.private.radarr.port;
dataDir = service_configs.radarr.dataDir;
# See services/arr/sonarr.nix for the rationale -- Radarr exhibits the same
# bug, and has already imported ~10 FGT junk PROPER 2160p Remuxes (CF -9995)
# over good releases because PreferAndUpgrade ignored the CF score.
settings.mediamanagement.downloadPropersAndRepacks = "doNotPrefer";
})
]; ];
services.radarr = { services.radarr = {

View File

@@ -21,6 +21,17 @@
port = service_configs.ports.private.sonarr.port; port = service_configs.ports.private.sonarr.port;
auth = true; auth = true;
}) })
(lib.mkArrSettingsService {
name = "sonarr";
port = service_configs.ports.private.sonarr.port;
dataDir = service_configs.sonarr.dataDir;
# Stop Sonarr from auto-upgrading to PROPER/REPACK releases purely on
# revision. Repack/Proper +5 in the recyclarr custom formats already gives
# them a small preference; PreferAndUpgrade made revision override CF score
# entirely, which silently swapped scored 4K WEB-DL files for low-scored
# 1080p Bluray Remux PROPERs.
settings.mediamanagement.downloadPropersAndRepacks = "doNotPrefer";
})
]; ];
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [