Migrating Debian and Ubuntu packages to systemd
Skillfully Packaged
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 thesource
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.
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
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).
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.
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
(incl. VAT)