You start the server, it prints its startup lines, everything works. You close the terminal and go to bed. In the morning the server is down and nobody can tell you why.
Nothing crashed. Closing the SSH session killed the process, because the process was a child of that session and the session ended.
This is the first thing everyone running a Linux game server discovers, and there are three answers to it. Which one you should use depends on whether the server matters yet.
Why it happens
When you log in over SSH you get a session, and anything you start belongs to it. When the session ends, you disconnect, your connection drops, your laptop sleeps: the system sends a signal to everything in it, and most programs respond by exiting.
That is correct behaviour. It stops abandoned processes accumulating forever on shared machines. It is just not what you want for a server.
screen: the quick answer
screen creates a session that survives disconnection. You attach to it, run things, detach, and reattach later from anywhere.
screen -S myserver
./start.sh
Then press Ctrl-A followed by d to detach. The server keeps running. Later:
screen -r myserver
You are back at the console, output and all.
What it is good for. Testing. First setup. Anything where you want to watch the console output and interact with it directly.
What it is bad for. Anything that matters. Screen does not start your server when the machine reboots, does not restart it when it crashes, and does not log anything unless you arrange it separately. A server in a screen session is a server that is running until the first time something goes wrong.
The failure everyone meets: the machine reboots for a kernel update at 4am and the server does not come back. Nobody notices until the morning.
tmux: the same, better
tmux does what screen does with a nicer interface, split panes, and a configuration file people enjoy writing.
tmux new -s myserver
./start.sh
Ctrl-B then d to detach; tmux attach -t myserver to return.
For the purposes of a game server it has exactly the same limitation as screen: it keeps a process alive across your disconnection, and does nothing about reboots or crashes.
Use whichever you prefer. If you have no preference, tmux.
systemd: the real answer
For a server anyone else depends on, this is the answer, and it is worth the hour it takes to set up.
systemd is the service manager on essentially every modern Linux distribution. Handing it your server means it:
- starts on boot, without you
- restarts on crash, within seconds
- logs everything to a queryable place
- runs as a specific user with specific permissions
- stops cleanly when you ask it to
A minimal unit file, at /etc/systemd/system/mygame.service:
[Unit]
Description=My game server
After=network.target
[Service]
Type=simple
User=gameserver
WorkingDirectory=/home/gameserver/server
ExecStart=/home/gameserver/server/start.sh
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Then:
sudo systemctl daemon-reload
sudo systemctl enable mygame
sudo systemctl start mygame
systemctl status mygame tells you whether it is running. journalctl -u mygame -f follows the log live, which replaces the tail -f you would otherwise be running against a file.
The three lines that matter most
User= — run as an unprivileged user, never root. If the process is compromised through a plugin or an exploit, this is the difference between losing a game server and losing a machine. Security basics covers the wider picture.
Restart=on-failure, comes back after a crash. Use on-failure rather than always, so that a server you deliberately stop stays stopped.
RestartSec=10; waits before restarting. Without it, a server that crashes on startup restarts in a tight loop, which fills your disk with logs and makes the actual error much harder to find.
The trap: restart loops hide the problem
A server that crashes and restarts every ten seconds looks, from outside, like a server that is up. The listing shows it online most of the time. Players connect and get dropped. Nothing obviously alarming appears.
Two defences:
StartLimitBurst and StartLimitIntervalSec tell systemd to give up after a few rapid failures rather than looping forever. A service in a failed state is much more visible than one restarting silently.
Actual monitoring. A restart loop shows up in uptime history as a pattern of small gaps rather than one large one, which is exactly the shape worth alerting on. Reading your stats page covers what those gaps look like from the outside.
Sending commands to a server you cannot see
The obvious objection to systemd is that you lose the interactive console. With screen you could type into it; with systemd the process has no terminal attached.
Three answers:
RCON, where the game supports it. The proper answer, a remote console over the network, which also works from your phone.
A named pipe. Point the server's stdin at a FIFO and write commands into it. Works everywhere, feels like a hack, is entirely reliable.
Run inside tmux, managed by systemd. A hybrid some people like: systemd starts a tmux session, and you can still attach to it. More moving parts, and worth it if you frequently need the console.
For most servers RCON covers it and the console is not missed.
Stopping cleanly
The half of this that nobody thinks about until they lose a world.
Most game servers need to save state before exiting. Killed abruptly, they lose whatever was in memory — the last few minutes of building, the last few transactions, occasionally a corrupted save file rather than merely a stale one.
systemd sends SIGTERM first and waits, then sends SIGKILL if the process has not exited. Two settings control whether that is enough:
TimeoutStopSec=: how long to wait before the kill. The default is often 90 seconds, which is generous for most games and not for a large world that takes two minutes to save. Set it deliberately.
ExecStop=, a command to run instead of the signal. For games with RCON, this is the correct approach: issue a save and a stop command, and let the server shut itself down the way it expects to.
ExecStop=/usr/local/bin/rcon-send "save-all"
The test is simple and worth doing once: systemctl stop the server, watch the log, and confirm it saved before exiting. Finding out during an emergency reboot is the expensive version.
This matters most on persistent-world games; anything where players build. On a round-based server there is usually nothing to lose, and a hard stop costs nothing.
Automatic restarts on a schedule
Separate from restarting after a crash, and a different tool.
Many servers benefit from a periodic restart — memory fragments, some games leak, and a nightly restart in the quiet hours costs nothing. systemd handles this with a timer unit rather than cron, which keeps everything in one place and logs the same way.
The important part is not the mechanism, it is the timing and the warning: restarting during your actual peak is an expensive, self-inflicted outage, and restarting with no notice loses people whatever they were mid-way through. Automating server restarts without annoying everyone covers both, including how to find your genuine quiet hour rather than the one you assume.
Which to use
Testing something for ten minutes: screen or tmux, and do not think about it.
A server your friends use: systemd. It takes an hour once.
A server strangers use: systemd, plus monitoring, plus scheduled restarts, plus backups that you have tested restoring from.
The progression is not academic. A server left in a screen session works perfectly until the day the host reboots the machine for maintenance, and that day arrives eventually for everyone. The gap between "came back automatically" and "came back when I noticed the next morning" is the entire difference in what your uptime figure looks like to a stranger deciding whether to join.
Running several servers on one machine
Once you have one service, adding a second is nearly free, and there are a few conventions that keep it manageable.
One unit file per server, named for what it is, minecraft-survival.service, minecraft-creative.service. Resist the urge to write a single script that starts everything, because then you cannot stop one without stopping all of them.
One user per server, or at least one user per game. If a plugin on one server is compromised, it should not be able to read the other server's files. This costs nothing and closes a real gap.
Different ports, written down. The most common self-inflicted problem with multiple servers is two of them trying to bind the same port, which produces an Address already in use error and a server that silently does not start. Keep a note.
Watch memory. Two servers on a machine sized for one will both work fine until a busy evening, at which point the kernel picks one and kills it. free -h and hardware specs cover what you need.
Stagger the restarts. If both restart at 5am, both are down at 5am. Offset them.
And before adding a second server at all, it is worth being honest about whether you should: when to run a second server instead of a bigger one covers why splitting a population is usually the wrong move, and the technical ease of doing it is precisely what makes it tempting.
Before you move on
Once the server is a service, three things become easy that were awkward before: it survives reboots, journalctl gives you readable logs without configuring anything, and a scheduled restart is a one-line timer rather than a script fighting a screen session.
Those three are most of the operational work of running a server, which is why this is the hour worth spending first.
Common questions
- How do you view systemd server logs in real time?
- Run `journalctl -u mygame -f` to follow the service log live. This replaces having to manually run a tail command against a log file, keeping output accessible in one queryable place.
- How can you type console commands into a server managed by systemd?
- You can connect over the network using RCON if the game supports it. Alternatively, you can point stdin at a named pipe FIFO to write commands, or run the server inside tmux managed directly by systemd.
- How do you prevent systemd from killing a server before it finishes saving?
- Adjust the `TimeoutStopSec=` setting to give the process enough time to write its world to disk before receiving a kill signal. For games with RCON, you can also set `ExecStop=` to issue a save and stop command automatically.
Published · 7 min read