𝔩𝔢𝔩𝕠𝔭𝔢𝔷
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