From c7624baa78147ed9af59fe5913f2ef412bbf4919 Mon Sep 17 00:00:00 2001 From: Pim Kunis Date: Wed, 17 Jul 2024 11:59:48 +0200 Subject: [PATCH] feat(media): Move to separate k8s namespace --- README.md | 1 + flake-parts/kubenix.nix | 2 + kubenix-modules/all.nix | 11 +- kubenix-modules/base.nix | 8 +- kubenix-modules/media.nix | 663 ++++++++++++++++++------------------ kubenix-modules/volumes.nix | 47 +-- 6 files changed, 362 insertions(+), 370 deletions(-) diff --git a/README.md b/README.md index f1bd22f..e91a270 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Currently, the applications being deployed like this are: - `inbucket` - `dnsmasq` - `bind9` +- `media` ## Known bugs diff --git a/flake-parts/kubenix.nix b/flake-parts/kubenix.nix index fdf4418..ff873cb 100644 --- a/flake-parts/kubenix.nix +++ b/flake-parts/kubenix.nix @@ -100,4 +100,6 @@ "${self}/kubenix-modules/dnsmasq.nix" "dnsmasq" "dns"; kubenix.bind9 = mkDeployScriptAndManifest "${self}/kubenix-modules/bind9" "bind9" "dns"; + kubenix.media = mkDeployScriptAndManifest + "${self}/kubenix-modules/media.nix" "media" "media"; }) diff --git a/kubenix-modules/all.nix b/kubenix-modules/all.nix index 8e77fc0..83a1e2c 100644 --- a/kubenix-modules/all.nix +++ b/kubenix-modules/all.nix @@ -1,12 +1,7 @@ -let - applications = [ - ./media.nix - # ./argo.nix - # ./minecraft.nix - ]; -in { imports = [ + # ./argo.nix + # ./minecraft.nix ./base.nix ./longhorn.nix ./esrom.nix @@ -17,5 +12,5 @@ in ./traefik.nix ./volumes.nix ./custom-types.nix - ] ++ applications; + ]; } diff --git a/kubenix-modules/base.nix b/kubenix-modules/base.nix index ebef733..dfff269 100644 --- a/kubenix-modules/base.nix +++ b/kubenix-modules/base.nix @@ -44,17 +44,16 @@ longhorn = { chart = nixhelm.chartsDerivations.${system}.longhorn.longhorn; includeCRDs = true; + values = { + persistence.defaultClassReplicaCount = 2; + defaultSettings = { defaultDataPath = "/mnt/longhorn"; storageMinimalAvailablePercentage = 0; allowRecurringJobWhileVolumeDetached = true; backupTarget = "nfs://lewis.dmz:/mnt/longhorn/persistent/longhorn-backup"; }; - - persistence = { - defaultClassReplicaCount = 2; - }; }; }; }; @@ -76,6 +75,7 @@ attic = { }; inbucket = { }; dns = { }; + media = { }; }; nodes = diff --git a/kubenix-modules/media.nix b/kubenix-modules/media.nix index 6aad73e..f921ebe 100644 --- a/kubenix-modules/media.nix +++ b/kubenix-modules/media.nix @@ -1,462 +1,405 @@ { myLib, ... }: { kubernetes.resources = { - configMaps = { - jellyfin-env.data.JELLYFIN_PublishedServerUrl = "https://media.kun.is"; - transmission-env.data = { - PUID = "1000"; - PGID = "1000"; - TZ = "Europe/Amsterdam"; - }; - - jellyseerr-env.data = { - LOG_LEVEL = "debug"; - TZ = "Europe/Amsterdam"; - }; - - radarr-env.data = { - PUID = "1000"; - PGID = "1000"; - TZ = "Europe/Amsterdam"; - }; - - prowlarr-env.data = { - PUID = "1000"; - PGID = "1000"; - TZ = "Europe/Amsterdam"; - }; - - sonarr-env.data = { - PUID = "1000"; - PGID = "1000"; - TZ = "Europe/Amsterdam"; - }; - - bazarr-env.data = { - PUID = "1000"; - PGID = "1000"; - TZ = "Europe/Amsterdam"; - }; - }; - deployments = { - jellyfin = { - metadata.labels = { + jellyfin.spec = { + selector.matchLabels = { app = "media"; component = "jellyfin"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "jellyfin"; }; - strategy = { - type = "RollingUpdate"; + spec = { + containers.jellyfin = { + image = "jellyfin/jellyfin:10.9.7"; + ports.web.containerPort = 8096; + imagePullPolicy = "Always"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + env.JELLYFIN_PublishedServerUrl.value = "https://media.kun.is"; - template = { - metadata.labels = { - app = "media"; - component = "jellyfin"; + volumeMounts = [ + { + name = "config"; + mountPath = "/config"; + } + { + name = "media"; + mountPath = "/media"; + } + { + name = "cache"; + mountPath = "/config/transcodes"; + } + ]; }; - spec = { - containers.jellyfin = { - image = "jellyfin/jellyfin:10.9.7"; - envFrom = [{ configMapRef.name = "jellyfin-env"; }]; - ports.web.containerPort = 8096; - imagePullPolicy = "Always"; + volumes = { + config.persistentVolumeClaim.claimName = "jellyfin"; + cache.persistentVolumeClaim.claimName = "jellyfin-cache"; - volumeMounts = [ - { - name = "config"; - mountPath = "/config"; - } - { - name = "media"; - mountPath = "/media"; - } - { - name = "cache"; - mountPath = "/config/transcodes"; - } - ]; + media.hostPath = { + path = "/mnt/longhorn/persistent/media"; + type = "Directory"; }; + }; - volumes = { - config.persistentVolumeClaim.claimName = "jellyfin"; - cache.persistentVolumeClaim.claimName = "jellyfin-cache"; + securityContext = { + fsGroup = 0; + fsGroupChangePolicy = "OnRootMismatch"; + }; - media.hostPath = { - path = "/mnt/longhorn/persistent/media"; - type = "Directory"; - }; - }; - - securityContext = { - fsGroup = 0; - fsGroupChangePolicy = "OnRootMismatch"; - }; - - affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms = [{ - matchExpressions = [{ - key = "hasMedia"; - operator = "In"; - values = [ "true" ]; - }]; + affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms = [{ + matchExpressions = [{ + key = "hasMedia"; + operator = "In"; + values = [ "true" ]; }]; - }; + }]; }; }; }; - transmission = { - metadata.labels = { + transmission.spec = { + selector.matchLabels = { app = "media"; component = "transmission"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "transmission"; }; - strategy = { - type = "RollingUpdate"; + spec = { + containers.transmission = { + image = "lscr.io/linuxserver/transmission:4.0.6"; + imagePullPolicy = "Always"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + ports = { + web.containerPort = 9091; + bittorrent.containerPort = 31780; + }; - template = { - metadata.labels = { - app = "media"; - component = "transmission"; + env = { + PUID.value = "1000"; + PGID.value = "1000"; + TZ.value = "Europe/Amsterdam"; + }; + + volumeMounts = [ + { + name = "config"; + mountPath = "/config"; + } + { + name = "media"; + mountPath = "/media"; + } + ]; }; - spec = { - containers.transmission = { - image = "lscr.io/linuxserver/transmission:4.0.6"; - envFrom = [{ configMapRef.name = "transmission-env"; }]; - imagePullPolicy = "Always"; + volumes = { + config.persistentVolumeClaim.claimName = "transmission"; + media.persistentVolumeClaim.claimName = "media"; + }; - ports = { - web.containerPort = 9091; - bittorrent.containerPort = 31780; - }; - - volumeMounts = [ - { - name = "config"; - mountPath = "/config"; - } - { - name = "media"; - mountPath = "/media"; - } - ]; - }; - - volumes = { - config.persistentVolumeClaim.claimName = "transmission"; - media.persistentVolumeClaim.claimName = "media"; - }; - - securityContext = { - fsGroup = 1000; - fsGroupChangePolicy = "OnRootMismatch"; - }; + securityContext = { + fsGroup = 1000; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; - jellyseerr = { - metadata.labels = { + jellyseerr.spec = { + selector.matchLabels = { app = "media"; component = "jellyseerr"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "jellyseerr"; }; - strategy = { - type = "RollingUpdate"; + spec = { + volumes.config.persistentVolumeClaim.claimName = "jellyseerr"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + containers.jellyseerr = { + image = "fallenbagel/jellyseerr:1.9.2"; + ports.web.containerPort = 5055; + imagePullPolicy = "Always"; - template = { - metadata.labels = { - app = "media"; - component = "jellyseerr"; - }; - - spec = { - volumes.config.persistentVolumeClaim.claimName = "jellyseerr"; - - containers.jellyseerr = { - image = "fallenbagel/jellyseerr:1.9.2"; - envFrom = [{ configMapRef.name = "jellyseerr-env"; }]; - ports.web.containerPort = 5055; - imagePullPolicy = "Always"; - - volumeMounts = [{ - name = "config"; - mountPath = "/app/config"; - }]; + env = { + LOG_LEVEL.value = "debug"; + TZ.value = "Europe/Amsterdam"; }; - securityContext = { - fsGroup = 0; - fsGroupChangePolicy = "OnRootMismatch"; - }; + volumeMounts = [{ + name = "config"; + mountPath = "/app/config"; + }]; + }; + + securityContext = { + fsGroup = 0; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; - radarr = { - metadata.labels = { + radarr.spec = { + selector.matchLabels = { app = "media"; component = "radarr"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "radarr"; }; - strategy = { - type = "RollingUpdate"; + spec = { + containers.radarr = { + image = "lscr.io/linuxserver/radarr:5.7.0"; + ports.web.containerPort = 7878; + imagePullPolicy = "Always"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + env = { + PUID.value = "1000"; + PGID.value = "1000"; + TZ.value = "Europe/Amsterdam"; + }; - template = { - metadata.labels = { - app = "media"; - component = "radarr"; + volumeMounts = [ + { + name = "config"; + mountPath = "/config"; + } + { + name = "media"; + mountPath = "/media"; + } + ]; }; - spec = { - containers.radarr = { - image = "lscr.io/linuxserver/radarr:5.7.0"; - envFrom = [{ configMapRef.name = "radarr-env"; }]; - ports.web.containerPort = 7878; - imagePullPolicy = "Always"; + volumes = { + config.persistentVolumeClaim.claimName = "radarr"; + media.persistentVolumeClaim.claimName = "media"; + }; - volumeMounts = [ - { - name = "config"; - mountPath = "/config"; - } - { - name = "media"; - mountPath = "/media"; - } - ]; - }; - - volumes = { - config.persistentVolumeClaim.claimName = "radarr"; - media.persistentVolumeClaim.claimName = "media"; - }; - - securityContext = { - fsGroup = 1000; - fsGroupChangePolicy = "OnRootMismatch"; - }; + securityContext = { + fsGroup = 1000; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; - prowlarr = { - metadata.labels = { + prowlarr.spec = { + selector.matchLabels = { app = "media"; component = "prowlarr"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "prowlarr"; }; - strategy = { - type = "RollingUpdate"; + spec = { + volumes.config.persistentVolumeClaim.claimName = "prowlarr"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + containers.prowlarr = { + image = "lscr.io/linuxserver/prowlarr:1.20.1"; + ports.web.containerPort = 9696; + imagePullPolicy = "Always"; - template = { - metadata.labels = { - app = "media"; - component = "prowlarr"; - }; - - spec = { - volumes.config.persistentVolumeClaim.claimName = "prowlarr"; - - containers.prowlarr = { - image = "lscr.io/linuxserver/prowlarr:1.20.1"; - envFrom = [{ configMapRef.name = "prowlarr-env"; }]; - ports.web.containerPort = 9696; - imagePullPolicy = "Always"; - - volumeMounts = [{ - name = "config"; - mountPath = "/config"; - }]; + env = { + PUID.value = "1000"; + PGID.value = "1000"; + TZ.value = "Europe/Amsterdam"; }; - securityContext = { - fsGroup = 1000; - fsGroupChangePolicy = "OnRootMismatch"; - }; + volumeMounts = [{ + name = "config"; + mountPath = "/config"; + }]; + }; + + securityContext = { + fsGroup = 1000; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; - sonarr = { - metadata.labels = { + sonarr.spec = { + selector.matchLabels = { app = "media"; component = "sonarr"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "sonarr"; }; - strategy = { - type = "RollingUpdate"; + spec = { + containers.sonarr = { + image = "lscr.io/linuxserver/sonarr:4.0.6"; + ports.web.containerPort = 8989; + imagePullPolicy = "Always"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + env = { + PUID.value = "1000"; + PGID.value = "1000"; + TZ.value = "Europe/Amsterdam"; + }; - template = { - metadata.labels = { - app = "media"; - component = "sonarr"; + volumeMounts = [ + { + name = "config"; + mountPath = "/config"; + } + { + name = "media"; + mountPath = "/media"; + } + ]; }; - spec = { - containers.sonarr = { - image = "lscr.io/linuxserver/sonarr:4.0.6"; - envFrom = [{ configMapRef.name = "sonarr-env"; }]; - ports.web.containerPort = 8989; - imagePullPolicy = "Always"; + volumes = { + config.persistentVolumeClaim.claimName = "sonarr"; + media.persistentVolumeClaim.claimName = "media"; + }; - volumeMounts = [ - { - name = "config"; - mountPath = "/config"; - } - { - name = "media"; - mountPath = "/media"; - } - ]; - }; - - volumes = { - config.persistentVolumeClaim.claimName = "sonarr"; - media.persistentVolumeClaim.claimName = "media"; - }; - - securityContext = { - fsGroup = 1000; - fsGroupChangePolicy = "OnRootMismatch"; - }; + securityContext = { + fsGroup = 1000; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; }; - bazarr = { - metadata.labels = { + bazarr.spec = { + selector.matchLabels = { app = "media"; component = "bazarr"; }; - spec = { - selector.matchLabels = { + strategy = { + type = "RollingUpdate"; + + rollingUpdate = { + maxSurge = 0; + maxUnavailable = 1; + }; + }; + + template = { + metadata.labels = { app = "media"; component = "bazarr"; }; - strategy = { - type = "RollingUpdate"; + spec = { + containers.bazarr = { + image = "lscr.io/linuxserver/bazarr:1.4.3"; + ports.web.containerPort = 6767; + imagePullPolicy = "Always"; - rollingUpdate = { - maxSurge = 0; - maxUnavailable = 1; - }; - }; + env = { + PUID.value = "1000"; + PGID.value = "1000"; + TZ.value = "Europe/Amsterdam"; + }; - template = { - metadata.labels = { - app = "media"; - component = "bazarr"; + volumeMounts = [ + { + name = "config"; + mountPath = "/config"; + } + { + name = "media"; + mountPath = "/media"; + } + ]; }; - spec = { - containers.bazarr = { - image = "lscr.io/linuxserver/bazarr:1.4.3"; - envFrom = [{ configMapRef.name = "bazarr-env"; }]; - ports.web.containerPort = 6767; - imagePullPolicy = "Always"; + volumes = { + config.persistentVolumeClaim.claimName = "bazarr"; + media.persistentVolumeClaim.claimName = "media"; + }; - volumeMounts = [ - { - name = "config"; - mountPath = "/config"; - } - { - name = "media"; - mountPath = "/media"; - } - ]; - }; - - volumes = { - config.persistentVolumeClaim.claimName = "bazarr"; - media.persistentVolumeClaim.claimName = "media"; - }; - - securityContext = { - fsGroup = 1000; - fsGroupChangePolicy = "OnRootMismatch"; - }; + securityContext = { + fsGroup = 1000; + fsGroupChangePolicy = "OnRootMismatch"; }; }; }; @@ -564,9 +507,18 @@ }; }; - persistentVolumeClaims.jellyfin-cache.spec = { - accessModes = [ "ReadWriteOnce" ]; - resources.requests.storage = "20Gi"; + persistentVolumeClaims = { + jellyfin-cache.spec = { + accessModes = [ "ReadWriteOnce" ]; + resources.requests.storage = "20Gi"; + }; + + media.spec = { + accessModes = [ "ReadWriteMany" ]; + storageClassName = ""; + resources.requests.storage = "1Mi"; + volumeName = "media-media"; + }; }; }; @@ -641,5 +593,42 @@ }; }; }; + + longhorn.persistentVolumeClaim = { + jellyfin = { + volumeName = "jellyfin"; + storage = "5Gi"; + }; + + transmission = { + volumeName = "transmission"; + storage = "25Mi"; + }; + + jellyseerr = { + volumeName = "jellyseerr"; + storage = "75Mi"; + }; + + radarr = { + volumeName = "radarr"; + storage = "300Mi"; + }; + + prowlarr = { + volumeName = "prowlarr"; + storage = "150Mi"; + }; + + sonarr = { + volumeName = "sonarr"; + storage = "150Mi"; + }; + + bazarr = { + volumeName = "bazarr"; + storage = "25Mi"; + }; + }; }; } diff --git a/kubenix-modules/volumes.nix b/kubenix-modules/volumes.nix index 0890cd7..8a1b88c 100644 --- a/kubenix-modules/volumes.nix +++ b/kubenix-modules/volumes.nix @@ -12,27 +12,30 @@ # volumes.freshrss.persistentVolumeClaim.claimName = "freshrss"; # }; - kubernetes.resources.persistentVolumes.music-syncthing.spec = { - capacity.storage = "1Gi"; - accessModes = [ "ReadWriteMany" ]; + kubernetes.resources.persistentVolumes = { + music-syncthing.spec = { + capacity.storage = "1Gi"; + accessModes = [ "ReadWriteMany" ]; - nfs = { - server = "lewis.dmz"; - path = "/mnt/longhorn/persistent/media/music"; + nfs = { + server = "lewis.dmz"; + path = "/mnt/longhorn/persistent/media/music"; + }; + }; + + media-media.spec = { + capacity.storage = "1Gi"; + accessModes = [ "ReadWriteMany" ]; + + nfs = { + server = "lewis.dmz"; + path = "/mnt/longhorn/persistent/media"; + }; }; }; lab = { - longhornVolumes = { - minecraft.storage = "1Gi"; - jellyfin.storage = "5Gi"; - transmission.storage = "25Mi"; - jellyseerr.storage = "75Mi"; - radarr.storage = "300Mi"; - prowlarr.storage = "150Mi"; - sonarr.storage = "150Mi"; - bazarr.storage = "25Mi"; - }; + longhornVolumes.minecraft.storage = "1Gi"; longhorn.persistentVolume = { freshrss.storage = "1Gi"; @@ -55,11 +58,13 @@ immich-db.storage = "5Gi"; attic.storage = "15Gi"; attic-db.storage = "150Mi"; - }; - - nfsVolumes = { - media.path = "media"; - # music.path = "media/music"; + jellyfin.storage = "5Gi"; + transmission.storage = "25Mi"; + jellyseerr.storage = "75Mi"; + radarr.storage = "300Mi"; + prowlarr.storage = "150Mi"; + sonarr.storage = "150Mi"; + bazarr.storage = "25Mi"; }; }; }