GitOps for Minecraft: Making your two-week minecraft phase more organized
It was that time of year again. A group chat exploded with “let’s play Minecraft!”, a dozen adults suddenly nostalgic for 2012.
I had a beautiful vision: a completely immutable Minecraft server. A Docker container, built once, that does not change at runtime. Just like a production system for enterprises. Plugins? Configs? All baked in. Updates? Only via new image deployments. Perfect.

No more of “Can we add this plugin?” Sure, let me SSH in mid-game and, oops, crash the server.
The Failed Dream: Immutable Perfection
My first instinct was to treat it like an enterprise-grade system: immutable infrastructure. A Docker container, built once, never touched at runtime. Plugins? Baked into the image. Configs? Added at build time. Updates? Only via new deployments.
Beautiful. Elegant. Doomed. It crashed and burned quicker than my smile disappeared from my face.
Plugins and Server Software are chaotic neutral
Most plugins don’t just read configs and generate the initial ones. Oh no, they spew files everywhere. A read-only filesystem? Instant exception rain.
Microsoft’s EULA: The Legal Wrench
Since Minecraft’s 2023 EULA update, pre-built server software is banned. You must download the JAR at runtime. This also means the first startup means remapping things, and unfortunately also loading those at each start. My immutable dream collapsed under legalese early on.

The Pivot: GitOps or a home-server variant of it
I accepted defeat, but on my terms. If the server had to be mutable, the mutations would be version-controlled. Let's throw all of this in a Git repository, easy to test locally and smooth to update. Even on the go, via the Web UI!
How It Works
- Build on the Server (Not in CI): The Dockerfile downloads PaperMC at runtime (EULA-compliant) and installs plugins from the repo:
- Pros: No CI ARM builds, so your Raspberry Pi can finally be used for something without any extra setup.
- Cons: First startup takes 90 seconds. (We survive.)
- Git as the Single Source of Truth: Everything except worlds/logs lives in Git. Everything else is removed on each update.
- Player Management: YAML > JSON: Managing
whitelist.jsonand dozen of config files manually is asking for typos. A Python script converts the centralplayers.ymlat build time to all the various configuration files. It can be extended to touch multiple config files, without having to do it manually each time. It just works. - Deployments via Git = No More Mid-Game Panic
- “Can we add [X plugin]?” → “Open an MR or I can test this locally and test this out in peace, push once stable.”
- “I need keep inventory!” → Edit
players.yml→ commit → server restarts once (not during raid night).

Try It Yourself
- Clone the blueprint repo (hosting on GitLab.com or your self-hosted Gitea preferred).
- Profit: Your server is now a Git repo. Break something? Simply rollback to the last working commit.