𝔩𝔢𝔩𝕠𝔭𝔢𝔷
Theme

Homelab

Minecraft Hardening

Hardening Minecraft: Encrypted Storage, NetworkPolicy, and Security

Overview

This article hardens the Minecraft server by migrating to encrypted storage, adding NetworkPolicy, and pinning Helm versions. Game servers are internet-exposed via playit.gg - hardening limits the blast radius if compromised.

Tip

Having trouble? See v1.8.0 for what your setup should look like after completing this article.

Before You Begin

Prerequisites

What We're Hardening

ComponentBeforeAfter
StorageUnencrypted longhornEncrypted longhorn-encrypted
NetworkPolicyNoneEgress limited
Helm chartFloating versionPinned version

Why These Controls

Encrypted Storage: World data and player information protected at rest. Physical disk theft or node compromise no longer exposes plaintext data.

NetworkPolicy: Minecraft needs to reach the internet for player authentication and playit.gg tunnel. We can still block access to other VLANs (Network, Drive).

Helm Pinning: Ensures reproducible deployments without surprise breaking changes.

How Longhorn Encryption Works

Longhorn uses LUKS (Linux Unified Key Setup) for block-level encryption1. You cannot convert existing unencrypted volumes - the block format differs. Instead, we backup the data, create a new encrypted volume, and restore2.

Backup World Data

Create a tar backup of the entire data directory (/data mount).

# Get pod name
POD=$(kubectl get pod -n minecraft -o jsonpath='{.items[0].metadata.name}')

# Create backup inside container
kubectl exec -n minecraft $POD -- tar czf /tmp/minecraft-backup.tar.gz -C /data .

# Copy to local machine
kubectl cp minecraft/$POD:/tmp/minecraft-backup.tar.gz ./minecraft-backup-$(date +%Y%m%d).tar.gz

Verify the backup:

# Check file exists and size
ls -lh ./minecraft-backup-$(date +%Y%m%d).tar.gz

# List contents
tar tzf ./minecraft-backup-$(date +%Y%m%d).tar.gz | head -20

Expected: File is several hundred MB, contents show world folders, server.properties, etc.

Harden Minecraft

Check Current Version

# Find current chart version to pin
helm list -n minecraft

Note the chart version (e.g., minecraft-5.1.1) - this is what you'll pin.

PVC

Update to use the encrypted volume.

k8s/apps/minecraft/pvc.yaml:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: minecraft-data-encrypted # CHANGE from minecraft-data
    namespace: minecraft
spec:
    accessModes:
        - ReadWriteOnce
    storageClassName: longhorn-encrypted # CHANGE from longhorn
    resources:
        requests:
            storage: 20Gi

HelmRelease

k8s/apps/minecraft/helmrelease.yaml:

# ... existing HelmRepository ...
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
    name: minecraft
    namespace: minecraft
spec:
    interval: 30m
    chart:
        spec:
            chart: minecraft
            version: "5.1.1" # PIN to current version
            sourceRef:
                kind: HelmRepository
                name: minecraft
    # ... existing install, upgrade ...
    values:
        # ... existing values ...
        persistence:
            dataDir:
                enabled: true
                existingClaim: minecraft-data-encrypted # CHANGE from minecraft-data

NetworkPolicy

k8s/apps/minecraft/networkpolicy.yaml:

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
    name: minecraft
    namespace: minecraft
spec:
    podSelector: {}
    policyTypes:
        - Egress
    egress:
        # DNS resolution
        - to:
              - namespaceSelector:
                    matchLabels:
                        kubernetes.io/metadata.name: kube-system
          ports:
              - protocol: UDP
                port: 53
        # Internet (Mojang auth, playit.gg, plugin downloads)
        # Block private ranges
        - to:
              - ipBlock:
                    cidr: 0.0.0.0/0
                    except:
                        - 10.0.0.0/8
                        - 172.16.0.0/12
                        - 192.168.0.0/16

Kustomization

k8s/apps/minecraft/kustomization.yaml:

# ... existing header ...
resources:
    - namespace.yaml
    - pvc.yaml
    - secret.sops.yaml
    - helmrelease.yaml
    - networkpolicy.yaml # ADD

Deploy Changes

Commit Changes

git add k8s/apps/minecraft/
git commit -m "feat(minecraft): harden with encrypted storage and NetworkPolicy"
git push

Reconcile

flux reconcile source git flux-system
flux reconcile kustomization sync

Minecraft will start with an empty encrypted volume.

Restore Data

Copy and extract the backup to the running pod:

# Get pod name
POD=$(kubectl get pod -n minecraft -o jsonpath='{.items[0].metadata.name}')

# Copy backup to pod
kubectl cp ./minecraft-backup-*.tar.gz minecraft/$POD:/tmp/backup.tar.gz

# Extract backup (clears existing data first)
kubectl exec -n minecraft $POD -- sh -c "rm -rf /data/* && tar xzf /tmp/backup.tar.gz -C /data"

Restart to load restored data:

kubectl rollout restart deploy -n minecraft minecraft

Verify Hardening

Verify Pod Running

kubectl get pods -n minecraft

Expected: Pod shows Running with all containers ready.

Verify Encrypted PVC

Confirm the pod is using the encrypted volume:

kubectl get pod -n minecraft -l app=minecraft -o jsonpath='{.items[0].spec.volumes[?(@.name=="datadir")].persistentVolumeClaim.claimName}'

Expected: minecraft-data-encrypted

Verify NetworkPolicy

kubectl get networkpolicy -n minecraft

Expected: minecraft policy listed.

Verify World Loads

Check logs for successful startup:

kubectl logs -n minecraft deploy/minecraft --tail=20

Expected: World loaded, no errors. Login to the server to confirm player data and world are intact.

Clean Up Old Volume

After verifying Minecraft works:

# Remove old unencrypted volume
kubectl delete pvc -n minecraft minecraft-data

Next Steps

With Minecraft hardened, continue with Factorio hardening.

See: Factorio Hardening

Resources

Footnotes

  1. Longhorn, "Volume Encryption," longhorn.io. Accessed: Feb. 28, 2026. [Online]. Available: https://longhorn.io/docs/1.9.2/advanced-resources/security/volume-encryption/

  2. Longhorn, "Encrypt existing volume," github.com. Accessed: Feb. 28, 2026. [Online]. Available: https://github.com/longhorn/longhorn/issues/9502

Previous
Longhorn Hardening