feat(k8s/media): migrate backups from rclone to restic, add seerr-db backup

This commit is contained in:
2026-03-20 22:10:55 +02:00
parent a7aad86538
commit 8df7e38744
4 changed files with 124 additions and 86 deletions

View File

@@ -1,10 +1,10 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: sonarr-db-backup
name: media-db-backup
namespace: media
labels:
app: sonarr-db-backup
app: media-backup
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
@@ -15,11 +15,11 @@ spec:
template:
metadata:
labels:
app: sonarr-db-backup
app: media-backup
spec:
restartPolicy: OnFailure
initContainers:
- name: pg-dump
- name: pg-dump-sonarr
image: postgres:14.21
env:
- name: PGHOST
@@ -42,52 +42,11 @@ spec:
command:
- sh
- -c
- pg_dump --clean --if-exists -v > /backup/dump.sql
- pg_dump --clean --if-exists > /backup/sonarr.sql
volumeMounts:
- name: backup
- name: backup-tmp
mountPath: /backup
containers:
- name: rclone-upload
image: rclone/rclone:1.69
command:
- sh
- -c
- rclone copy /backup/dump.sql b2crypt:sonarr/ --config /config/rclone/rclone.conf -v 2>&1
volumeMounts:
- name: backup
mountPath: /backup
- name: rclone-config
mountPath: /config/rclone
readOnly: true
volumes:
- name: backup
emptyDir: {}
- name: rclone-config
secret:
secretName: rclone-config
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: radarr-db-backup
namespace: media
labels:
app: radarr-db-backup
spec:
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
metadata:
labels:
app: radarr-db-backup
spec:
restartPolicy: OnFailure
initContainers:
- name: pg-dump
- name: pg-dump-radarr
image: postgres:14.21
env:
- name: PGHOST
@@ -110,26 +69,70 @@ spec:
command:
- sh
- -c
- pg_dump --clean --if-exists -v > /backup/dump.sql
- pg_dump --clean --if-exists > /backup/radarr.sql
volumeMounts:
- name: backup
- name: backup-tmp
mountPath: /backup
containers:
- name: rclone-upload
image: rclone/rclone:1.69
- name: pg-dump-seerr
image: postgres:14.21
env:
- name: PGHOST
value: seerr-db
- name: PGUSER
valueFrom:
secretKeyRef:
name: seerr-credentials
key: SEERR_DB_USER
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: seerr-credentials
key: SEERR_DB_PASSWORD
- name: PGDATABASE
valueFrom:
secretKeyRef:
name: seerr-credentials
key: SEERR_DB_NAME
command:
- sh
- -c
- rclone copy /backup/dump.sql b2crypt:radarr/ --config /config/rclone/rclone.conf -v 2>&1
- pg_dump --clean --if-exists > /backup/seerr.sql
volumeMounts:
- name: backup
- name: backup-tmp
mountPath: /backup
- name: rclone-config
mountPath: /config/rclone
containers:
- name: resticprofile
image: creativeprojects/resticprofile:0.32.0
command:
- sh
- -c
- |
resticprofile -c /secrets/profiles.yaml -n sonarr-db backup
resticprofile -c /secrets/profiles.yaml -n sonarr-db copy
resticprofile -c /secrets/profiles.yaml -n radarr-db backup
resticprofile -c /secrets/profiles.yaml -n radarr-db copy
resticprofile -c /secrets/profiles.yaml -n seerr-db backup
resticprofile -c /secrets/profiles.yaml -n seerr-db copy
env:
- name: B2_ACCOUNT_ID
valueFrom:
secretKeyRef:
name: media-backup-config
key: B2_ACCOUNT_ID
- name: B2_ACCOUNT_KEY
valueFrom:
secretKeyRef:
name: media-backup-config
key: B2_ACCOUNT_KEY
volumeMounts:
- name: secrets
mountPath: /secrets
readOnly: true
- name: backup-tmp
mountPath: /backup
volumes:
- name: backup
emptyDir: {}
- name: rclone-config
- name: secrets
secret:
secretName: rclone-config
secretName: media-backup-config
- name: backup-tmp
emptyDir: {}

View File

@@ -52,7 +52,7 @@ spec:
app: sonarr
- podSelector:
matchLabels:
app: sonarr-db-backup
app: media-backup
---
# radarr-db: only reachable from radarr and backup jobs
apiVersion: networking.k8s.io/v1
@@ -73,7 +73,7 @@ spec:
app: radarr
- podSelector:
matchLabels:
app: radarr-db-backup
app: media-backup
---
# Allow prowlarr to receive connections from sonarr and radarr
apiVersion: networking.k8s.io/v1
@@ -169,7 +169,7 @@ spec:
matchLabels:
app: jellyfin
---
# seerr-db: only reachable from seerr
# seerr-db: only reachable from seerr and backup jobs
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
@@ -186,3 +186,34 @@ spec:
- podSelector:
matchLabels:
app: seerr
- podSelector:
matchLabels:
app: media-backup
---
# Allow backup pods egress to Synology (rest-server), B2, DNS, and DB
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backup-egress
namespace: media
spec:
podSelector:
matchLabels:
app: media-backup
policyTypes:
- Egress
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
- ports:
- port: 8888
protocol: TCP
- ports:
- port: 443
protocol: TCP
- ports:
- port: 5432
protocol: TCP

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Secret
metadata:
name: media-backup-config
namespace: media
stringData:
profiles.yaml: ENC[AES256_GCM,data:FvqC4eyDKTqy+rCcuq5XiAcOF6oVFGVrsPKY0ElwMVqhsxTxdbGmfoeB6tjvOaz4IS0MyM7hekU4ydGCQN+O9O97eazNj2QIrmjw354Ckt+k/5R+i61jua96ErVnJef9RzrhfW1L+4gV3nYTx4oy6YVGoGk0FDpCuD98SR0TGWxbk+HOJ7BN7QZ91GPNre8G4SrizAoTIkYUmfQK/h8XvKhgScLdAZf4f9UDfW2bra9oekQc1EzzA33XeeOxuWr7lTeTG7/EIJCijtFmu+XdAvxWHgQ6S7breHGcAbyRtXF/ZSdPxtU/4y9RCxDmcd4tNhmP9b0QOaBeo6AAqq7epu7SC/dXHriOROJJ0orF88OVX+ptrP+3OwFE3WyuDCTcoOFoznXdGii+CHX7DJRnnsY3Q4HAL3jxOSGmtqauvoB6hMVO3l45gMG/DRJofHTJbIXZY08fw27cukeJlh0cWKyA+/KTPYI/V18OdMNfKrTuQ6rrpD29j6xbmI0m4Ho9FbeInatDtix21JJ2EpFEtBi3RrCeDXk0uqPU1eC7buUHdVQ3VO+01KLGrMIaVx5taP+4tclzdzbatEZ3hjI8u0g84jMJUryG0yjFpqAuZLqwFRuYzCALyWXtfj8aQt3+7ljEXaf8Ho2Pq3xDJAz1u7NArci7CYOXHHtJXINhgVEyFI+LTtkphdMP39k6rZ63KG7HISjzH1Fchqqzl8FJj6wyTIGLK2PoSizjBNoKO1bc3mMtbM+/x4MV5tYGOVzbQ9z9xqutEXoUZaBat7fWdKIMK4TsdOcrQt0x65Sa5/AewyGcHJh2yq2QgvaCPKzT6pY+88NGoWGUeqB62GO/nDybWFUPk1rdv2hdCwKIuLjbxxP5P123VOeOdfodKRqIjGZq97lZLiccCObrW9WvOuAKnDTL3s0fWa5zmYM19xJaq/Iwg9GyjUJMRhRaTdrttaOMYle2Yt+E0VW4ETGEG/3PwH7M/FzjEyGn4FTjYxbxcmkJha75JX3L3Q6bb5x9bIV6s0uDvptX3pKlw2431TUaWDkuJ+ZzpcLJwFZvNJ40maF3bI+LC9abHYQHtIxtPDF6EI70G3paO0UVItpd33+J92X/qiCFCTasdjzAr+HqGQ1SepkV74Puj/sIKs+6f1Sot+i22USXASGdaD0F/IqpwbgJXufbiYSrRdVw/EgZ7WuzGme0gL1AW7lchw0jBcNA7T2dKbVeuhmN3hUHe6rCCAS+mmBg+KxybXH9UJabfe9N7XYzjCeZ5afmSn663UxCq5V3wC0qh8edLih41XYTAMOw2ytlBWxZsVQE8mwTJRQrXDZrj3aB3Xc10vmj+mlma38lfz4ghGb3AqAFtdALJyqYeBxx1Wan6KA2tpWR39hCj1Jj3dPlAZc/ZXcs/zQJTsf3ohVqjBJD7s/42jp5wTO9lEvPESyekYsvaS82gSSuAJ57K0Yvbx278jciHyjX6vhi1uzdXFep0TPjQ3/rBf8PgngOyEjWV216C7dBLry0ou8B3HJElqItFuchtBVOHXvFY4B55OzzEaDJJ2eWFW7LZKS2UO12j/xFzfSdx2UdGkGUuJ9DjpvRdLB58HtbSDjclECvmyLQ7iRN7Q0W+7ei/aSWj/3t3ZC01IoCrj4arg4JlrjtC4VYxpKI4hyhX1M5ibdw8J3rOX/KqBtFBwoEiQgvSP5YxD1sfjwPRelaMgUHO8n6eXrfNTA0X2LJB++5B6nDaxTmNEq9eVu9L/kUo/WuE59UulRtkYs/ClP5zTclqUKdTVkPnNRQV9dcZOCjuiSpyDTIOlxwUR3I/7xRVP7B33CCgkXOWUISZb98RmQOJFkBPsXqiyRYVgHfn/SbarrvqvWF3XXNcQ+at2taYGF/WJB1Y2B+oFTppC+mNHfxmklJKwcIcwk39Q==,iv:hP5emno4sxU0g+hcCpfXtf8lhxhk7NDCjwcq5lSjmQ8=,tag:K3bNiO9BnGnMRqvM7E9TfQ==,type:str]
restic-password-nas: ENC[AES256_GCM,data:OfCOmmU85bnWWFAAir90+Vj3d0Vh0bUqNICQg+2aCksd5aiVl3M+OUXZaVhQQtukVd2Mw22y4Die3zO7wlzXAQ==,iv:M7SuVZfm541Rvm7m3Gh8EkDgQ3kU2gKIMJZ+u1s+xf8=,tag:5EwXbugyG+idxt12sJXNhQ==,type:str]
restic-password-b2: ENC[AES256_GCM,data:dSt6fWJknKPslHKrjfaCLRI+r4K2lhz9hYYE4CKcEaTutxFNBfAoj70abwtIj1hoLv0SzyZUWtxrIrZCILR/yw==,iv:5tRzv0KQMqbw5zAx9eBGGxngiowOxLYSMf3vsvoRcVA=,tag:2utz3OFpup4/NK/sWKzKVg==,type:str]
B2_ACCOUNT_ID: ENC[AES256_GCM,data:os8HLCWv9ujoZWLFEuhondgCVvRwMNBlHQ==,iv:bQNshEL7pFF/+1hjStaRo8Aa2uzVmai3L+5wFLoC8BE=,tag:7JGG/ocByA83E1ncNoZEXw==,type:str]
B2_ACCOUNT_KEY: ENC[AES256_GCM,data:+CNHqdPcTqHONYOY4DYJZ9G+mi3RHfX8hxzLXuSemw==,iv:Ojx0XDGUdvt+9UvEopQLpqQhoCmAzlz4kZTdYtq+Qcs=,tag:lYq7T2Q+wvycnU1JcNpvZQ==,type:str]
sops:
age:
- recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlQnBxVFhqY3l4U1hLZlhC
RWE5RHlIQXo3U2FqZVg3d2ZpRDhmbk1XSkI4CmxFcEt5VjBPZTNGQlRDYmIxMU91
VVphNE5TcUdnK29mcXVIc0VYaFkwWVEKLS0tIExOWTdjUGd5eHlBOVJTcXJHNFFQ
cER0MEpOb1J2Y1ZYQWlwT3A3dkdkZ1kK0PhrZsURFuA8c4rMVRE/jLiHBkxQ65ds
iVqJJHjuiOuOed5Wcr4FbAaghKIsc5AiZO06Zsj+pfpt5aQGdcettw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-03-22T09:08:31Z"
mac: ENC[AES256_GCM,data:veSRpp9RZatCrGkS5w/OPrPz1Av2SZQ+M5d/MlNYFraoMFluhejAQIt3vh+mO3Bd1hxPm3PPZzxHvLwpVH10lczxD9Uvc+LhA7FWrhr0BWrjbN5WKwhP3T3v/VFfkJctPi9ITOd/aGkusWfZ9ghVWnW4oe7RXxtCZhsh141QBHs=,iv:JPvqfB6T9DGFFsNrSGbrlaHv0UhQJB005Uj5tJgBVJQ=,tag:ih/gh7+FORz+CfP/nKahmA==,type:str]
encrypted_regex: ^(data|stringData|email)$
version: 3.12.2

View File

@@ -1,22 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: rclone-config
namespace: media
stringData:
rclone.conf: ENC[AES256_GCM,data:aTthn7P4ESDNtqRDW+R7RI1e0B2ftgHg6406vqHtsUPW25SEaNUiGuWlSY/BoiCuagBBM6TM+Gow2XrtTQauPND1irb5D5xyhcphFM5uF+8dE4qNJV4J09NjBd7Lzdp1udej2BJoRAeCwgAEwq8857log4TRwrbGzNrfRKOPrz7D3okBQP2hyxfZ85dlQH0ojUEodPi4U3mpwgXc8Kb0JhziZc1KjHbIzZ1/GkaKcYLI8Rl8q7esdqxnrA51sssWVkmSC4zoiPjwPwUWifSNMb7KC8L8bXRIVdpP8/f4rDyYJoa9uC7GW44nYIBVfLJrM015ZtpSzh05/IS9ev6N2REkjudLmOwwvOw52s8dKh1IRXixcV1JPk3knam2jnezYcnvmLYgyReryZFRFFP0xgaVOmZa5is=,iv:zrFW+ssUTt8T14TZz5n30rVr792FiDYxr89BdIIxn1c=,tag:XVtMvVbuo1vQU3hp8VTnHQ==,type:str]
sops:
age:
- recipient: age1zffnskvuezntkk703a0pyxsd5m8vx2hm33dr47wdfy8mn4fdw4sqgw0jgc
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlR1BZak5zZWdmZ2g3YktL
Q1lqZzVTWEtpVGhqSk9WamxmRm1WSFNnNkN3CjNzMEtyMnh6bEtjbW9BY0NGZm1G
dnMyOW5DVFpZT3JMVGNxVW9raWZkSzAKLS0tIHNHMXdZTlhXYWFRYmYvS21tQUps
MXB5QVkyZDZlQWlMd1NqdEl1V0g0d00KMSyMsWeN5oEx3s5Zh3x9MHiRywFvRuZm
lZEdl0ho90lJ8m+rPHIT+pI7vBMHLB3mJiBfIVR4KJQRUkhPjGSMRQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-22T16:12:51Z"
mac: ENC[AES256_GCM,data:gUyVh53pNCUHfW9+pww9sQ10kL/U92N0AV1Ys+fKt3W/wq4msyXLErQVVJBrHoPQo/ncKUMbCUGvMNHsUnJT7H8g8LuqMUxLbZhFju6rLHrgg+1hIKeA1cStOlTgBTQLbXA2gfsclQQ+nAf9zeAsgz3MfuK8PEHs3U2O8cSrtP4=,iv:fQd6lggTw3OI+8lZ1BOZvD+lLt7p5wlelf59sFsQHZE=,tag:4V8do9D3IiNPDDR5GRLXOg==,type:str]
encrypted_regex: ^(data|stringData|email)$
version: 3.11.0