mineOps - Part 1: Manual Minecraft Server Installation

As was discussed in the Introduction to this series, we will be focusing on deploying Minecraft Servers as part of a fictitious business. This business needs to get up and going with their first customer, so we need to get at least one Minecraft Server up and running. Let's get going!


NOTE:

Throughout this series we will be focusing our efforts on RPM based Operating Systems (RHEL, CentOS, Fedora etc...). Almost all of the examples will carry over with a few exceptions to Debian based Operating Systems (Debian, Ubuntu etc...) and we will call out those differences where they come up.

Another item to note is this guide will not outline the creation of any Virtual Machines or the use of any cloud providers. This series will use oVirt for the virtual machines used, but will not come into play. Note that Ansible can be used to provision Virtual Machines in whichever platform you happen to utilize, but will not be discussed in this series.

One final item of note is that "sudo" will not be used throughout this guide. All commands will assume you have root privileges on the servers.


Minecraft Server Prerequisites

CPU and Memory resources will be low for this series, but in a real world deployment you would want to ensure you have ample resources for each of the servers being used. 2 vCPU and 4GB of Ram per server will be enough for the purposes of this series.

Outside of resources one of the primary and nearly only requirement for running a Minecraft Server is java. There are a few ways to do this, but the easiest of which is to use the package manager of your system. For RPM based operating systems this can be done with a simple command:

dnf install -y java-17-openjdk

Java 17 is installed as it is the "oldest" version compatible with Minecraft Server.

Acquiring Minecraft Server

To run a Minecraft Server you will need to obtain the server.jar from Minecraft.net. You can obtain the URL for the file by copying the download link here. You can either obtain the link and download it directly from the "to be" Minecraft Server (using curl or wget) or you can download it to your local machine and copy it over via scp, rsync or some other method.

In the spirit of automating and making life easier overall, we have a much quicker path. The server will need jq installed and can be handled in a simple one-liner (if you already have jq installed on your server you can skip this step):

curl -o /usr/bin/jq -sL https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 && chmod +x /usr/bin/jq

This will place jq in your /usr/bin/ which should be in the path, but this now enables us to run and grab the latest Minecraft Server .jar file. Here is a handy script to grab the latest release of Minecraft Server:

curl -o server.jar $(curl `curl -sL https://launchermeta.mojang.com/mc/game/version_manifest.json | jq -r '.latest.release as $release | .versions[] | select (.id == $release) | .url'` | jq -r '.downloads.server.url')

The above script will reach out to Mojang servers and look through the latest releases and grab whichever happens to be the latest.

If you wish to obtain a specific version of Minecraft Server (which would need to for some customers) you can run the same script, but with a slightly different lookup. Notice we have removed early parts of the first jq query and turned $release into "1.18.1" where "1.18.1" is the specific version you are requiring:

curl -o server.jar $(curl `curl -sL https://launchermeta.mojang.com/mc/game/version_manifest.json | jq -r '.versions[] | select (.id == "1.18.1") | .url'` | jq -r '.downloads.server.url')

Starting Minecraft Server

We are just about to spin up our first Minecraft Server, but there is only one item that will block us from starting. If you attempt to run Minecraft Server without accepting the EULA, you will get a failure similar to what you see below:

java -jar server.jar
<OMITTED OUTPUT>
[22:59:42] [ServerMain/ERROR]: Failed to load properties from file: server.properties
[22:59:42] [ServerMain/WARN]: Failed to load eula.txt
[22:59:42] [ServerMain/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.

However you can prevent this message by accepting the EULA with another simple one-liner:

echo "eula=true" > eula.txt

Once you have "accepted" the EULA, Minecraft Server will be able to start, thus getting us one step closer to having customers paying for this service. Let's give it a go. Fair warning depending on the server's resources, the initial start-up may take a minute or more.

$ java -jar server.jar
Starting net.minecraft.server.Main
[23:03:08] [ServerMain/INFO]: Environment: authHost='https://authserver.mojang.com', accountsHost='https://api.mojang.com', sessionHost='https://sessionserver.mojang.com', servicesHost='https://api.minecraftservices.com', name='PROD'
[23:03:09] [ServerMain/INFO]: Reloading ResourceManager: Default
[23:03:10] [Worker-Main-2/INFO]: Loaded 7 recipes
[23:03:11] [Worker-Main-2/INFO]: Loaded 1141 advancements
[23:03:13] [Server thread/INFO]: Starting minecraft server version 1.18.1
[23:03:13] [Server thread/INFO]: Loading properties
[23:03:13] [Server thread/INFO]: Default game type: SURVIVAL
[23:03:13] [Server thread/INFO]: Generating keypair
[23:03:14] [Server thread/INFO]: Starting Minecraft server on *:25565
[23:03:14] [Server thread/INFO]: Using epoll channel type
[23:03:14] [Server thread/INFO]: Preparing level "world"
[23:03:22] [Server thread/INFO]: Preparing start region for dimension minecraft:overworld
[23:03:24] [Worker-Main-2/INFO]: Preparing spawn area: 0%
<OMITTED OUTPUT>
[23:04:27] [Worker-Main-2/INFO]: Preparing spawn area: 84%
[23:04:27] [Worker-Main-2/INFO]: Preparing spawn area: 84%
[23:04:31] [Server thread/INFO]: Time elapsed: 68584 ms
[23:04:31] [Server thread/INFO]: Done (77.021s)! For help, type "help"

Verifying Connectivity to Minecraft Server

At this point we can try to connect to our newly deployed Minecraft Server. If you are familiar with Minecraft, you will know to click "Multiplayer" and then for our tests click "Direct Connect". You will need to input the IP address of your server and the default port for Minecraft Server which is 25565. This will attempt a connection to your Minecraft Server.

If you are unsure of the IP address of your Minecraft Server you can run ip address on your system and look for the primary NIC:

$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 56:6f:0d:9a:00:00 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.50/24 brd 10.0.0.255 scope global noprefixroute enp1s0
       valid_lft forever preferred_lft forever
    inet6 fe80::c0ea:7070:3ce9:7c0f/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
Obtaining the primary NIC IP address

We may run into one more blocker before the Minecraft Server is operational and that is a firewall blocking the port.

If you attempt to connect to your server by putting into the "Server Address:" field the ip-address:port of the server you deployed Minecraft Server to, you may run into something like you see in the video "Connection Refused". To prevent this from being an issue, we will need to open up a port in the firewall for Minecraft.

firewall-cmd --add-port=25565/tcp

Please note the above command is not persistent and will not survive a server reboot. To have this persist your command will look slightly different:

firewall-cmd -add-port=25565/tcp --permanent && firewall-cmd --reload

The default port for Minecraft is 25565 and can be changed in a file we are about to look at (before runtime). With the firewall opened and the server running, we should be able to connect to our newly deployed Minecraft Server.

Tuning Minecraft Server

At this point we have a running Minecraft Server, but what is granting configuration to it? If we hit CTRL+C the server will exit, but we can take a look at the files that now exist in our directory. There are a few files of note, but the rest can be reviewed at the Minecraft Wiki. For the purposes of configuring this Minecraft Server for our customer we will focus on server.properties, but as you can see there are many configuration files that now exist in our directory:

$ ls -lhF
total 45M
-rw-r--r--.  1 root root    2 Dec 28 23:08 banned-ips.json
-rw-r--r--.  1 root root    2 Dec 28 23:08 banned-players.json
-rw-r--r--.  1 root root   10 Dec 28 23:03 eula.txt
drwxr-xr-x.  8 root root   77 Dec 28 22:59 libraries/
drwxr-xr-x.  2 root root   78 Dec 28 23:08 logs/
-rw-r--r--.  1 root root    2 Dec 28 23:08 ops.json
-rw-r--r--.  1 root root  45M Dec 28 22:59 server.jar
-rw-r--r--.  1 root root 1.1K Dec 28 23:08 server.properties
-rw-r--r--.  1 root root  109 Dec 28 23:12 usercache.json
drwxr-xr-x.  3 root root   20 Dec 28 22:59 versions/
-rw-r--r--.  1 root root    2 Dec 28 23:03 whitelist.json
drwxr-xr-x. 12 root root 4.0K Dec 28 23:15 world/

Inside server.properties we have quite a few tunable variables to look into. Some of these include the port in which Minecraft Server runs on, or whether or not to enable PVP (Player Versus Player actions). Each of these settings would be up to the customer to decide which to use, but we will need to tune these to meet customer demands.

Operating a Minecraft Server

Now that we have a running server and are able to make changes to its configuration, how do we keep it running? What about backing up the data for the customer in case there is an issue either from their side or yours? We will quickly focus on these items here.

For keeping a server running and having it run without taking up a shell/terminal, we will need to have a system service run it for us. There are a few things to consider to ensure we have a clean running environment. Let's outline those below:

  • A directory dedicated to this server
  • A user to be the "owner" of the server
  • A systemd unit file to manage the state of the server

Some of these can be handled quite easily. For the dedicated directory we can create it via mkdir -p /opt/minecraft as its a logical place and out of the normal paths. If we are going to deploy multiple servers for customers, they will each need their own unique location. A unique directory should be created for each server using their customer ID or email address. If a customer has multiple servers, you could create a directory with a unique world name (customer choice) like so: mkdir -p /opt/myfunworld-00012345.

For the user to be the "manager" of the Minecraft Server we can just run useradd minecraft. However if we are going to have multiple customer servers running, it may be more logical to have a username that is inline with the customer. This would be most likely their customer ID or email address of the customer. For now we will just use minecraft.

The final piece would be the systemd service unit to keep the server running for us without having a terminal dedicated to running java -jar server.jar. Let's create a systemd unit file.

cat << EOF >> minecraft.service
[Unit]
Description=start and stop the minecraft-server

[Service]
WorkingDirectory=/opt/minecraft/

User=minecraft
Group=minecraft
Restart=on-failure
RestartSec=20 5

ExecStart=/usr/bin/java -Xms512M -Xmx3048M -jar server.jar nogui

[Install]
WantedBy=multi-user.target
EOF

If you notice the line ExecStart you will see a similar command to what we used to run the server the first time, however this command has a few new flags included. -Xms and -Xmx are the minimum and maximum amounts of memory the JVM can use while running Minecraft. The nogui flag tells Java to not run a Java GUI for the application. You may have noticed (if your server has a GUI) when you initially ran the commands for java -jar server.jar a window pop-up showing logs and a possibly resource utilization. This isn't something we want running as its wasting resources for what needs to be used for our Minecraft Server.

Now lets get this systemd unit file into place and enable it.

cp minecraft.service /usr/lib/systemd/system/ && systemctl enable --now minecraft

So something that will need to be done from time to time is to back-up this server and its configurations you will need to copy the contents of /opt/minecraft to some other location (ideally not connected to the server). We will not be going over a script to accomplish this because it will be very different for each environment. However the principal is the same, copy the data somewhere else except to cleanly grab the data, you will need to stop the Minecraft Server first.

Outcome

After all this effort to get one server going, what about the next customer? Quite a bit was done just to get a single server running and if we had to do this for multiple customers or multiple customers with multiple servers, it would become quite chaotic very quickly. What if all of these servers had multiple configuration changes? How would we manage and maintain all of them?

The next two items we are going to look at in the next few blog posts are Ansible for automating all of the deploys and Git to keep it all in line.