Homelab
Longhorn Hardening
Hardening Longhorn: Pinned Version, Encryption, and NetworkPolicy
Overview
This article hardens Longhorn by pinning the Helm chart version, enabling encryption, and adding NetworkPolicy. Physical disk theft or node compromise currently exposes all persistent data in plaintext - we'll enable the encryption infrastructure here, then migrate existing volumes in each application's hardening article.
| Tip: | Having trouble? See v1.7.0 for what your setup should look like after completing this article. |
Before You Begin
Prerequisites
- MetalLB & Ingress Hardening completed
What We're Hardening
| Component | Before | After |
|---|---|---|
| Helm chart | 1.7.x (floating) | Pinned version |
| Encryption | None | Infrastructure enabled |
| NetworkPolicy | None | Egress limited |
Why These Controls
Helm Pinning: Floating versions can introduce breaking changes or vulnerabilities without notice. Pinning ensures reproducible deployments.
Encryption: Longhorn uses LUKS encryption for volumes. Without it, anyone with physical disk access can read all data. Encryption protects data at rest.
NetworkPolicy: Longhorn components need to communicate with each other and the Kubernetes API. We can limit egress to only required destinations.
| Note: | Encryption applies to NEW volumes only. Existing volumes are migrated in each application's hardening article (Phase 4). |
Harden Longhorn
Check: Current Helm Version
helm list -n longhorn-system Note the chart version (e.g., 1.7.3) - this is what you'll pin.
HelmRelease: Pin Chart Version
k8s/core/longhorn/helmrelease.yaml:
# ... existing header ...
spec:
interval: 1h
chart:
spec:
chart: longhorn
version: "1.7.3" # CHANGE from "1.7.x"
sourceRef:
kind: HelmRepository
name: longhorn
namespace: flux-system
# ... existing install, upgrade, values ... Update the version to match your current deployment if different.
Secret: Encryption Key
Create a secret with the encryption passphrase. Generate a strong passphrase and store it in your password manager.
k8s/core/longhorn/secret.sops.yaml:
---
apiVersion: v1
kind: Secret
metadata:
name: longhorn-crypto
namespace: longhorn-system
type: Opaque
stringData:
CRYPTO_KEY_VALUE: "<your-encryption-passphrase>"
CRYPTO_KEY_PROVIDER: "secret"
CRYPTO_KEY_CIPHER: "aes-xts-plain64"
CRYPTO_KEY_HASH: "sha256"
CRYPTO_KEY_SIZE: "256"
CRYPTO_PBKDF: "argon2i" Encrypt the secret:
sops -e -i k8s/core/longhorn/secret.sops.yaml StorageClass: Encrypted Volumes
k8s/core/longhorn/storageclass-encrypted.yaml:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-encrypted
provisioner: driver.longhorn.io
allowVolumeExpansion: true
reclaimPolicy: Retain
volumeBindingMode: Immediate
parameters:
numberOfReplicas: "2"
staleReplicaTimeout: "2880"
fromBackup: ""
encrypted: "true"
csi.storage.k8s.io/provisioner-secret-name: "longhorn-crypto"
csi.storage.k8s.io/provisioner-secret-namespace: "longhorn-system"
csi.storage.k8s.io/node-publish-secret-name: "longhorn-crypto"
csi.storage.k8s.io/node-publish-secret-namespace: "longhorn-system"
csi.storage.k8s.io/node-stage-secret-name: "longhorn-crypto"
csi.storage.k8s.io/node-stage-secret-namespace: "longhorn-system" NetworkPolicy: Restrict Longhorn Egress
k8s/core/longhorn/networkpolicy.yaml:
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: longhorn
namespace: longhorn-system
spec:
podSelector: {}
policyTypes:
- Egress
egress:
# DNS resolution
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
# Kubernetes API
- to:
- ipBlock:
cidr: 192.168.10.30/32
- ipBlock:
cidr: 192.168.10.31/32
- ipBlock:
cidr: 192.168.10.32/32
ports:
- protocol: TCP
port: 6443
# Lab VLAN (node communication for replica sync)
- to:
- ipBlock:
cidr: 192.168.10.0/24 Kustomization: Add Encryption and Policy
k8s/core/longhorn/kustomization.yaml:
# ... existing header ...
resources:
- namespace.yaml
- helmrepository.yaml
- helmrelease.yaml
- secret.sops.yaml # ADD
- storageclass-encrypted.yaml # ADD
- networkpolicy.yaml # ADD Deploy Changes
Git: Commit Encryption and Policy
git add k8s/core/longhorn/
git commit -m "feat(longhorn): harden with encryption and NetworkPolicy"
git push Flux: Sync Encryption and Policy
flux reconcile source git flux-system
flux reconcile kustomization sync Verify Hardening
Verify: Pinned Helm Version
kubectl get helmrelease -n longhorn-system longhorn -o jsonpath='{.spec.chart.spec.version}' Expected: Your pinned version. HelmChart reconciliation can take a minute.
Verify: Encryption Resources
kubectl get secret -n longhorn-system longhorn-crypto
kubectl get storageclass longhorn-encrypted Expected: Both resources exist.
Verify: NetworkPolicy Applied
kubectl get networkpolicy -n longhorn-system Expected: longhorn policy listed.
Next Steps
| Important: | If you're on Longhorn 1.7.x (from the v2 series), upgrade before creating encrypted volumes. Encryption fails on Talos 1.9+ without Longhorn 1.9.x. |
See: Longhorn Upgrade
With Longhorn hardened and upgraded, continue with application hardening.
See: Minecraft Hardening