Creating Systemd Service Files

Introduction

systemd is used in many mainstream Linux distributions like Arch Linux, CentOS, Debian/Ubuntu, RedHat/Fedora, openSuse, Slackware, CoreOS and more. It provides an easy way to manage and control services and a simple method of creating your own services. This will cover the process of creating and managing your own custom service.

You should copy your .service file to /etc/systemd/system. Do not symlink it. One, you can't run systemctl enable because you it will not follow a symlink. Two, it potentially opens up a security risk (e.g. a shell). For example, you run your service as a low privilege user but you are symlinking the .service file. Someone finds a flaw in your service where they are able to overwrite or modify files. They can turn that in to code execution by modifying the .service file that your low privilege user has access to and changing the command that is run (ExecStart). When the service is restarted the attackers command is run. This is also why you should not run the service as root.

Note that you can also put the files in /usr/lib/systemd/system/ but that should be reserved for system level packages. Anything in /etc/systemd/system will override it and that is where user changes should go.

The .service file

Create a .service file in the systemd folder. For example /etc/systemd/system/my_daemon.service. Here is an example .service file. If you want to create a user service that you can run yourself without needing root permissions, you can put the service file in $HOME/.config/systemd/user/my_daemon.service.

[Unit]
Description=My Miscellaneous Service
After=network.target

[Service]
Type=simple
# Another Type: forking
User=nanodano
WorkingDirectory=/home/nanodano
ExecStart=/home/nanodano/my_daemon --option=123
Restart=on-failure
# Other restart options: always, on-abort, etc

# The install section is needed to use
# `systemctl enable` to start on boot
# For a user service that you want to enable
# and start automatically, use `default.target`
# For system level services, use `multi-user.target`
[Install]
WantedBy=multi-user.target

There are more options you can specify. For example, in addition to ExecStart you can specify ExecStop and ExecReload to control what happens when stopping and restarting. Those are not required though. If you omit the ExecStop option, it is smart enough to know it should kill the process. If you need a more graceful shutdown though, specify that with ExecStop. To see some more options, look at man systemd.service in your distribution. Freedesktop.org's man systemd.service .

# Read all the service options
man systemd.service

Controlling the Service

If you are working with a user service, add --user flag to all systemctl commands.

# Control whether service loads on boot
sudo systemctl enable my_service
sudo systemctl disable my_service

# Manual start and stop
sudo systemctl start my_service
sudo systemctl stop my_service

# Restarting/reloading
sudo systemctl daemon-reload # Run if .service file has changed
sudo systemctl restart my_restart

# Or if working with a user service add --user flag
systemctl --user restart my_user_service

View Status/Logs

These commands show how to use systemctl to view the status of all services, specific services, and user services. It also shows how to use journalctl to review logs. Note that if you want to use journalctl as a low-privilege user to view user service logs, the user needs to be in the systemd-journal group.

# See if running, uptime, view latest logs
sudo systemctl status
sudo systemctl status my_service
# Or for a user service
systemctl --user status my_service

# See all systemd logs
sudo journalctl

# Tail logs
sudo journalctl -f

# Show logs for specific service
sudo journalctl -u my_daemon
# For user service
journalctl --user-unit my_user_daemon

Conclusion

After reading this, you should understand how to create simple systemd services for the system and as a low-privilege user. You should also know how to manage, view status, control, and view logs for services.