MinePanel
Self-hosted Minecraft server management platform focused on Docker lifecycle, real-time state and safe backend operations. ⛏️

The Story
Running a Minecraft server is easy. Running one properly, keeping it manageable, giving other people controlled access, watching resource usage, handling authentication, and doing all of that without handing the whole thing over to somebody else's cloud platform is where it starts getting annoying.
I wanted something that felt closer to the rest of my self-hosted infrastructure: deploy it on hardware I control, understand exactly where the data lives, and keep the whole stack portable. I didn't want another service where the "easy setup" eventually turns into a subscription, proprietary infrastructure, or a dashboard that owns more of the server than I do.
That frustration became MinePanel. What started as "I want a clean way to control Minecraft servers running in Docker" gradually turned into a much larger question: what would a proper self-hosted Minecraft management platform look like if I treated it like real infrastructure instead of a weekend game-server script?
What Makes It Special
The main idea behind MinePanel is pretty simple: your server should actually be yours. ⛏️
MinePanel runs on your own machine, controls your own Docker daemon, stores state in your own PostgreSQL database, and runs every Minecraft instance inside its own container. There is no required MinePanel cloud sitting in the middle and no infrastructure you need permission to leave later. Point a domain at the machine, configure the environment, bring the Compose stack up, and you have a proper HTTPS management backend running on hardware you control.
The part I like most is that this simplicity doesn't come from hiding the difficult parts. Underneath the one-command deployment is proper authentication, 2FA, granular authorization, access-request workflows, container lifecycle management, real-time metrics, resource admission checks, and a backend designed around the fact that access to the Docker socket is serious infrastructure access. The goal is to make the outside feel boringly simple while keeping the inside intentionally engineered.
The Technical Craft
Core Features
- 🚀 One-command self-hosting - bring up the core stack with Docker Compose instead of assembling a panel, database, reverse proxy, and TLS setup manually.
- 📦 Container-per-server isolation - every Minecraft server gets its own Docker container, keeping instances separated and making lifecycle management predictable.
- 🎯 Granular server permissions - ADMIN, MOD, and USER roles combine with per-server permissions instead of relying on one global "moderator can do everything" switch.
- 🔄 Server access workflows - OPEN, REQUEST, and PRIVATE visibility modes let communities decide exactly how players gain access.
- ⚙️ Real-time host monitoring - CPU, RAM, and disk information is streamed over WebSockets so administrators can see what the host is doing without constantly polling it.
- 🎨 Dedicated web experience - the management UI lives in a React PWA, separate from the backend, while the public-facing MinePanel site uses SvelteKit.
- 🔐 Authentication built for an actual panel - JWT sessions use HttpOnly cookies, with refresh sessions, 2FA, recovery flows, rate limiting, and automatic first-admin bootstrapping.
- 🧱 Infrastructure you own - PostgreSQL, Minecraft data, Docker containers, and the management API all remain under the operator's control.
The Secret Sauce
Built this using:
- NestJS 11 + TypeScript for the backend. I wanted strong module boundaries, dependency injection, guards, validation, and enough structure that the API could grow without becoming a giant collection of routes.
- Bun 1.3.14 as the production JavaScript runtime and package manager. Fast startup and a very lightweight development workflow fit the project well.
- PostgreSQL 16 as the single stateful dependency. MinePanel intentionally avoids introducing Redis, a separate queue, or another infrastructure service unless the project actually needs one.
- Drizzle ORM 0.45.2 for database access and migrations. It keeps the schema close to TypeScript while still feeling much closer to SQL than a heavy abstraction layer.
- Dockerode 4 to talk directly to the local Docker daemon. This is what allows MinePanel to create, inspect, start, stop, restart, and remove Minecraft containers programmatically.
- itzg/minecraft-server as the Minecraft container base. It provides a mature Docker-friendly foundation while MinePanel handles orchestration and management around it.
- Caddy 2 for automatic HTTPS and reverse proxying. TLS should not be another twenty-step tutorial just to deploy a Minecraft panel.
- Socket.IO for real-time communication, starting with host metrics and leaving room for richer live server events later.
- React 19 + Vite 7 + TanStack Query for the PWA dashboard. The frontend is deliberately its own application rather than being coupled to NestJS templates.
- Svelte 5 + SvelteKit 2 for the marketing site. It gave me a small, fast stack for a site whose job is very different from the management application.
- Kotlin Multiplatform + Compose Multiplatform is the direction planned for the future mobile client, with Android and iOS sharing the same application core.
Challenges and Solutions
Giving an App Control of Docker 🔐
- Challenge: Mounting
/var/run/docker.sockinto an application effectively gives that application enormous control over the host. Treating it like a normal API dependency would have been irresponsible. - Solution: I designed the Docker layer around explicit trust boundaries. The NestJS API is not directly exposed to the internet, Minecraft data is mounted read-only into the backend, Docker socket configuration is validated, Minecraft containers are created through controlled server-side paths, and lifecycle/resource rules are enforced before operations are accepted.
- Result: MinePanel can provide the convenience of dynamic container management without pretending that Docker daemon access is harmless. The architecture makes the dangerous boundary explicit and gives me a clear place to keep hardening it.
Permissions Without a Giant Pile of if Statements 🎯
- Challenge: A simple ADMIN / USER split stops working almost immediately once moderators, private servers, community servers, and server-specific responsibilities enter the picture.
- Solution: I separated global roles from per-server authorization. MinePanel has ADMIN, MOD, and USER roles, granular MOD permissions, server-level visibility, and explicit REQUEST approval flows. Authorization is enforced in the backend rather than being treated as frontend UI state.
- Result: A moderator can be trusted with exactly the operations they need, while individual servers can still have their own access policies. It gives MinePanel room to grow into multi-user communities instead of being useful only to one administrator.
Making Server State Survive Reality 🔄
- Challenge: Docker operations are asynchronous, external, and occasionally fail in inconvenient places. A database saying a server is
RUNNINGdoes not magically make the container run, and two lifecycle requests arriving together can easily create inconsistent state. - Solution: Server lifecycle transitions are designed around explicit state changes, compare-and-swap style updates, resource admission checks, and failure paths that avoid silently claiming success when Docker's outcome is uncertain.
- Result: The backend behaves much more like an infrastructure controller than a CRUD wrapper around Docker. That distinction became increasingly important as MinePanel grew.
Behind the Scenes
The current MinePanel backend has been evolving for roughly six months, and it definitely stopped being a small side project somewhere along the way. Every time I finished one layer, the next real-world problem appeared: authentication led to sessions, sessions led to recovery and 2FA, roles led to per-server permissions, Docker lifecycle management led to concurrency and resource admission, and self-hosting led to deployment security and trust boundaries.
A big part of the learning experience has been realizing how quickly "just build a panel" turns into systems design. The UI is almost the easy part. The interesting work is deciding what happens when Docker disappears halfway through an operation, how you prevent two requests from fighting over the same server state, how a moderator's permissions should compose with server visibility, or how much you should trust an application that can reach the Docker daemon.
I've also used AI coding agents heavily while building MinePanel. They have been extremely useful as implementation workers, reviewers, and extra pairs of eyes, but that actually made having a strong specification and clear architecture more important, not less. When you can generate code quickly, bad architectural decisions can spread just as quickly. A lot of my work shifted from typing every line myself toward defining invariants, reviewing decisions, testing assumptions, and making sure the pieces still describe one coherent system.
That is probably why MinePanel matters to me more than its surface-level description suggests. Yes, it is a Minecraft server panel, but for me it has also become an exercise in building a real backend-heavy product: authentication, permissions, databases, container orchestration, real-time communication, infrastructure security, multiple clients, deployment, and a roadmap that has to remain coherent as all of those pieces grow. Some of that has been genuinely difficult, and there are still hardening items and entire phases left to build. That's also the point. I don't want MinePanel to be a polished mockup of an ambitious idea. I want to keep turning the ambitious idea into working infrastructure.
Getting Started
You need a Linux machine with Docker, a domain pointing to the host, and ports 80 and 443 available.
Code
Copied!
git clone https://github.com/MinePanelProject/minepanel-backend
cd minepanel-backend
cp .env.example .env
# Configure your domain, database password, JWT secret,
# encryption key, setup token and Minecraft data path.
$EDITOR .env
docker compose pull
docker compose up -dCaddy handles certificate provisioning automatically, PostgreSQL migrations run as part of the deployment flow, and MinePanel can then start managing Minecraft containers on the host.
The backend is currently in its v1.0 release-candidate phase, with the authorization foundation already extending into the next phase. From here, the roadmap gets much more interesting: richer real-time server controls, console access, backups, scheduled tasks, player and plugin management, server creation presets, networking features, a complete PWA experience, and eventually the KMP mobile app.
The end goal hasn't changed: make running serious Minecraft infrastructure on your own hardware feel as convenient as using a hosted panel, without giving up ownership to get there.

