Autossh and Systemd Service

Several months ago, I wrote a post to describe how to setup an autossh daemon with upstart. Since Ubuntu 15.04 has switched to systemd, I would like to do the same with systemd. I will give a brief introduction to systemd in this post.

Systemd Unit File

Systemd services are configured by unit files. By convention, these files use .service as their file name extension.

On Ubuntu, there are two directories for unit files:

  • /lib/systemd -- This is the directory for unit files provided by the installed packages.
  • /etc/systemd -- This is the directory for the administrators to create, override, modify or mask the unit files in /lib/systemd.

Although the autossh package does not come with any unit file, we can create one in /lib/systemd:

$ sudo vim /lib/systemd/system/autossh.service

Here's the content of the unit file:

[Unit]
Description=autossh
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=autossh
EnvironmentFile=/etc/default/autossh
ExecStart=
ExecStart=/usr/bin/autossh $SSH_OPTIONS
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

Some explanations to the options:

  • Description= contains some words that can describe the service. This will show up in the logs.

  • Wants= specifies the dependencies of the services. If this service is activated, systemd will also activate the listed services.

    In our case, we would like to make sure that the network interface is ready, thus we specified network-online.target [1].

  • After= specifies the order to launch the service. With the After option, systemd will only launch the service after the activation of listed services. Notice that this option is orthogonal to Wants (or Requires.) If After is not specified, systemd may launch the dependencies simultaneously.

  • Type= specifies the type of the service. There are several options: simple, fork, oneshot, and etc.

    • A simple service will contain one long running process. The process will not stop unless we kill the service.
    • A fork service means that the ExecStart command will fork a subprocess and return immediately. In the other words, the command will manage the process by themselves.
    • An oneshot service will launch a new process whenever an event triggers this service.
  • User= specifies the user as whom the service process is run. By default, the process is run as root.

  • EnvironmentFile= specifies the path to an environment file, which contains the environment variables for the service process.

  • ExecStart= specifies the command to launch the service. We have to specify the full path to the executable to be executed.

    Notice that there are two ExecStart in our unit file. They are not typos. In order to allow this unit file to be included by another unit file, we have to clear ExecStart before specifying a new command.

  • WantedBy= specifies the init stage to launch the service (if the service is enabled.)

Now, we can create a soft link in /etc/systemd/system:

$ sudo ln -s /lib/systemd/system/autossh.service \
      /etc/systemd/system/autossh.service

Environment File

Did you notice that there is a variable $SSH_OPTIONS in the ExecStart option above? It will be substituted by the environment variable from the file specified by EnvironmentFile. Environment files are the files which contain the configurations which should be passed to the service.

Let's create an environment file:

$ sudo vim /etc/default/autossh

The environment file resembles to a Bash script. Here's the example for our autossh service:

AUTOSSH_POLL=60
AUTOSSH_FIRST_POLL=30
AUTOSSH_GATETIME=0
AUTOSSH_PORT=22000
SSH_OPTIONS="-N -R 2222:localhost:22 example.com -i /home/autossh/.ssh/id_rsa"

We can find more options by reading autossh man pages.

Start the Service

Before we can start our service, we have to ask systemd to reload all unit files:

$ sudo systemctl daemon-reload

Now, we can start autossh service with:

$ sudo systemctl start autossh

And then, we can check the status with:

$ sudo systemctl status autossh

With this command, you should be able to see the following output (if the unit file is correct):

* autossh.service - autossh
   Loaded: loaded (/lib/systemd/system/autossh.service; enabled;
vendor preset: enabled)
   Active: active (running) since Sun 2015-11-15 22:51:25 CST; 1min 1s ago
 Main PID: 14382 (autossh)
   CGroup: /system.slice/autossh.service
           |-14382 /usr/lib/autossh/autossh -N -R 8022:localhost:22 ....
           `-14385 /usr/bin/ssh -L ...

If there are some problems, check /var/log/syslog for more details.

BTW, to stop the service, we can use the following command:

$ sudo systemctl stop autossh

Launch Service at Boot Time

OK. If everything goes well, then we may ask systemd to launch our service during the boot time. To do so, we have to enable the service with:

$ sudo systemctl enable autossh

Conclusion

In this post, I have covered some basic concept of systemd unit files and basic commands to control systemd:

  • Reload unit files with sudo systemctl daemon-reload
  • Start/stop service with: sudo systemctl [start/stop] [name]
  • Check service status with: sudo systemctl status [name]
  • Register/unregister the service for the boot time with: sudo systemctl [enable/disable] [name]

Hope you enjoy this article.