Minecraft Worlds
Quickstart: Bring a World Up
-
Create via Web Control Plane (
https://mc.drheck.dev) or CLI (ipctl):- Web UI (Recommended): Open https://mc.drheck.dev, click + New World, style the world name/MOTD and 64Γ64 icon, preview/reroll the world seed with the live 2D biome map, and click Create & Provision World.
- CLI (
ipctl):
(Allocates backend IPv6sudo /data/minecraft/ipctl create <name> --dnsfd77:7777:5010::1337:3c:d00d:<hex>/64in/etc/systemd/network/20-wired.network.d/minecraft.conf, configures HAProxy SNI routing in/etc/haproxy/conf.d/minecraft_backends.cfgand/etc/haproxy/minecraft_hosts.map, adds<name>.drheck.devto/var/unbound/etc/unbound.minecraft.confondanknastyusing a short-lived 5-minutestep-caSSH user certificate, and syncs public A/AAAA records to deSEC.io).
-
Configure the backend server: In your backend server's
server.properties:server-ip=fd77:7777:5010::1337:3c:d00d:<hex> server-port=25565 online-mode=true(Backend servers run with
online-mode=true, listening on standard port25565on their dedicated ULA IPv6 address). -
Start the server: Start via
https://mc.drheck.dev(Start button or automatic On-Demand wake-on-join) orsudo systemctl start minecraft@<slug>.service. -
Connect: Players connect using
<name>.drheck.dev(standard port25565). Microsoft account authentication takes place directly between the client and the backend server.
Quickstart: Take a World Down
-
Stop the backend server: Click Stop in
https://mc.drheck.dev, sendstopin the live web console, or runsudo systemctl stop minecraft@<slug>.service. -
What Players See When Offline or Standby (
On-Demand): HAProxy intercepts all Multiplayer Server List pings ($\text{state} = 1$) and offline/standby Login joins ($\text{state} = 2$) via/etc/haproxy/minecraft.luaandmc-manager:- In the Multiplayer Server List (
state = 1): Returns the server's configured custom MOTD and 64Γ64server-icon.png(favicon) immediately, with version status badgeStandby (Join to Wake)(forondemandservers) orOffline(formanualservers). - When Clicking "Join Server" (
state = 2):ondemandStandby: Automatically triggersminecraft@<slug>.serviceto boot and displays a gold countdown screen (Waking up <Server>... Ready in ~20s!).manualOffline: Immediately disconnects with a clean red screen (<Server> is currently offline. Start at mc.drheck.dev).
- In the Multiplayer Server List (
-
Disable or remove router mapping & DNS (Teardown):
- Temporary takedown (disable in router only):
sudo /data/minecraft/ipctl route disable <name> - Complete teardown (release IP, remove HAProxy route, purge DNS):
sudo /data/minecraft/ipctl delete <name> --dns
- Temporary takedown (disable in router only):
Architecture & Design Details
1. Unified Endpoint Model
All public and LAN client connections resolve to the single Minecraft Router endpoint pair:
- IPv4:
10.0.0.113(NAT port-forwarded from WAN IPv4:25565ondanknasty) - IPv6:
fd77:7777:5010::1337:f1ac:d00d:3c(dynamically mapped to GUA<gua_prefix>:1337:f1ac:d00d:3cin public DNS)
Whether connecting via pokelovers.drheck.dev, desertworld.drheck.dev, or any other server subdomain, players connect to this exact IP pair on standard port 25565.
2. Transparent TCP SNI Handshake Routing & Live Ping Injection (HAProxy + mc-manager)
Rather than using an application-level proxy (which breaks vanilla Diffie-Hellman encryption and forces online-mode=false), HAProxy performs transparent pre-handshake packet inspection:
- HAProxy listens dual-stack on
10.0.0.113:25565and[fd77:7777:5010::1337:f1ac:d00d:3c]:25565. - When a player connects, HAProxy peeks at the initial unencrypted Minecraft handshake packet (
0x00) via/etc/haproxy/minecraft.luaand extracts the requested hostname (txn.mc_host, e.g.pokelovers.drheck.dev) and handshake state (txn.mc_state:1= Status Ping,2= Login Join). - For All Multiplayer Server List Pings ($\text{state} = 1$):
Each backend uses the rule:
tcp-request content use-service lua.mc_offline if { var(txn.mc_state) -m int eq 1 } || !{ nbsrv(<slug>) gt 0 }lua.mc_offlinequeriesmc-manager(http://127.0.0.1:8095/internal/haproxywithSTATUS <slug>). If the backend JVM is running,mc-managerqueries the backend's live TCP status (0x00) to obtain real-time online player counts and version metadata, then overlays the latestmotdfromserver.propertiesandfaviconfrom/data/minecraft/<dir>/server-icon.png. This ensures MOTD styling and 64Γ64 icon changes saved inmc.drheck.devappear immediately on client Refresh without restarting a running Minecraft server. - For Player Login Joins ($\text{state} = 2$):
- If the backend server is UP: HAProxy splices the raw TCP stream directly to
[fd77:7777:5010::1337:3c:d00d:<hex>]:25565. The client and backend perform native Microsoft/Mojangonline-mode=trueauthentication directly over the spliced TCP connection. - If the backend server is DOWN:
lua.mc_offlinesendsJOIN <slug>tomc-manager, which wakesondemandservers automatically and returns a formatted Minecraft Disconnect packet (0x00).
- If the backend server is UP: HAProxy splices the raw TCP stream directly to
3. Backend IPv6 Address Scheme & Active Worlds
Each backend Minecraft server is isolated on a dedicated Unique Local Address (ULA) on interface eth77 of ul:
- Prefix:
fd77:7777:5010::1337:3c:d00d:<hex>/64 - Port: Each server binds to standard port
25565on its assigned IPv6 address. - Active Managed Worlds:
| Hex ID | Slug / Subdomain | Display Name | Backend ULA IPv6 Address | Lifecycle Mode |
|---|---|---|---|---|
1 |
pokelovers.drheck.dev |
Poke Lovers |
fd77:7777:5010::1337:3c:d00d:1/64 |
ondemand (20G heap) |
2 |
desertworld.drheck.dev |
β ππ’π°π’π―π± ππ¬π―π©π‘ β |
fd77:7777:5010::1337:3c:d00d:2/64 |
ondemand (8G heap) |
4. Web Map (BlueMap) & Authentik Gated HTTPS
Interactive 3D web mapping for Minecraft is powered by BlueMap running in standalone watch mode:
- Service:
bluemap-pokelovers.servicerunning from/data/minecraft/poke lovers/bluemap.- Automatically updates the rendered 3D map as chunks change in
/data/minecraft/poke lovers/world. - Serves live map data & Server-Sent Events (SSE) updates on internal port
8100.
- Automatically updates the rendered 3D map as chunks change in
- Reverse Proxy & Authentication: NGINX terminates SSL on port
443at/etc/nginx/sites-available/pokeloversand gates access behind Authentik ForwardAuth (/outpost.goauthentik.io/auth/nginx).- Serves directly at
https://pokelovers.drheck.dev. - Unauthenticated visitors are automatically redirected to
auth.drheck.devto log in before viewing the 3D map.
- Serves directly at
5. Network & DNS Automation (ipctl) β Externalized Configs & Short-Lived SSH CA
To prevent dynamic Minecraft world provisioning from mutating code-reviewed host and router configuration files (/etc/systemd/network/20-wired.network, /etc/haproxy/haproxy.cfg, and /home/luke/git/router_config/unbound.conf), /data/minecraft/ipctl (symlinked at /home/luke/bin/ipctl) operates exclusively on dedicated external drop-in and include files:
| Subsystem | Static Code-Reviewed Base Config (Never Modified by ipctl) |
Dynamic External File Managed by ipctl |
Mirror in /data/minecraft/.network/ |
|---|---|---|---|
systemd-networkd (ul) |
/etc/systemd/network/20-wired.network |
/etc/systemd/network/20-wired.network.d/minecraft.conf |
minecraft.network.conf |
HAProxy Map (ul) |
/etc/haproxy/haproxy.cfg |
/etc/haproxy/minecraft_hosts.map |
minecraft_hosts.map |
HAProxy Backends (ul) |
/etc/haproxy/haproxy.cfg (loads -f /etc/haproxy/conf.d) |
/etc/haproxy/conf.d/minecraft_backends.cfg |
minecraft_backends.cfg |
Unbound DNS (danknasty) |
/home/luke/git/router_config/unbound.conf (has include: "/var/unbound/etc/unbound.minecraft.conf") |
/var/unbound/etc/unbound.minecraft.conf |
unbound.minecraft.conf |
Programmatic Short-Lived SSH CA Authentication (step-ca $\longrightarrow$ danknasty)
When /data/minecraft/ipctl is invoked with --dns (either interactively or unattended by mc-manager.service after a reboot when no ssh-agent is active):
ipctlgenerates a fresh ephemeral Ed25519 keypair in a mode-0700temporary directory (atexit-cleaned).ipctlrequests a 5-minute (--not-after=5m) SSH user certificate for principallukefrom the localstep-cacontainer using thewebshell-svcJWK provisioner (the same short-lived CA used bywebshell.drheck.dev).danknastyvalidates the certificate againstTrustedUserCAKeys /etc/ssh/drheck_ca_user_key.pub(configured in/etc/sshd_config.d/10-drheck-certs.conf), allowingipctlto update/var/unbound/etc/unbound.minecraft.conf, rundoas unbound-checkconfanddoas rcctl restart unbound, and invoke/home/luke/git/router_config/dns_danger_sync.py --forceto synchronize publicAandAAAArecords to deSEC.io.- Both
update_dns.pyanddns_danger_sync.py(as well asverify_dns.sh) ondanknastyrecursively followinclude:directives inunbound.conf, ensuring all external Minecraft subdomains are automatically included during prefix rotations and deSEC.io synchronization.
Backups & Disaster Recovery
Both the HAProxy router layer and the mc-manager control plane (including all external network, proxy, and DNS mirror files) are integrated into /home/luke/git/backups/ul/scripts/:
- Control Plane & External Network Backup:
/home/luke/git/backups/ul/scripts/backup/mc_manager- Archives
/data/minecraft/.manager,/data/minecraft/.network,/data/minecraft/ipctl,/usr/local/bin/{mc-manager,mc-runner,mc-seed-render},/etc/systemd/system/{mc-manager.service,minecraft@.service},/etc/systemd/network/20-wired.network.d/minecraft.conf,/etc/nginx/sites-available/mc,/etc/haproxy/minecraft.lua,/etc/haproxy/minecraft_hosts.map, and/etc/haproxy/conf.d/minecraft_backends.cfgwith 10%par2parity into/data/backups/services/current/mc_manager/.
- Archives
- Control Plane Restore:
/home/luke/git/backups/ul/scripts/restore/mc_manager [timestamp] - Router Backup & Restore:
/home/luke/git/backups/ul/scripts/backup/minecraft_routerand/home/luke/git/backups/ul/scripts/restore/minecraft_router [timestamp]
6. Minecraft Server Manager & On-Demand Architecture (Production Architecture)
Production Control Plane: The unified web control plane at https://mc.drheck.dev (bound to [fd77:7777:5010::1337:f1ac:d00d:3c00]:8095 behind Nginx and Authentik ForwardAuth) manages all Minecraft worlds on ul, automates ipctl networking and systemd lifecycle management, wakes sleeping servers on-demand via HAProxy when players join, streams live PTY server consoles, and provides an integrated Seed Preview Studio and Text, MOTD, Color Gradient & 8-Bit Pixel Icon Studio.
6.1 Canonical Definition of a "Server"
Every managed Minecraft world on ul is a self-contained unit consisting of five standardized components:
$$\text{Server}(\text{slug}) = \left\lbrace\text{Directory}, \quad \text{Manifest } (\texttt{server.json}), \quad \text{Network } (\texttt{ipctl}), \quad \text{Units } (\texttt{systemd}), \quad \text{Lifecycle Policy}\right\rbrace$$
| Component | Path / Identifier | Description |
|---|---|---|
| 1. Dedicated Directory | /data/minecraft/<dir_name>/ |
Holds server.json, server .jar / libraries, mods/ or plugins/, server.properties, server-icon.png, whitelist.json, ops.json, world/, and optional bluemap/. Existing worlds in /data/minecraft/* can be adopted in-place without moving files. |
| 2. Declarative Manifest | /data/minecraft/<dir_name>/server.json |
Stores the human display name, DNS slug (<slug>), loader type (paper, vanilla, fabric, neoforge, forge, custom), Minecraft version, JVM path (/usr/lib/jvm/default/bin/java), heap size (memory_min/memory_max), seed, and start_mode (manual, ondemand, always). |
3. Network & DNS (ipctl) |
fd77:7777:5010::1337:3c:d00d:<hex>/64 |
Dedicated internal IPv6 address on eth77 in /etc/systemd/network/20-wired.network.d/minecraft.conf, bound in server.properties (server-ip= and server-port=25565), mapped in /etc/haproxy/minecraft_hosts.map + /etc/haproxy/conf.d/minecraft_backends.cfg, and published as <slug>.drheck.dev in /var/unbound/etc/unbound.minecraft.conf on danknasty and deSEC.io. |
4. Dedicated systemd Service & PTY Wrapper |
minecraft@<slug>.service (via /usr/local/bin/mc-runner) |
Runs the server JVM inside a managed pseudo-terminal (PTY) with a 1,000-line ring buffer and UNIX domain socket /run/mc-manager/<slug>.sock, enabling real-time WebSocket log streaming and console command injection (SendRunnerCommand) as well as graceful save-all + stop on shutdown. |
| 5. Lifecycle Policy | manual | ondemand | always |
Controls when the server consumes RAM on ul (see Section 6.2). |
Click to expand example /data/minecraft/desertworld/server.json manifest
{
"slug": "desertworld",
"display_name": "β ππ’π°π’π―π± ππ¬π―π©π‘ β",
"dir_name": "desertworld",
"domain": "desertworld.drheck.dev",
"ipv6": "fd77:7777:5010::1337:3c:d00d:2",
"hex_id": "2",
"port": 25565,
"start_mode": "ondemand",
"idle_timeout_minutes": 20,
"type": "paper",
"mc_version": "1.21.4",
"jar_file": "server_26.3.jar",
"java_bin": "/usr/lib/jvm/default/bin/java",
"memory_min": "8G",
"memory_max": "8G",
"seed": "4900633019313953717",
"admins": [],
"created_at": "2026-10-10T18:03:46-04:00"
}
6.2 Resource Management & Server Lifecycle Modes
Because each active Minecraft JVM allocates $8\text{--}20\text{ GiB}$ of pinned heap memory (-Xms = -Xmx with +AlwaysPreTouch), running all $25+$ worlds in /data/minecraft simultaneously is impossible. Each server is assigned one of three lifecycle modes:
manual(Cold / Archived):minecraft@<slug>.serviceis disabled and stopped ($0\text{ GiB}$ RAM).- Only starts when explicitly clicked in the Web UI.
- When stopped, HAProxy returns
<name> is currently offline. Start at mc.drheck.dev.
ondemand(Wake-on-Join + Idle Auto-Stop):- Stopped by default ($0\text{ GiB}$ RAM).
- Automatically started when a player clicks Join Server in Minecraft (intercepted by HAProxy Lua $\longrightarrow$
mc-manager). - Automatically stopped (
save-all$\longrightarrow$stop) once $0$ players have been online continuously for $T_{\text{idle}}$ minutes (default $20\text{ min}$).
always(Pinned Production):minecraft@<slug>.serviceis enabled and active across host reboots (systemctl enable --now).- Used for primary worlds that should remain online $24/7$ regardless of player count.
6.3 HAProxy On-Demand Wake-on-Join & Live Status Ping Architecture
The Minecraft protocol sends a Handshake packet (0x00) at the start of every TCP connection containing a Next State VarInt:
- $\text{Next State} = 1$ (Status Ping): Sent when a client refreshes their Multiplayer Server List.
- $\text{Next State} = 2$ (Login Join): Sent only when a player clicks Join Server.
/etc/haproxy/minecraft.lua extracts both txn.mc_host and txn.mc_state and delegates status pings and offline joins to mc-manager (http://127.0.0.1:8095/internal/haproxy):
$$\text{Client Packet } (\texttt{0x00}) \longrightarrow \begin{cases} \text{state} = 1 \text{ (Status Ping)} & \longrightarrow \text{Return live JSON MOTD + } \texttt{server-icon.png} \text{ from } \texttt{mc-manager} \text{ without waking} \\ \text{state} = 2 \text{ (Login Join)} & \longrightarrow \text{If } \texttt{ONLINE}\text{: TCP splice to backend; if } \texttt{ondemand}\text{: wake server + return countdown} \end{cases}$$
State Machine for Managed Worlds
| Server State | Multiplayer List Ping (state = 1) MOTD & Icon |
Player Clicks "Join Server" (state = 2) |
|---|---|---|
SLEEPING (ondemand) |
Configured custom MOTD (or Β§e<name> Β§7[Standby] β Β§aClick Join to wake server!) + server-icon.png + version badge Standby (Join to Wake) |
HAProxy Lua sends JOIN <slug> to mc-manager, starts minecraft@<slug>.service, and disconnects client with: "β‘ Waking up <name>... Server is starting on-demand. Please reconnect in ~20 seconds!" |
STARTING |
Configured custom MOTD + server-icon.png + version badge Starting... |
Disconnects client with: "β³ <name> is currently booting up! Please wait ~15 seconds and try connecting again." |
ONLINE |
Live player count & sample from backend JVM overlaid with latest custom MOTD (server.properties) and server-icon.png (favicon) |
Native TCP splice to [fd77:7777:5010::1337:3c:d00d:<hex>]:25565 with full Microsoft online-mode=true auth |
OFFLINE (manual) |
Configured custom MOTD + server-icon.png + version badge Offline |
Disconnects client with: "<name> is currently offline. Start it from https://mc.drheck.dev" |
Idle Shutdown Timer
For any running server in ondemand mode, mc-manager tracks the time since the last player disconnected ($N_{\text{players}} = 0$). When:
$$t_{\text{empty}} \ge T_{\text{idle}} \quad (\text{default } 20\text{ min})$$
mc-manager issues save-all and stop via the /run/mc-manager/<slug>.sock PTY socket and stops minecraft@<slug>.service, freeing the JVM heap until the next join request.
6.4 Web Control Plane (https://mc.drheck.dev)
The web frontend is served over HTTPS behind Nginx + Authentik ForwardAuth and provides two primary workspaces designed with a clean, hardware-ops dark interface:
1. Existing Servers Dashboard & Live PTY Console
2. Minecraft Text, MOTD, Color Gradient & 8-Bit Pixel Icon Studio
Built directly into both the + New World screen and the Configuration panel of every existing server:
- Unicode Font Converter (Copy/Paste Safe):
- Converts text into Minecraft Java Edition font variants without resource packs:
Small Caps (κ±α΄α΄),Gothic / Fraktur (ππ²π―π³π¦π³ππ©),Double-Struck (ππ¦π£π§ππ§ππ),Full-Width (οΌ³οΌοΌ°), andMonospace. - Includes one-click Java-Safe Decorative Symbols & Borders:
β,β,β,β‘,π,β,β¦,β,Β»,Β«, andβ ... β.
- Converts text into Minecraft Java Edition font variants without resource packs:
- Β§ Color Gradient & Formatting Code Builder:
- Interpolates any two RGB colors (
Gradient Start$\longrightarrow$Gradient End) across the input string and maps each character to the nearest native Minecraft color code (Β§0βΒ§f), combined with optionalΒ§l(Bold),Β§o(Italic),Β§n(Underline),Β§m(Strikethrough), orΒ§k(Obfuscated). - Can be applied with one click to either MOTD (
server.properties) or Display Name (server.json), with a real-time Minecraft Multiplayer Server List Preview renderingΒ§codes and the 64Γ64 icon side-by-side.
- Interpolates any two RGB colors (
- 8-Bit Pixel Icon & Badge Generator (
64Γ64 server-icon.png):- Generates crisp 64Γ64 pixel-art server icons in the browser using 6 Minecraft material themes (
Stone,Dirt & Grass,Diamond,Glowstone,Nether,Enchanted Glint), 7 pixel-art stamps (Sword,Pickaxe,Creeper,Crown,Heart,Star,PokΓ©ball), and 1β3 character 8-bit bitmap text with 3D drop shadows, or accepts any custom uploaded PNG/JPG/WebP image (auto-cropped and resampled to64Γ64).
- Generates crisp 64Γ64 pixel-art server icons in the browser using 6 Minecraft material themes (
3. Interactive Seed Preview Studio (cubiomes Native Renderer)
- Uses
/usr/local/bin/mc-seed-render(compiled againstcubiomes) onulto render a 2D biome map ($\pm 2048$ blocks around $(0,0)$) and locate nearest structures (Village,Ancient City,Mansion,Monument,Outpost,Stronghold,Ruined Portal) in $< 50\text{ ms}$ per seed. - Supports Roll Random Seed and interactive biome legend inspection prior to provisioning a new world.
6.5 Authentik Gate, RBAC & Automatic /op (ops.json) Synchronization
Access to https://mc.drheck.dev is gated at the Nginx perimeter via Authentik ForwardAuth (X-Authentik-Username), and mc-manager maps authenticated identities via /data/minecraft/.manager/users.json:
$$\text{Authentik SSO } (\texttt{auth.drheck.dev}) \longrightarrow \text{Nginx ForwardAuth } (\texttt{X-Authentik-Username}) \longrightarrow \texttt{mc-manager} \text{ RBAC + } \texttt{ops.json} \text{ Sync}$$
- Global Admins (
global_admin: true, e.g.,luke): Full access to create servers, provision network/DNS, manage the Users & Operators Registry (with live Mojang API username $\longrightarrow$ UUID lookup), and administer all worlds. - Per-Server Admins (
server.jsonadmins): Full control to start/stop/restart, access the live console, and edit configuration/whitelist/icon on their assigned worlds. - Automatic
ops.jsonSynchronization: Adding a user as a Global Admin or Server Admin automatically syncs their Mojang UUID and username intoops.json(Level 4 operator withbypassesPlayerLimit: true).