From 718ccc506f7e51c1a3b73546efd1a4525d111209 Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Thu, 17 Jul 2025 22:28:24 +0100 Subject: [PATCH] Fix atomic media moves Signed-off-by: Nikolaos Karaolidis --- .../storm/configs/console/podman/default.nix | 1 - .../configs/console/podman/media/default.nix | 16 ++-- .../libraries/movies/Anime Films.json | 2 +- .../jellyfin/libraries/movies/Films.json | 2 +- .../libraries/tvshows/Anime Shows.json | 2 +- .../jellyfin/libraries/tvshows/Shows.json | 2 +- .../podman/media/jellyseerr/pre-start.sh | 16 +--- .../podman/media/prowlarr/post-start.sh | 2 +- .../podman/media/radarr/apps/common.nix | 2 +- .../console/podman/media/radarr/default.nix | 8 +- .../console/podman/media/radarr/post-start.sh | 2 +- .../podman/media/sonarr/apps/common.nix | 4 +- .../console/podman/media/sonarr/default.nix | 8 +- .../console/podman/media/sonarr/post-start.sh | 2 +- .../podman/media/transmission/default.nix | 69 ++++++++++++++++ .../console/podman/transmission/default.nix | 82 ------------------- 16 files changed, 99 insertions(+), 121 deletions(-) create mode 100644 hosts/jupiter/users/storm/configs/console/podman/media/transmission/default.nix delete mode 100644 hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix diff --git a/hosts/jupiter/users/storm/configs/console/podman/default.nix b/hosts/jupiter/users/storm/configs/console/podman/default.nix index a158427..fc7d3b8 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/default.nix @@ -18,7 +18,6 @@ in (import ./shlink { inherit user home; }) (import ./sish { inherit user home; }) (import ./traefik { inherit user home; }) - (import ./transmission { inherit user home; }) (import ./vaultwarden { inherit user home; }) (import ./whoami { inherit user home; }) ]; diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/default.nix b/hosts/jupiter/users/storm/configs/console/podman/media/default.nix index 5ad6416..724b3c4 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/media/default.nix @@ -18,7 +18,6 @@ in { imports = [ (import ./jellyfin { inherit user home; }) - (import ./jellyseerr { inherit user @@ -27,7 +26,6 @@ in sonarrs ; }) - (import ./prowlarr { inherit user @@ -36,7 +34,6 @@ in sonarrs ; }) - (import ./recyclarr { inherit user @@ -45,19 +42,18 @@ in sonarrs ; }) - (import ./radarr { inherit user home radarrs; }) - (import ./sonarr { inherit user home sonarrs; }) + (import ./transmission { inherit user home; }) ]; home-manager.users.${user} = { systemd.user.tmpfiles.rules = [ - "d /mnt/storage/private/storm/containers/storage/volumes/media/_data 700 storm storm" - "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/films 755 storm storm" - "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/shows 755 storm storm" - "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/anime/films 755 storm storm" - "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/anime/shows 755 storm storm" + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data 700 storm storm" + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/libraries/films 755 storm storm" + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/libraries/shows 755 storm storm" + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/libraries/anime/films 755 storm storm" + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/libraries/anime/shows 755 storm storm" ]; virtualisation.quadlet.networks.media = { }; diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Anime Films.json b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Anime Films.json index 284e74c..58835fd 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Anime Films.json +++ b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Anime Films.json @@ -121,7 +121,7 @@ "LyricFetcherOrder": [], "PathInfos": [ { - "Path": "/var/lib/media/anime/films" + "Path": "/var/lib/media/libraries/anime/films" } ] } diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Films.json b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Films.json index cdb9345..ee81551 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Films.json +++ b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/movies/Films.json @@ -121,7 +121,7 @@ "LyricFetcherOrder": [], "PathInfos": [ { - "Path": "/var/lib/media/films" + "Path": "/var/lib/media/libraries/films" } ] } diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Anime Shows.json b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Anime Shows.json index 7c34caa..cbc0c7c 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Anime Shows.json +++ b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Anime Shows.json @@ -197,7 +197,7 @@ "LyricFetcherOrder": [], "PathInfos": [ { - "Path": "/var/lib/media/anime/shows" + "Path": "/var/lib/media/libraries/anime/shows" } ] } diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Shows.json b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Shows.json index 7f24020..f26f3d6 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Shows.json +++ b/hosts/jupiter/users/storm/configs/console/podman/media/jellyfin/libraries/tvshows/Shows.json @@ -197,7 +197,7 @@ "LyricFetcherOrder": [], "PathInfos": [ { - "Path": "/var/lib/media/shows" + "Path": "/var/lib/media/libraries/shows" } ] } diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/jellyseerr/pre-start.sh b/hosts/jupiter/users/storm/configs/console/podman/media/jellyseerr/pre-start.sh index 65d8fe0..9f31a38 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/jellyseerr/pre-start.sh +++ b/hosts/jupiter/users/storm/configs/console/podman/media/jellyseerr/pre-start.sh @@ -54,20 +54,6 @@ libraries="$( ]' )" -tmpfile="$(mktemp)" -jq -s \ - --arg serverId "$serverId" \ - --arg apiKey "$jellyseerr_key" \ - --argjson libraries "$libraries" \ - '.[0] * .[1] # merge default + existing - | .jellyfin.serverId = $serverId - | .jellyfin.apiKey = $apiKey - | .jellyfin.libraries = $libraries' \ - /var/lib/jellyseerr/settings.json \ - /etc/jellyseerr/settings.default.json \ - > "$tmpfile" -mv "$tmpfile" /var/lib/jellyseerr/settings.json - try_forever() { until "$@" 2>&1; do echo "Try failed: $* - retrying in 1s" @@ -139,6 +125,8 @@ for f in /etc/jellyseerr/apps/sonarr/*.json; do sonarr_json="$(echo "$sonarr_json" "$enriched" | jq -s '.[0] + [.[1]]')" done +[ -f /var/lib/jellyseerr/settings.json ] || echo '{}' > /var/lib/jellyseerr/settings.json + tmpfile=$(mktemp) jq -s \ --argjson libs "$libraries" \ diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/prowlarr/post-start.sh b/hosts/jupiter/users/storm/configs/console/podman/media/prowlarr/post-start.sh index d056d3b..01a51a3 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/prowlarr/post-start.sh +++ b/hosts/jupiter/users/storm/configs/console/podman/media/prowlarr/post-start.sh @@ -139,7 +139,7 @@ build_transmission_payload() { "fields": [ { "name": "host", "value": "transmission" }, { "name": "port", "value": 9091 }, - { "name": "urlBase", "value": "" } + { "name": "urlBase", "value": "/manage/torrents/" } ], "categories": [], "implementation": "Transmission", diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/radarr/apps/common.nix b/hosts/jupiter/users/storm/configs/console/podman/media/radarr/apps/common.nix index 5fa4b97..29e86dc 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/radarr/apps/common.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/media/radarr/apps/common.nix @@ -79,7 +79,7 @@ rec { hostname = hostName; baseUrl = urlBase; activeProfileName = recyclarrProfile; - activeDirectory = "/var/lib/media${mediaFolderBase}"; + activeDirectory = "/var/lib/media/libraries${mediaFolderBase}"; minimumAvailability = "released"; isDefault = !isAnime; externalUrl = "https://media.karaolidis.com${urlBase}"; diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/radarr/default.nix b/hosts/jupiter/users/storm/configs/console/podman/media/radarr/default.nix index 138cfcd..04b9755 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/radarr/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/media/radarr/default.nix @@ -35,6 +35,11 @@ in ); }; + systemd.user.tmpfiles.rules = builtins.map ( + radarr: + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/downloads/transmission/${radarr.hostName} 755 storm storm" + ) radarrs; + virtualisation.quadlet = { networks.media = { }; @@ -67,13 +72,12 @@ in [ "${postStart}:/etc/radarr/post-start.sh:ro" "${volumes.${radarr.hostName}.ref}:/var/lib/radarr" - "/mnt/storage/private/storm/containers/storage/volumes/transmission-data/_data:/var/lib/transmission" "/mnt/storage/private/storm/containers/storage/volumes/media/_data:/var/lib/media" ]; environments = { INSTANCE_NAME = radarr.name; URL_BASE = radarr.urlBase; - ROOT_FOLDER = "/var/lib/media${radarr.mediaFolderBase}"; + ROOT_FOLDER = "/var/lib/media/libraries${radarr.mediaFolderBase}"; DOWNLOAD_CATEGORY = radarr.hostName; }; environmentFiles = [ hmConfig.sops.templates."${radarr.hostName}-env".path ]; diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/radarr/post-start.sh b/hosts/jupiter/users/storm/configs/console/podman/media/radarr/post-start.sh index 44a5b57..6966d67 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/radarr/post-start.sh +++ b/hosts/jupiter/users/storm/configs/console/podman/media/radarr/post-start.sh @@ -129,7 +129,7 @@ build_transmission_payload() { "fields": [ { "name": "host", "value": "transmission" }, { "name": "port", "value": 9091 }, - { "name": "urlBase", "value": "" }, + { "name": "urlBase", "value": "/manage/torrents/" }, { "name": "movieCategory", "value": "$DOWNLOAD_CATEGORY" } ], "implementation": "Transmission", diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/apps/common.nix b/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/apps/common.nix index 54a1511..4a009e0 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/apps/common.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/apps/common.nix @@ -79,9 +79,9 @@ rec { hostname = hostName; baseUrl = urlBase; activeProfileName = recyclarrProfile; - activeDirectory = "/var/lib/media${mediaFolderBase}"; + activeDirectory = "/var/lib/media/libraries${mediaFolderBase}"; activeAnimeProfileName = recyclarrProfile; - activeAnimeDirectory = "/var/lib/media${mediaFolderBase}"; + activeAnimeDirectory = "/var/lib/media/libraries${mediaFolderBase}"; isDefault = !isAnime; enableSeasonFolders = true; externalUrl = "https://media.karaolidis.com${urlBase}"; diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/default.nix b/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/default.nix index 414075c..34995f8 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/default.nix @@ -35,6 +35,11 @@ in ); }; + systemd.user.tmpfiles.rules = builtins.map ( + sonarr: + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/downloads/transmission/${sonarr.hostName} 755 storm storm" + ) sonarrs; + virtualisation.quadlet = { networks.media = { }; @@ -67,13 +72,12 @@ in [ "${postStart}:/etc/sonarr/post-start.sh:ro" "${volumes.${sonarr.hostName}.ref}:/var/lib/sonarr" - "/mnt/storage/private/storm/containers/storage/volumes/transmission-data/_data:/var/lib/transmission" "/mnt/storage/private/storm/containers/storage/volumes/media/_data:/var/lib/media" ]; environments = { INSTANCE_NAME = sonarr.name; URL_BASE = sonarr.urlBase; - ROOT_FOLDER = "/var/lib/media${sonarr.mediaFolderBase}"; + ROOT_FOLDER = "/var/lib/media/libraries${sonarr.mediaFolderBase}"; DOWNLOAD_CATEGORY = sonarr.hostName; }; environmentFiles = [ hmConfig.sops.templates."${sonarr.hostName}-env".path ]; diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/post-start.sh b/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/post-start.sh index 5f2f2d0..6bdeb98 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/post-start.sh +++ b/hosts/jupiter/users/storm/configs/console/podman/media/sonarr/post-start.sh @@ -129,7 +129,7 @@ build_transmission_payload() { "fields": [ { "name": "host", "value": "transmission" }, { "name": "port", "value": 9091 }, - { "name": "urlBase", "value": "" }, + { "name": "urlBase", "value": "/manage/torrents/" }, { "name": "tvCategory", "value": "$DOWNLOAD_CATEGORY" } ], "implementation": "Transmission", diff --git a/hosts/jupiter/users/storm/configs/console/podman/media/transmission/default.nix b/hosts/jupiter/users/storm/configs/console/podman/media/transmission/default.nix new file mode 100644 index 0000000..57c1ac6 --- /dev/null +++ b/hosts/jupiter/users/storm/configs/console/podman/media/transmission/default.nix @@ -0,0 +1,69 @@ +{ user, home }: +{ + config, + inputs, + pkgs, + system, + ... +}: +let + selfPkgs = inputs.self.packages.${system}; + hmConfig = config.home-manager.users.${user}; + inherit (hmConfig.virtualisation.quadlet) volumes networks; +in +{ + home-manager.users.${user} = { + sops.secrets."transmission/protonvpn".sopsFile = ../../../../../../../secrets/secrets.yaml; + + systemd.user.tmpfiles.rules = [ + "d /mnt/storage/private/storm/containers/storage/volumes/media/_data/downloads/transmission 755 storm storm" + ]; + + virtualisation.quadlet = { + networks.transmission = { }; + + volumes.transmission-config = { }; + + containers.transmission = { + containerConfig = { + image = "docker-archive:${selfPkgs.docker-transmission-protonvpn}"; + networks = [ + networks.transmission.ref + networks.traefik.ref + ]; + addCapabilities = [ "NET_ADMIN" ]; + volumes = + let + config = (pkgs.formats.json { }).generate "settings.override.json" { + ratio-limit-enabled = true; + ratio-limit = 5; + download-queue-size = 10; + peer-limit-per-torrent = 50; + peer-limit-global = 500; + rpc-url = "/manage/torrents/"; + download-dir = "/var/lib/media/downloads/transmission"; + incomplete-dir = "/var/lib/media/downloads/transmission/incomplete"; + }; + in + [ + "${hmConfig.sops.secrets."transmission/protonvpn".path}:/etc/wireguard/privatekey:ro" + "${config}:/etc/transmission/settings.override.json:ro" + "${volumes.transmission-config.ref}:/etc/transmission" + "/mnt/storage/private/storm/containers/storage/volumes/media/_data:/var/lib/media" + ]; + environments = { + WIREGUARD_PUBLIC_KEY = "zctOjv4DH2gzXtLQy86Tp0vnT+PNpMsxecd2vUX/i0U="; + WIREGUARD_ENDPOINT = "146.70.179.50:51820"; + }; + labels = [ + "traefik.enable=true" + "traefik.http.routers.transmission.rule=Host(`media.karaolidis.com`) && PathPrefix(`/manage/torrents`)" + "traefik.http.routers.transmission.middlewares=authelia@docker" + ]; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + }; + }; +} diff --git a/hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix b/hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix deleted file mode 100644 index c877a39..0000000 --- a/hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix +++ /dev/null @@ -1,82 +0,0 @@ -{ user, home }: -{ - config, - inputs, - pkgs, - system, - ... -}: -let - selfPkgs = inputs.self.packages.${system}; - hmConfig = config.home-manager.users.${user}; - inherit (hmConfig.virtualisation.quadlet) volumes networks; -in -{ - home-manager.users.${user} = { - sops.secrets."transmission/protonvpn".sopsFile = ../../../../../../secrets/secrets.yaml; - - systemd.user.tmpfiles.rules = [ - "d /mnt/storage/private/storm/containers/storage/volumes/transmission-data/_data 700 storm storm" - ]; - - virtualisation.quadlet = { - networks.transmission = { }; - - volumes.transmission-config = { }; - - containers = { - transmission = { - containerConfig = { - image = "docker-archive:${selfPkgs.docker-transmission-protonvpn}"; - networks = [ - networks.transmission.ref - networks.traefik.ref - ]; - addCapabilities = [ "NET_ADMIN" ]; - volumes = - let - config = (pkgs.formats.json { }).generate "settings.override.json" { - ratio-limit-enabled = true; - ratio-limit = 5; - download-queue-size = 10; - peer-limit-per-torrent = 50; - peer-limit-global = 500; - }; - in - [ - "${hmConfig.sops.secrets."transmission/protonvpn".path}:/etc/wireguard/privatekey:ro" - "${config}:/etc/transmission/settings.override.json:ro" - "${volumes.transmission-config.ref}:/etc/transmission" - "/mnt/storage/private/storm/containers/storage/volumes/transmission-data/_data:/var/lib/transmission" - ]; - environments = { - WIREGUARD_PUBLIC_KEY = "zctOjv4DH2gzXtLQy86Tp0vnT+PNpMsxecd2vUX/i0U="; - WIREGUARD_ENDPOINT = "146.70.179.50:51820"; - }; - labels = [ - "traefik.enable=true" - "traefik.http.routers.transmission.rule=Host(`torrent.karaolidis.com`)" - "traefik.http.routers.transmission.middlewares=authelia@docker" - ]; - }; - - unitConfig.After = [ "sops-nix.service" ]; - }; - - authelia.containerConfig.volumes = - let - config = (pkgs.formats.yaml { }).generate "transmission.yaml" { - access_control.rules = [ - { - domain = "torrent.karaolidis.com"; - policy = "one_factor"; - subject = [ "group:media" ]; - } - ]; - }; - in - [ "${config}:/etc/authelia/conf.d/transmission.yaml:ro" ]; - }; - }; - }; -}