Sandbox a QuiltMC Minecraft server in a container/docker!
Any software can be attacked and exploited - recent events in the Minecraft community like log4j and fractureiser have made it clear that Minecraft servers and mods can be targets for attackers. Isolating and sandboxing the Minecraft server can reduce the severity of such attacks by limiting the server's ability to run code or access external data. Without bypassing the container's sandbox, it can't read any data besides the server data, and all java code is either read-only or will be reset upon a container restart (so any tampering with .jar files should not have any impact). Please note that this is an improvement compared to just running the server, but it is not a perfect solution! Containers can have their own vulnerabilities.
There are several other minecraft server containers, but I couldn't find one using QuiltMC that primarily focused on security (limiting permissions, file-grained permissions, distroless images, etc).
QuiltMC is an open-source mod loader for Minecraft. It can be installed on the Minecraft server to allow for installation of mods, which this container will do. At the time of writing, it is compatible with Fabric mods. It's well suited for playing with a couple of friends - if you're intending to host many players, you should look into PaperMC and related projects like Purpur and Pufferfish, which stray a bit from vanilla Minecraft behavior in exchange for performance and stability. Be sure to look at what the current state-of-the-art is though! The admincraft community has been very helpful.
Warning I'm not a security expert! There may be massive oversights. This should be an improvement compared to just running the server, but do not treat this as a perfect solution.
This technique relies on
containerization.
We put the server in its own limited computing environment, where the
container software (like Podman or
Docker) limits the environment to only running the
server and accessing server files. The container is built on a distroless
image from Google,
which means it does not have a shell (bash
, sh
, etc) or a package manager
(apt
, dnf
, etc), drastically reducing attack surface. We also limit the
computer resources the server can use, make as much data read-only as we can,
and drop all capabilities.
The current weaknesses are that the image is running as root and we are using bind mounts instead of a volume - please see the Contributing section for more.
If you're interested, please read more about container hardening at Wonderfall's blog, which was the main resource I used in creating this (along with plenty of container documentation like the compose spec and the Containerfile man page).
You're expected to understand how to run a Minecraft server. Please read this wiki article if you're unfamiliar. If you want your server to be accessible to the internet, please read the section about port forwarding carefully.
You'll need software for containerization - on Linux, I'd highly recommend podman and podman-compose and running the containers as a non-root user. If you're on Mac or Windows, you will likely find installing Podman Desktop to be easier. However, please note that the rest of the instructions will assume you're running on Linux. Podman is recommended since Docker runs the containers as root, and as such any attacker that escapes the container would not have root privileges.
If you prefer Docker, you can also install and use Docker Desktop - this comes with docker and docker compose.
You can optionally install Just to use the Justfile if you're using podman - it's optional though, you can look inside the file to see the commands to run.
Note This Containerfile will download a Minecraft server jar. This notice appears on https://www.minecraft.net/en-us/download/server:
Just so you know, by downloading any of the software on this page, you agree to the Minecraft End User License Agreement and Privacy Policy.
Due to this, I'm a bit uncomfortable posting an entire image and hosting Mojang's code, so I'm pushing the installation to you.
Clone this repo. If you have Just, you can
run just install
. Otherwise, make a copy the data-template
folder, name it
data
, optionally remove the .keep
file in any folders in data
, then run
podman-compose build
or docker compose build
. It will download the quilt
installer and create the server image. You should also be able to choose the
repo and build it in Podman/Docker Desktop.
Take a look at the compose.yaml
file and change it to your liking. Most
importantly, set the MINECRAFT_VERSION, change deploy.resources.limits
to the
limits you want, and change the ports if desired!
To run the image, run just up
or podman-compose up --detach
or docker compose up --detach
. This will start the server. The server will then stop
because you need to agree to the EULA - run just down
/ podman-compose down
/ docker compose down
, then go to the data
folder, agree to the EULA,
establish your settings in server.properties
, put any Quilt/Fabric mods in
the mods
folder, do any other adminstration work, and put the server back
up! You should be able to connect to it from your local machine with the server
name localhost
, or use your local IP to connect to it on a local network, or a
public IP if you've port forwarded.
To stop it, do just down
/ podman-compose down
/ docker compose down
.
You can see the logs with just logs
/ podman-compose logs
/ docker compose logs
. To attach to the server, you can use the Justfile or note the name of the
container in podman container ls
/ docker container ls
(with podman-compose
it should be minecraft-quiltmc-server-container_quilt-server_1) and then you
can perform actions like attach
(which will open a terminal session to run
commands on the server like op
or whitelist
).
All data is stored in the data
folder. Remember to back up this folder, as it
holds all your server data!
At least once a week, you should update your server image by running just update
/ podman-compose build --pull --no-cache
/ docker compose build --pull --no-cache
. This will pull the latest images (including the latest Java
version and distro fixes). You can also run podman image prune
/ sudo docker image prune
after an update to remove unneeded images.
These are the current remaining problems. I'm not intending on working on these unless a splash of inspiration hits me, but I'd be more than happy to accept any PRs dealing with these:
- We're using bind mounts instead of Docker volumes - we need to be able to
change the server configuration (for example, the
server.properties
file). We cannot do it from inside the distroless container since it doesn't have a shell. Therefore, since we shouldn't change Docker volumes from outside the container, it's better for us to do a bind mount. - However, since we're using a bind mount, the container is running as root -
bind mounts don't play nicely with nonroot
users. Since we're running in a
distroless image, we can't run
chmod
to fix this :) This is less of an issue since this is a distroless image so being root does not enable much more, but it's recommended to use podman instead of Docker to run the container itself without root on your system.
MIT