Skip to content

Instantly share code, notes, and snippets.

@justincjahn
Last active January 16, 2024 20:15
Show Gist options
  • Save justincjahn/4fe65b552b0622662420928cc8ffc7c0 to your computer and use it in GitHub Desktop.
Save justincjahn/4fe65b552b0622662420928cc8ffc7c0 to your computer and use it in GitHub Desktop.
Minecraft server(s) using systemd and screen.

Install

# Install dependencies
sudo yum install -y java-1.8.0-openjdk screen

# Create a new unprivileged user for minecraft
useradd -r -m -d /opt/minecraft minecraft

# Create the directory that will house our minecraft instances
sudo su --shell /bin/bash minecraft
mkdir instances
exit

# Copy the [email protected] file into the correct place.
sudo vi /etc/systemd/system/[email protected]

# Reload systemd units
sudo systemctl daemon-reload

Provision a new server

# Sudo into the minecraft user's shell
sudo su --shell /bin/bash minecraft

# Move into the instances directory
cd instances

# Create a new folder to house your instance
mkdir server1

# Install your minecraft instance, and make sure there is a minecraft_server.jar file.
# If you use Forge servers, you can use the following:
ln -s forge*.jar minecraft_server.jar

# Start and enable (start after boot) the server.
sudo systemctl start minecraft@server1
sudo systemctl enable minecraft@server1
[Unit]
Description=Minecraft Server: %i
After=network.target
[Service]
WorkingDirectory=/opt/minecraft/instances/%i
User=minecraft
Group=minecraft
Restart=always
ExecStart=/usr/bin/screen -DmS mc-%i /usr/bin/java -Xmx2G -jar minecraft_server.jar nogui
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 15 SECONDS..."\015'
ExecStop=/bin/sleep 5
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 10 SECONDS..."\015'
ExecStop=/bin/sleep 5
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 5 SECONDS..."\015'
ExecStop=/bin/sleep 5
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "save-all"\015'
ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "stop"\015'
[Install]
WantedBy=multi-user.target
@aklinker1
Copy link

@magicus Hmm, I forgot I did that. Shouldn't make a difference, it just won't copy and minecraft will generate one for you. I'll add a comment on that line telling people to change it if needed

@lukewhrit
Copy link

Are there any issues with using this on Ubuntu server?

@aklinker1
Copy link

That's what I use!

@prydin
Copy link

prydin commented May 20, 2020

Thanks! This was just what I was looking for!

@ryan77627
Copy link

Hey, love the example service. I would suggest one edit. As it stands, once the last command is run when stopping the service ExecStop=/usr/bin/screen -p 0 -S mc-%i -X eval 'stuff "stop"\015', systemd will consider the process completed and kill any processes remaining. This is bad since it kills screen the moment after it's told to type stop in the MC console. This means the server never has a chance to properly stop, since it is immediately killed along with screen.

I would recommend adding KillMode=none to somewhere under the [Service] section to stop systemd from killing anything by itself so the server has a chance to gracefully shutdown. Screen will still terminate itself when java exits

My only concern is systemd will consider the process ended after sending the stop command though, so linux may still shutdown before the server is shutdown, but I'm not too concerned about that because I haven;t done a lot of testing in that case yet

@Nullcaller
Copy link

Thanks, @ryan77627! KillMode=none is absolutely necessary for using screen with systemd, you've solved my issue with it.

@lukasfink1
Copy link

lukasfink1 commented Oct 31, 2020

I would recommend adding KillMode=none to somewhere under the [Service] section to stop systemd from killing anything by itself so the server has a chance to gracefully shutdown. Screen will still terminate itself when java exits

My only concern is systemd will consider the process ended after sending the stop command though, so linux may still shutdown before the server is shutdown, but I'm not too concerned about that because I haven;t done a lot of testing in that case yet

My approach is to use KillSignal=SIGCONT instead of KillMode=none. The advantage is that it’ll wait for the server to exit at system shutdown but kill the server with SIGKILL if the server didn’t stop after a timeout (by default 90 s).

Edit: grammar

@JamesAnunda
Copy link

JamesAnunda commented Nov 1, 2020

To view the console su to minecraft with:

sudo su minecraft

then

screen -R mc-server1

you have no idea how long I been looking for this. Digital Ocean seriously needs to update their documentation on this.

@katian
Copy link

katian commented Nov 7, 2020

what do you think about :
ExecStop=/bin/bash -c "while ps -p $MAINPID > /dev/null; do /bin/sleep 1; done"

@cbytestech
Copy link

How does this handle the server.Properties file? If setting this up for each user to have their own, wouldn't they each need their own copy?

@njaksch
Copy link

njaksch commented Jul 6, 2021

So I copied your service unit, modified it to fit my server and added recommendations from comments.
This is my first systemd unit and if I start it the ExecStop commands all immediatly execute?

[Unit]
Description=Minecraft Forge Server
After=network.target

[Service]
WorkingDirectory=/home/niclas/forge

User=niclas
Group=niclas

Restart=always
KillMode=none

ExecStart=/usr/bin/screen -dmS forge /usr/lib/jvm/java-11-openjdk-amd64/bin/java -Xms1G -Xmx8G -jar forge-1.16.5-36.1.32.jar nogui

ExecStop=/usr/bin/screen -p 0 -S forge -X eval 'stuff "say SERVER SHUTTING DOWN IN 5 SECONDS..."\015'
ExecStop=/bin/sleep 5
ExecStop=/usr/bin/screen -p 0 -S forge -X eval 'stuff "save-all"\015'
ExecStop=/usr/bin/screen -p 0 -S forge -X eval 'stuff "stop"\015'
ExecStop=/bin/sleep 10

[Install]
WantedBy=multi-user.target

@MaxSMoke-KillSZ-Official
Copy link

MaxSMoke-KillSZ-Official commented Jul 26, 2021

What is or who is a "stuff"?

@thomasphillipsgb
Copy link

@MaxSMoke-KillSZ-Official I was wondering what this did too. It's a screen command for inputting text or keyboard commands to a running screen session.
https://www.gnu.org/software/screen/manual/screen.html#:~:text=Stuff%20a%20string%20in%20the%20input%20buffer%20of%20a%20window
\015 is the ASCII keycode for a carriage return, the Enter key

@Aviatorpaal
Copy link

Aviatorpaal commented Sep 8, 2021

I had to add "Type=forking" to the file for systemctl to interpret it correctly, and not start/stop-loop the [email protected]

[Unit]
Description=Minecraft Unmodded: %i
After=network.target

[Service]
Type=forking
WorkingDirectory=/opt/survival
User=minecraft
Group=minecraft
Restart=always
ExecStart=/usr/bin/screen -dmS mc%i /usr/bin/java -Xmx4G -jar minecraft_server.jar nogui
ExecStop=/usr/bin/screen -p 0 -S mc%i -X eval 'stuff "say SERVER SHUTTING DOWN IN 10 SECONDS..."\015'
ExecStop=/bin/sleep 10
ExecStop=/usr/bin/screen -p 0 -S mc%i -X eval 'stuff "save-all"\015'
ExecStop=/usr/bin/screen -p 0 -S mc%i -X eval 'stuff "stop"\015'
ExecStop=/bin/sleep 25

[Install]
WantedBy=multi-user.target

@GwynethLlewelyn
Copy link

I'm using systemd + screen to launch a different application (similar in concept to launching a Minecraft server) so I tried to adapt things to my own purposes. This was not easy, but I've encountered the same issue as @Aviatorpaal and had to use Type=forking as well. There were also some slight differences in the parameters sent to screen, some of them not obvious. Ultimately, I got my own setup working using the skeleton framework suggestion posted on the Unix StackExchange (see point 2.), which worked quite well for me. It should also work fine for Minecraft or any kind of interactive server application that benefits from having a console.

@Fiwi1265
Copy link

Thanks this thread is exactly what I needed.

@Dominik-Gubrynowicz
Copy link

Hi, I have an error: screen[2355]: No screen session found. Any ideas what might be wrong? (Ubuntu 20.04)

@sublok
Copy link

sublok commented Jan 24, 2022

Will this work with 1.18.1 java @user_jvm_args.txt @libraries/net/minecraftforge/forge/1.18.1-39.0.45/unix_args.txt "$@"?

@RAD750
Copy link

RAD750 commented Mar 16, 2022

To view the console su to minecraft with:

sudo su minecraft

then

screen -R mc-server1

Don't use sudo su. Instead, do sudo -u minecraft -s, or directly sudo -u minecraft screen -R mc-server1

Cheers

@mitcherthewitcher
Copy link

This thread helped me out. Thanks 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment