𝔩𝔢𝔩𝕠𝔭𝔢𝔷
Theme
Connect With Me on LinkedIn Buy Me a Coffee

Homelab

Minecraft Paper Server

Deploy a Minecraft Paper Server on Kubernetes with Persistent Storage and Tailscale Access

Overview

This article walks through deploying a Minecraft Java Edition server on your Kubernetes cluster with persistent world storage and Tailscale-based remote access. You will use the itzg/minecraft-server Helm chart with Paper server type for optimal performance and plugin support.

Tip:Having trouble? See v0.12.0 for what your setup should look like after completing this article.

Before You Begin

Prerequisites

Create Minecraft Manifests

Using the itzg/minecraft-server chart1 with the Docker Minecraft Server image2. Server types include VANILLA, PAPER3, FORGE, and FABRIC - we use PAPER for performance optimizations and plugin support. The configuration includes Aikar's JVM flags4 for optimal Paper performance.

Init Workspace

cd ~/homelab
export KUBECONFIG=$(pwd)/talos/clusterconfig/kubeconfig
mkdir -p k8s/apps/minecraft
git checkout -b dev

Namespace

k8s/apps/minecraft/namespace.yaml:

---
apiVersion: v1
kind: Namespace
metadata:
  name: minecraft

PersistentVolumeClaim

Persistent storage for world data.

k8s/apps/minecraft/pvc.yaml:

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

HelmRelease

k8s/apps/minecraft/helmrelease.yaml:

---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: minecraft
  namespace: minecraft
spec:
  interval: 24h
  url: https://itzg.github.io/minecraft-server-charts
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: minecraft
  namespace: minecraft
spec:
  interval: 30m
  chart:
    spec:
      chart: minecraft
      sourceRef:
        kind: HelmRepository
        name: minecraft
  install:
    remediation:
      retries: 3
  upgrade:
    remediation:
      retries: 3
  values:
    # Server type options: VANILLA, PAPER, FORGE, FABRIC
    # We use PAPER for performance and plugin support
    minecraftServer:
      eula: 'TRUE'
      version: '1.21.11'
      type: 'PAPER'
      difficulty: normal
      motd: 'Experience is merely the name men gave to their mistakes.'
      maxPlayers: 10
      gameMode: survival
      pvp: false
      onlineMode: true # Requires Mojang auth
      memory: 4096M
      viewDistance: 32
      enableCommandBlock: true
      serviceType: LoadBalancer # MetalLB assigns IP for Tailscale access

    # Persistence - use our PVC for world data
    persistence:
      dataDir:
        enabled: true
        existingClaim: minecraft-data

    # Resource limits - scale based on player count:
    # 1-5 players: 2-3GB RAM, 1-2 cores
    # 5-10 players: 3-4GB RAM, 2-3 cores
    # 10-20 players: 4-6GB RAM, 3-4 cores
    resources:
      requests:
        memory: 4Gi
        cpu: 2000m
      limits:
        memory: 6Gi
        cpu: 4000m

    # Aikar's JVM flags for optimal Paper performance
    extraEnv:
      JVM_XX_OPTS: '-XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+ParallelRefProcEnabled -XX:+PerfDisableSharedMem -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:G1HeapWastePercent=5 -XX:G1MaxNewSizePercent=40 -XX:G1MixedGCCountTarget=4 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1NewSizePercent=30 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:G1ReservePercent=20 -XX:InitiatingHeapOccupancyPercent=15 -XX:MaxGCPauseMillis=200 -XX:MaxTenuringThreshold=1 -XX:SurvivorRatio=32 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true'

Kustomization

k8s/apps/minecraft/kustomization.yaml:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - namespace.yaml
  - pvc.yaml
  - helmrelease.yaml

Apps Kustomization

Add minecraft to k8s/apps/kustomization.yaml:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - plex
  - factorio
  - minecraft

Deploy Minecraft

Commit Changes

cd ~/homelab

git add k8s/apps/minecraft/ k8s/apps/kustomization.yaml
git commit -m "feat(minecraft): add Minecraft server"

git checkout main
git merge --ff-only dev
git push

Reconcile Flux

flux reconcile source git flux-system && flux reconcile kustomization sync

Verify Minecraft

Deployment Status

# Check HelmRelease status
flux get helmreleases -n minecraft

# Check pods (first startup takes 2-5 min)
kubectl get pods -n minecraft -w

# Check service (note the EXTERNAL-IP)
kubectl get svc -n minecraft

# View logs
kubectl logs -n minecraft -l app=minecraft -f

Tailscale Access

Get the LoadBalancer IP:

kubectl get svc -n minecraft minecraft -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

Connect:

  1. Ensure your device is connected to Tailscale
  2. Open Minecraft Java Edition
  3. Multiplayer → Add Server
  4. Server Address: <EXTERNAL-IP>:25565
  5. Save and connect

At this point, Minecraft is working via Tailscale.

Next Steps

This concludes the core homelab series. Your cluster now runs media streaming, game servers, and has secure remote access from anywhere.

For optional enhancements to your Minecraft server:

Resources

Footnotes

  1. itzg, "Minecraft Server Charts," github.com. Accessed: Dec. 22, 2025. [Online]. Available: https://github.com/itzg/minecraft-server-charts

  2. itzg, "Docker Minecraft Server," github.com. Accessed: Dec. 22, 2025. [Online]. Available: https://github.com/itzg/docker-minecraft-server

  3. PaperMC, "Paper Documentation," docs.papermc.io. Accessed: Dec. 22, 2025. [Online]. Available: https://docs.papermc.io/

  4. PaperMC, "Aikar's Flags," docs.papermc.io. Accessed: Dec. 22, 2025. [Online]. Available: https://docs.papermc.io/paper/aikars-flags

Previous
Factorio Kubernetes Server