Adam's blog: Join to start a Minecraft server

10 Jun 2023, 704 words

Multiple Minecraft servers are running on my cheap VPS with limited RAM – how to make accessing them as user-friendly as possible?

All of my servers are running almost effortlessly thanks to the amazing Docker Minecraft server. However, in a situation when one of the servers wants to eat at least 6 GiB of memory while the maximal memory available is 8 GiB, all servers can’t be running at the same time. Some of them must be stopped.

AutoStop & AutoPause

The amazing docker image provides the option to pause (to free up the CPU) or to stop the server. Supposedly, when a pause happens, a knock server is fired up on the same port and listens for an incoming TCP connection. When the TCP connection is established, the Minecraft server is started again. Unfortunately, this did not work for me (the server was always running when I checked the RAM usage) and I did not feel like debugging. I wanted something better anyway.

Recreating the behaviour

I liked the idea of a knock server starting the server again. For that, I have written a simple bash script that checks if a docker container is running and if not, creates a NetCat server that waits for a connection. When a TCP connection is established, the Minecraft server is started. To shutdown the server again, I have set AutoStop to shut down the server after one hour without any players:

#!/bin/bash
# Example: the container is named mc_server1 and is using port 25565
# -> run with ./autostart server1 25565

set -u
SERVER="$1"
PORT="$2"

echo "Will check for $SERVER on port $PORT"

CONTAINER="mc_$SERVER"
while true; do
    if docker ps | fgrep --quiet "$CONTAINER"; then
        sleep 10
        continue
    fi

    netcat -lw 1 0.0.0.0 "$PORT" &&
    echo "Starting $SERVER" &&
    docker start "$CONTAINER"
done

Making it user-friendly

This is nice, but the server starts as soon as any player (or bots) checks if the server is online (does not even have to try to establish a player session). As I am using whitelists on the server, I would want the autostart script to respond only to the whitelisted users. For that to work, I asked my brother (as he has much more Minecraft-related experience than me) to create a script that would:

You can download the mock Minecraft server here. The only required change to my autostart script was to replace the netcat with the custom Python script:

#!/bin/bash
# Example: the container is named mc_server1 and is using port 25565
# -> run with ./autostart server1 25565

set -u
SERVER="$1"
PORT="$2"

echo "Will check for $SERVER on port $PORT"

CONTAINER="mc_$SERVER"
while true; do
    if docker ps | fgrep --quiet "$CONTAINER"; then
        sleep 10
        continue
    fi

    python mock-server.py "/ot/minecraft-autostart/$SERVER.json" &&
    echo "Starting $SERVER" &&
    docker start "$CONTAINER"
done

What users see

The final workflow is pretty rewarding to see:

Minecraft server list showing mock server The server is offline - join to start the server

A message that the user was kicked from the server Notification that the server is starting now

Minecraft server lists showing the server offline Wait few moments for the real server to start

Minecraft server lists showing the server offline The real server is running