jellyfin: back up the config PVC with a k8up Schedule
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful

Protect the jellyfin-config PVC (library metadata, plugins, config XML)
with daily restic backups to the new Ceph RGW config-backup bucket.

- Add a k8up.io Schedule: daily backup (02:00), weekly prune (Sun 03:00,
  keep 14 daily/8 weekly/12 monthly) and weekly check (Sun 04:00)
- Source S3 creds from the cephrgw BucketAccess Secret and the restic
  repo password from Vault via a VaultStaticSecret (kv path
  kubernetes/namespace/jellyfin/default/k8up-restic)
- Add the namespace VaultAuth (default role/SA) VSO needs to sync it
- Mount the reflected vault-ca-cert into the restic pods so restic trusts
  the internal unkin.net CA on s3.ceph.unkin.net
- Wire the new files into the jellyfin kustomization
This commit is contained in:
2026-08-15 12:08:50 +10:00
parent 6b30958a24
commit 57ac95bdec
4 changed files with 105 additions and 0 deletions
+3
View File
@@ -8,6 +8,9 @@ resources:
- cnpg_pooler.yaml
- cnpg_backup.yaml
- cephrgw-config-backup.yaml
- vaultauth.yaml
- vaultstaticsecret.yaml
- schedule.yaml
- pvc-config.yaml
- pvc-transcode.yaml
- pvc-media-tv.yaml
+58
View File
@@ -0,0 +1,58 @@
---
# k8up Schedule: restic backups of the jellyfin-config PVC (library metadata,
# plugins, config XML) to the dedicated Ceph RGW config-backup bucket. S3 creds
# come from the cephrgw BucketAccess Secret (jellyfin-config-backup-s3); the
# restic repo password comes from Vault via the jellyfin-k8up-restic Secret.
#
# s3.ceph.unkin.net presents the internal unkin.net CA, which the k8up/restic
# image does not trust by default, so the reflected vault-ca-cert Secret is
# mounted into every job pod and pointed at via backend.tlsOptions.caCert.
apiVersion: k8up.io/v1
kind: Schedule
metadata:
name: jellyfin-config
namespace: jellyfin
spec:
backend:
repoPasswordSecretRef:
name: jellyfin-k8up-restic
key: password
s3:
endpoint: https://s3.ceph.unkin.net
bucket: jellyfin-config-backup
accessKeyIDSecretRef:
name: jellyfin-config-backup-s3
key: AWS_ACCESS_KEY_ID
secretAccessKeySecretRef:
name: jellyfin-config-backup-s3
key: AWS_SECRET_ACCESS_KEY
tlsOptions:
caCert: /etc/k8up/ca/ca.crt
volumeMounts:
- name: vault-ca
mountPath: /etc/k8up/ca
readOnly: true
backup:
schedule: "0 2 * * *"
failedJobsHistoryLimit: 3
successfulJobsHistoryLimit: 3
volumes:
- name: vault-ca
secret:
secretName: vault-ca-cert
prune:
schedule: "0 3 * * 0"
retention:
keepDaily: 14
keepWeekly: 8
keepMonthly: 12
volumes:
- name: vault-ca
secret:
secretName: vault-ca-cert
check:
schedule: "0 4 * * 0"
volumes:
- name: vault-ca
secret:
secretName: vault-ca-cert
+20
View File
@@ -0,0 +1,20 @@
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: jellyfin
annotations:
argocd.argoproj.io/sync-wave: "0"
spec:
allowedNamespaces:
- jellyfin
kubernetes:
audiences:
- vault
role: default
serviceAccount: default
tokenExpirationSeconds: 600
method: kubernetes
mount: k8s/au/syd1
vaultConnectionRef: vso-system/default
+24
View File
@@ -0,0 +1,24 @@
---
# restic repository password for the k8up jellyfin-config backups. Seeded at
# kv/kubernetes/namespace/jellyfin/default/k8up-restic (key: password); the
# default k8s role's templated policy already grants read here, so no
# terraform-vault change is needed. VSO syncs it into the jellyfin-k8up-restic
# Secret that the Schedule references via backend.repoPasswordSecretRef.
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: jellyfin-k8up-restic
namespace: jellyfin
annotations:
argocd.argoproj.io/sync-wave: "0"
spec:
destination:
create: true
name: jellyfin-k8up-restic
overwrite: true
hmacSecretData: true
mount: kv
path: kubernetes/namespace/jellyfin/default/k8up-restic
refreshAfter: 5m
type: kv-v2
vaultAuthRef: default