feat(minecraft): deploy journey-into-imagination PaperMC server
- PaperMC 26.1.2 via itzg/minecraft-server:2026.7.0 - Namespace: minecraft, Service: journey-into-imagination - TCP port 10182 (non-standard) via ingress-nginx tcp forwarding - Pure Storage CSI PVC (pure-block, 50Gi) for world data - World seed hardcoded: -5177989977648707969 - RCON password via ExternalSecret + 1Password Connect - SleepMost v5.6.2 plugin for single-player sleep - Whitelist off at launch, toggle-ready - ExternalDNS annotations for internal Technitium record - Manual steps: UniFi port forward WAN:10182→10.1.71.80:10182, Cloudflare A record + SRV for journey-into-imagination.mk-labs.cloud
This commit is contained in:
304
cluster/applications/minecraft/DEPLOYMENT-PLAN.md
Normal file
304
cluster/applications/minecraft/DEPLOYMENT-PLAN.md
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
# Journey Into Imagination — Minecraft Server Deployment Plan
|
||||||
|
|
||||||
|
**Application:** PaperMC Minecraft Server
|
||||||
|
**Namespace:** `minecraft`
|
||||||
|
**Deployment name:** `papermc`
|
||||||
|
**Service / DNS name:** `journey-into-imagination`
|
||||||
|
**ArgoCD path:** `cluster/applications/minecraft/`
|
||||||
|
**Reviewed:** _Pending Ryan approval_
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version Pinning
|
||||||
|
|
||||||
|
| Component | Version |
|
||||||
|
|-----------|---------|
|
||||||
|
| itzg/minecraft-server image | `2026.7.0` |
|
||||||
|
| PaperMC (Minecraft version) | `1.21.4` (build 232 — last stable 1.21.x) |
|
||||||
|
| SleepMost plugin | `5.6.2` (auto-downloaded at server start) |
|
||||||
|
|
||||||
|
> **Note on PaperMC versioning:** PaperMC migrated to a new version scheme (`26.x`) as of mid-2026. The task requested 1.21.x, so we pin `VERSION=1.21.4`. When you're ready to upgrade to the latest stable, change `VERSION` in `deployment.yaml` and `configmap.yaml` to `26.2` and bump the image tag to the latest `itzg/minecraft-server` release. Check plugin compatibility (SleepMost) before upgrading.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Storage
|
||||||
|
|
||||||
|
- **StorageClass:** `pure-block` (confirmed live — `kubectl get storageclass`)
|
||||||
|
- **PVC size:** 50Gi — expandable via Pure Storage CSI if the world grows
|
||||||
|
- **Mount:** `/data` inside the container (worlds, plugins, configs all live here)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Networking Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Internet (players)
|
||||||
|
|
|
||||||
|
| DNS: journey-into-imagination.mk-labs.cloud → WAN IP (Cloudflare A record)
|
||||||
|
|
|
||||||
|
UniFi UDM Pro
|
||||||
|
| Port Forward: WAN:25565 → 10.1.71.80:25565 (TCP)
|
||||||
|
|
|
||||||
|
ingress-nginx LoadBalancer (10.1.71.80)
|
||||||
|
| tcp-services ConfigMap: 25565 → minecraft/journey-into-imagination:25565
|
||||||
|
|
|
||||||
|
journey-into-imagination Service (ClusterIP, minecraft namespace)
|
||||||
|
|
|
||||||
|
papermc Pod (port 25565)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites — Manual Steps Before Deploying
|
||||||
|
|
||||||
|
### 1. Generate a real RCON password
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate a secure password
|
||||||
|
openssl rand -base64 24
|
||||||
|
# Output example: abc123... (save this — you'll need it)
|
||||||
|
|
||||||
|
# Base64-encode it for the Secret
|
||||||
|
echo -n 'YOUR_GENERATED_PASSWORD' | base64
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `cluster/applications/minecraft/secret.yaml` and replace the placeholder value:
|
||||||
|
```yaml
|
||||||
|
data:
|
||||||
|
rcon-password: <your-base64-encoded-password>
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ Do NOT commit real credentials in plaintext. If this is a concern long-term,
|
||||||
|
> migrate to ExternalSecrets + 1Password (Day 2 operation).
|
||||||
|
|
||||||
|
### 2. UniFi Port Forward (Ryan — manual step)
|
||||||
|
|
||||||
|
In UniFi Network → Firewall & Security → Port Forwarding:
|
||||||
|
- **Name:** `minecraft-papermc`
|
||||||
|
- **Protocol:** TCP
|
||||||
|
- **External Port:** 25565
|
||||||
|
- **Internal IP:** 10.1.71.80 (ingress-nginx LoadBalancer)
|
||||||
|
- **Internal Port:** 25565
|
||||||
|
- **Enabled:** Yes
|
||||||
|
|
||||||
|
### 3. Cloudflare DNS Records (Ryan — manual step)
|
||||||
|
|
||||||
|
In Cloudflare Dashboard → mk-labs.cloud zone:
|
||||||
|
|
||||||
|
**A Record (public server address):**
|
||||||
|
| Type | Name | Value | Proxy |
|
||||||
|
|------|------|-------|-------|
|
||||||
|
| A | `journey-into-imagination` | `<your-WAN-IP>` | DNS only (gray cloud) |
|
||||||
|
|
||||||
|
> Minecraft uses raw TCP — Cloudflare proxy (orange cloud) will NOT work.
|
||||||
|
> Use DNS-only mode (gray cloud).
|
||||||
|
|
||||||
|
**SRV Record (allows clients to connect without specifying port):**
|
||||||
|
| Type | Name | Service | Proto | Priority | Weight | Port | Target |
|
||||||
|
|------|------|---------|-------|----------|--------|------|--------|
|
||||||
|
| SRV | `_minecraft._tcp.journey-into-imagination` | `_minecraft` | `_tcp` | 0 | 5 | 25565 | `journey-into-imagination.mk-labs.cloud` |
|
||||||
|
|
||||||
|
> The SRV record allows players to connect using `journey-into-imagination.mk-labs.cloud`
|
||||||
|
> without specifying `:25565`. Most modern Minecraft clients resolve SRV records.
|
||||||
|
|
||||||
|
### 4. Internal DNS (Technitium — automated via ExternalDNS)
|
||||||
|
|
||||||
|
The Service in `service.yaml` has this annotation:
|
||||||
|
```yaml
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: journey-into-imagination.local.mk-labs.cloud
|
||||||
|
```
|
||||||
|
|
||||||
|
ExternalDNS (Technitium provider) will create the internal A record automatically when ArgoCD syncs.
|
||||||
|
No manual action required for internal DNS.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment Steps
|
||||||
|
|
||||||
|
### Step 1: Update the RCON Secret
|
||||||
|
|
||||||
|
Complete prerequisite #1 above, then commit the updated secret.
|
||||||
|
|
||||||
|
### Step 2: Commit and Push to Gitea
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/git/homelab
|
||||||
|
git status # review what changed
|
||||||
|
git add cluster/applications/minecraft/ cluster/platform/ingress-nginx/values.yaml
|
||||||
|
git commit -m "feat(minecraft): add Journey Into Imagination PaperMC server
|
||||||
|
|
||||||
|
- Namespace, Deployment, Service (journey-into-imagination), PVC, Secret, ConfigMap
|
||||||
|
- ArgoCD Application at cluster/applications/minecraft/
|
||||||
|
- ingress-nginx TCP forwarding: 25565 -> minecraft/journey-into-imagination:25565
|
||||||
|
- PaperMC 1.21.4, itzg/minecraft-server:2026.7.0, SleepMost 5.6.2
|
||||||
|
- StorageClass: pure-block, 50Gi PVC for world data"
|
||||||
|
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Verify ArgoCD Discovers and Syncs
|
||||||
|
|
||||||
|
ArgoCD app-of-apps auto-discovers `cluster/applications/minecraft/application.yaml`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Watch ArgoCD pick it up (from carousel-of-progress)
|
||||||
|
kubectl get application minecraft -n argocd -w
|
||||||
|
|
||||||
|
# Or check ArgoCD UI at argocd.local.mk-labs.cloud
|
||||||
|
```
|
||||||
|
|
||||||
|
Wait for status: `Synced` / `Healthy`
|
||||||
|
|
||||||
|
### Step 4: Watch the Pod Start Up
|
||||||
|
|
||||||
|
First startup will download the PaperMC jar — this can take 2-3 minutes.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pods -n minecraft -w
|
||||||
|
|
||||||
|
# Tail the logs to watch PaperMC boot
|
||||||
|
kubectl logs -n minecraft -l app.kubernetes.io/component=papermc -f
|
||||||
|
```
|
||||||
|
|
||||||
|
Look for:
|
||||||
|
```
|
||||||
|
[Server thread/INFO]: Done (X.XXXs)! For help, type "help"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Install SleepMost Plugin (auto via PLUGINS env var)
|
||||||
|
|
||||||
|
The `PLUGINS` env var in the ConfigMap points to the SleepMost JAR download URL.
|
||||||
|
itzg/minecraft-server downloads and installs it automatically on startup.
|
||||||
|
|
||||||
|
Verify it loaded:
|
||||||
|
```bash
|
||||||
|
kubectl exec -n minecraft -it deployment/papermc -- rcon-cli
|
||||||
|
# In rcon console:
|
||||||
|
plugins
|
||||||
|
# Should list: SleepMost
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Verify Connectivity
|
||||||
|
|
||||||
|
**Internal test (from carousel-of-progress):**
|
||||||
|
```bash
|
||||||
|
# Port probe — should succeed
|
||||||
|
nc -zv journey-into-imagination.local.mk-labs.cloud 25565
|
||||||
|
|
||||||
|
# Or via the ClusterIP directly
|
||||||
|
kubectl get svc -n minecraft
|
||||||
|
nc -zv <CLUSTER-IP> 25565
|
||||||
|
```
|
||||||
|
|
||||||
|
**External test (after UniFi port forward + DNS configured):**
|
||||||
|
- Open Minecraft Java Edition
|
||||||
|
- Add server: `journey-into-imagination.mk-labs.cloud`
|
||||||
|
- Should connect and show MOTD: "Journey Into Imagination"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Plugin Details
|
||||||
|
|
||||||
|
### SleepMost v5.6.2
|
||||||
|
|
||||||
|
- **Source:** https://github.com/mrgeneralq/sleep-most
|
||||||
|
- **Download:** https://github.com/mrgeneralq/sleep-most/releases/download/v5.6.2/SleepMost-5.6.2.jar
|
||||||
|
- **Compatibility:** PaperMC 1.8 through 1.21.x (use 5.6.2 for 1.21.x; 5.7.0+ drops backward compat)
|
||||||
|
- **Configuration:** Lives at `/data/plugins/SleepMost/config.yml` after first boot
|
||||||
|
|
||||||
|
Default behavior: configurable percentage of online players must sleep to skip night.
|
||||||
|
To tune (exec into the pod after first start):
|
||||||
|
```bash
|
||||||
|
kubectl exec -n minecraft -it deployment/papermc -- bash
|
||||||
|
cat /data/plugins/SleepMost/config.yml
|
||||||
|
# Edit as needed, then /sleepmost reload in rcon
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Geyser compatibility note:** SleepMost 5.x does NOT require Geyser to function.
|
||||||
|
> If you add Geyser later for Bedrock crossplay, SleepMost is compatible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Day 2 Operations
|
||||||
|
|
||||||
|
### Enabling the Whitelist
|
||||||
|
|
||||||
|
When ready to lock the server to approved players:
|
||||||
|
|
||||||
|
1. Edit `cluster/applications/minecraft/configmap.yaml`:
|
||||||
|
```yaml
|
||||||
|
WHITE_LIST: "true"
|
||||||
|
ENFORCE_WHITELIST: "true"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add players via RCON (live, no restart needed):
|
||||||
|
```bash
|
||||||
|
kubectl exec -n minecraft -it deployment/papermc -- rcon-cli
|
||||||
|
whitelist add <player_name>
|
||||||
|
whitelist list
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Commit the ConfigMap change for GitOps consistency.
|
||||||
|
Note: the Deployment will restart when the ConfigMap changes (env var reload).
|
||||||
|
Players will be briefly disconnected — plan accordingly.
|
||||||
|
|
||||||
|
### Console / RCON Access
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Interactive RCON (from inside the pod)
|
||||||
|
kubectl exec -n minecraft -it deployment/papermc -- rcon-cli
|
||||||
|
|
||||||
|
# One-shot command
|
||||||
|
kubectl exec -n minecraft -it deployment/papermc -- rcon-cli "list"
|
||||||
|
kubectl exec -n minecraft -it deployment/papermc -- rcon-cli "say Server restarting in 5 minutes"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upgrading PaperMC Version
|
||||||
|
|
||||||
|
1. Check PaperMC API: `curl -sA 'Mozilla/5.0' https://fill.papermc.io/v3/projects/paper/versions | head`
|
||||||
|
2. Update `VERSION` in `deployment.yaml` env vars and the comment header
|
||||||
|
3. Update image tag if a new `itzg/minecraft-server` release is out
|
||||||
|
4. Verify SleepMost compatibility with the new version
|
||||||
|
5. Commit, push — ArgoCD handles the rolling restart (Recreate strategy)
|
||||||
|
|
||||||
|
### Expanding PVC Storage
|
||||||
|
|
||||||
|
Pure Storage CSI supports online volume expansion:
|
||||||
|
```bash
|
||||||
|
kubectl patch pvc papermc-world-data -n minecraft \
|
||||||
|
-p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'
|
||||||
|
```
|
||||||
|
No pod restart required.
|
||||||
|
|
||||||
|
### Backups
|
||||||
|
|
||||||
|
No automated backup is configured in this skeleton.
|
||||||
|
Recommended Day 2 addition: CronJob that runs `rcon-cli save-all` + `rcon-cli save-off`,
|
||||||
|
copies `/data/world*` to a separate PVC or object store, then `rcon-cli save-on`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
| Symptom | Check |
|
||||||
|
|---------|-------|
|
||||||
|
| Pod stuck in `Init` / slow start | `kubectl logs -n minecraft -l app.kubernetes.io/component=papermc` — jar download may be slow |
|
||||||
|
| Port 25565 connection refused externally | Verify UniFi port forward is active; `kubectl get svc -n minecraft` shows correct ClusterIP |
|
||||||
|
| Players can't authenticate | `ONLINE_MODE=true` requires Mojang auth; check player has a valid Java account |
|
||||||
|
| World data lost after pod restart | Verify PVC is `Bound`; check `pure-block` StorageClass is healthy |
|
||||||
|
| EULA error in logs | `EULA=TRUE` is set in deployment.yaml — this should not occur; check env var injection |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Manifest Summary
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `namespace.yaml` | `minecraft` namespace |
|
||||||
|
| `application.yaml` | ArgoCD Application (sync-wave 20) |
|
||||||
|
| `pvc.yaml` | 50Gi pure-block PVC for world data |
|
||||||
|
| `secret.yaml` | RCON password (⚠️ placeholder — update before deploy) |
|
||||||
|
| `configmap.yaml` | server.properties overrides + SleepMost plugin download |
|
||||||
|
| `deployment.yaml` | PaperMC Deployment (Recreate strategy, resource limits set) |
|
||||||
|
| `service.yaml` | ClusterIP Service named `journey-into-imagination` |
|
||||||
|
| `../../../platform/ingress-nginx/values.yaml` | Added `tcp: 25565` forwarding entry |
|
||||||
23
cluster/applications/minecraft/application.yaml
Normal file
23
cluster/applications/minecraft/application.yaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: minecraft
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "20"
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://gitea.mk-labs.cloud/rblundon/homelab.git
|
||||||
|
targetRevision: main
|
||||||
|
path: cluster/applications/minecraft
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: minecraft
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
45
cluster/applications/minecraft/configmap.yaml
Normal file
45
cluster/applications/minecraft/configmap.yaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
# server.properties overrides for Journey Into Imagination
|
||||||
|
# itzg/minecraft-server reads these as environment variables and
|
||||||
|
# writes them into server.properties on startup.
|
||||||
|
# Full list: https://docker-minecraft-server.readthedocs.io/en/latest/configuration/server-properties/
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: papermc-config
|
||||||
|
namespace: minecraft
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
data:
|
||||||
|
# Server identity
|
||||||
|
MOTD: "Journey Into Imagination"
|
||||||
|
SERVER_NAME: "Journey Into Imagination"
|
||||||
|
|
||||||
|
# Game settings
|
||||||
|
GAMEMODE: "survival"
|
||||||
|
DIFFICULTY: "normal"
|
||||||
|
PVP: "true"
|
||||||
|
MAX_PLAYERS: "20"
|
||||||
|
ALLOW_FLIGHT: "true"
|
||||||
|
SPAWN_PROTECTION: "0"
|
||||||
|
SEED: "-5177989977648707969"
|
||||||
|
|
||||||
|
# Auth
|
||||||
|
ONLINE_MODE: "true"
|
||||||
|
|
||||||
|
# Whitelist — set to true when ready to lock down the server
|
||||||
|
WHITE_LIST: "false"
|
||||||
|
ENFORCE_WHITELIST: "false"
|
||||||
|
|
||||||
|
# Performance / tick safety
|
||||||
|
MAX_TICK_TIME: "180000"
|
||||||
|
|
||||||
|
# RCON (enabled so plugins/admin tools can connect)
|
||||||
|
ENABLE_RCON: "true"
|
||||||
|
RCON_PORT: "25575"
|
||||||
|
|
||||||
|
# Plugin auto-download — SleepMost for single-player sleep
|
||||||
|
# SleepMost v5.6.2: supports PaperMC 1.21.x (use latest release for 1.21.11+)
|
||||||
|
# Source: https://github.com/mrgeneralq/sleep-most/releases
|
||||||
|
PLUGINS: "https://github.com/mrgeneralq/sleep-most/releases/download/v5.6.2/SleepMost-5.6.2.jar"
|
||||||
179
cluster/applications/minecraft/deployment.yaml
Normal file
179
cluster/applications/minecraft/deployment.yaml
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
---
|
||||||
|
# PaperMC Minecraft Server — Journey Into Imagination
|
||||||
|
#
|
||||||
|
# Image: itzg/minecraft-server:2026.7.0
|
||||||
|
# PaperMC version: 26.1.2 (new PaperMC versioning scheme, mid-2026+; requires Java 25)
|
||||||
|
# NOTE: 26.x series uses PaperMC's independent versioning (not Minecraft version-based).
|
||||||
|
# Plugin ecosystem is still catching up — verify plugin compat before adding new ones.
|
||||||
|
#
|
||||||
|
# itzg image documentation: https://docker-minecraft-server.readthedocs.io
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: papermc
|
||||||
|
namespace: minecraft
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
app.kubernetes.io/version: "26.1.2"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
# Recreate strategy — Minecraft server requires exclusive access to world data.
|
||||||
|
# RollingUpdate WILL cause world corruption if both pods mount the PVC simultaneously.
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
app.kubernetes.io/version: "26.1.2"
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: false # itzg image requires root for some setup steps
|
||||||
|
fsGroup: 1000
|
||||||
|
containers:
|
||||||
|
- name: papermc
|
||||||
|
# Pinned tag — never use :latest in production
|
||||||
|
image: itzg/minecraft-server:2026.7.0
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: minecraft
|
||||||
|
containerPort: 25565
|
||||||
|
protocol: TCP
|
||||||
|
- name: rcon
|
||||||
|
containerPort: 25575
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: EULA
|
||||||
|
value: "TRUE"
|
||||||
|
- name: TYPE
|
||||||
|
value: "PAPER"
|
||||||
|
- name: VERSION
|
||||||
|
value: "26.1.2"
|
||||||
|
# Server settings from ConfigMap
|
||||||
|
- name: MOTD
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: MOTD
|
||||||
|
- name: SERVER_NAME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: SERVER_NAME
|
||||||
|
- name: GAMEMODE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: GAMEMODE
|
||||||
|
- name: DIFFICULTY
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: DIFFICULTY
|
||||||
|
- name: PVP
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: PVP
|
||||||
|
- name: MAX_PLAYERS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: MAX_PLAYERS
|
||||||
|
- name: ALLOW_FLIGHT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: ALLOW_FLIGHT
|
||||||
|
- name: SPAWN_PROTECTION
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: SPAWN_PROTECTION
|
||||||
|
- name: SEED
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: SEED
|
||||||
|
- name: ONLINE_MODE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: ONLINE_MODE
|
||||||
|
- name: WHITE_LIST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: WHITE_LIST
|
||||||
|
- name: ENFORCE_WHITELIST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: ENFORCE_WHITELIST
|
||||||
|
- name: MAX_TICK_TIME
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: MAX_TICK_TIME
|
||||||
|
- name: ENABLE_RCON
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: ENABLE_RCON
|
||||||
|
- name: RCON_PORT
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: RCON_PORT
|
||||||
|
- name: PLUGINS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: papermc-config
|
||||||
|
key: PLUGINS
|
||||||
|
# RCON password from Secret
|
||||||
|
- name: RCON_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: papermc-rcon
|
||||||
|
key: rcon-password
|
||||||
|
volumeMounts:
|
||||||
|
- name: world-data
|
||||||
|
mountPath: /data
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: "1"
|
||||||
|
memory: "2Gi"
|
||||||
|
limits:
|
||||||
|
cpu: "4"
|
||||||
|
memory: "6Gi"
|
||||||
|
# Startup probe — give the server time to download PaperMC jar on first boot
|
||||||
|
startupProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: minecraft
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30 # 5 minutes total
|
||||||
|
# Liveness probe — restart if the TCP port goes away
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: minecraft
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 30
|
||||||
|
failureThreshold: 3
|
||||||
|
# Readiness probe — only route traffic when server is accepting connections
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: minecraft
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 3
|
||||||
|
volumes:
|
||||||
|
- name: world-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: papermc-world-data
|
||||||
28
cluster/applications/minecraft/externalsecret.yaml
Normal file
28
cluster/applications/minecraft/externalsecret.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
# ExternalSecret — pulls RCON password from 1Password Connect
|
||||||
|
# Prereq: create a "minecraft" item in the mk-labs 1Password vault
|
||||||
|
# with a field named "rcon_password" set to a strong random password.
|
||||||
|
# Generate one: openssl rand -base64 24
|
||||||
|
#
|
||||||
|
# ClusterSecretStore: onepassword-connect (platform/onepassword-connect/)
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: papermc-rcon
|
||||||
|
namespace: minecraft
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: onepassword-connect
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
target:
|
||||||
|
name: papermc-rcon
|
||||||
|
creationPolicy: Owner
|
||||||
|
data:
|
||||||
|
- secretKey: rcon-password
|
||||||
|
remoteRef:
|
||||||
|
key: minecraft
|
||||||
|
property: rcon_password
|
||||||
8
cluster/applications/minecraft/namespace.yaml
Normal file
8
cluster/applications/minecraft/namespace.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: minecraft
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/managed-by: argocd
|
||||||
18
cluster/applications/minecraft/pvc.yaml
Normal file
18
cluster/applications/minecraft/pvc.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
# World data persistent volume — Pure Storage block CSI
|
||||||
|
# StorageClass confirmed: pure-block (pxd.portworx.com, RWO, allowVolumeExpansion=true)
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: papermc-world-data
|
||||||
|
namespace: minecraft
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
storageClassName: pure-block
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 50Gi
|
||||||
30
cluster/applications/minecraft/service.yaml
Normal file
30
cluster/applications/minecraft/service.yaml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# Service named after the thematic identity: journey-into-imagination
|
||||||
|
# This is the DNS name used in ingress-nginx TCP forwarding config.
|
||||||
|
# Internal DNS: journey-into-imagination.local.mk-labs.cloud
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: journey-into-imagination
|
||||||
|
namespace: minecraft
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
annotations:
|
||||||
|
# Internal DNS via ExternalDNS + Technitium
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: journey-into-imagination.local.mk-labs.cloud
|
||||||
|
# Non-standard external port 10182 → internal 25565 (via ingress-nginx tcp forwarding)
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: minecraft
|
||||||
|
app.kubernetes.io/component: papermc
|
||||||
|
ports:
|
||||||
|
- name: minecraft
|
||||||
|
port: 25565
|
||||||
|
targetPort: 25565
|
||||||
|
protocol: TCP
|
||||||
|
- name: rcon
|
||||||
|
port: 25575
|
||||||
|
targetPort: 25575
|
||||||
|
protocol: TCP
|
||||||
@@ -41,3 +41,18 @@ controller:
|
|||||||
labelSelector:
|
labelSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: ingress-nginx
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# TCP port forwarding — raw TCP services (non-HTTP)
|
||||||
|
# Each entry maps an external port to a namespace/service:port target.
|
||||||
|
# The Helm chart automatically:
|
||||||
|
# 1. Creates the tcp-services ConfigMap in the ingress-nginx namespace
|
||||||
|
# 2. Passes --tcp-services-configmap=ingress-nginx/tcp-services to the controller
|
||||||
|
# 3. Adds the port to the nginx-ingress LoadBalancer Service
|
||||||
|
#
|
||||||
|
# After ArgoCD syncs, add a UniFi port forward:
|
||||||
|
# WAN:10182 → 10.1.71.80:10182 (TCP)
|
||||||
|
# Non-standard port for security (default 25565 avoided).
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
tcp:
|
||||||
|
10182: "minecraft/journey-into-imagination:25565"
|
||||||
|
|||||||
Reference in New Issue
Block a user