7.2 KiB
VAPORA Backup & Recovery Scripts
Automated backup and recovery procedures for VAPORA using Nushell 0.109.0+.
Dual Backup Strategy:
- S3: Direct file uploads with AES-256 encryption
- Restic: Incremental, deduplicated backups with compression
Scripts Overview
Backup Scripts
| Script | Purpose | Schedule | Target |
|---|---|---|---|
database-backup.nu |
Export SurrealDB to S3 (compressed + encrypted) | Manual or Hourly | S3 |
config-backup.nu |
Backup Kubernetes ConfigMaps/Secrets | Manual or Daily | S3 |
restic-backup.nu |
Incremental backup to Restic repository | Manual | Restic |
orchestrate-backup-recovery.nu |
Coordinate all backup types | CronJob | S3 + Restic |
Recovery Scripts
| Script | Purpose | Input |
|---|---|---|
database-recovery.nu |
Restore SurrealDB from S3 backup | Encrypted S3 file |
orchestrate-backup-recovery.nu |
One-command recovery | S3 or Restic location |
Verification
| Script | Purpose | Checks |
|---|---|---|
verify-backup-health.nu |
Health check for backup infrastructure | S3, Restic, DB, freshness, rotation |
Quick Start
Local Backup
# Set environment
export SURREAL_URL="ws://localhost:8000"
export SURREAL_PASS="your-password"
export S3_BUCKET="vapora-backups"
export ENCRYPTION_KEY_FILE="/path/to/key"
# Run full backup
nu scripts/orchestrate-backup-recovery.nu \
--operation backup \
--mode full \
--surreal-url "$SURREAL_URL" \
--surreal-pass "$SURREAL_PASS" \
--s3-bucket "$S3_BUCKET" \
--encryption-key "$ENCRYPTION_KEY_FILE" \
--iac-dir "provisioning"
Local Recovery
# Restore from S3 backup
nu scripts/orchestrate-backup-recovery.nu \
--operation recovery \
--s3-location "s3://vapora-backups/backups/database/database-20260112-010000.sql.gz.enc" \
--encryption-key "$ENCRYPTION_KEY_FILE" \
--surreal-url "$SURREAL_URL" \
--surreal-pass "$SURREAL_PASS"
Health Check
nu scripts/verify-backup-health.nu \
--s3-bucket "$S3_BUCKET" \
--surreal-url "$SURREAL_URL" \
--surreal-pass "$SURREAL_PASS"
Kubernetes Automation
CronJobs defined in kubernetes/09-backup-cronjobs.yaml:
- Hourly (00:00 UTC): Database backup (S3 + Restic)
- Daily (02:00 UTC): Configuration backup
- Daily (03:00 UTC): Health verification
- Monthly (04:00 first day): Snapshot rotation/cleanup
Deploy:
kubectl apply -f kubernetes/09-backup-cronjobs.yaml
Monitor:
kubectl get cronjobs -n vapora
kubectl logs -n vapora -l backup-type=database -f
Features
✅ Dual backup approach (S3 + Restic) ✅ Encryption (AES-256 at rest, encrypted transfer) ✅ Compression (gzip for S3, built-in for Restic) ✅ Incremental (Restic only - no duplicate data) ✅ Verification (post-backup integrity checks) ✅ Retention (daily/weekly/monthly policies) ✅ Health checks (automated daily verification) ✅ Recovery (one-command restore) ✅ Kubernetes native (CronJobs, RBAC, secrets)
Implementation Details
All scripts follow NUSHELL_GUIDELINES.md (0.109.0+) strictly:
✓ Function signatures with BOTH : and ->
✓ NO mutable variables (use reduce --fold)
✓ External commands with ^ prefix
✓ Error handling with do { } | complete
✓ Variable interpolation with [$var] for variables, ($expr) for expressions
✓ NO try-catch blocks
✓ NO type annotations on boolean flags
✓ Pipelines in conditionals are parenthesized
Configuration
Environment Variables
SurrealDB:
SURREAL_URL=ws://localhost:8000
SURREAL_USER=root
SURREAL_PASS=<password>
AWS S3:
S3_BUCKET=vapora-backups
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=<key>
AWS_SECRET_ACCESS_KEY=<secret>
Restic:
RESTIC_REPO=s3:s3.amazonaws.com/vapora-backups/restic
RESTIC_PASSWORD=<password>
Encryption:
ENCRYPTION_KEY_FILE=/path/to/encryption.key
Kubernetes Secrets
# Database credentials
kubectl create secret generic vapora-secrets \
--from-literal=surreal_password="$SURREAL_PASS" \
--from-literal=restic_password="$RESTIC_PASSWORD" \
-n vapora
# AWS credentials
kubectl create secret generic vapora-aws-credentials \
--from-literal=access_key_id="$AWS_ACCESS_KEY_ID" \
--from-literal=secret_access_key="$AWS_SECRET_ACCESS_KEY" \
-n vapora
# Encryption key
kubectl create secret generic vapora-encryption-key \
--from-file=encryption.key=/path/to/encryption.key \
-n vapora
Backup Locations
S3 Paths
s3://vapora-backups/
├── backups/
│ ├── database/
│ │ └── database-20260112-010000.sql.gz.enc
│ └── config/
│ └── configs-20260112-020000.tar.gz
└── restic/
├── data/
├── index/
├── snapshots/
└── config
Restic Repository
s3://vapora-backups/restic/
├── data/ # Backup data files
├── index/ # Index files
├── snapshots/ # Snapshot metadata
└── config # Repository config
Recovery Procedures
Database Recovery (S3)
- Download encrypted backup from S3
- Decrypt with AES-256 key
- Decompress backup
- Scale down StatefulSet
- Delete current PVC
- Scale up StatefulSet (creates new PVC)
- Import backup to database
- Verify data integrity
Time: 30-60 seconds (depends on backup size)
Restic Recovery
# List available snapshots
restic -r "$RESTIC_REPO" snapshots
# Restore specific snapshot to directory
restic -r "$RESTIC_REPO" restore <snapshot-id> --target /recovery
Troubleshooting
Backup Fails
Check logs:
kubectl logs -n vapora -l backup-type=database --tail=100
Verify credentials:
# S3
aws s3 ls s3://vapora-backups/
# Restic
RESTIC_PASSWORD="$RESTIC_PASSWORD" restic -r "$RESTIC_REPO" list snapshots
Recovery Fails
Ensure database is stopped:
kubectl scale statefulset surrealdb --replicas=0 -n vapora
Verify PVC deleted:
kubectl get pvc -n vapora
Check encryption key exists:
kubectl get secrets -n vapora vapora-encryption-key
Health Check Fails
Run detailed check:
nu scripts/verify-backup-health.nu \
--s3-bucket "$S3_BUCKET" \
--surreal-url "$SURREAL_URL" \
--surreal-pass "$SURREAL_PASS" \
--max-age-hours 25
Integration with Disaster Recovery
These scripts implement the backup strategy defined in:
docs/disaster-recovery/backup-strategy.mddocs/disaster-recovery/database-recovery-procedures.md
See docs/operations/backup-recovery-automation.md for comprehensive integration guide.
Support
Documentation:
- Backup Strategy:
docs/disaster-recovery/backup-strategy.md - Disaster Recovery:
docs/disaster-recovery/README.md - Operations Guide:
docs/operations/README.md
Issues:
- Check logs:
kubectl logs -n vapora -l backup-type=database - Verify configuration: Check all environment variables are set
- Test connectivity:
aws s3 ls,surreal list namespaces
Last Updated: January 12, 2026 Nushell Version: 0.109.0+ Status: Production-Ready