MC Admin: Family Minecraft Control Plane
I built MC Admin so my kids could hop between custom Bedrock worlds without renting third-party realms or waiting on me to hand-configure droplets, DNS, and LAN workarounds. The stack now spins servers up on demand, keeps costs down by auto-suspending idle hosts, and even bridges our living-room consoles into the action.

Overview
MC Admin is three services that cooperate:
mc-admin-api(Go) is the control plane that knows about worlds, hosts, DNS, DigitalOcean, and Spaces backups.mc-admin(Next.js 15) is the Auth0-protected dashboard the family uses to start/stop/share worlds.mc-admin-lan(Go) is a Raspberry Pi daemon that launches Phantom proxies so Xbox/Switch clients see the servers under “LAN”.
Together they let the kids tap “Start World”, wait a few seconds for the droplet + server container, scan a QR code, and get playing—no SSH, no surprise billing.
mc-admin-api: Orchestrating Worlds
The backend exposes a bearer-protected HTTP API plus future CLI mode for everything infrastructure:
- World lifecycle:
POST /worldsdefines minecraft_type/version/config, thenPOST /worlds/{id}/startplaces it on a host; stopping uploads data back into Spaces so storage is cheap when idle. - Host pool management: Each DigitalOcean droplet runs 3–4 servers. Hosts carry region, slot counts, and status so the scheduler can find capacity or tell me to provision manually.
- Networking & DNS: Every running world gets
{name}.mynecraft.worldwith ports allocated per edition (Bedrock 19132–19135 UDP, Java 25565–25568 TCP). - Auto-idle protection: Two background tickers handle pings and housekeeping. The ping loop (30s) uses RakNet to watch player counts and updates
last_player_activity. The housekeeping loop (60s) enforcesidle_threshold_minsper world andAUTO_HOST_IDLE_MINSfor empty hosts, shutting things down before DigitalOcean bills rack up. - Secrets & knobs: Env vars like
MC_ADMIN_MK,DO_TOKEN,MC_ADMIN_API_SSH_PRIVATE_KEY, andMC_DOMAINkeep auth + provisioning secure, whileHOUSEKEEPING_INTERVAL_SECONDSandAUTO_HOST_IDLE_MINStune aggressiveness.
Because everything emits structured operation logs (server-sent events), the UI can stream Docker output line-by-line so the kids see when “Downloading Bedrock image…” flips to “Server ready”.
mc-admin: Auth0 Dashboard
The frontend is a Next.js 15 app with Auth0 login that proxies all API calls through /mc-admin/api (lib/api.js) so browsers never touch master keys. A few highlights:
- Instant redirect:
pages/index.jswatches Auth0 state and bounces authenticated users straight to/dashboard, otherwise renders a simple hero with a “Sign In” CTA. - Real-time dashboard:
pages/dashboard.jspollsapi.listHosts()andapi.listWorlds()every 3 seconds, driving tabbed views with status badges, elapsed timers, and CTA buttons (“+ New World”, “+ New Host”). - World detail cockpit:
pages/worlds/[id].jsloads world + host inventory + latest operation in parallel, lets me pick explicit hosts, start/stop worlds, copy{fqdn}:{port}, display QR codes (components/ServerQRCode), and tail logs viaOperationLogswhen an action is running. - Guardrails: Delete/edit buttons disable while a server runs; no host? The UI links straight to
/hosts/new. Tabs sync to URL query params so refreshing stays on “Activity” when monitoring a start.
The dashboard design leans on badges, cards, and the elapsed timer hook so even non-tech family members can see “server is starting… 00:28” and know to grab snacks.
mc-admin-lan: Raspberry Pi Bridge
Bedrock consoles only see LAN broadcasts, so mc-admin-lan handles the Phantom proxy work:
MC_ADMIN_MK=<token> ./mc-admin-lan \
--api-url https://<host>/mc-admin-api \
--phantom-path /opt/phantom \
--poll-interval 20s
- Built in Go with Make targets for arm64, armv7, and armv6 so I can drop binaries on any Pi from Zero to 5.
- Polls
/mc-admin-api/worldsevery ~20s, launches one Phantom per running world, and usesSO_REUSEPORTso multiple UDP 19132 listeners coexist. - Auto-downloads the right Phantom release into
~/.cache/mc-admin-lanunless I point it at a custom binary. - Respects
--bind,--bind-port-start, and--no-downloadflags, meaning a single Pi on the network makes every MC Admin world appear under “LAN Games” for local consoles.
Operating the Stack
- Local dev is simple:
go run main.gofor the API,next devfor the dashboard, andgo build ./cmd/mc-admin-lanfor the bridge. - Production is containerized on DigitalOcean; droplets get my SSH key via
MC_ADMIN_API_DO_SSH_KEY, and Spaces handles world archives so I can wipe hosts without losing progress. - Env consistency lives in Terraform (
mc-admin-api/terraform/) plus Dockerfiles for reproducible builds.