Skip to content

S3 Backup Setup

This guide covers configuring VolumeBackup with S3-compatible storage backends including AWS S3, MinIO, Ceph RGW, Wasabi, and b'nerd Object Storage.

Repository URL Format

The URL format varies by provider:

Provider URL Format
AWS S3 s3:s3.amazonaws.com/bucket/path
AWS S3 (specific region) s3:s3.eu-central-1.amazonaws.com/bucket/path
MinIO s3:https://minio.example.com/bucket/path
Ceph RGW s3:https://rgw.example.com/bucket/path
Wasabi s3:s3.eu-central-1.wasabisys.com/bucket/path
b'nerd Object Storage s3:https://storage.muc1.de.bnerd.com/bucket/path

Credentials Secret

Create a Secret with your S3 credentials and Restic repository password:

apiVersion: v1
kind: Secret
metadata:
  name: s3-backup-credentials
  namespace: default
type: Opaque
stringData:
  AWS_ACCESS_KEY_ID: "your-access-key-id"
  AWS_SECRET_ACCESS_KEY: "your-secret-access-key"
  RESTIC_PASSWORD: "your-restic-repository-password"

For region-specific endpoints, you can optionally include:

stringData:
  AWS_DEFAULT_REGION: "eu-central-1"

Warning

The RESTIC_PASSWORD encrypts your repository. If lost, your backups cannot be decrypted. Store it securely outside of the cluster.

Full Example

apiVersion: backups.k8s.bnerd.com/v1
kind: VolumeBackup
metadata:
  name: app-data-backup
  namespace: default
spec:
  volumeClaimRef:
    name: app-data-pvc

  schedule: "0 3 * * *"  # Daily at 3 AM

  repository:
    type: s3
    url: s3:s3.eu-central-1.amazonaws.com/my-bucket/app-data
    secretRef:
      name: s3-backup-credentials

  paths:
    - /data
    - /config

  exclude:
    - "*.tmp"
    - "*.log"
    - "lost+found"

  retention:
    keepLast: 15
    keepDaily: 7
    keepWeekly: 4
    keepMonthly: 6

  cache:
    enabled: true
    size: "5Gi"

  resources:
    requests:
      memory: "256Mi"
      cpu: "200m"
    limits:
      memory: "1Gi"
      cpu: "1000m"

Retention Policy

The retention policy controls how many snapshots are kept after each backup run. Restic applies these rules in order, keeping the union of all matching snapshots:

Field Default Description
keepLast 15 Always keep the N most recent snapshots
keepDaily 7 Keep one snapshot per day for N days
keepWeekly 4 Keep one snapshot per week for N weeks
keepMonthly 6 Keep one snapshot per month for N months

After applying the retention policy, Restic runs forget --prune to reclaim storage.

Cache Configuration

The operator creates a persistent cache PVC to speed up incremental backups. Restic stores repository metadata in the cache, avoiding repeated downloads from the remote backend.

Field Default Description
cache.enabled true Enable/disable the cache PVC
cache.size 5Gi Cache volume size
cache.storageClass (cluster default) Storage class for the cache PVC
cache.accessMode ReadWriteOnce PVC access mode

The cache PVC is named {backup-name}-cache and is automatically cleaned up when the VolumeBackup is deleted.

Integrity Checks

Enable periodic repository integrity checks to detect corruption early:

spec:
  check:
    enabled: true
    schedule: "0 4 * * *"  # Daily at 4 AM, after backups
    readDataSubset: "10%"  # Verify 10% of data per run
    resources:
      requests:
        memory: "256Mi"
        cpu: "200m"
      limits:
        memory: "1Gi"
        cpu: "1000m"

This creates a separate CronJob ({name}-check) that runs restic check --read-data-subset. Over multiple runs, different subsets are checked, eventually covering the entire repository.

Restore Testing

Enable automated restore testing to verify your backups are actually recoverable:

spec:
  restoreTest:
    enabled: true
    schedule: "0 5 * * 0"  # Weekly on Sunday at 5 AM
    storage:
      type: emptyDir   # Fast, auto-cleaned (or "pvc" for persistent)
      size: "5Gi"
    fileCount: 50       # Restore 50 random files
    verifyChecksums: true  # Verify SHA-256 checksums
    resources:
      requests:
        memory: "512Mi"
        cpu: "500m"
      limits:
        memory: "6Gi"
        cpu: "2000m"

This creates a CronJob ({name}-restore-test) that:

  1. Lists all files in the latest snapshot
  2. Selects a random sample of files
  3. Restores them to a temporary volume
  4. Verifies SHA-256 checksums match the originals

Troubleshooting

"connection refused" or timeout errors

  • Verify the endpoint URL is reachable from the cluster
  • Check if your S3 endpoint requires HTTPS
  • For non-AWS endpoints, ensure the full URL including protocol is specified

"wrong credentials" / "access denied"

  • Verify AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in the Secret
  • Check that the IAM user/role has s3:GetObject, s3:PutObject, s3:ListBucket, and s3:DeleteObject permissions on the bucket
  • For path-style endpoints (MinIO, Ceph), the URL must include the protocol

"bucket not found"

  • The bucket must exist before creating the VolumeBackup -- Restic does not create buckets
  • Verify the bucket name in the repository URL matches exactly