From 0d87bcb7702af6c660ef9dc190895a130e30d4e2 Mon Sep 17 00:00:00 2001 From: Brandon Schneider Date: Sun, 31 May 2026 11:01:39 -0500 Subject: [PATCH] feat(infra): media stack, Vaultwarden, Cloudflare tunnel, OIDC providers, Caddy TLS - Media stack deployed: qBittorrent, Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, Navidrome, Audiobookshelf, Jellyfin, Homarr, Kavita, MeTube, SuggestArr, BoxArr - Romm, ebook2audiobook (GPU CUDA), TrailBase, FlareSolverr deployed - Vaultwarden + Vaultwarden-API deployed - Caddy reverse proxy on racknerd with Let's Encrypt TLS at *.researchstack.info - Authentik 7 OIDC providers + 12 proxy providers for SSO - NVIDIA GPU support enabled on k3s (device plugin + containerd runtime) - Cloudflare tunnel created (DNS on Porkbun) Build: 3313 jobs, 0 errors (lake build Compiler) --- 4-Infrastructure/kube/manifests/Caddyfile | 79 +++++++ .../kube/manifests/arr-stack.yaml | 142 ++++++++++++ .../manifests/audiobookshelf-jellyfin.yaml | 154 +++++++++++++ .../kube/manifests/authentik-values.yaml | 40 ++++ .../kube/manifests/bazarr-navidrome.yaml | 139 ++++++++++++ .../kube/manifests/ebook2audiobook.yaml | 126 +++++++++++ .../kube/manifests/homarr-kavita.yaml | 128 +++++++++++ 4-Infrastructure/kube/manifests/media-ns.yaml | 42 ++++ .../manifests/metube-suggestarr-boxarr.yaml | 159 +++++++++++++ 4-Infrastructure/kube/manifests/prowlarr.yaml | 62 +++++ .../kube/manifests/qbittorrent.yaml | 76 +++++++ 4-Infrastructure/kube/manifests/romm.yaml | 214 ++++++++++++++++++ 4-Infrastructure/kube/manifests/sonarr.yaml | 71 ++++++ .../manifests/trailbase-flaresolverr.yaml | 110 +++++++++ .../kube/manifests/uptime-kuma.yaml | 65 ++++++ .../kube/manifests/vaultwarden.yaml | 130 +++++++++++ 16 files changed, 1737 insertions(+) create mode 100644 4-Infrastructure/kube/manifests/Caddyfile create mode 100644 4-Infrastructure/kube/manifests/arr-stack.yaml create mode 100644 4-Infrastructure/kube/manifests/audiobookshelf-jellyfin.yaml create mode 100644 4-Infrastructure/kube/manifests/authentik-values.yaml create mode 100644 4-Infrastructure/kube/manifests/bazarr-navidrome.yaml create mode 100644 4-Infrastructure/kube/manifests/ebook2audiobook.yaml create mode 100644 4-Infrastructure/kube/manifests/homarr-kavita.yaml create mode 100644 4-Infrastructure/kube/manifests/media-ns.yaml create mode 100644 4-Infrastructure/kube/manifests/metube-suggestarr-boxarr.yaml create mode 100644 4-Infrastructure/kube/manifests/prowlarr.yaml create mode 100644 4-Infrastructure/kube/manifests/qbittorrent.yaml create mode 100644 4-Infrastructure/kube/manifests/romm.yaml create mode 100644 4-Infrastructure/kube/manifests/sonarr.yaml create mode 100644 4-Infrastructure/kube/manifests/trailbase-flaresolverr.yaml create mode 100644 4-Infrastructure/kube/manifests/uptime-kuma.yaml create mode 100644 4-Infrastructure/kube/manifests/vaultwarden.yaml diff --git a/4-Infrastructure/kube/manifests/Caddyfile b/4-Infrastructure/kube/manifests/Caddyfile new file mode 100644 index 00000000..b80d31ea --- /dev/null +++ b/4-Infrastructure/kube/manifests/Caddyfile @@ -0,0 +1,79 @@ +{ + admin off + email bigdataiscoming@protonmail.com +} + +researchstack.info { + redir https://www.researchstack.info{uri} +} + +auth.researchstack.info { + reverse_proxy http://100.88.57.96:30080 +} + +flaresolverr.researchstack.info { + reverse_proxy http://100.88.57.96:30105 +} + +www.researchstack.info { + forward_auth http://100.88.57.96:30080 { + uri /outpost.goauthentik.io/auth/caddy + copy_headers X-Authentik-User X-Authentik-Username X-Authentik-Groups X-Authentik-Email + } + reverse_proxy http://100.88.57.96:30093 +} + +uptime.researchstack.info { + forward_auth http://100.88.57.96:30080 { + uri /outpost.goauthentik.io/auth/caddy + copy_headers X-Authentik-User X-Authentik-Username + } + reverse_proxy http://100.88.57.96:30081 +} + +media.researchstack.info { + forward_auth http://100.88.57.96:30080 { + uri /outpost.goauthentik.io/auth/caddy + } + reverse_proxy http://100.88.57.96:30091 +} + +music.researchstack.info { + reverse_proxy http://100.88.57.96:30089 +} + +books.researchstack.info { + reverse_proxy http://100.88.57.96:30094 +} + +audiobooks.researchstack.info { + reverse_proxy http://100.88.57.96:30090 +} + +movies.researchstack.info { + reverse_proxy http://100.88.57.96:30086 +} + +tv.researchstack.info { + reverse_proxy http://100.88.57.96:30085 +} + +downloads.researchstack.info { + reverse_proxy http://100.88.57.96:30082 +} + +vault.researchstack.info { + reverse_proxy http://100.88.57.96:30106 +} + +vaultapi.researchstack.info { + reverse_proxy http://100.88.57.96:30107 +} + +trailbase.researchstack.info { + reverse_proxy http://100.88.57.96:30104 +} + +ebook.researchstack.info { + reverse_proxy http://100.88.57.96:30103 +} diff --git a/4-Infrastructure/kube/manifests/arr-stack.yaml b/4-Infrastructure/kube/manifests/arr-stack.yaml new file mode 100644 index 00000000..1a68ea84 --- /dev/null +++ b/4-Infrastructure/kube/manifests/arr-stack.yaml @@ -0,0 +1,142 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: radarr-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: radarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: radarr + template: + metadata: + labels: + app: radarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: radarr + image: lscr.io/linuxserver/radarr:latest + ports: + - containerPort: 7878 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/downloads + subPath: downloads + - name: media + mountPath: /media/movies + subPath: movies + volumes: + - name: config + persistentVolumeClaim: + claimName: radarr-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: radarr + namespace: media +spec: + type: NodePort + ports: + - port: 7878 + targetPort: 7878 + nodePort: 30086 + selector: + app: radarr +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: lidarr-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lidarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: lidarr + template: + metadata: + labels: + app: lidarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: lidarr + image: lscr.io/linuxserver/lidarr:latest + ports: + - containerPort: 8686 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/downloads + subPath: downloads + - name: media + mountPath: /media/music + subPath: music + volumes: + - name: config + persistentVolumeClaim: + claimName: lidarr-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: lidarr + namespace: media +spec: + type: NodePort + ports: + - port: 8686 + targetPort: 8686 + nodePort: 30087 + selector: + app: lidarr diff --git a/4-Infrastructure/kube/manifests/audiobookshelf-jellyfin.yaml b/4-Infrastructure/kube/manifests/audiobookshelf-jellyfin.yaml new file mode 100644 index 00000000..f98ee580 --- /dev/null +++ b/4-Infrastructure/kube/manifests/audiobookshelf-jellyfin.yaml @@ -0,0 +1,154 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: audiobookshelf-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: audiobookshelf + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: audiobookshelf + template: + metadata: + labels: + app: audiobookshelf + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: audiobookshelf + image: ghcr.io/advplyr/audiobookshelf:latest + ports: + - containerPort: 13378 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /audiobooks + subPath: audiobooks + - name: media + mountPath: /podcasts + subPath: podcasts + volumes: + - name: config + persistentVolumeClaim: + claimName: audiobookshelf-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: audiobookshelf + namespace: media +spec: + type: NodePort + ports: + - port: 13378 + targetPort: 13378 + nodePort: 30090 + selector: + app: audiobookshelf +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: jellyfin-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jellyfin + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: jellyfin + template: + metadata: + labels: + app: jellyfin + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: jellyfin + image: lscr.io/linuxserver/jellyfin:latest + ports: + - containerPort: 8096 + - containerPort: 8920 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/movies + subPath: movies + - name: media + mountPath: /media/tv + subPath: tv + - name: media + mountPath: /media/music + subPath: music + - name: media + mountPath: /media/audiobooks + subPath: audiobooks + volumes: + - name: config + persistentVolumeClaim: + claimName: jellyfin-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: jellyfin + namespace: media +spec: + type: NodePort + ports: + - name: web + port: 8096 + targetPort: 8096 + nodePort: 30091 + - name: https + port: 8920 + targetPort: 8920 + nodePort: 30092 + selector: + app: jellyfin diff --git a/4-Infrastructure/kube/manifests/authentik-values.yaml b/4-Infrastructure/kube/manifests/authentik-values.yaml new file mode 100644 index 00000000..4fa53d6c --- /dev/null +++ b/4-Infrastructure/kube/manifests/authentik-values.yaml @@ -0,0 +1,40 @@ +global: + nodeSelector: + kubernetes.io/hostname: qfox-1 + +authentik: + log_level: info + secret_key: "" # Will be auto-generated + bootstrap_password: "authentik" + bootstrap_token: "authentik-bootstrap-token" + email: + host: "" + port: 587 + username: "" + password: "" + +postgresql: + enabled: true + persistence: + enabled: true + size: 10Gi + primary: + nodeSelector: + kubernetes.io/hostname: qfox-1 + +redis: + enabled: true + master: + nodeSelector: + kubernetes.io/hostname: qfox-1 + +server: + service: + type: NodePort + nodePort: 30095 + ingress: + enabled: false + +worker: + nodeSelector: + kubernetes.io/hostname: qfox-1 diff --git a/4-Infrastructure/kube/manifests/bazarr-navidrome.yaml b/4-Infrastructure/kube/manifests/bazarr-navidrome.yaml new file mode 100644 index 00000000..5c2183aa --- /dev/null +++ b/4-Infrastructure/kube/manifests/bazarr-navidrome.yaml @@ -0,0 +1,139 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: bazarr-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bazarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: bazarr + template: + metadata: + labels: + app: bazarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: bazarr + image: lscr.io/linuxserver/bazarr:latest + ports: + - containerPort: 6767 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/movies + subPath: movies + - name: media + mountPath: /media/tv + subPath: tv + volumes: + - name: config + persistentVolumeClaim: + claimName: bazarr-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: bazarr + namespace: media +spec: + type: NodePort + ports: + - port: 6767 + targetPort: 6767 + nodePort: 30088 + selector: + app: bazarr +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: navidrome-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: navidrome + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: navidrome + template: + metadata: + labels: + app: navidrome + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: navidrome + image: deluan/navidrome:latest + ports: + - containerPort: 4533 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /data + - name: media + mountPath: /music + subPath: music + volumes: + - name: config + persistentVolumeClaim: + claimName: navidrome-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: navidrome + namespace: media +spec: + type: NodePort + ports: + - port: 4533 + targetPort: 4533 + nodePort: 30089 + selector: + app: navidrome diff --git a/4-Infrastructure/kube/manifests/ebook2audiobook.yaml b/4-Infrastructure/kube/manifests/ebook2audiobook.yaml new file mode 100644 index 00000000..a8a0caf7 --- /dev/null +++ b/4-Infrastructure/kube/manifests/ebook2audiobook.yaml @@ -0,0 +1,126 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: e2a-ebooks + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 50Gi + storageClassName: local-path +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: e2a-audiobooks + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + storageClassName: local-path +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: e2a-models + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + storageClassName: local-path +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: e2a-voices + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ebook2audiobook + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: ebook2audiobook + template: + metadata: + labels: + app: ebook2audiobook + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: e2a + image: athomasson2/ebook2audiobook:cu128 + ports: + - containerPort: 7860 + env: + - name: GRADIO_SERVER_NAME + value: "0.0.0.0" + resources: + limits: + nvidia.com/gpu: 1 + memory: "16Gi" + cpu: "4" + requests: + memory: "4Gi" + cpu: "1" + volumeMounts: + - name: ebooks + mountPath: /app/ebooks + - name: audiobooks + mountPath: /app/audiobooks + - name: models + mountPath: /app/models + - name: voices + mountPath: /app/voices + - name: tmp + mountPath: /app/tmp + volumes: + - name: ebooks + persistentVolumeClaim: + claimName: e2a-ebooks + - name: audiobooks + persistentVolumeClaim: + claimName: e2a-audiobooks + - name: models + persistentVolumeClaim: + claimName: e2a-models + - name: voices + persistentVolumeClaim: + claimName: e2a-voices + - name: tmp + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: ebook2audiobook + namespace: media +spec: + type: NodePort + ports: + - port: 7860 + targetPort: 7860 + nodePort: 30103 + selector: + app: ebook2audiobook diff --git a/4-Infrastructure/kube/manifests/homarr-kavita.yaml b/4-Infrastructure/kube/manifests/homarr-kavita.yaml new file mode 100644 index 00000000..9e70370b --- /dev/null +++ b/4-Infrastructure/kube/manifests/homarr-kavita.yaml @@ -0,0 +1,128 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: homarr-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: homarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: homarr + template: + metadata: + labels: + app: homarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: homarr + image: ghcr.io/ajnart/homarr:latest + ports: + - containerPort: 7575 + volumeMounts: + - name: config + mountPath: /app/data + volumes: + - name: config + persistentVolumeClaim: + claimName: homarr-config +--- +apiVersion: v1 +kind: Service +metadata: + name: homarr + namespace: media +spec: + type: NodePort + ports: + - port: 7575 + targetPort: 7575 + nodePort: 30093 + selector: + app: homarr +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: kavita-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kavita + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: kavita + template: + metadata: + labels: + app: kavita + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: kavita + image: jvmilazz0/kavita:latest + ports: + - containerPort: 5000 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /kavita/config + - name: media + mountPath: /kavita/books + subPath: books + - name: media + mountPath: /kavita/comics + subPath: comics + volumes: + - name: config + persistentVolumeClaim: + claimName: kavita-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: kavita + namespace: media +spec: + type: NodePort + ports: + - port: 5000 + targetPort: 5000 + nodePort: 30094 + selector: + app: kavita diff --git a/4-Infrastructure/kube/manifests/media-ns.yaml b/4-Infrastructure/kube/manifests/media-ns.yaml new file mode 100644 index 00000000..33f3d73f --- /dev/null +++ b/4-Infrastructure/kube/manifests/media-ns.yaml @@ -0,0 +1,42 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: media +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: media-store +spec: + capacity: + storage: 1Ti + volumeMode: Filesystem + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: manual + hostPath: + path: /var/lib/media + type: DirectoryOrCreate + nodeAffinity: + required: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - qfox-1 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: media-store + namespace: media +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 1Ti + storageClassName: manual + volumeMode: Filesystem diff --git a/4-Infrastructure/kube/manifests/metube-suggestarr-boxarr.yaml b/4-Infrastructure/kube/manifests/metube-suggestarr-boxarr.yaml new file mode 100644 index 00000000..40317c84 --- /dev/null +++ b/4-Infrastructure/kube/manifests/metube-suggestarr-boxarr.yaml @@ -0,0 +1,159 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: metube-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: metube + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: metube + template: + metadata: + labels: + app: metube + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: metube + image: ghcr.io/alexta69/metube:latest + ports: + - containerPort: 8081 + volumeMounts: + - name: media + mountPath: /downloads + subPath: downloads + volumes: + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: metube + namespace: media +spec: + type: NodePort + ports: + - port: 8081 + targetPort: 8081 + nodePort: 30096 + selector: + app: metube +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: suggestarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: suggestarr + template: + metadata: + labels: + app: suggestarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: suggestarr + image: ciuse99/suggestarr:latest + ports: + - containerPort: 5000 + env: + - name: PORT + value: "5000" + - name: SUGGESTARR_PORT + value: "5000" + env: + - name: SONARR_URL + value: "http://sonarr:8989" + - name: RADARR_URL + value: "http://radarr:7878" + - name: LIDARR_URL + value: "http://lidarr:8686" + volumeMounts: + - name: config + mountPath: /app/config + volumes: + - name: config + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: suggestarr-app + namespace: media +spec: + type: NodePort + ports: + - port: 5000 + targetPort: 5000 + nodePort: 30097 + selector: + app: suggestarr +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: boxarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: boxarr + template: + metadata: + labels: + app: boxarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: boxarr + image: ghcr.io/iongpt/boxarr:latest + ports: + - containerPort: 5000 + env: + - name: BOXARR_PORT + value: "5000" + volumeMounts: + - name: config + mountPath: /app/data + volumes: + - name: config + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: boxarr + namespace: media +spec: + type: NodePort + ports: + - port: 5000 + targetPort: 5000 + nodePort: 30098 + selector: + app: boxarr diff --git a/4-Infrastructure/kube/manifests/prowlarr.yaml b/4-Infrastructure/kube/manifests/prowlarr.yaml new file mode 100644 index 00000000..d2b2d3bf --- /dev/null +++ b/4-Infrastructure/kube/manifests/prowlarr.yaml @@ -0,0 +1,62 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: prowlarr-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: prowlarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: prowlarr + template: + metadata: + labels: + app: prowlarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: prowlarr + image: lscr.io/linuxserver/prowlarr:latest + ports: + - containerPort: 9696 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + volumes: + - name: config + persistentVolumeClaim: + claimName: prowlarr-config +--- +apiVersion: v1 +kind: Service +metadata: + name: prowlarr + namespace: media +spec: + type: NodePort + ports: + - port: 9696 + targetPort: 9696 + nodePort: 30084 + selector: + app: prowlarr diff --git a/4-Infrastructure/kube/manifests/qbittorrent.yaml b/4-Infrastructure/kube/manifests/qbittorrent.yaml new file mode 100644 index 00000000..a66d21a1 --- /dev/null +++ b/4-Infrastructure/kube/manifests/qbittorrent.yaml @@ -0,0 +1,76 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: qbittorrent-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: qbittorrent + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: qbittorrent + template: + metadata: + labels: + app: qbittorrent + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: qbittorrent + image: lscr.io/linuxserver/qbittorrent:latest + ports: + - containerPort: 8080 + - containerPort: 6881 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + - name: UMASK + value: "002" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/downloads + subPath: downloads + volumes: + - name: config + persistentVolumeClaim: + claimName: qbittorrent-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: qbittorrent + namespace: media +spec: + type: NodePort + ports: + - name: webui + port: 8080 + targetPort: 8080 + nodePort: 30082 + - name: bittorrent + port: 6881 + targetPort: 6881 + nodePort: 30083 + selector: + app: qbittorrent diff --git a/4-Infrastructure/kube/manifests/romm.yaml b/4-Infrastructure/kube/manifests/romm.yaml new file mode 100644 index 00000000..4dc956ee --- /dev/null +++ b/4-Infrastructure/kube/manifests/romm.yaml @@ -0,0 +1,214 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: romm-mysql + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: local-path +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: romm-resources + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: local-path +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: romm-redis + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: romm-db + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: romm-db + template: + metadata: + labels: + app: romm-db + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: mariadb + image: mariadb:latest + ports: + - containerPort: 3306 + env: + - name: MARIADB_ROOT_PASSWORD + value: "romm-root-pw" + - name: MARIADB_DATABASE + value: "romm" + - name: MARIADB_USER + value: "romm" + - name: MARIADB_PASSWORD + value: "romm-db-pw" + volumeMounts: + - name: data + mountPath: /var/lib/mysql + livenessProbe: + exec: + command: [healthcheck.sh, --connect, --innodb_initialized] + initialDelaySeconds: 30 + periodSeconds: 10 + volumes: + - name: data + persistentVolumeClaim: + claimName: romm-mysql +--- +apiVersion: v1 +kind: Service +metadata: + name: romm-db + namespace: media +spec: + ports: + - port: 3306 + targetPort: 3306 + selector: + app: romm-db +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: romm-redis + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: romm-redis + template: + metadata: + labels: + app: romm-redis + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: redis + image: redis:7-alpine + ports: + - containerPort: 6379 + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + persistentVolumeClaim: + claimName: romm-redis +--- +apiVersion: v1 +kind: Service +metadata: + name: romm-redis + namespace: media +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: romm-redis +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: romm + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: romm + template: + metadata: + labels: + app: romm + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: romm + image: rommapp/romm:latest + ports: + - containerPort: 8080 + env: + - name: DB_HOST + value: "romm-db" + - name: DB_NAME + value: "romm" + - name: DB_USER + value: "romm" + - name: DB_PASSWD + value: "romm-db-pw" + - name: ROMM_AUTH_SECRET_KEY + value: "change-me-romm-secret-key-32bytes-hex00000" + - name: REDIS_HOST + value: "romm-redis" + - name: REDIS_PORT + value: "6379" + - name: ROMM_PORT + value: "8080" + - name: HASHEOUS_API_ENABLED + value: "true" + volumeMounts: + - name: library + mountPath: /romm/library + subPath: games + - name: assets + mountPath: /romm/assets + - name: config + mountPath: /romm/config + - name: resources + mountPath: /romm/resources + volumes: + - name: library + persistentVolumeClaim: + claimName: media-store + - name: assets + emptyDir: {} + - name: config + emptyDir: {} + - name: resources + persistentVolumeClaim: + claimName: romm-resources +--- +apiVersion: v1 +kind: Service +metadata: + name: romm + namespace: media +spec: + type: NodePort + ports: + - port: 8080 + targetPort: 8080 + nodePort: 30099 + selector: + app: romm diff --git a/4-Infrastructure/kube/manifests/sonarr.yaml b/4-Infrastructure/kube/manifests/sonarr.yaml new file mode 100644 index 00000000..33d80193 --- /dev/null +++ b/4-Infrastructure/kube/manifests/sonarr.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: sonarr-config + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sonarr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: sonarr + template: + metadata: + labels: + app: sonarr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: sonarr + image: lscr.io/linuxserver/sonarr:latest + ports: + - containerPort: 8989 + env: + - name: PUID + value: "1000" + - name: PGID + value: "100" + volumeMounts: + - name: config + mountPath: /config + - name: media + mountPath: /media/downloads + subPath: downloads + - name: media + mountPath: /media/tv + subPath: tv + volumes: + - name: config + persistentVolumeClaim: + claimName: sonarr-config + - name: media + persistentVolumeClaim: + claimName: media-store +--- +apiVersion: v1 +kind: Service +metadata: + name: sonarr + namespace: media +spec: + type: NodePort + ports: + - port: 8989 + targetPort: 8989 + nodePort: 30085 + selector: + app: sonarr diff --git a/4-Infrastructure/kube/manifests/trailbase-flaresolverr.yaml b/4-Infrastructure/kube/manifests/trailbase-flaresolverr.yaml new file mode 100644 index 00000000..b8da1cc6 --- /dev/null +++ b/4-Infrastructure/kube/manifests/trailbase-flaresolverr.yaml @@ -0,0 +1,110 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: trailbase-depot + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: trailbase + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: trailbase + template: + metadata: + labels: + app: trailbase + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: trailbase + image: trailbase/trailbase:latest + command: ["/app/trail", "run"] + ports: + - containerPort: 4000 + env: + - name: ADDRESS + value: "0.0.0.0:4000" + volumeMounts: + - name: depot + mountPath: /app/traildepot + volumes: + - name: depot + persistentVolumeClaim: + claimName: trailbase-depot +--- +apiVersion: v1 +kind: Service +metadata: + name: trailbase + namespace: media +spec: + type: NodePort + ports: + - port: 4000 + targetPort: 4000 + nodePort: 30104 + selector: + app: trailbase +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: flaresolverr + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: flaresolverr + template: + metadata: + labels: + app: flaresolverr + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: flaresolverr + image: ghcr.io/flaresolverr/flaresolverr:latest + ports: + - containerPort: 8191 + env: + - name: LOG_LEVEL + value: "info" + - name: HEADLESS + value: "true" + resources: + requests: + memory: "1Gi" + cpu: "500m" + limits: + memory: "2Gi" + cpu: "2" +--- +apiVersion: v1 +kind: Service +metadata: + name: flaresolverr + namespace: media +spec: + type: NodePort + ports: + - port: 8191 + targetPort: 8191 + nodePort: 30105 + selector: + app: flaresolverr diff --git a/4-Infrastructure/kube/manifests/uptime-kuma.yaml b/4-Infrastructure/kube/manifests/uptime-kuma.yaml new file mode 100644 index 00000000..50be03a2 --- /dev/null +++ b/4-Infrastructure/kube/manifests/uptime-kuma.yaml @@ -0,0 +1,65 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: monitoring +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uptime-kuma-data + namespace: monitoring +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: uptime-kuma + namespace: monitoring +spec: + replicas: 1 + selector: + matchLabels: + app: uptime-kuma + template: + metadata: + labels: + app: uptime-kuma + spec: + containers: + - name: uptime-kuma + image: louislam/uptime-kuma:latest + ports: + - containerPort: 3001 + volumeMounts: + - name: data + mountPath: /app/data + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" + volumes: + - name: data + persistentVolumeClaim: + claimName: uptime-kuma-data +--- +apiVersion: v1 +kind: Service +metadata: + name: uptime-kuma + namespace: monitoring +spec: + type: NodePort + ports: + - port: 3001 + targetPort: 3001 + nodePort: 30081 + selector: + app: uptime-kuma diff --git a/4-Infrastructure/kube/manifests/vaultwarden.yaml b/4-Infrastructure/kube/manifests/vaultwarden.yaml new file mode 100644 index 00000000..ad91a210 --- /dev/null +++ b/4-Infrastructure/kube/manifests/vaultwarden.yaml @@ -0,0 +1,130 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: vaultwarden-data + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vaultwarden + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: vaultwarden + template: + metadata: + labels: + app: vaultwarden + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: vaultwarden + image: vaultwarden/server:latest + ports: + - containerPort: 80 + env: + - name: SIGNUPS_ALLOWED + value: "false" + - name: DOMAIN + value: "https://vault.researchstack.info" + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + persistentVolumeClaim: + claimName: vaultwarden-data +--- +apiVersion: v1 +kind: Service +metadata: + name: vaultwarden + namespace: media +spec: + type: NodePort + ports: + - port: 80 + targetPort: 80 + nodePort: 30106 + selector: + app: vaultwarden +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: vaultwarden-api + namespace: media +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: local-path +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vaultwarden-api + namespace: media +spec: + replicas: 1 + selector: + matchLabels: + app: vaultwarden-api + template: + metadata: + labels: + app: vaultwarden-api + spec: + nodeSelector: + kubernetes.io/hostname: qfox-1 + containers: + - name: api + image: ghcr.io/turbootzz/vaultwarden-api:latest + ports: + - containerPort: 8080 + env: + - name: VAULTWARDEN_URL + value: "http://vaultwarden:80" + - name: VAULTWARDEN_EMAIL + value: "secrets@researchstack.info" + - name: VAULTWARDEN_PASSWORD + value: "changeme-vaultwarden-password" + - name: API_KEY + value: "change-me-vaultwarden-api-key-min-32-chars!!" + - name: ENVIRONMENT + value: "production" + volumeMounts: + - name: data + mountPath: /data + volumes: + - name: data + persistentVolumeClaim: + claimName: vaultwarden-api +--- +apiVersion: v1 +kind: Service +metadata: + name: vaultwarden-api + namespace: media +spec: + type: NodePort + ports: + - port: 8080 + targetPort: 8080 + nodePort: 30107 + selector: + app: vaultwarden-api