From a9649be705805da042b6b13436f9fe61d790cb83 Mon Sep 17 00:00:00 2001 From: ediblerope Date: Thu, 30 Apr 2026 20:00:33 +0100 Subject: [PATCH] profilarr: swap recyclarr for Dictionarry's Profilarr Profilarr replaces the recyclarr/TRaSH-Guides flow with a stateful web service that owns *arr profiles end-to-end via its own UI. Runs as an oci-container on 127.0.0.1:6868, fronted by nginx at profilarr.nordhammer.it behind Authelia (one_factor). Co-Authored-By: Claude Opus 4.7 --- common.nix | 2 +- services/authelia.nix | 1 + services/nginx.nix | 1 + services/profilarr.nix | 28 ++++++++ services/recyclarr.nix | 147 ----------------------------------------- 5 files changed, 31 insertions(+), 148 deletions(-) create mode 100644 services/profilarr.nix delete mode 100644 services/recyclarr.nix diff --git a/common.nix b/common.nix index 4eaade9..b3a2c9e 100644 --- a/common.nix +++ b/common.nix @@ -31,7 +31,7 @@ ./services/authelia.nix ./services/homepage.nix ./services/arr-interconnect.nix - ./services/recyclarr.nix + ./services/profilarr.nix ./services/adguard.nix ./services/router.nix ./services/crowdsec.nix diff --git a/services/authelia.nix b/services/authelia.nix index 6805e99..4c3ff62 100644 --- a/services/authelia.nix +++ b/services/authelia.nix @@ -79,6 +79,7 @@ in { domain = "bazarr.nordhammer.it"; policy = "one_factor"; } { domain = "prowlarr.nordhammer.it"; policy = "one_factor"; } { domain = "torrent.nordhammer.it"; policy = "one_factor"; } + { domain = "profilarr.nordhammer.it"; policy = "one_factor"; } ]; }; diff --git a/services/nginx.nix b/services/nginx.nix index 98e64c6..f4b3a3e 100644 --- a/services/nginx.nix +++ b/services/nginx.nix @@ -111,6 +111,7 @@ in "homepage.nordhammer.it" = protectedProxy 8082; "7dtd.nordhammer.it" = protectedProxy 8090; "adguard.nordhammer.it" = protectedProxy 3000; + "profilarr.nordhammer.it" = protectedProxy 6868; # --- Local-only: serves update history JSON to Homepage's customapi widget --- "homepage-updates.local" = { diff --git a/services/profilarr.nix b/services/profilarr.nix new file mode 100644 index 0000000..07bdac4 --- /dev/null +++ b/services/profilarr.nix @@ -0,0 +1,28 @@ +# services/profilarr.nix — Dictionarry's Profilarr quality-profile manager. +# +# Replaces the old recyclarr/TRaSH-Guides flow. Profilarr runs as a stateful +# web service with its own UI; *arr API keys, profile selections, custom +# formats, and sync schedule all live inside its own DB. Nix only owns the +# container, the storage dir, and the nginx vhost — everything else is +# configured at https://profilarr.nordhammer.it after first boot. +{ config, lib, ... }: +{ + config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") { + + systemd.tmpfiles.rules = [ + "d /var/lib/profilarr 0755 root root -" + ]; + + virtualisation.oci-containers.containers.profilarr = { + image = "ghcr.io/dictionarry-hub/profilarr:latest"; + volumes = [ + "/var/lib/profilarr:/config" + ]; + # Localhost-only; nginx fronts it at profilarr.nordhammer.it behind Authelia + ports = [ "127.0.0.1:6868:6868" ]; + environment = { + TZ = "Europe/London"; + }; + }; + }; +} diff --git a/services/recyclarr.nix b/services/recyclarr.nix deleted file mode 100644 index 62dff57..0000000 --- a/services/recyclarr.nix +++ /dev/null @@ -1,147 +0,0 @@ -# services/recyclarr.nix — TRaSH-Guide quality profiles for Sonarr & Radarr. -# -# Pulls the latest custom formats + quality profiles from TRaSH and pushes -# them into each *arr's API. API keys are extracted at runtime from each -# *arr's config.xml (same pattern as arr-interconnect.nix) so there's no -# secret to manage. Runs weekly via systemd timer; idempotent. -# -# Profiles installed: -# Sonarr: WEB-1080p (default) | WEB-2160p (per-show opt-in, WEB only) -# Radarr: HD Bluray + WEB (default) | UHD Bluray + WEB (per-movie opt-in) -# -# AV1 is banned across all 4 profiles (GPU lacks hardware decode). -# -# Manual sync: sudo systemctl start recyclarr-sync -{ config, lib, pkgs, ... }: -let - recyclarrConfig = pkgs.writeText "recyclarr.yml" '' - sonarr: - sonarr-main: - base_url: http://127.0.0.1:8989 - api_key: !env_var SONARR_API_KEY - - delete_old_custom_formats: true - replace_existing_custom_formats: true - - quality_definition: - type: series - - include: - - template: sonarr-quality-definition-series - - template: sonarr-v4-quality-profile-web-1080p - - template: sonarr-v4-custom-formats-web-1080p - - template: sonarr-v4-quality-profile-web-2160p - - template: sonarr-v4-custom-formats-web-2160p - - custom_formats: - # AV1 ban — GPU has no hardware decode for AV1. - - trash_ids: - - 15a05bc7c1a36e2b57fd628f8977e2fc - assign_scores_to: - - name: WEB-1080p - score: -10000 - - name: WEB-2160p - score: -10000 - - # x265 (HD) preference — TRaSH defaults this to -10000 because - # most x265-1080p is lazy re-encodes. We override to +500 to - # actively prefer HEVC for disk space. Bad encodes are still - # filtered by Scene/No-RlsGroup/Retags/Obfuscated (each -10000). - - trash_ids: - - 47435ece6b99a0b477caf360e79ba0bb - assign_scores_to: - - name: WEB-1080p - score: 500 - - radarr: - radarr-main: - base_url: http://127.0.0.1:7878 - api_key: !env_var RADARR_API_KEY - - delete_old_custom_formats: true - replace_existing_custom_formats: true - - quality_definition: - type: movie - - include: - - template: radarr-quality-definition-movie - - template: radarr-quality-profile-hd-bluray-web - - template: radarr-custom-formats-hd-bluray-web - - template: radarr-quality-profile-uhd-bluray-web - - template: radarr-custom-formats-uhd-bluray-web - - custom_formats: - # AV1 ban - - trash_ids: - - cae4ca30163749b891686f95532519bd - assign_scores_to: - - name: HD Bluray + WEB - score: -10000 - - name: UHD Bluray + WEB - score: -10000 - - # x265 (HD) preference — same rationale as Sonarr above. - - trash_ids: - - dc98083864ea246d05a42df0d05f81cc - assign_scores_to: - - name: HD Bluray + WEB - score: 2000 - ''; - - syncScript = pkgs.writeShellScript "recyclarr-sync" '' - set -euo pipefail - PATH="${lib.makeBinPath [ pkgs.recyclarr pkgs.gnused pkgs.coreutils ]}:$PATH" - - extract_arr_key() { - if [ -f "$1" ]; then - sed -n 's/.*\(.*\)<\/ApiKey>.*/\1/p' "$1" - fi - } - - SONARR_API_KEY=$(extract_arr_key /var/lib/sonarr/config.xml) - RADARR_API_KEY=$(extract_arr_key /var/lib/radarr/config.xml) - - if [ -z "$SONARR_API_KEY" ] || [ -z "$RADARR_API_KEY" ]; then - echo "Sonarr or Radarr API key not available yet — skipping sync." - exit 0 - fi - - export SONARR_API_KEY RADARR_API_KEY - - recyclarr sync --app-data /var/lib/recyclarr --config ${recyclarrConfig} - ''; -in -{ - config = lib.mkIf (config.networking.hostName == "FredOS-Mediaserver") { - - systemd.tmpfiles.rules = [ - "d /var/lib/recyclarr 0700 root root -" - ]; - - systemd.services.recyclarr-sync = { - description = "Sync TRaSH-Guide profiles into Sonarr & Radarr"; - after = [ - "sonarr.service" - "radarr.service" - "arr-interconnect.service" - "network-online.target" - ]; - wants = [ "network-online.target" ]; - serviceConfig = { - Type = "oneshot"; - ExecStart = syncScript; - }; - }; - - systemd.timers.recyclarr-sync = { - description = "Weekly TRaSH-Guide profile sync"; - wantedBy = [ "timers.target" ]; - timerConfig = { - OnCalendar = "weekly"; - Persistent = true; - RandomizedDelaySec = "30m"; - }; - }; - }; -}