The Association of Mad Scientists

Using systemd, the init system

Despite its controversy, the systemd init system provides stability and simplicity to the Linux ecosystem. My computers are all Debian and Arch-Linux based, which use systemd by default. If you have something you want to start up in the background when you turn on your Linux desktop or server, or even at other predefined points, a systemd "unit" is probably the best way to do it.

So, I'll quickly walk you through creating a systemd unit. This example will be a simple docker deployment of my (mostly) static web-page resume, but remember this is just the beginning. systemd units offer you powerful controls to run arbitrary commands at arbitrary times.

The whole project repository can be found here. Let me walk you through how all this works, starting with the minimal-resume.service file.

[Unit]
Description="D. Scott Boggs' resume site"
Requires=docker.service

[Service]
ExecStartPre=/media/deployments/minimal_resume/update.sh
ExecStart=/usr/bin/docker run minimal_resume
# you could specify an ExecStop here, or ExecStopPost, etc.

[Install]
WantedBy=multi-user.target

Your unit file should have each of these sections. The Install section should more-than-likely be the same, if you want the service to start at boot. The Unit section should contain a description, like mine, and specify any other services that need to be ready when this service is started. In this case, we're using the docker command, so we have to be sure docker has started before we can start this service. If the service you're trying to start relies on a database, this would be where to specify it.

The service section specifies what gets run to start the service. You can specify a lot of directives, like ExecStartPost, ExecStop, etc., but if you're just running a simple command you can just use ExecStart. Note that the Exec... directives require the full path of the file being executed, which can be obtained using the which command (that is, on my system, which docker outputs /usr/bin/docker).

Once your unit file has been created and any files are in place that it requires, copy the unit file to /etc/systemd/system and run the following commands as root (or prefix them with sudo):

systemctl start minimal-resume.service
systemctl enable minimal-resume.service

The first starts the service; if it fails to start, you know you need to fix something before running the second command which installs the service to be run at startup.

So, to recap quickly:

  1. Write a .service file with an ExecStart directive, description, and WantedBy set to multi-user.target.
  2. Copy the .service file into /etc/systemd/system
  3. Make sure the service starts
  4. Install the service

As I said at the top of the article, this is just the tip of the controversially-large iceberg that is the "system daemon". For more of the many many things that you can do with systemd, run man systemd.unit from your terminal or visit this page in your web browser.

Side-note: If you noticed the ExecPre directive in the unit file, and were wondering what it's for, in this case it's an update script. It pulls the latest version of the repository from git and then builds a new docker image.