diff --git a/apps/base/jellyfin/kustomization.yaml b/apps/base/jellyfin/kustomization.yaml index edab63d..33ded07 100644 --- a/apps/base/jellyfin/kustomization.yaml +++ b/apps/base/jellyfin/kustomization.yaml @@ -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 diff --git a/apps/base/jellyfin/schedule.yaml b/apps/base/jellyfin/schedule.yaml new file mode 100644 index 0000000..6043a18 --- /dev/null +++ b/apps/base/jellyfin/schedule.yaml @@ -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 diff --git a/apps/base/jellyfin/vaultauth.yaml b/apps/base/jellyfin/vaultauth.yaml new file mode 100644 index 0000000..9fbc2c2 --- /dev/null +++ b/apps/base/jellyfin/vaultauth.yaml @@ -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 diff --git a/apps/base/jellyfin/vaultstaticsecret.yaml b/apps/base/jellyfin/vaultstaticsecret.yaml new file mode 100644 index 0000000..9de7ef2 --- /dev/null +++ b/apps/base/jellyfin/vaultstaticsecret.yaml @@ -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