On this page
If you start your game server by running its script over SSH, it dies when you close the terminal. That is not a bug in the game server, it is how a login session works: the processes you start belong to that session, and when the session ends they are told to end with it. The fix is to hand the program to systemd instead, so it belongs to the system rather than to your terminal.
Doing that also gets you three things you would otherwise build by hand: it starts at boot, it restarts after a crash, and its output goes somewhere you can read later. This page covers running the services that came with your server, reading their logs, and writing a unit file for something that did not come with one.
systemctl, the six commands you need
Every command here runs as root or with sudo.
systemctl status nginx
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl enable nginx
systemctl disable nginxThe distinction that catches everyone: start and stop act on right now, enable and disable act on the next boot. A service you started but never enabled is gone after a reboot. A service you disabled but never stopped is still running until you stop it or reboot. When you mean both, say both:
systemctl enable --now fivem
systemctl disable --now postfixTwo more that answer questions directly, without you reading through status output:
systemctl is-active fivem
systemctl is-enabled fivemAnd reload, which some services support, asks the service to re-read its
configuration without dropping what it is doing. systemctl reload nginx keeps
connections alive where restart would break them. Not every service implements
it, and systemctl reload-or-restart falls back for you.
To see what is on the machine:
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabledThe first is what is running now, the second is what will come back after a reboot. Comparing the two is a good way to find something you started by hand months ago and forgot to enable.
Reading systemctl status
systemctl status fivem is the first thing to run when something is wrong. Read
it in this order:
- The
Loaded:line. It names the unit file on disk and says whether it isenabledordisabled. If it saysnot-found, the unit does not exist, usually a typo in the name. - The
Active:line.active (running)is healthy.inactive (dead)means it is not running and nothing is trying.failedmeans it tried and gave up, and the same line carries the reason. - The exit code on a failure, shown as
status=followed by a number. Common ones are covered under troubleshooting below. - The last log lines, printed underneath. They are usually the actual
answer, and
journalctlgives you the rest of them.
journalctl
systemd captures whatever a service writes to standard output and standard error, so a program that prints to the screen when you run it by hand has its output collected without you configuring any logging at all.
Narrow by unit first, because the whole journal is everything on the machine:
journalctl -u fivemThen narrow further. These combine freely:
journalctl -u fivem -n 200
journalctl -u fivem -f
journalctl -u fivem --since "2026-08-18 20:00" --until "2026-08-18 21:00"
journalctl -u fivem --since "30 min ago"
journalctl -u fivem -p err
journalctl -u fivem -b
journalctl -u fivem -b -1What each one does:
-n 200shows the last 200 lines instead of the default 10.-ffollows the log live, liketail -f. This is the one to have open in a second window while you restart something.--sinceand--untiltake an absolute timestamp or plain English such asyesterday,1 hour ago, ortoday.-p errshows only entries at error priority or worse, which cuts a noisy log down to the lines that matter.-p warningis a gentler filter.-blimits to the current boot, and-b -1to the previous one, which is how you find out what happened before an unplanned reboot.-kshows kernel messages only, which is where an out-of-memory kill appears. See Disk, memory and swap.
By default the journal pages through less, so q quits, / searches, and
-e jumps straight to the end. Add --no-pager when you want to pipe it:
journalctl -u fivem --since today --no-pager | grep -i errorWriting a unit file
A unit file is a text file that tells systemd how to run your program. Put your
own in /etc/systemd/system/, which is the directory reserved for the
administrator, and name it after the service with a .service extension.
Before you write it, create an account for the service to run as and give that account ownership of its files. See Users, groups and sudo for why this matters more than anything else on this page.
Here is a complete unit for a game server, /etc/systemd/system/fivem.service:
[Unit]
Description=FiveM game server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=fivem
Group=fivem
WorkingDirectory=/opt/fivem/server-data
ExecStart=/opt/fivem/server/run.sh +exec server.cfg
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.targetTaking the settings that carry real weight in turn.
User= and Group=
The account the process runs as. systemd drops to it before your program starts, so the program never has root at all, and a flaw in it cannot reach beyond what that account owns. Leaving this out means running as root, which is the single worst default on this page.
If the unit fails immediately with status=217/USER, the account named here does
not exist.
WorkingDirectory=
The directory the process starts in. Game servers care about this more than most
software, because their configuration and resource paths are usually written
relative to where the server was launched, so the same command that works when
you cd there by hand fails from systemd without it.
If the unit fails with status=200/CHDIR, this directory is missing, or the
account in User= cannot enter it.
ExecStart=
The command to run. Two rules that account for most first-attempt failures:
- It needs an absolute path. There is no
PATHlookup the way there is in your shell. - It is not a shell. Pipes,
&&, output redirection with>, wildcards, and environment variable expansion do not work, because no shell is involved. If you need any of them, either put the command in a small script and pointExecStartat the script, or run it explicitly through one with/bin/sh -cfollowed by the quoted command line.
status=203/EXEC means the path is wrong, the file is not executable, or its
interpreter line points at something that is not there.
Environment variables that your program needs go in the unit, either inline or from a file, which is the tidier place for secrets:
Environment=FIVEM_PORT=30120
EnvironmentFile=/etc/fivem/envRestart= and RestartSec=
Restart= decides what happens when the program exits:
nois the default. It stays down.on-failurerestarts when it exits with a non-zero code or is killed by a signal, and leaves it down after a clean exit. This is the right choice for most things, because a clean exit usually means it was told to stop.alwaysrestarts whatever the exit code was. Use it for a program that exits cleanly when it should not, which some game servers do on a fatal configuration error.
systemctl stop never triggers a restart under any setting, so you can always
stop a service by hand.
RestartSec= is how long to wait before trying again. The default is 100
milliseconds, which for anything that binds a port is too fast: the old socket
may still be closing. A few seconds is kinder and makes the logs readable.
After= and Wants=
After= controls ordering, not dependency: it says start this later than that.
Wants= says pull that in as well, without failing if it does not come up.
network-online.target is the pairing you want for anything that binds to your
public address at startup, because plain network.target is reached before an
address has been assigned.
If your server needs a database on the same machine, add its unit to both, for
example After=mariadb.service and Wants=mariadb.service.
WantedBy=multi-user.target
This is what systemctl enable acts on. It is the reason enabling works at all,
so a unit without an [Install] section can be started by hand but cannot be
enabled.
Putting it in service
After creating or editing any unit file, systemd needs to re-read it. It does not notice changes on its own:
systemctl daemon-reload
systemctl enable --now fivem
systemctl status fivemsystemd-analyze verify catches typos and unknown settings before you find them
the hard way:
systemd-analyze verify /etc/systemd/system/fivem.serviceThen confirm the port is actually listening, and that the rules on the network side let players reach it:
ss -lntup | grep 30120See Port rules for the network half.
Changing a service you did not write
Do not edit a unit file that came from a package. The next upgrade overwrites it. Use a drop-in instead, which systemd merges over the packaged unit:
systemctl edit nginxThat opens an empty override file, writes it to
/etc/systemd/system/nginx.service.d/override.conf, and runs daemon-reload
when you save. Put only the settings you are changing in it.
To see the result, including every drop-in in the order they apply:
systemctl cat nginxOne quirk worth knowing: settings that can appear more than once, ExecStart
among them, add to the list rather than replacing it. To replace one, set it to
nothing first, on its own line, and then set your value.
When a unit will not start
Work through these in order.
Read the status and the last logs together.
systemctl status fivem -l --no-pager
journalctl -u fivem -n 100 --no-pagerMatch the exit code. systemctl status prints it as status= and a number:
| Code | Meaning |
|---|---|
203/EXEC | The ExecStart binary was not found, is not executable, or its interpreter is missing |
200/CHDIR | WorkingDirectory does not exist or is not reachable by the service account |
217/USER | The user or group named in the unit does not exist |
226/NAMESPACE | A sandboxing setting such as ProtectSystem or PrivateTmp could not be applied |
1 | Your program started and exited on its own. Its own logs have the reason |
Run the same command by hand as the service account. This separates "systemd is configured wrong" from "the program is broken", which is worth ten minutes of guessing:
sudo -u fivem /opt/fivem/server/run.sh +exec server.cfgCheck permissions if it exits immediately with nothing useful. A service account that cannot write to its own data directory fails in ways that look unrelated. See Users, groups and sudo.
Check the disk is not full. A service that cannot write refuses to start, and this is common enough to be worth ruling out early. See Disk, memory and swap.