Hybrid cloud cluster monorepo with Ansible, K8s, NixOS, and Terraform. cute.haus
ansible terraform nix k8s
0

Configure Feed

Select the types of activity you want to include in your feed.

move jellyfin to k8s

Aly Raffauf (Jun 24, 2026, 10:12 PM EDT) de6e4451 42ef0964

+226 -57
-1
k8s/charts/aly-codes/Chart.yaml
··· 3 3 description: Static site for aly.codes 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0"
-1
k8s/charts/audiobookshelf/Chart.yaml
··· 3 3 description: Audiobookshelf with an rclone B2 sidecar for media 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "2.32.0"
-1
k8s/charts/bluesky-pds/Chart.yaml
··· 3 3 description: Bluesky PDS — atproto Personal Data Server 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "latest"
-1
k8s/charts/cluster-tls/Chart.yaml
··· 3 3 description: TLS Secrets for cluster ingresses (cert + key per domain) 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0"
-1
k8s/charts/collabora/Chart.yaml
··· 3 3 description: Collabora Online (CODE) document server for Nextcloud Office 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "26.04"
-1
k8s/charts/error-pages/Chart.yaml
··· 3 3 description: Custom error pages served by Traefik on 5xx responses 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "4"
-1
k8s/charts/external-routes/Chart.yaml
··· 3 3 description: Ingress routes for non-cluster services (homelab hosts via tailscale) 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0"
-5
k8s/charts/external-routes/values.yaml
··· 3 3 # Each route gets a Service + Endpoints + Ingress. 4 4 # Service name == route name. Tls secret must exist in the same namespace as the Ingress (default). 5 5 routes: 6 - - name: jellyfin 7 - host: jellyfin.cute.haus 8 - target: { ip: 100.81.61.31, port: 8096 } # jubilife 9 - tls: { secretName: cute-haus-tls } 10 - 11 6 - name: plex 12 7 host: plex.cute.haus 13 8 target: { ip: 100.81.61.31, port: 32400 } # jubilife
-1
k8s/charts/forgejo/Chart.yaml
··· 3 3 description: Forgejo (gitea fork) — git hosting 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "15"
-1
k8s/charts/forward-auth/Chart.yaml
··· 3 3 description: traefik-forward-auth (thomseddon) for SSO-gating apps, one TFA per app 4 4 type: application 5 5 version: 0.2.0 6 - appVersion: "2"
-1
k8s/charts/gotenberg/Chart.yaml
··· 3 3 description: Gotenberg document-to-PDF conversion service 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "8"
-1
k8s/charts/immich/Chart.yaml
··· 3 3 description: Immich photo library 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "2.7.5"
+5
k8s/charts/jellyfin/Chart.yaml
··· 1 + apiVersion: v2 2 + name: jellyfin 3 + description: Jellyfin media server 4 + type: application 5 + version: 0.1.0
+89
k8s/charts/jellyfin/templates/deployment.yaml
··· 1 + apiVersion: apps/v1 2 + kind: Deployment 3 + metadata: 4 + name: {{ .Chart.Name }} 5 + labels: 6 + app: {{ .Chart.Name }} 7 + spec: 8 + replicas: 1 9 + strategy: 10 + type: Recreate 11 + selector: 12 + matchLabels: 13 + app: {{ .Chart.Name }} 14 + template: 15 + metadata: 16 + labels: 17 + app: {{ .Chart.Name }} 18 + spec: 19 + terminationGracePeriodSeconds: 30 20 + enableServiceLinks: false 21 + nodeSelector: 22 + kubernetes.io/hostname: jubilife 23 + tolerations: 24 + - key: node.kubernetes.io/not-ready 25 + operator: Exists 26 + effect: NoExecute 27 + tolerationSeconds: 60 28 + - key: node.kubernetes.io/unreachable 29 + operator: Exists 30 + effect: NoExecute 31 + tolerationSeconds: 60 32 + containers: 33 + - name: {{ .Chart.Name }} 34 + image: docker.io/jellyfin/jellyfin:10.11.11@sha256:aefb67e6a7ff1debdd154a78a7bbb780fd0c873d8639210a7f6a2016ad2b35db 35 + imagePullPolicy: IfNotPresent 36 + env: 37 + - name: TZ 38 + value: "America/New_York" 39 + ports: 40 + - name: http 41 + containerPort: 8096 42 + resources: 43 + requests: 44 + cpu: 200m 45 + memory: 512Mi 46 + gpu.intel.com/i915: "1" 47 + limits: 48 + cpu: "4" 49 + memory: 4Gi 50 + gpu.intel.com/i915: "1" 51 + volumeMounts: 52 + - name: config 53 + mountPath: /config 54 + - name: media 55 + mountPath: /mnt/Media 56 + readOnly: true 57 + - name: backblaze 58 + mountPath: /mnt/Backblaze 59 + readOnly: true 60 + mountPropagation: HostToContainer 61 + startupProbe: 62 + httpGet: 63 + path: /health 64 + port: http 65 + periodSeconds: 10 66 + failureThreshold: 30 67 + livenessProbe: 68 + httpGet: 69 + path: /health 70 + port: http 71 + periodSeconds: 30 72 + readinessProbe: 73 + httpGet: 74 + path: /health 75 + port: http 76 + periodSeconds: 10 77 + failureThreshold: 3 78 + volumes: 79 + - name: config 80 + persistentVolumeClaim: 81 + claimName: {{ .Chart.Name }}-config 82 + - name: media 83 + persistentVolumeClaim: 84 + claimName: {{ .Chart.Name }}-media 85 + readOnly: true 86 + - name: backblaze 87 + hostPath: 88 + path: /mnt/Backblaze 89 + type: Directory
+23
k8s/charts/jellyfin/templates/ingress.yaml
··· 1 + apiVersion: networking.k8s.io/v1 2 + kind: Ingress 3 + metadata: 4 + name: {{ .Chart.Name }} 5 + labels: 6 + app: {{ .Chart.Name }} 7 + spec: 8 + ingressClassName: traefik 9 + tls: 10 + - hosts: 11 + - "jellyfin.cute.haus" 12 + secretName: cute-haus-tls 13 + rules: 14 + - host: "jellyfin.cute.haus" 15 + http: 16 + paths: 17 + - path: / 18 + pathType: Prefix 19 + backend: 20 + service: 21 + name: {{ .Chart.Name }} 22 + port: 23 + number: 80
+83
k8s/charts/jellyfin/templates/pvc.yaml
··· 1 + apiVersion: v1 2 + kind: PersistentVolume 3 + metadata: 4 + name: {{ .Chart.Name }}-config 5 + labels: 6 + app: {{ .Chart.Name }} 7 + spec: 8 + capacity: 9 + storage: 10Gi 10 + accessModes: 11 + - ReadWriteOnce 12 + persistentVolumeReclaimPolicy: Retain 13 + storageClassName: "" 14 + nodeAffinity: 15 + required: 16 + nodeSelectorTerms: 17 + - matchExpressions: 18 + - key: kubernetes.io/hostname 19 + operator: In 20 + values: 21 + - jubilife 22 + hostPath: 23 + path: /mnt/Data/jellyfin 24 + type: Directory 25 + --- 26 + apiVersion: v1 27 + kind: PersistentVolumeClaim 28 + metadata: 29 + name: {{ .Chart.Name }}-config 30 + labels: 31 + app: {{ .Chart.Name }} 32 + annotations: 33 + helm.sh/resource-policy: keep 34 + spec: 35 + accessModes: 36 + - ReadWriteOnce 37 + storageClassName: "" 38 + volumeName: {{ .Chart.Name }}-config 39 + resources: 40 + requests: 41 + storage: 10Gi 42 + --- 43 + apiVersion: v1 44 + kind: PersistentVolume 45 + metadata: 46 + name: {{ .Chart.Name }}-media 47 + labels: 48 + app: {{ .Chart.Name }} 49 + spec: 50 + capacity: 51 + storage: 14Ti 52 + accessModes: 53 + - ReadOnlyMany 54 + persistentVolumeReclaimPolicy: Retain 55 + storageClassName: "" 56 + nodeAffinity: 57 + required: 58 + nodeSelectorTerms: 59 + - matchExpressions: 60 + - key: kubernetes.io/hostname 61 + operator: In 62 + values: 63 + - jubilife 64 + hostPath: 65 + path: /mnt/Media 66 + type: Directory 67 + --- 68 + apiVersion: v1 69 + kind: PersistentVolumeClaim 70 + metadata: 71 + name: {{ .Chart.Name }}-media 72 + labels: 73 + app: {{ .Chart.Name }} 74 + annotations: 75 + helm.sh/resource-policy: keep 76 + spec: 77 + accessModes: 78 + - ReadOnlyMany 79 + storageClassName: "" 80 + volumeName: {{ .Chart.Name }}-media 81 + resources: 82 + requests: 83 + storage: 14Ti
+14
k8s/charts/jellyfin/templates/service.yaml
··· 1 + apiVersion: v1 2 + kind: Service 3 + metadata: 4 + name: {{ .Chart.Name }} 5 + labels: 6 + app: {{ .Chart.Name }} 7 + spec: 8 + type: ClusterIP 9 + selector: 10 + app: {{ .Chart.Name }} 11 + ports: 12 + - name: http 13 + port: 80 14 + targetPort: 8096
-1
k8s/charts/longhorn-creds/Chart.yaml
··· 3 3 description: B2 credentials Secret for Longhorn's S3-compatible backup target. 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0" 7 6 dependencies: 8 7 - name: common 9 8 version: 0.1.0
-1
k8s/charts/morsels/Chart.yaml
··· 3 3 description: morsels.blue atproto pastebin 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0"
-1
k8s/charts/navidrome/Chart.yaml
··· 3 3 description: Navidrome music server 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "0.62.0"
-1
k8s/charts/nextcloud/Chart.yaml
··· 3 3 description: Nextcloud 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "33"
-1
k8s/charts/ombi/Chart.yaml
··· 3 3 description: Ombi media request management 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "latest"
-1
k8s/charts/paperless/Chart.yaml
··· 3 3 description: paperless-ngx document management 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "2"
-1
k8s/charts/pg-shared/Chart.yaml
··· 3 3 description: Shared CNPG postgres cluster (operator-managed) 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "17"
-1
k8s/charts/pocket-id/Chart.yaml
··· 3 3 description: Pocket ID passkey-only OIDC provider 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "v1"
-1
k8s/charts/switchyard/Chart.yaml
··· 3 3 description: Switchyard marketing site (switchyard.aly.codes) 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0"
-1
k8s/charts/tika/Chart.yaml
··· 3 3 description: Apache Tika document parsing and OCR service 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "3.3.1"
-1
k8s/charts/tranquil-pds/Chart.yaml
··· 3 3 description: Tranquil PDS (atproto Personal Data Server, postgres-backed) 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "latest"
-1
k8s/charts/uptime-kuma/Chart.yaml
··· 3 3 description: Uptime monitoring + status pages 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "2"
-1
k8s/charts/valkey/Chart.yaml
··· 3 3 description: Shared Valkey instance used as cache/queue/session/broker backend by other apps 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "9"
-1
k8s/charts/vaultwarden/Chart.yaml
··· 3 3 description: Vaultwarden (Bitwarden-compatible) password vault 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "latest"
-1
k8s/charts/watsup/Chart.yaml
··· 3 3 description: Watsup homelab dashboard 4 4 type: application 5 5 version: 0.1.0 6 - appVersion: "1.0.0"
+8
k8s/helmfile.yaml
··· 170 170 version: 0.36.0 171 171 needs: 172 172 - intel-device-plugin/intel-device-plugins-operator 173 + values: 174 + - sharedDevNum: 2 173 175 174 176 # ─── Shared platform services ─────────────────────────────────────────── 175 177 ··· 279 281 - default/valkey 280 282 values: 281 283 - values/secrets/immich.yaml 284 + 285 + - name: jellyfin 286 + namespace: default 287 + chart: ./charts/jellyfin 288 + needs: 289 + - default/cluster-tls 282 290 283 291 - name: navidrome 284 292 namespace: default
+3 -25
nix/hosts/jubilife.nix
··· 166 166 "d /mnt/Data/arm/home 0755 1000 1000 - -" 167 167 "d /mnt/Data/arm/config 0755 1000 1000 - -" 168 168 "d /mnt/Data/arm 0755 1000 1000 - -" 169 + "d /mnt/Data/jellyfin 0700 1000 1000 - -" 169 170 ]; 170 171 171 172 virtualisation.oci-containers.containers = { ··· 273 274 274 275 # services 275 276 ( 276 - { 277 - config, 278 - pkgs, 279 - ... 280 - }: let 281 - stop = service: "${pkgs.systemd}/bin/systemctl stop ${service}"; 282 - start = service: "${pkgs.systemd}/bin/systemctl start ${service}"; 283 - in { 277 + {config, ...}: { 284 278 myBackups.jobs = { 285 279 immich = { 286 280 paths = [ ··· 292 286 }; 293 287 294 288 jellyfin = { 295 - backupCleanupCommand = start "jellyfin"; 296 - backupPrepareCommand = stop "jellyfin"; 297 - paths = [config.services.jellyfin.dataDir]; 289 + paths = ["${dataDirectory}/jellyfin"]; 298 290 }; 299 291 }; 300 292 ··· 323 315 reverse_proxy jubilife:6767 324 316 ''; 325 317 326 - "jellyfin.${tnet}".extraConfig = '' 327 - bind tailscale/jellyfin 328 - encode zstd gzip 329 - reverse_proxy jubilife:8096 { 330 - flush_interval -1 331 - } 332 - ''; 333 - 334 318 "lidarr.${tnet}".extraConfig = '' 335 319 bind tailscale/lidarr 336 320 encode zstd gzip ··· 372 356 encode zstd gzip 373 357 reverse_proxy jubilife:8181 374 358 ''; 375 - }; 376 - 377 - jellyfin = { 378 - enable = true; 379 - openFirewall = true; 380 - dataDir = "${dataDirectory}/jellyfin"; 381 359 }; 382 360 383 361 nfs.server = {
+1 -1
nix/nixos/services/caddy.nix
··· 25 25 26 26 package = pkgs.caddy.withPlugins { 27 27 plugins = ["github.com/tailscale/caddy-tailscale@v0.0.0-20260106222316-bb080c4414ac"]; 28 - hash = "sha256-XBdYjtuPVu/beIgFgFcVp6ln4r9kq0B6+4xJ8+WWYn0="; 28 + hash = "sha256-vC/nyCKMD2jKgbGVA5NIJP6dGXiP9z0yEA8WINgFcVc="; 29 29 }; 30 30 }; 31 31