Velero Backup Testing Guide
This guide explains how to test your Velero backups using a temporary K3d cluster.
Features
- Creates isolated K3d test cluster
- Installs nginx-ingress controller for ingress support
- Installs cert-manager with self-signed certificates (no real DNS/certs needed)
- Automatically rewrites ingress hosts from
*.hensen.ioto*.local - Bypasses authentication proxies (sol-auth) by rewriting ingress backends
- Generates
/etc/hostsentries for local DNS resolution - Restores backups with storage class mapping (longhorn -> local-path)
Prerequisites
Ensure you have the following tools installed on your local machine:
- Docker
- kubectl
- Helm
- K3d
- Velero CLI
- jq (for JSON parsing)
Setup
- First, clone this repository to your local machine:
git clone https://github.com/yourusername/backup-testing.git
cd backup-testing
- Make the scripts executable:
chmod +x test-velero-backup.sh validate-restore.sh
Running a Backup Test
Execute the test script with appropriate parameters:
./test-velero-backup.sh \
--s3-access-key <ACCESS_KEY> \
--s3-secret-key <SECRET_KEY> \
--backup-name <BACKUP_NAME> \
--original-namespace <NAMESPACE> \
--test-namespace <NAMESPACE> \
--generate-hosts
This will:
- Create a temporary K3d cluster
- Install nginx-ingress controller
- Install cert-manager with self-signed ClusterIssuer
- Install Velero configured to access your MinIO backup location
- Restore the specified backup (excluding sol-auth and certificates)
- Remove any restored sol-auth resources
- Rewrite ingress backends from sol-auth to direct backend services
- Rewrite ingress hosts from
*.hensen.ioto*.local - Generate
/etc/hostsentries (with--generate-hostsflag)
Command Line Options
| Option | Description | Default |
|---|---|---|
--backup-name NAME |
Name of the Velero backup to restore | (lists backups if empty) |
--s3-access-key KEY |
S3/MinIO access key | (required) |
--s3-secret-key KEY |
S3/MinIO secret key | (required) |
--s3-bucket BUCKET |
S3 bucket containing backups | velero-backups |
--s3-region REGION |
S3 region | minio |
--s3-url URL |
S3 endpoint URL | http://192.168.1.99:9000 |
--original-namespace NS |
Namespace in the original backup | (required) |
--test-namespace NS |
Namespace for restoration | default |
--original-domain DOMAIN |
Domain to replace in ingresses | hensen.io |
--local-domain DOMAIN |
Local domain suffix | local |
--skip-ingress-setup |
Skip nginx-ingress and cert-manager | false |
--generate-hosts |
Generate /etc/hosts entries | false |
--debug |
Enable debug output | false |
Local DNS Resolution
After the restore completes, the script can generate /etc/hosts entries. Add these to your /etc/hosts file to access services locally:
# Example output with --generate-hosts:
127.0.0.1 foto.local
127.0.0.1 immich.local
Then access your restored services at https://foto.local or https://immich.local.
Note: Your browser will show certificate warnings since we use self-signed certificates. This is expected for local testing.
Testing Specific Applications
Immich
For testing Immich backups:
./test-velero-backup.sh \
--s3-access-key <ACCESS_KEY> \
--s3-secret-key <SECRET_KEY> \
--backup-name daily-backup-YYYYMMDD \
--original-namespace immich \
--test-namespace immich \
--generate-hosts
Then add the generated hosts entries and access via https://immich.local
Alternatively, use port-forwarding:
kubectl port-forward service/helm-immich-server -n immich 8080:2283
Reachable on localhost:8080
Custom Domain Mapping
By default, the script rewrites *.hensen.io to *.local. You can customize this:
./test-velero-backup.sh \
--s3-access-key YOUR_ACCESS_KEY \
--s3-secret-key YOUR_SECRET_KEY \
--backup-name your-backup \
--original-namespace myapp \
--original-domain example.com \
--local-domain test.local
This will rewrite app.example.com to app.test.local.
Authentication Proxy Bypass
The production environment uses sol-auth (an Apache httpd-based OpenID Connect proxy) to protect certain applications like Immich. For local testing, this authentication is bypassed:
- Sol-auth resources are removed after restore (deployment, service, configmap)
- Ingress backends are rewritten from
sol-auth-svc:8002to the actual backend service (e.g.,helm-immich-server:2283)
This allows you to access the application directly without needing to authenticate through the Scouting login portal.
Production flow:
Browser -> Ingress -> sol-auth-svc:8002 -> (OpenID auth) -> helm-immich-server:2283
Test flow:
Browser -> Ingress -> helm-immich-server:2283 (direct, no auth)
Storage Class Mapping
The script automatically applies change-storage-class.yaml which maps:
longhorn->local-path
This allows backups from Longhorn storage to be restored using K3d's default local-path provisioner.
Troubleshooting
Check Velero logs
kubectl logs -n velero deploy/velero
Examine restore details
velero restore describe <RESTORE_NAME>
velero restore logs <RESTORE_NAME>
Check cluster resources
kubectl get pods -A
kubectl get pvc -A
kubectl get ingress -A
Check ingress controller
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller
Check cert-manager
kubectl get certificates -A
kubectl get clusterissuer
Debug mode
Run with --debug for verbose output:
./test-velero-backup.sh --debug ...
Architecture
+------------------+ +------------------+ +------------------+
| K3d Cluster | | MinIO | | Your Browser |
| | | (NAS/S3) | | |
| +-----------+ | | | | |
| | Velero |<--+-----+ velero-backups | | |
| +-----------+ | | bucket | | |
| | | +------------------+ | |
| v | | |
| +-----------+ | | |
| | Restored | | | |
| | App | | | |
| +-----------+ | | |
| | | | |
| v | | |
| +-----------+ | *.local domains | |
| | Ingress |<---------------------------------+ https://app.local
| | nginx | | (via /etc/hosts) | |
| +-----------+ | | |
| | | | |
| v | | |
| +-----------+ | | |
| |cert-manager| | Self-signed certs | |
| |(selfsigned)| | | |
| +-----------+ | | |
+------------------+ +------------------+