arrstack: add sonarr/radarr/prowlarr/nzbget on shared CephFS media
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- pv-media-tv.yaml
|
||||||
|
- pv-media-movies.yaml
|
||||||
|
- pvc-media-tv.yaml
|
||||||
|
- pvc-media-movies.yaml
|
||||||
|
- sonarr
|
||||||
|
- radarr
|
||||||
|
- prowlarr
|
||||||
|
- nzbget
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: arrstack
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nzbget
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
# RWO config PVC + single queue state: never run two pods at once.
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nzbget
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nzbget
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
initContainers:
|
||||||
|
# Seed download layout onto the shared media PVCs (not /config or an
|
||||||
|
# emptyDir) so completed downloads land beside the arr libraries and
|
||||||
|
# imports are same-filesystem hardlink moves. Reuses the image's own
|
||||||
|
# template (inherits correct WebDir/ConfigTemplate) and appends the
|
||||||
|
# path/category overrides once; nzbget honours the last value for a
|
||||||
|
# repeated option, and the grep guard keeps re-runs idempotent so admin
|
||||||
|
# UI edits to the persisted /config/nzbget.conf survive restarts.
|
||||||
|
- name: seed-config
|
||||||
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/linuxserver/nzbget:v26.2
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
if [ ! -f /config/nzbget.conf ]; then
|
||||||
|
cp /app/nzbget/share/nzbget/nzbget.conf /config/nzbget.conf
|
||||||
|
fi
|
||||||
|
if ! grep -q '# arrstack-managed' /config/nzbget.conf; then
|
||||||
|
cat >> /config/nzbget.conf << 'CONF'
|
||||||
|
|
||||||
|
# arrstack-managed download layout (appended once; last value wins).
|
||||||
|
# Downloads land on the shared media PVCs by category so sonarr/radarr
|
||||||
|
# import with atomic hardlink moves (download dir + library share one
|
||||||
|
# filesystem per media type). InterDir is empty: nzbget writes each
|
||||||
|
# download straight into its category DestDir, so BOTH tv and movies
|
||||||
|
# stay on their own PVC with no cross-filesystem intermediate copy.
|
||||||
|
MainDir=/media/tv
|
||||||
|
InterDir=
|
||||||
|
DestDir=/media/tv/downloads
|
||||||
|
NzbDir=/config/nzb
|
||||||
|
QueueDir=/config/queue
|
||||||
|
TempDir=/config/tmp
|
||||||
|
ControlIP=0.0.0.0
|
||||||
|
ControlPort=6789
|
||||||
|
Category1.Name=tv
|
||||||
|
Category1.DestDir=/media/tv/downloads
|
||||||
|
Category2.Name=movies
|
||||||
|
Category2.DestDir=/media/movies/downloads
|
||||||
|
CONF
|
||||||
|
fi
|
||||||
|
mkdir -p /media/tv/series /media/tv/downloads /media/movies/films /media/movies/downloads
|
||||||
|
chown 1000:1000 /config/nzbget.conf \
|
||||||
|
/media/tv /media/tv/series /media/tv/downloads \
|
||||||
|
/media/movies /media/movies/films /media/movies/downloads
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 10m
|
||||||
|
memory: 32Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
- name: media-tv
|
||||||
|
mountPath: /media/tv
|
||||||
|
- name: media-movies
|
||||||
|
mountPath: /media/movies
|
||||||
|
containers:
|
||||||
|
- name: nzbget
|
||||||
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/linuxserver/nzbget:v26.2
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 6789
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: PUID
|
||||||
|
value: "1000"
|
||||||
|
- name: PGID
|
||||||
|
value: "1000"
|
||||||
|
- name: TZ
|
||||||
|
value: Australia/Sydney
|
||||||
|
livenessProbe:
|
||||||
|
# nzbget's root path requires auth (401); a TCP check is the
|
||||||
|
# dependency-free liveness signal for the web/JSON-RPC server.
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
# Headroom for par2 repair + unpack of large downloads.
|
||||||
|
cpu: "2"
|
||||||
|
memory: 2Gi
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
- name: media-tv
|
||||||
|
mountPath: /media/tv
|
||||||
|
- name: media-movies
|
||||||
|
mountPath: /media/movies
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: nzbget-config
|
||||||
|
- name: media-tv
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: media-tv
|
||||||
|
- name: media-movies
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: media-movies
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: Gateway
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
traefik.io/instance: internal
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: vault-issuer
|
||||||
|
cert-manager.io/common-name: nzbget.k8s.syd1.au.unkin.net
|
||||||
|
cert-manager.io/private-key-size: "4096"
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: nzbget.k8s.syd1.au.unkin.net
|
||||||
|
external-dns.alpha.kubernetes.io/target: 198.18.200.4
|
||||||
|
name: nzbget
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
gatewayClassName: traefik-internal
|
||||||
|
listeners:
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: nzbget.k8s.syd1.au.unkin.net
|
||||||
|
name: http
|
||||||
|
port: 80
|
||||||
|
protocol: HTTP
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: nzbget.k8s.syd1.au.unkin.net
|
||||||
|
name: https
|
||||||
|
port: 443
|
||||||
|
protocol: HTTPS
|
||||||
|
tls:
|
||||||
|
certificateRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
name: nzbget-tls
|
||||||
|
mode: Terminate
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: nzbget-http-redirect
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- nzbget.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: nzbget
|
||||||
|
sectionName: http
|
||||||
|
rules:
|
||||||
|
- filters:
|
||||||
|
- type: RequestRedirect
|
||||||
|
requestRedirect:
|
||||||
|
scheme: https
|
||||||
|
statusCode: 301
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: nzbget-route
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- nzbget.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: nzbget
|
||||||
|
sectionName: https
|
||||||
|
rules:
|
||||||
|
- backendRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
name: nzbget
|
||||||
|
port: 6789
|
||||||
|
weight: 1
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- pvc-config.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- gateway.yaml
|
||||||
|
- httproute.yaml
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# NZBGet config + queue/temp state. RWO on cephrbd (block). Retain: this is
|
||||||
|
# state. The download data itself lives on the shared media PVCs, not here.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: nzbget-config
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: cephrbd-fast-retain
|
||||||
|
volumeMode: Filesystem
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nzbget
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 6789
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app: nzbget
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: prowlarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
# RWO config PVC + single stateful SQLite DB: never run two pods at once.
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: prowlarr
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: prowlarr
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
containers:
|
||||||
|
- name: prowlarr
|
||||||
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/linuxserver/prowlarr:2.5.2
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 9696
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: PUID
|
||||||
|
value: "1000"
|
||||||
|
- name: PGID
|
||||||
|
value: "1000"
|
||||||
|
- name: TZ
|
||||||
|
value: Australia/Sydney
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /ping
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /ping
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: 512Mi
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: prowlarr-config
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: Gateway
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
traefik.io/instance: internal
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: vault-issuer
|
||||||
|
cert-manager.io/common-name: prowlarr.k8s.syd1.au.unkin.net
|
||||||
|
cert-manager.io/private-key-size: "4096"
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: prowlarr.k8s.syd1.au.unkin.net
|
||||||
|
external-dns.alpha.kubernetes.io/target: 198.18.200.4
|
||||||
|
name: prowlarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
gatewayClassName: traefik-internal
|
||||||
|
listeners:
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: prowlarr.k8s.syd1.au.unkin.net
|
||||||
|
name: http
|
||||||
|
port: 80
|
||||||
|
protocol: HTTP
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: prowlarr.k8s.syd1.au.unkin.net
|
||||||
|
name: https
|
||||||
|
port: 443
|
||||||
|
protocol: HTTPS
|
||||||
|
tls:
|
||||||
|
certificateRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
name: prowlarr-tls
|
||||||
|
mode: Terminate
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: prowlarr-http-redirect
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- prowlarr.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: prowlarr
|
||||||
|
sectionName: http
|
||||||
|
rules:
|
||||||
|
- filters:
|
||||||
|
- type: RequestRedirect
|
||||||
|
requestRedirect:
|
||||||
|
scheme: https
|
||||||
|
statusCode: 301
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: prowlarr-route
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- prowlarr.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: prowlarr
|
||||||
|
sectionName: https
|
||||||
|
rules:
|
||||||
|
- backendRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
name: prowlarr
|
||||||
|
port: 9696
|
||||||
|
weight: 1
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- pvc-config.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- gateway.yaml
|
||||||
|
- httproute.yaml
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# Prowlarr config + SQLite DB. RWO on cephrbd (block) — the arr apps' SQLite
|
||||||
|
# does not tolerate CephFS locking. Retain: this is state.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: prowlarr-config
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: cephrbd-fast-retain
|
||||||
|
volumeMode: Filesystem
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: prowlarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 9696
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app: prowlarr
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
# Static PV for the shared MOVIES CephFS subvolume. Same rootPath as jellyfin's
|
||||||
|
# movies PV so radarr/nzbget write and jellyfin reads the identical library
|
||||||
|
# tree; each namespace gets its own PV (unique name + volumeHandle) pinned by
|
||||||
|
# claimRef.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: arrstack-media-movies
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 1Ti
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
storageClassName: ""
|
||||||
|
volumeMode: Filesystem
|
||||||
|
claimRef:
|
||||||
|
namespace: arrstack
|
||||||
|
name: media-movies
|
||||||
|
csi:
|
||||||
|
driver: cephfs.csi.ceph.com
|
||||||
|
volumeHandle: arrstack-media-movies-static
|
||||||
|
nodeStageSecretRef:
|
||||||
|
name: csi-cephfs-secret
|
||||||
|
namespace: csi-cephfs
|
||||||
|
volumeAttributes:
|
||||||
|
staticVolume: "true"
|
||||||
|
clusterID: cephfs_csi_ssd_ec_4_1
|
||||||
|
fsName: cephfs
|
||||||
|
rootPath: /volumes/csi_ssd_ec_4_1/media-movies/e95d8ace-c736-465a-acc3-0c3e46dcede9
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# Static PV for the shared TV CephFS subvolume. Same rootPath as jellyfin's TV
|
||||||
|
# PV so sonarr/nzbget write and jellyfin reads the identical library tree; each
|
||||||
|
# namespace gets its own PV (unique name + volumeHandle) pinned by claimRef.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: arrstack-media-tv
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 1Ti
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
storageClassName: ""
|
||||||
|
volumeMode: Filesystem
|
||||||
|
claimRef:
|
||||||
|
namespace: arrstack
|
||||||
|
name: media-tv
|
||||||
|
csi:
|
||||||
|
driver: cephfs.csi.ceph.com
|
||||||
|
volumeHandle: arrstack-media-tv-static
|
||||||
|
nodeStageSecretRef:
|
||||||
|
name: csi-cephfs-secret
|
||||||
|
namespace: csi-cephfs
|
||||||
|
volumeAttributes:
|
||||||
|
staticVolume: "true"
|
||||||
|
clusterID: cephfs_csi_ssd_ec_4_1
|
||||||
|
fsName: cephfs
|
||||||
|
rootPath: /volumes/csi_ssd_ec_4_1/media-tv/4692957d-f5df-4f72-b9c9-56e4ee6d1333
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# Movies library + downloads, shared RWX across radarr and nzbget. Statically
|
||||||
|
# bound to the arrstack-media-movies PV (same CephFS subvolume jellyfin mounts
|
||||||
|
# read-only). storageClassName "" + volumeName disables dynamic provisioning and
|
||||||
|
# binds the pre-created static PV. Downloads and library live on one filesystem
|
||||||
|
# so import is an atomic hardlink move.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: media-movies
|
||||||
|
namespace: arrstack
|
||||||
|
annotations:
|
||||||
|
k8up.io/backup: "false"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Ti
|
||||||
|
storageClassName: ""
|
||||||
|
volumeName: arrstack-media-movies
|
||||||
|
volumeMode: Filesystem
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# TV library + downloads, shared RWX across sonarr and nzbget. Statically bound
|
||||||
|
# to the arrstack-media-tv PV (same CephFS subvolume jellyfin mounts read-only).
|
||||||
|
# storageClassName "" + volumeName disables dynamic provisioning and binds the
|
||||||
|
# pre-created static PV. Downloads and library live on one filesystem so import
|
||||||
|
# is an atomic hardlink move.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: media-tv
|
||||||
|
namespace: arrstack
|
||||||
|
annotations:
|
||||||
|
k8up.io/backup: "false"
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteMany
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Ti
|
||||||
|
storageClassName: ""
|
||||||
|
volumeName: arrstack-media-tv
|
||||||
|
volumeMode: Filesystem
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: radarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
# RWO config PVC + single stateful SQLite DB: never run two pods at once.
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: radarr
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: radarr
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
containers:
|
||||||
|
- name: radarr
|
||||||
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/linuxserver/radarr:6.3.0
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 7878
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: PUID
|
||||||
|
value: "1000"
|
||||||
|
- name: PGID
|
||||||
|
value: "1000"
|
||||||
|
- name: TZ
|
||||||
|
value: Australia/Sydney
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /ping
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /ping
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: 1Gi
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
- name: media-movies
|
||||||
|
mountPath: /media/movies
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: radarr-config
|
||||||
|
- name: media-movies
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: media-movies
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: Gateway
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
traefik.io/instance: internal
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: vault-issuer
|
||||||
|
cert-manager.io/common-name: radarr.k8s.syd1.au.unkin.net
|
||||||
|
cert-manager.io/private-key-size: "4096"
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: radarr.k8s.syd1.au.unkin.net
|
||||||
|
external-dns.alpha.kubernetes.io/target: 198.18.200.4
|
||||||
|
name: radarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
gatewayClassName: traefik-internal
|
||||||
|
listeners:
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: radarr.k8s.syd1.au.unkin.net
|
||||||
|
name: http
|
||||||
|
port: 80
|
||||||
|
protocol: HTTP
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: radarr.k8s.syd1.au.unkin.net
|
||||||
|
name: https
|
||||||
|
port: 443
|
||||||
|
protocol: HTTPS
|
||||||
|
tls:
|
||||||
|
certificateRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
name: radarr-tls
|
||||||
|
mode: Terminate
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: radarr-http-redirect
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- radarr.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: radarr
|
||||||
|
sectionName: http
|
||||||
|
rules:
|
||||||
|
- filters:
|
||||||
|
- type: RequestRedirect
|
||||||
|
requestRedirect:
|
||||||
|
scheme: https
|
||||||
|
statusCode: 301
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: radarr-route
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- radarr.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: radarr
|
||||||
|
sectionName: https
|
||||||
|
rules:
|
||||||
|
- backendRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
name: radarr
|
||||||
|
port: 7878
|
||||||
|
weight: 1
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- pvc-config.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- gateway.yaml
|
||||||
|
- httproute.yaml
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# Radarr config + SQLite DB. RWO on cephrbd (block) — the arr apps' SQLite
|
||||||
|
# does not tolerate CephFS locking. Retain: this is state.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: radarr-config
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: cephrbd-fast-retain
|
||||||
|
volumeMode: Filesystem
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: radarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 7878
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app: radarr
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: sonarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
# RWO config PVC + single stateful SQLite DB: never run two pods at once.
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: sonarr
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: sonarr
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
# LinuxServer images init as root via s6 then step down to PUID/PGID.
|
||||||
|
# fsGroup makes the shared CephFS group-writable for that user;
|
||||||
|
# OnRootMismatch avoids a recursive chown of the whole media tree.
|
||||||
|
fsGroup: 1000
|
||||||
|
fsGroupChangePolicy: OnRootMismatch
|
||||||
|
containers:
|
||||||
|
- name: sonarr
|
||||||
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/linuxserver/sonarr:4.0.19
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8989
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: PUID
|
||||||
|
value: "1000"
|
||||||
|
- name: PGID
|
||||||
|
value: "1000"
|
||||||
|
- name: TZ
|
||||||
|
value: Australia/Sydney
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /ping
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /ping
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
failureThreshold: 3
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: "1"
|
||||||
|
memory: 1Gi
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
- name: media-tv
|
||||||
|
mountPath: /media/tv
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: sonarr-config
|
||||||
|
- name: media-tv
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: media-tv
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: Gateway
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
traefik.io/instance: internal
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: vault-issuer
|
||||||
|
cert-manager.io/common-name: sonarr.k8s.syd1.au.unkin.net
|
||||||
|
cert-manager.io/private-key-size: "4096"
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: sonarr.k8s.syd1.au.unkin.net
|
||||||
|
external-dns.alpha.kubernetes.io/target: 198.18.200.4
|
||||||
|
name: sonarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
gatewayClassName: traefik-internal
|
||||||
|
listeners:
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: sonarr.k8s.syd1.au.unkin.net
|
||||||
|
name: http
|
||||||
|
port: 80
|
||||||
|
protocol: HTTP
|
||||||
|
- allowedRoutes:
|
||||||
|
namespaces:
|
||||||
|
from: Same
|
||||||
|
hostname: sonarr.k8s.syd1.au.unkin.net
|
||||||
|
name: https
|
||||||
|
port: 443
|
||||||
|
protocol: HTTPS
|
||||||
|
tls:
|
||||||
|
certificateRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Secret
|
||||||
|
name: sonarr-tls
|
||||||
|
mode: Terminate
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: sonarr-http-redirect
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- sonarr.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: sonarr
|
||||||
|
sectionName: http
|
||||||
|
rules:
|
||||||
|
- filters:
|
||||||
|
- type: RequestRedirect
|
||||||
|
requestRedirect:
|
||||||
|
scheme: https
|
||||||
|
statusCode: 301
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
---
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: sonarr-route
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
hostnames:
|
||||||
|
- sonarr.k8s.syd1.au.unkin.net
|
||||||
|
parentRefs:
|
||||||
|
- group: gateway.networking.k8s.io
|
||||||
|
kind: Gateway
|
||||||
|
name: sonarr
|
||||||
|
sectionName: https
|
||||||
|
rules:
|
||||||
|
- backendRefs:
|
||||||
|
- group: ""
|
||||||
|
kind: Service
|
||||||
|
name: sonarr
|
||||||
|
port: 8989
|
||||||
|
weight: 1
|
||||||
|
matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- pvc-config.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- gateway.yaml
|
||||||
|
- httproute.yaml
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
# Sonarr config + SQLite DB. RWO on cephrbd (block) — the arr apps' SQLite
|
||||||
|
# does not tolerate CephFS locking. Retain: this is state.
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: sonarr-config
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 5Gi
|
||||||
|
storageClassName: cephrbd-fast-retain
|
||||||
|
volumeMode: Filesystem
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: sonarr
|
||||||
|
namespace: arrstack
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8989
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app: sonarr
|
||||||
|
type: ClusterIP
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- ../../../base/arrstack
|
||||||
@@ -11,6 +11,7 @@ spec:
|
|||||||
revision: HEAD
|
revision: HEAD
|
||||||
directories:
|
directories:
|
||||||
- path: apps/overlays/*/jellyfin
|
- path: apps/overlays/*/jellyfin
|
||||||
|
- path: apps/overlays/*/arrstack
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
name: 'media-{{path[3]}}'
|
name: 'media-{{path[3]}}'
|
||||||
|
|||||||
Reference in New Issue
Block a user