A Kubernetes CSI driver that provides LUKS encryption on top of local storage, similar to rancher.io/local-path but with built-in encryption capabilities.
- LUKS Encryption: Automatically encrypts volumes using LUKS (Linux Unified Key Setup)
- Local Storage: Uses local filesystem for storage (similar to local-path provisioner)
- Secret Management: Integrates with Kubernetes secrets for passphrase management
- CSI Compliance: Full CSI specification compliance with staging/unstaging support
- Filesystem Support: Supports ext4, ext3, and xfs filesystems
The driver consists of:
- Controller Service: Handles volume provisioning and deprovisioning
- Node Service: Handles LUKS operations, formatting, mounting/unmounting
- Identity Service: Provides driver metadata and capabilities
The driver supports the following StorageClass parameters:
parameters:
# Local path where volumes will be stored (optional)
local-path: "/opt/local-path-provisioner"
# LUKS encryption secret reference (required)
csi.storage.k8s.io/node-stage-secret-name: "luks-secret"
csi.storage.k8s.io/node-stage-secret-namespace: "kube-system"
# Key name within the secret that contains the passphrase (optional, default: "passphrase")
passphraseKey: "passphrase"
# Filesystem type (optional, default: ext4)
fsType: "ext4"
# Manual fsGroup override (optional)
# If set, this fsGroup will be used for this StorageClass instead of auto-detecting from pods
fsGroup: "26" # Example: Use PostgreSQL group ID- Kubernetes 1.20+
cryptsetuputility available on all nodes- Privileged containers support (for LUKS operations)
-
Add the Helm repository:
helm repo add lukscryptwalker-csi https://algonomia.github.io/lukscryptwalker-csi/ helm repo update
-
Install with Helm:
# Install with default configuration helm install my-lukscryptwalker lukscryptwalker-csi/lukscryptwalker-csi \ --namespace kube-system \ --create-namespace # Or with custom values helm install my-lukscryptwalker lukscryptwalker-csi/lukscryptwalker-csi \ --namespace kube-system \ --create-namespace \ --values my-values.yaml
-
Customize installation:
# my-values.yaml image: repository: my-registry/lukscryptwalker-csi tag: "v1.0.3" storage: localPath: "/mnt/encrypted-volumes" # Create multiple StorageClasses for different use cases storageClasses: - name: my-encrypted-storage isDefault: true fsGroup: 26 # PostgreSQL secret: name: luks-secret namespace: kube-system passphraseKey: "passphrase" - name: mysql-encrypted fsGroup: 999 # MySQL localPath: "/mnt/mysql-volumes" secret: name: luks-secret namespace: kube-system passphraseKey: "passphrase"
-
Build the driver:
make docker-build
-
Deploy to Kubernetes:
kubectl apply -f deploy/
-
Create a secret with your passphrase:
kubectl create secret generic luks-secret \ --from-literal=passphrase=your-secure-passphrase \ -n kube-system
-
Create a StorageClass:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: lukscryptwalker-local provisioner: lukscryptwalker.csi.k8s.io parameters: local-path: "/opt/local-path-provisioner" csi.storage.k8s.io/node-stage-secret-name: "luks-secret" csi.storage.k8s.io/node-stage-secret-namespace: "kube-system" passphraseKey: "passphrase" reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true
-
Create a PVC:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: encrypted-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: lukscryptwalker-local
-
Use in a Pod:
apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name: app image: nginx volumeMounts: - name: encrypted-storage mountPath: /data volumes: - name: encrypted-storage persistentVolumeClaim: claimName: encrypted-pvc
-
Expand a volume:
# Edit the PVC to increase the size kubectl patch pvc encrypted-pvc -p '{"spec":{"resources":{"requests":{"storage":"2Gi"}}}}' # Or edit directly kubectl edit pvc encrypted-pvc
The expansion process includes:
- Controller expands the backing file
- Node service resizes the LUKS device
- Node service resizes the filesystem (ext4/xfs)
- Changes are reflected in the pod automatically
-
Using custom passphrase key names:
# Create secret with custom key name kubectl create secret generic my-luks-secret \ --from-literal=encryption-key=my-secure-passphrase \ -n kube-system# StorageClass with custom passphrase key apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: custom-lukscryptwalker provisioner: lukscryptwalker.csi.k8s.io parameters: csi.storage.k8s.io/node-stage-secret-name: "my-luks-secret" csi.storage.k8s.io/node-stage-secret-namespace: "kube-system" passphraseKey: "encryption-key" # Custom key name reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true
The driver supports flexible file system permission management:
By default, the driver automatically detects the fsGroup from requesting pods and sets appropriate permissions:
apiVersion: v1
kind: Pod
metadata:
name: postgres-pod
spec:
securityContext:
fsGroup: 26 # PostgreSQL group
containers:
- name: postgres
image: postgres:15
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: postgres-pvcThe driver will automatically:
- Create directories with
0775permissions - Set group ownership to
26(PostgreSQL group) - Allow both the container user and group to write
For scenarios where specific StorageClasses should always use a particular group, configure it directly in the StorageClass:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: postgres-encrypted
provisioner: lukscryptwalker.csi.k8s.io
parameters:
fsGroup: "26" # Manual override for PostgreSQL
csi.storage.k8s.io/node-stage-secret-name: "luks-secret"
csi.storage.k8s.io/node-stage-secret-namespace: "kube-system"- No fsGroup:
0755permissions (owner only) - uses auto-detection from pod - With fsGroup:
0775permissions + group ownership - uses specified fsGroup from StorageClass - StorageClass fsGroup takes precedence over automatic pod detection
- Passphrase Management: Store passphrases in Kubernetes secrets with appropriate RBAC
- Node Access: The driver requires privileged access on nodes for LUKS operations
- Data at Rest: All data is encrypted using LUKS with AES-256 encryption by default
- Key Rotation: Consider implementing key rotation policies for production use
-
Setup development environment:
make dev-setup
-
Run tests:
make test -
Deploy to kind cluster:
make kind-deploy
-
Clean up:
make kind-clean
kubectl logs -n kube-system -l app=lukscryptwalker-csi-node
kubectl logs -n kube-system -l app=lukscryptwalker-csi-controller# On the node
sudo cryptsetup status
ls -la /dev/mapper/- Permission denied errors: Ensure the driver has privileged access
- cryptsetup command not found: Install cryptsetup on all nodes
- Secret not found: Verify the secret exists in the correct namespace
- Mount failures: Check filesystem support and device permissions
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
This project is licensed under the Apache License 2.0.