Toger Blog

Minecraft and SystemD

In the first installment I launched a basic Minecraft service on CentOS7. However, a proper service should not be run from the command line, instead it should be controlled by the system service daemon. In years past this would be by writing a ‘sysV init script’ which would try to determine if the process was running, if not launch it and capture its PID for future reference, and capture its output to a file. CentOS-7 has switched away from that model to one called SystemD which makes much of that easier. There is some controversy over the SystemD model (is it UNIX-y? Too monolithic? Taking over everything?) but seems pretty handy for what it needs to do, plus has some nice security features.

So I will create a Minecraft service definition for SystemD. I used http://0pointer.de/blog/projects/systemd-for-admins-3.html to help me with this. The unit file will look like:

/etc/systemd/system/minecraft.service:

/etc/systemd/system/minecraft.servicelink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Unit]
Description=Minecraft server
After=syslog.target
RequiresMountsFor=/minecraft

[Service]
ExecStart=/bin/java -Xmx1024M -Xms1024M -jar /minecraft/bin/minecraft_server.jar nogui
WorkingDirectory=/minecraft/var
User=minecraft
Group=minecraft
PrivateTmp=true
NoNewPrivileges=true
InaccessibleDirectories=/home
ReadOnlyDirectories=/bin /lib /usr /etc /
ReadWriteDirectories=/minecraft

[Install]
WantedBy=multi-user.target

What this does:

  • Defines the service name
  • Designates that it requires the /minecraft mount and should run after the logging daemon starts.
  • Provides the startup command, working directory, user/group
  • Designates that /tmp should be private for that process
  • Prevents the process from gaining any privileges.
  • Hides /home from the process
  • Makes most system directories read-only (to protect against accidental permissions issues)
  • Makes /minecraft read-writeable.

The last few are for system protection — even if the java daemon is subverted to try to read the contents of /home, it can’t see it. Between the hidden and read-only directories, the limitation of privileges and the non-privileged launching user, there is much less chance of MineCraft causing system-wide havoc.

After putting the service defintion into place, reload systemd, restart the daemon and check its output:

1
2
3
4
systemctl daemon-reload
systemctl restart minecraft.service
systemctl enable minecraft.service
journalctl -u minecraft.service

To stop the service:

1
systemctl stop minecraft.service

Output will be:

1
2
3
4
5
6
7
8
9
10
11
12
Jan 12 04:18:02 ip-10-10-0-239.ec2.internal systemd[1]: Starting Daemon to detect crashing apps...
Jan 12 04:18:02 ip-10-10-0-239.ec2.internal systemd[1]: Started Daemon to detect crashing apps.
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Starting minecraft server version 1.8.1
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Loading properties
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Default game type: SURVIVAL
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Generating keypair
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Starting Minecraft server on *:25565
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Using epoll channel type
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Preparing level "world"
Jan 12 04:18:06 ip-10-10-0-239.ec2.internal java[2198]: [04:18:06] [Server thread/INFO]: Preparing start region for level 0
Jan 12 04:18:07 ip-10-10-0-239.ec2.internal java[2198]: [04:18:07] [Server thread/INFO]: Preparing spawn area: 94%
Jan 12 04:18:07 ip-10-10-0-239.ec2.internal java[2198]: [04:18:07] [Server thread/INFO]: Done (1.192s)! For help, type "help" or "?"

Update: dietrich@teilgedanken.de sent me a link to https://teilgedanken.de/Blog/post/8/ which takes this a step further and utilizes MCRCON to more gracefully control the servers shutdown state, and integrate with FirewallD if your system utilizes it.