From 5fd37cfbe307b4ad85dfff22affd59ed238c1e9a Mon Sep 17 00:00:00 2001 From: Yuto Nishida Date: Thu, 2 Jul 2026 20:08:30 -0700 Subject: [PATCH] [milky-way] Migrate sonarr to sdx instance --- .../stage00/orion-system/main.jsonnet | 56 ++++++++++--------- secrets/k8s-config/k8s-secret-values.jsonnet | 6 +- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/milky-way/environments/stage00/orion-system/main.jsonnet b/milky-way/environments/stage00/orion-system/main.jsonnet index 4a304da..b68a0c4 100644 --- a/milky-way/environments/stage00/orion-system/main.jsonnet +++ b/milky-way/environments/stage00/orion-system/main.jsonnet @@ -15,7 +15,7 @@ local openclaw = import 'milky-way/lib/openclaw.libsonnet'; local qbittorrent = import 'milky-way/lib/qbittorrent.libsonnet'; local vpnProxy = import 'milky-way/lib/vpn-proxy.libsonnet'; local thelounge = import 'milky-way/lib/thelounge.libsonnet'; -local sonarr = import 'milky-way/lib/sonarr.libsonnet'; +local sonarrForSdxarr = import 'milky-way/lib/sonarr.libsonnet'; local prowlarr = import 'milky-way/lib/prowlarr.libsonnet'; local jellyfin = import 'milky-way/lib/jellyfin.libsonnet'; local seanime = import 'milky-way/lib/seanime.libsonnet'; @@ -229,22 +229,26 @@ local pubkeys = import 'magic/common/public_keys.json'; serverCountries = "United States", ), - // Sonarr: monitors/grabs TV episodes, hands torrents to qbittorrent + // sonarr-for-sdxarr: the Sonarr instance dedicated to being reconciled by SeaDexArr (hence the + // name -- its supported use-case is the seadexarr wiring below, NOT a general/global Sonarr). + // Monitors/grabs TV episodes, hands torrents to qbittorrent // (qbittorrent.default.svc.cluster.local:8080), then imports completed downloads by hardlinking - // them out of /data/downloads/qbittorrent into a library tree (/data/library/Animations and - // '/data/library/TV Shows', set as Sonarr root folders via buildarrConfig below) on the + // them out of /data/downloads/qbittorrent into a library tree ('/data/library/Animations (Seadexarr)' + // and '/data/library/TV Shows (Seadexarr)', set as Sonarr root folders via buildarrConfig below -- + // the '(Seadexarr)' suffix marks them as this instance's SeaDexArr-managed roots) on the // SHARED mdata volume -- same PVC, same /data mount path as qbittorrent, so hardlinks/atomic // moves stay on one filesystem. WebUI via Tailscale L7 ingress; SQLite config on its own iSCSI // RWO PVC. The download-client/indexer links are entered in the UI post-deploy (they need API // keys each app generates on first boot). - sonarr: sonarr.new( - apiKey = secrets.sonarr.apiKey, - tailscaleHostname = "sonarr", + sonarrForSdxarr: sonarrForSdxarr.new( + apiKey = secrets.sonarrForSdxarr.apiKey, + tailscaleHostname = "sonarr-for-sdxarr", + name = "sonarr-for-sdxarr", mediaVolumeClaimName = this.mdataPvc.metadata.name, ), // Prowlarr: indexer manager. No media volume -- it pushes indexer configs to Sonarr - // (sonarr.default.svc.cluster.local:8989, and later Radarr) over ClusterIP DNS. WebUI via + // (sonarr-for-sdxarr.default.svc.cluster.local:8989, and later Radarr) over ClusterIP DNS. WebUI via // Tailscale L7 ingress; SQLite config on its own iSCSI RWO PVC. prowlarr: prowlarr.new( apiKey = secrets.prowlarr.apiKey, @@ -278,7 +282,7 @@ local pubkeys = import 'magic/common/public_keys.json'; // autobrr: download automation. Watches indexer announces (IRC/RSS), matches releases against // filters, and forwards each match to a download client -- typically Sonarr as an "arr" client - // (Sonarr then grabs via its own qBittorrent client under tv-sonarr, owning the category), or + // (Sonarr then grabs via its own qBittorrent client under sonarr-for-sdxarr, owning the category), or // qBittorrent directly under a per-filter category. No media volume / no VPN sidecar: it hands // releases to Sonarr / qBittorrent over ClusterIP, it isn't a torrent client itself. The download // clients + indexers + filters + categories are runtime UI/DB state -- autobrr has no @@ -302,7 +306,7 @@ local pubkeys = import 'magic/common/public_keys.json'; // webui port as ports[0] after asserting ports[0] really is the webui entry (qbittorrent's Service // also exposes gluetun-ctrl). API keys come from sops. local buildarrConfig = - local sonarrOrionSystemInstanceName = 'sonarr-orion-system'; + local sonarrForSdxarrInstanceName = 'sonarr-for-sdxarr'; local prowlarrOrionSystemInstanceName = 'prowlarr-orion-system'; local httpUrl(hostname, port) = 'http://%s:%d' % [hostname, port]; { @@ -325,11 +329,11 @@ local pubkeys = import 'magic/common/public_keys.json'; media_management: { delete_unmanaged_root_folders: false }, }, instances: { - [sonarrOrionSystemInstanceName]: { - hostname: utils.domainOfService(this.sonarr.service), - port: utils.associateObjectsByKey(this.sonarr.service.spec.ports, 'name')['webui'].port, + [sonarrForSdxarrInstanceName]: { + hostname: utils.domainOfService(this.sonarrForSdxarr.service), + port: utils.associateObjectsByKey(this.sonarrForSdxarr.service.spec.ports, 'name')['webui'].port, protocol: 'http', - api_key: secrets.sonarr.apiKey, + api_key: secrets.sonarrForSdxarr.apiKey, settings: { download_clients: { delete_unmanaged: false, // also explicit per-instance (belt & suspenders) @@ -340,7 +344,7 @@ local pubkeys = import 'magic/common/public_keys.json'; port: utils.associateObjectsByKey(this.qbittorrent.service.spec.ports, 'name')['webui'].port, // No username/password: qBittorrent's AuthSubnetWhitelist bypasses auth for // in-cluster callers (Sonarr is in the pod CIDR). See lib/qbittorrent.libsonnet. - category: 'tv-sonarr', // qBittorrent category Sonarr tags its grabs with + category: 'sonarr-for-sdxarr', // qBittorrent category Sonarr tags its grabs with }, }, }, @@ -369,13 +373,13 @@ local pubkeys = import 'magic/common/public_keys.json'; // rejects a non-existent path). The paths below stay LITERAL on purpose -- they must // not auto-follow an accidental mountPath change. local mediaMount = utils.associateObjectsByKey( - this.sonarr.deployment.spec.template.spec.containers[0].volumeMounts, 'name' + this.sonarrForSdxarr.deployment.spec.template.spec.containers[0].volumeMounts, 'name' )['media'], assert mediaMount.mountPath == '/data' : 'sonarr media mount must be at /data for these buildarr root_folders to resolve', root_folders: [ - '/data/library/Animations', - '/data/library/TV Shows', + '/data/library/Animations (Seadexarr)', + '/data/library/TV Shows (Seadexarr)', ], }, }, @@ -403,14 +407,14 @@ local pubkeys = import 'magic/common/public_keys.json'; // its API key itself. The two URLs are still required explicitly (instance_name // only links the key): prowlarr_url is how Sonarr dials back to Prowlarr for the // indexer proxy; base_url is how Prowlarr reaches Sonarr to push the sync. - instance_name: sonarrOrionSystemInstanceName, + instance_name: sonarrForSdxarrInstanceName, prowlarr_url: httpUrl( utils.domainOfService(this.prowlarr.service), utils.associateObjectsByKey(this.prowlarr.service.spec.ports, 'name')['webui'].port, ), base_url: httpUrl( - utils.domainOfService(this.sonarr.service), - utils.associateObjectsByKey(this.sonarr.service.spec.ports, 'name')['webui'].port, + utils.domainOfService(this.sonarrForSdxarr.service), + utils.associateObjectsByKey(this.sonarrForSdxarr.service.spec.ports, 'name')['webui'].port, ), sync_level: 'full_sync', }, @@ -426,7 +430,7 @@ local pubkeys = import 'magic/common/public_keys.json'; // SeaDexArr: scheduled daemon (no web UI -> no Service/Ingress) that reads the Sonarr library, picks // SeaDex's "best" release per anime, and adds its torrent straight into qBittorrent under the - // tv-sonarr category (so Sonarr imports it) tagged `from-seadexarr`. qBittorrent creds are omitted: + // sonarr-for-sdxarr category (so Sonarr imports it) tagged `from-seadexarr`. qBittorrent creds are omitted: // its AuthSubnetWhitelist bypasses auth for in-cluster callers (same as buildarr/Sonarr). Radarr // isn't deployed, so only Sonarr + qBittorrent are wired; the scheduled run tolerates the absent // Radarr per-module. Host/port for each app come from its Service (the source of truth) the same way @@ -435,10 +439,10 @@ local pubkeys = import 'magic/common/public_keys.json'; seadexarr: seadexarr.new( config = { sonarr_url: 'http://%s:%d' % [ - utils.domainOfService(this.sonarr.service), - utils.associateObjectsByKey(this.sonarr.service.spec.ports, 'name')['webui'].port, + utils.domainOfService(this.sonarrForSdxarr.service), + utils.associateObjectsByKey(this.sonarrForSdxarr.service.spec.ports, 'name')['webui'].port, ], - sonarr_api_key: secrets.sonarr.apiKey, + sonarr_api_key: secrets.sonarrForSdxarr.apiKey, qbit_info: { host: 'http://%s:%d' % [ utils.domainOfService(this.qbittorrent.service), @@ -447,7 +451,7 @@ local pubkeys = import 'magic/common/public_keys.json'; username: '', password: '', }, - sonarr_torrent_category: 'tv-sonarr', // matches Sonarr's qBittorrent download-client category (buildarr) + sonarr_torrent_category: 'sonarr-for-sdxarr', // matches Sonarr's qBittorrent download-client category (buildarr) torrent_tags: 'from-seadexarr', // qBittorrent tag on grabs, so SeaDexArr-added torrents are identifiable discord_url: secrets.seadexarr.discordUrl, }, diff --git a/secrets/k8s-config/k8s-secret-values.jsonnet b/secrets/k8s-config/k8s-secret-values.jsonnet index 92848f1..606b33e 100644 --- a/secrets/k8s-config/k8s-secret-values.jsonnet +++ b/secrets/k8s-config/k8s-secret-values.jsonnet @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data: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,iv:p19ISJ3rpWQRQPDXEo7FF87Duy2S+OPLyRZ5vhbsQ6o=,tag:wEh25IXhZ4G5vmtpDus0Rg==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:poWlhFwn7eNiENHvVGb1pe6dNQF9/yIywqjXMI/j4c4=,tag:L09t23gvdSWdmMckEjqVwg==,type:str]", "sops": { "age": [ { @@ -11,8 +11,8 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZNjF5OUx2M1k2YlRiekda\nWHh0QWdQNGZrNFpiM1haZlBPeGRBZjJOOTJrCm9wOVE3cVZhYmNIVjgwWGtDVjRQ\neHNGWW81c0tLK0VYY0RnMk5PSjRzYlkKLS0tIGJQWEhaY0wwaVV0NUNXaXFraExy\na2NwZUhCbng1YWxpUGp6dU9OVXBTNVUKUtj4Ms9tlqFEXbT+cirIiFNZFD8oPbPx\nPu9zxmIl7BC2I1v/c9ijFft7XR+somx7wX5ISIIhBwTDq9Pr4fqovA==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2026-06-29T07:00:02Z", - "mac": "ENC[AES256_GCM,data:Z+MLDW289vMRNCeQoSHfTtvDYPmDigkjwyzBKUZMXvdY0Tb5x4Jpw540AfkFBsqRPHgpnexsSP7jtCOoB8LUku2MKEDDkQzuS1J9J43iKl++e9waB/h/Uh8YciSO4QhYfLVMbveQnzU2G0yRMWDSyUxXduHIAaqi4nB2dd8qlEs=,iv:sjcLQ5NFEY7Ad8DGo7prhiuRlqhHpFr/rbISGETCV7g=,tag:B1hvJj84BuYJd6urZk1n9A==,type:str]", + "lastmodified": "2026-07-03T03:12:43Z", + "mac": "ENC[AES256_GCM,data:3aU6dg298uN6yiUBl4o/hpgzrDiN6t93NkvHclDJRRET0hdQuGGIJ95Rc4T0HwfoY8QL1+6Lyjv7KAFzrvweIBptqw2LUlr37i+v6oCxevgOKsw0Qp+te7NeRHQwHveDWZVAMmWj3XteaG2r6aOujgKwE6uko2mfQwVPkD/VwzQ=,iv:tkPr4gTKjOL/fIRRxFelKIaY5Y/uyMvOnUegOmcy1lo=,tag:xtbl+6DVoDqlcJm5UoYoKw==,type:str]", "unencrypted_suffix": "_unencrypted", "version": "3.10.2" } -- 2.54.0