apiVersion: batch/v1 kind: CronJob metadata: name: gitea-backup namespace: gitea spec: schedule: "0 3 * * *" # daily at 03:00 UTC concurrencyPolicy: Forbid successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 3 jobTemplate: spec: backoffLimit: 1 activeDeadlineSeconds: 1800 template: spec: restartPolicy: Never securityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 # Must run on the same node as Gitea to share the RWO volume affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app.kubernetes.io/name: gitea topologyKey: kubernetes.io/hostname initContainers: - name: gitea-dump image: gitea/gitea:1.25.4 command: - sh - -c - | gitea dump \ -c /data/gitea/conf/app.ini \ -f /backup/gitea-dump.zip \ -t /tmp/gitea-dump && \ echo "Dump completed: $(ls -lh /backup/gitea-dump.zip)" volumeMounts: - name: data mountPath: /data readOnly: true - name: backup mountPath: /backup - name: tmp mountPath: /tmp/gitea-dump containers: - name: upload image: minio/mc:latest env: - name: HOME value: /tmp command: - sh - -c - | mc alias set s3 "${S3_ENDPOINT}" "${AWS_ACCESS_KEY_ID}" "${AWS_SECRET_ACCESS_KEY}" TIMESTAMP=$(date +%Y%m%d-%H%M%S) KEY="gitea-dump-${TIMESTAMP}.zip" echo "Uploading ${KEY}..." mc cp /backup/gitea-dump.zip "s3/${S3_BUCKET}/${KEY}" && \ echo "Upload complete." # Prune backups older than 7 days echo "Pruning backups older than 7 days..." mc rm --older-than 7d --force "s3/${S3_BUCKET}/" 2>&1 || true echo "Pruning complete." envFrom: - secretRef: name: gitea-backup-s3 volumeMounts: - name: backup mountPath: /backup readOnly: true volumes: - name: data persistentVolumeClaim: claimName: gitea-shared-storage - name: backup emptyDir: sizeLimit: 5Gi - name: tmp emptyDir: sizeLimit: 5Gi