--- # OpenCloud Backup CronJob # Backs up Nextcloud data and database daily to Hetzner S3 bucket apiVersion: batch/v1 kind: CronJob metadata: name: opencloud-backup namespace: opencloud spec: # Run daily at 2 AM schedule: "0 2 * * *" successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 concurrencyPolicy: Forbid jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: backup image: ghcr.io/restic/restic:latest env: - name: RESTIC_REPOSITORY value: "s3:https://fsn1.your-objectstorage.com/basicstack-backups/opencloud" - name: RESTIC_PASSWORD valueFrom: secretKeyRef: name: opencloud-backup-secret key: restic-password - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: name: opencloud-backup-secret key: access-key - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: name: opencloud-backup-secret key: secret-key - name: BACKUP_DATE value: "$(date +%Y%m%d-%H%M%S)" command: - /bin/sh - -c - | set -e # Initialize repository if it doesn't exist restic snapshots || restic init # Backup PostgreSQL database echo "Backing up PostgreSQL database..." pg_dump -h postgres -U nextcloud nextcloud > /tmp/nextcloud-db-backup.sql # Backup Nextcloud data echo "Backing up Nextcloud data..." restic backup /var/www/html /tmp/nextcloud-db-backup.sql \ --tag opencloud \ --tag daily \ --host opencloud.basicstack.de # Clean up old backups (keep last 30 days, 12 months, 5 years) echo "Pruning old backups..." restic forget \ --keep-daily 30 \ --keep-monthly 12 \ --keep-yearly 5 \ --prune # Check repository integrity (once a week) if [ $(date +%u) -eq 1 ]; then echo "Running weekly repository check..." restic check fi echo "Backup completed successfully" volumeMounts: - name: nextcloud-data mountPath: /var/www/html readOnly: true - name: pg-password mountPath: /run/secrets/pg-password subPath: postgres-password readOnly: true volumes: - name: nextcloud-data persistentVolumeClaim: claimName: nextcloud-data - name: pg-password secret: secretName: opencloud-db-secret