Filesystem Repository for Kopia
Overview
The filesystem repository feature allows you to use a PersistentVolumeClaim (PVC) as a backup repository for Kopia. This provides an alternative to remote storage backends like S3, Azure, or GCS, enabling backups to local or network-attached storage with a simplified and secure API.
Use Cases
The filesystem repository is ideal for:
Local Backups: Store backups on local storage for quick access and recovery
NFS/Network Storage: Use existing NFS or other network storage infrastructure
Air-gapped Environments: Environments without internet connectivity or cloud storage access
Multi-tier Backup Strategy: Combine with remote backups for a comprehensive backup solution
Cost Optimization: Reduce cloud storage costs for frequently accessed backups
Compliance Requirements: Keep backups within specific geographic or infrastructure boundaries
Prerequisites
Before using filesystem repositories, ensure:
PVC Availability: The repository PVC must exist in the same namespace as the ReplicationSource
PVC Status: The PVC must be bound to a PersistentVolume before the backup job starts
Storage Capacity: The PVC must have sufficient capacity for your backup data and repository metadata
Access Mode: The PVC must support the access mode required by your backup jobs (typically ReadWriteOnce)
Password Secret: A Kopia password must be provided via the repository secret for encryption
Configuration
Basic Configuration
To use a filesystem repository, specify the repositoryPVC
field in your ReplicationSource:
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: backup-to-pvc
namespace: myapp
spec:
sourcePVC: myapp-data
trigger:
schedule: "0 2 * * *" # Daily at 2 AM
kopia:
# Reference to the repository configuration secret
repository: kopia-password-secret
# PVC to use as the filesystem repository
repositoryPVC: backup-storage-pvc
Password Secret Configuration
For filesystem repositories, the secret must contain the repository password for encryption:
apiVersion: v1
kind: Secret
metadata:
name: kopia-password-secret
namespace: myapp
type: Opaque
stringData:
# Optional: Explicitly specify filesystem repository type
# When repositoryPVC is set, this will be automatically set to "filesystem:///kopia/repository"
KOPIA_REPOSITORY: "filesystem:"
# Required: Password for repository encryption
KOPIA_PASSWORD: "your-secure-repository-password"
Note
When using repositoryPVC
, VolSync automatically sets KOPIA_REPOSITORY=filesystem:///kopia/repository
.
You can optionally include KOPIA_REPOSITORY: "filesystem:"
in the secret for clarity, but it’s not required.
API Reference
RepositoryPVC Field
The repositoryPVC
field provides a simplified API for filesystem-based repositories:
- repositoryPVC (string, optional)
The name of the PersistentVolumeClaim to use as the backup repository.
The PVC must exist in the same namespace as the ReplicationSource
The PVC is mounted at
/kopia
within the mover podThe repository is created at the fixed path
/kopia/repository
Minimum length: 1 character
The PVC is always mounted in read-write mode for repository operations
Important
Security Enhancement: The repository path is fixed at /kopia/repository
and cannot be configured.
This design choice:
Eliminates path injection vulnerabilities
Removes the need for path sanitization
Provides consistent, predictable repository locations
Aligns with Kopia’s standard filesystem URL format
Examples
Example 1: Local Storage Backup
This example backs up application data to a local storage PVC:
# Create the repository PVC
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-backup-storage
namespace: myapp
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: local-storage
# Create the password secret
---
apiVersion: v1
kind: Secret
metadata:
name: kopia-password
namespace: myapp
type: Opaque
stringData:
KOPIA_PASSWORD: "change-this-to-a-secure-password"
# Configure the backup
---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: myapp-backup
namespace: myapp
spec:
sourcePVC: myapp-data
trigger:
schedule: "0 */6 * * *" # Every 6 hours
kopia:
repository: kopia-password
# Simply reference the PVC - no path configuration needed
repositoryPVC: local-backup-storage
retain:
hourly: 24
daily: 7
weekly: 4
monthly: 3
Example 2: NFS Backup Repository
This example uses an NFS-backed PVC as the backup repository:
# Create NFS-backed PVC
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-backup-pv
spec:
capacity:
storage: 500Gi
accessModes:
- ReadWriteMany
nfs:
server: nfs-server.example.com
path: /exports/backups
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-backup-pvc
namespace: production
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 500Gi
volumeName: nfs-backup-pv
# Configure backup to NFS
---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: production-backup
namespace: production
spec:
sourcePVC: production-database
trigger:
schedule: "0 1 * * *" # Daily at 1 AM
kopia:
repository: kopia-secret
# NFS PVC as repository - simple and secure
repositoryPVC: nfs-backup-pvc
compression: "zstd"
retain:
daily: 30
weekly: 12
monthly: 6
Example 3: Multi-tier Backup Strategy
This example combines filesystem and remote backups for comprehensive data protection:
# Local fast backup for quick recovery
---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: app-backup-local
namespace: myapp
spec:
sourcePVC: app-data
trigger:
schedule: "0 */4 * * *" # Every 4 hours
kopia:
repository: kopia-password-local
repositoryPVC: fast-local-storage
retain:
hourly: 24
daily: 3
# Remote backup for disaster recovery
---
apiVersion: v1
kind: Secret
metadata:
name: kopia-s3-config
namespace: myapp
type: Opaque
stringData:
KOPIA_REPOSITORY: s3://backup-bucket/myapp
KOPIA_PASSWORD: "secure-password"
AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
---
apiVersion: volsync.backube/v1alpha1
kind: ReplicationSource
metadata:
name: app-backup-remote
namespace: myapp
spec:
sourcePVC: app-data
trigger:
schedule: "0 2 * * *" # Daily at 2 AM
kopia:
repository: kopia-s3-config
retain:
daily: 30
weekly: 12
monthly: 12
Simplified API Benefits
The new repositoryPVC
field replaces the previous nested filesystemDestination
structure, providing:
- Improved Security
Fixed repository path eliminates directory traversal vulnerabilities
No user-configurable paths reduce attack surface
Consistent security model across all deployments
- Simplified Configuration
Single field instead of nested structure
No path configuration or validation required
Clearer intent with descriptive field name
- Better Consistency
Aligns with other VolSync fields (
sourcePVC
,destinationPVC
)Uses standard Kopia filesystem URL format internally
Same
KOPIA_REPOSITORY
environment variable as other backends
- Easier Maintenance
Reduced complexity in implementation
Fewer edge cases to handle
Simplified troubleshooting
Migration from Remote to Filesystem
To switch from remote storage to a filesystem repository:
Create Repository PVC
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: backup-repository namespace: myapp spec: accessModes: - ReadWriteOnce resources: requests: storage: 200Gi
Update ReplicationSource
Add the
repositoryPVC
field and update the secret:apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: myapp-backup namespace: myapp spec: sourcePVC: myapp-data trigger: schedule: "0 2 * * *" kopia: repository: kopia-password # Now only contains KOPIA_PASSWORD repositoryPVC: backup-repository
Verify Operation
Monitor the ReplicationSource status:
kubectl get replicationsource myapp-backup -n myapp -o yaml kubectl logs -l app.kubernetes.io/component=volsync-kopia -n myapp
Security Considerations
Enhanced Security Design
The repositoryPVC
implementation includes several security enhancements:
Fixed Path: Repository always at
/kopia/repository
- no user-configurable pathsNo Path Injection: Eliminates directory traversal attack vectors
Simplified Validation: Fewer configuration options mean fewer potential misconfigurations
Consistent Isolation: Each PVC is mounted in a dedicated, isolated directory
Best Practices
Access Control: Restrict access to repository PVCs using appropriate RBAC policies
Encryption: Always use strong passwords (minimum 16 characters) for repository encryption
Network Storage: When using network storage, ensure proper network segmentation
Regular Testing: Periodically test restore operations to verify backup integrity
Capacity Monitoring: Monitor PVC usage to prevent repository corruption from full storage
Technical Implementation
The Kopia mover handles filesystem repositories as follows:
The repository PVC is mounted at
/kopia
The repository is initialized at
/kopia/repository
(fixed location)VolSync automatically sets
KOPIA_REPOSITORY=filesystem:///kopia/repository
The same parsing logic handles filesystem URLs as other backend types (s3://, azure://, etc.)
Troubleshooting
Common Issues
PVC Not Found
Error: PersistentVolumeClaim "backup-pvc" not found
Solution: Ensure the PVC exists in the same namespace as the ReplicationSource:
kubectl get pvc -n <namespace>
kubectl create -f backup-pvc.yaml -n <namespace>
PVC Not Bound
Error: PVC backup-pvc is not bound
Solution: Check PVC status and ensure a suitable PersistentVolume is available:
kubectl describe pvc backup-pvc -n <namespace>
kubectl get pv
Repository Not Initialized
Error: repository not initialized at /kopia/repository
Solution: The repository will be automatically initialized on first backup. If initialization fails, check:
PVC has sufficient space
PVC is writable
Password secret is properly configured
Permission Denied
Error: unable to create repository: permission denied
Solution: Verify the PVC supports write operations and has sufficient permissions:
# Check PVC access modes
kubectl get pvc <pvc-name> -n <namespace> -o jsonpath='{.spec.accessModes}'
# Verify storage class supports dynamic provisioning if applicable
kubectl get storageclass <storage-class-name>
Insufficient Storage
Error: no space left on device
Solution: Monitor PVC usage and expand capacity if needed:
kubectl exec -it <kopia-pod> -- df -h /kopia
kubectl patch pvc backup-pvc -n <namespace> -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'
Debugging Commands
Check ReplicationSource status:
kubectl describe replicationsource <name> -n <namespace>
View Kopia mover logs:
kubectl logs -n <namespace> -l app.kubernetes.io/component=volsync-kopia
Inspect the repository structure:
# Check if repository is properly mounted
kubectl exec -it <kopia-pod> -n <namespace> -- ls -la /kopia
# Verify repository initialization
kubectl exec -it <kopia-pod> -n <namespace> -- ls -la /kopia/repository
# Check repository status
kubectl exec -it <kopia-pod> -n <namespace> -- kopia repository status
# View repository configuration
kubectl exec -it <kopia-pod> -n <namespace> -- env | grep KOPIA_REPOSITORY
Performance Considerations
Storage Selection
Choose appropriate storage based on your requirements:
Local SSD: Best performance for frequent backups and quick restores
Network Storage (NFS): Good for shared access across multiple nodes
Object Storage: Better for long-term retention and disaster recovery
Optimization Tips
Compression: Use
zstd
compression for the best balance of speed and ratioParallelism: Adjust parallelism based on storage capabilities
Scheduling: Stagger backup schedules to avoid resource contention
Capacity Planning: Monitor storage usage trends and plan for growth
Limitations
Current Limitations
Namespace Scope: Repository PVC must exist in the same namespace as the ReplicationSource
Single Repository: Cannot use both
repositoryPVC
and remote repository configuration simultaneouslyFixed Path: Repository location is fixed at
/kopia/repository
for securitySingle PVC: Only one repository PVC can be specified per ReplicationSource
Compatibility Notes
The
repositoryPVC
field is available in VolSync v0.10.0 and laterRepositories created with
repositoryPVC
use standard Kopia filesystem formatCompatible with all Kopia retention and compression settings
Works with existing Kopia tooling for repository maintenance