Migrating Debian and Ubuntu packages to systemd

Skillfully Packaged

Article from Issue 184/2016
Author(s):

You might need to tweak your Debian or Ubuntu packages to get them to work with systemd.

Systemd [1] has finally established itself as the leading Linux init system, but the road has not been easy. The Debian project [2], in particular, had to hold lots of discussions until the developers were able to agree on a replacement for the aging System V init system in a general vote.

The Ubuntu project was actually in the process of developing its own init alternative before the systemd tidal wave washed over Linux world, and many Ubuntu users and developers were just getting used to Ubuntu's Upstart system when Mark Shuttleworth announced that Ubuntu was abandoning the Upstart project in favor of systemd [3]. (A "Benevolent Dictator for Life" is missing in the Debian project – otherwise, it would probably spare itself a lot of tedious discussions.)

Jessie was the first Debian version with a functioning systemd. Many Debian developers are now adapting to the new circumstances and migrating to systemd. Ubuntu developers are also striving to integrate systemd.

One important part of getting ready for systemd is making sure the packages are compatible. If you install a package that comes with a daemon, the package needs to provide the information necessary for setting up the daemon to work with systemd.

Of course, if you download packages from the Debian or Ubuntu repositories that are intended for systemd-ready release versions, you won't have to worry about converting the packages; however, if you develop or maintain .deb packages yourself, whether for a public project or an internal, homegrown application, you'll eventually need to tailor those packages for the systemd environment. This article offers some thoughts on converting your .deb packages for systemd.

Following systemd

The Debian project and Canonical have done a great job with packages in the official Debian and Ubuntu archives: All but a few packages are compatible with systemd. (The Ubuntu project maintains a list of packages that still need to be converted for systemd [4].)

However, many systems don't just use packages from the official archives. Some system administrators build their own packages from software that isn't yet in the Debian archive. Other users are simply dissatisfied with the distributor's packages and want to create their own. In any case, to create and maintain packages for Linux systems, you need to start moving your packages to systemd.

Fortunately, both Debian and Ubuntu provide a few helpers that automatically take care of various steps for building the package. The package maintainers essentially have to combine the existing tools.

The steps for creating Debian packages for Debian or Ubuntu are similar. The following procedures will work for both Debian and Ubuntu unless stated otherwise.

I'll start with a look at the anatomy of a Debian package. A package is essentially created by a program creator integrating a debian directory (Figure 1) with the source code. The debian directory includes all the instructions for the Debian package construction tools, such as the debhelper tool suite. The debian folder contains a file called rules – this file is almost always empty if you're using debhelper. Other files in the debian directory include:

  • The control file contains information about the binary packages created by the source code package.
  • The changelog file keeps track of the changes made to the Debian package.
  • The copyright file contains notes from the maintainer on which licenses apply to the individual files in the source code package.
  • The format file in the source subfolder contains information about which version of the Debian package standard applies to the source code package.
  • If you are using debhelper, a file called compat sets a debhelper compatibility level.

For simple programs, these six files are usually enough to create a .deb package compatible with the Debian or Ubuntu.

Figure 1: The debian directory often includes other files in addition to essential ingredients like changelog, control, copyright, and rules.

Sometimes in the debian folder (and frequently missing) are maintainer scripts. Maintainer scripts have names like preinst, postinst, prerm, and postrm. Their names reveal their function: preinst executes commands before unpacking package contents on the target system; postinst executes commands after unpacking. The prerm and postrm scripts remove packages instead of installing them. If multiple binary packages are embedded in a source package, the maintainer scripts are prepended with the package name: Packagename.preinst.

Program packages that support Upstart or System V init can use these maintainer scripts to perform steps to set up the init system. On SysV systems with Debian, for example, they call update-rc.d to link a new init script to the corresponding run levels in /etc.

Maintainer scripts sometimes unexpectedly appear in the finished Debian package even though they are missing in the debian folder of the non-packetized sources, because debhelper generates the scripts automatically as soon as the tool comes across files with the extensions .upstart or .init in the debian folder.

The authoritative debhelper tool goes by the name of dh_installinit. This tool automatically detects corresponding files in debian and copies them to the right place in the finished package. In addition, debhelper creates postinst and prerm scripts containing the necessary commands for integrating the script or the Upstart job.

For this automation to work, the names of the files in debian are important. Their names differ depending on the number of binary packages served up by the source package. For a binary package, the files are named service_name.init or service_name.upstart. In the case of a source package with the name gidentd, the script would just be named gidentd.init in /debian. If, however, the same source package were to produce a second binary package named gidentd-data, the filename in /debian would be gidentd.gidentd.init.

The good news is that not as much has changed regarding systemd. Ultimately, integrating systemd doesn't differ that much from the Upstart method: systemd also calls for descriptive files that belong in a specific place in the filesystem so the system detects them. In systemd speak, the descriptive file is called a unit file.

Integrating systemd in Debian packages therefore involves combining elements from both worlds in order to gain the desired result. Fortunately, the developers have already adapted tools such as debhelper to systemd, so anyone who maintains a Debian package using their own systemd unit file for their own servers has a fairly easy job. Just one question remains: Does the packaged software come with its own unit file for systemd, or do package maintainers need to write a unit file themselves?

A Unit File from the Program Authors?

Where it used to be necessary to maintain different SysV scripts for various distributions, systemd requires only a single unit file in the program's source code. The build process replaces a single variable with the complete path to the service that the unit file handles.

Little wonder the latest versions of many current tools come with unit files for systemd. The automated build process using the auto tools usually integrates these unit files. The make install step automatically installs the unit file. If the specified prefix is correct, the auto tools will place the unit file in the right place. The package maintainer only needs to make sure the postinst script activates the unit file as desired.

The steps for activating the unit file using debhelper depend greatly on the degree of automation used with the package. It has become established practice among Debian developers to have a target for all calls in the rules script that starts dh. If you append --with systemd to the dh command, the script will look for a systemd unit file (Figure 2). If the --with parameter is already present, append the systemd keyword to the list; a comma acts as the separator:

%:
dh $@ --with python2,system
Figure 2: Append --with systemd to the dh command to look for the systemd unit file.

If you make your Ubuntu package available on Launchpad, you don't need to upload a completed binary package but just the source package. Launchpad takes care of the rest using its automatic build daemons. The package needs to correctly declare its build dependencies in order for the operation to work. The build dependencies define the packages that need to be installed during the build process so the application you're installing will work.

The debhelper extension for systemd comes in a separate package named dh-systemd. The package is part of the build dependencies of a package for systemd (Figure 3).

Figure 3: Debhelper integration on systemd only works if dh-systemd is part of the build dependencies.

The dpkg-buildpackage call builds the package. The -S parameter is sufficient if the packager wants to distribute the package for Ubuntu using Launchpad. No parameters are required if dpkg-buildpackage will build the package locally.

To find out whether the .deb package resulting from the build process contains the unit file, run dpkg --contents against the .deb file: Ideally, developers will find the unit file under the path ./lib/systemd/system/service_name.service (Figure 4). It is possible to determine whether the integration in the maintainer scripts was successful by unpacking the Debian package, using a command such as:

ar -x gidentd_1.0-1_amd64.deb

The resulting file control.tar.gz should include a postinst file containing a line such as

deb-systemd-helper enable service_name.service >/dev/null || true

.If so, the package is ready for production. However, it wouldn't hurt to check that the package complies with Debian policy using the lintian command.

Figure 4: If systemd integration works as intended, a unit file will appear the in the /lib/systemd/system/ folder inside the package.

Less Ideal: Writing Unit Files Yourself

Sometimes the source code for the program doesn't come with a unit file, and you have to create a unit file yourself in order to build the package. If you're used to working with Upstart, and you want to build a systemd unit file, you might want to start by reading the comparison on the Ubuntu Wiki, which is directed at Upstart package maintainers who want to get started with systemd [5].

Unit files for systemd are not particularly complex. A few lines will do the trick at best: Three sections named Unit, Service, and Install supply systemd with all the information it needs to set up a service. The keywords Description for a brief description of the service and Documentation, which makes it possible to reference the program documentation, are in the Unit section.

In addition to information about the type (Type), Service contains information about the service's runtime environment (Environment), about commands invoked by the installation script before the actual command, and about the program command itself (ExecStartPre and ExecStart). Install ultimately determines when systemd starts the unit and what dependencies it has on other unit files.

The package maintainer places the unit file in the debian subdirectory of the program's unpackaged sources. The previously cited naming rules also apply to systemd because the dh_installinit tool, which makes sure the unit files for systemd are correctly installed, also maintains SysV scripts and Upstart jobs. . The tool detects Upstart jobs if their filenames end in .service. Again, the package name and service name must appear in the filename for a source package that generates several binaries, that is, gidentd.gidentd.service if the name of the target package and the name of the service are both gidentd.

The rest of the operation works as if the unit file came directly from the program provider: --with systemd needs to follow the dh call in debian/rules for debhelper to automatically take care of the rest. The dh-systemd also has to be in the build dependencies of the debian/control file. Of course it is also possible to find out whether the integration worked as expected in this example by using dpkg -l or unpacking the .deb package using ar -x.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Professor Knopper's Lab – Removing systemd

    The systemd service manager has been widely adopted by many Linux distros, so why would you want to remove it? The professor reveals why and how.

  • systemd-networkd

    The new networkd component of the systemd project supports basic network configuration. Despite its early stage of development, one thing is clear: This is a daemon with brains.

  • Systemd Graphical Tools

    Systemd has won the race, as indicated by the several tools that already offer a service just a mouse click away. We look at six of these tools.

  • Systemd Units

    Systemd units use files to control resources that Systemd manages.

  • Init Systems

    SysV init was formerly the sole candidate for starting processes on Linux, but today, a tech-savvy generation of init systems is waiting in the starting blocks.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News