apiVersion: v1 kind: ConfigMap metadata: name: s3-backup-script namespace: rook-ceph data: buckets.list: | nextcloud nextcloud wiki-js wiki-js pixelfed pixelfed quay quay influxdb influxdb asciinema asciinema nextcloud-new nextcloud loops loops synapse synapse authentik authentik mastodon mastodon gramps gramps backup.sh: | #!/bin/sh set -eu backup_fs=$(awk '$2 == "/backup" { print $3; exit }' /proc/mounts) echo "Backup filesystem: $backup_fs" test "$backup_fs" = bcachefs endpoint=http://rook-ceph-rgw-my-store.rook-ceph.svc:80 failures=0 while read -r bucket owner; do test -n "$bucket" || continue remote="BACKUP_$(printf '%s' "$bucket" | tr '[:lower:]-' '[:upper:]_')" access_key=$(cat "/run/rgw/$owner/AccessKey") secret_key=$(cat "/run/rgw/$owner/SecretKey") test -n "$access_key" -a -n "$secret_key" export "RCLONE_CONFIG_${remote}_TYPE=s3" export "RCLONE_CONFIG_${remote}_PROVIDER=Ceph" export "RCLONE_CONFIG_${remote}_ENDPOINT=$endpoint" export "RCLONE_CONFIG_${remote}_REGION=" export "RCLONE_CONFIG_${remote}_ACCESS_KEY_ID=$access_key" export "RCLONE_CONFIG_${remote}_SECRET_ACCESS_KEY=$secret_key" unset access_key secret_key echo "Syncing RGW bucket $bucket" if ! rclone --config /dev/null sync "$remote:$bucket" "/backup/$bucket" --transfers 2 --checkers 4 --stats 1m; then echo "RGW backup failed for bucket $bucket" >&2 failures=$((failures + 1)) fi done < /scripts/buckets.list test "$failures" -eq 0 || exit 1 echo "Completed all RGW bucket mirrors" --- apiVersion: batch/v1 kind: CronJob metadata: name: s3-backup namespace: rook-ceph spec: schedule: "0 13 * * *" timeZone: Europe/Vienna concurrencyPolicy: Forbid startingDeadlineSeconds: 3600 successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 7 jobTemplate: spec: backoffLimit: 0 activeDeadlineSeconds: 172800 template: spec: nodeSelector: kubernetes.io/hostname: arschrock tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule automountServiceAccountToken: false restartPolicy: Never securityContext: runAsUser: 962 runAsGroup: 962 containers: - name: rclone image: rclone/rclone:1.75.0 imagePullPolicy: IfNotPresent command: [/bin/sh, /scripts/backup.sh] env: - name: XDG_CONFIG_HOME value: /tmp/.config securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: [ALL] volumeMounts: - name: backup mountPath: /backup - name: scripts mountPath: /scripts readOnly: true - name: rgw-asciinema mountPath: /run/rgw/asciinema readOnly: true - name: rgw-authentik mountPath: /run/rgw/authentik readOnly: true - name: rgw-gramps mountPath: /run/rgw/gramps readOnly: true - name: rgw-influxdb mountPath: /run/rgw/influxdb readOnly: true - name: rgw-loops mountPath: /run/rgw/loops readOnly: true - name: rgw-mastodon mountPath: /run/rgw/mastodon readOnly: true - name: rgw-nextcloud mountPath: /run/rgw/nextcloud readOnly: true - name: rgw-pixelfed mountPath: /run/rgw/pixelfed readOnly: true - name: rgw-quay mountPath: /run/rgw/quay readOnly: true - name: rgw-synapse mountPath: /run/rgw/synapse readOnly: true - name: rgw-wiki-js mountPath: /run/rgw/wiki-js readOnly: true - name: tmp mountPath: /tmp volumes: - name: backup hostPath: path: /mnt/backup/kubernetes/s3 type: Directory - name: scripts configMap: name: s3-backup-script defaultMode: 0555 - name: rgw-asciinema secret: secretName: rook-ceph-object-user-my-store-asciinema defaultMode: 0444 - name: rgw-authentik secret: secretName: rook-ceph-object-user-my-store-authentik defaultMode: 0444 - name: rgw-gramps secret: secretName: rook-ceph-object-user-my-store-gramps defaultMode: 0444 - name: rgw-influxdb secret: secretName: rook-ceph-object-user-my-store-influxdb defaultMode: 0444 - name: rgw-loops secret: secretName: rook-ceph-object-user-my-store-loops defaultMode: 0444 - name: rgw-mastodon secret: secretName: rook-ceph-object-user-my-store-mastodon defaultMode: 0444 - name: rgw-nextcloud secret: secretName: rook-ceph-object-user-my-store-nextcloud defaultMode: 0444 - name: rgw-pixelfed secret: secretName: rook-ceph-object-user-my-store-pixelfed defaultMode: 0444 - name: rgw-quay secret: secretName: rook-ceph-object-user-my-store-quay defaultMode: 0444 - name: rgw-synapse secret: secretName: rook-ceph-object-user-my-store-synapse defaultMode: 0444 - name: rgw-wiki-js secret: secretName: rook-ceph-object-user-my-store-wiki-js defaultMode: 0444 - name: tmp emptyDir: {}