Home / Alt manpages / deb-systemd-helper(1p)

  • deb-systemd-helper(1p)
  • POSIX command
  • linux

Enable Units from Maintainer Scripts with deb-systemd-helper

Your package enables a service on install, and an admin who turned it off finds it back on after every upgrade. deb-systemd-helper exists to stop exactly that. By the end you will have a maintainer-script pattern that records a unit's enabled state without starting anything, plus a way to inspect the result and redirect operations into a chroot. It is a packaging helper, not a replacement for an administrator's systemctl command.

Before you start

Allow about 15 minutes. You need a Debian or Ubuntu package build or test environment, the init-system-helpers package, and a unit file your package actually ships. The installed man page here comes from init-system-helpers 1.66ubuntu1, dated 6 December 2023. Check behaviour outside that version against the target distribution.

Warning

Stop here if you are an administrator trying to enable a service on a running host. The man page says this helper is for maintainer scripts and is not intended for interactive use. Use systemctl when systemd is running, or leave the enabled state alone on a machine that does not run systemd.

1. Choose the maintainer-script action

Call the helper with an action, then one or more unit file names. A typical package postinst action is:

deb-systemd-helper enable example-worker.service

The helper's enable is deliberately not an unconditional systemctl enable. It happens only once, when the package is first installed. The first enable creates a state file, and purge removes that state. That lets a package upgrade leave the administrator's later choice alone.

Use the matching lifecycle actions in the maintainer scripts your package needs:

  • enable records the initial enabled state.
  • disable records that the unit should not be enabled.
  • purge removes the helper's package state.
  • reenable applies the helper's re-enable operation.
  • mask and unmask preserve the enabled or disabled state around a mask.

There is no start or stop action, so do not make one up. This helper manages enablement state. Starting or stopping a service is a separate operational decision.

2. Put the call in the package workflow

Maintainer scripts run with the privileges and environment the package manager supplies. Tie the unit name to a file the package ships, and quote a variable if your packaging code uses one:

unit_file='example-worker.service'
deb-systemd-helper enable "$unit_file"

That is ordinary shell, but it belongs in a maintainer-script test or a package build workflow, not a terminal on a production machine. Follow the package's normal error-handling policy too. Do not hide a failed helper call just to make an upgrade look successful.

Safety warning

purge changes and removes recorded state. Use it only on the package removal path, after checking the package really owns the unit. It is not an undo button for an arbitrary administrator change.

3. Query state without misreading it

The helper has several Debian-specific queries:

  • is-enabled checks the recorded enablement state.
  • was-enabled reports whether a service was enabled before an updated service file was installed. Handy when a script must preserve a previous choice.
  • debian-installed succeeds when the state file for at least one supplied unit exists.
deb-systemd-helper is-enabled example-worker.service
deb-systemd-helper was-enabled example-worker.service
deb-systemd-helper debian-installed example-worker.service

These answer mainly through their exit status. In a shell test, capture that status immediately:

if deb-systemd-helper is-enabled example-worker.service; then
    echo 'recorded as enabled'
else
    echo 'not recorded as enabled'
fi

Checkpoint

A non-zero result does not mean the service is stopped, broken or absent. It only means the recorded-state condition you asked about was not met. Do not turn this helper into a service-health check.

4. Test a package root safely

When a maintainer script works on a chroot, set DPKG_ROOT to that directory. The helper then operates under that root instead of the host root:

DPKG_ROOT=/srv/package-root   deb-systemd-helper update-state

update-state is a Debian-specific action. It removes obsolete entries and adds entries for new service files without enabling them. That suits synchronising the helper's state after package files change, but it does not activate a service.

Warning

Use an explicit, prepared test root such as /srv/package-root, and check the directory before you run the command. Do not point DPKG_ROOT at / to make a test feel realistic. If a test changes state, remove the disposable root with your normal package-test cleanup rather than repairing a production host by hand.

5. Turn on diagnostics only when investigating

For a maintainer-script or package-manager bug, export _DEB_SYSTEMD_HELPER_DEBUG=1. Debug messages go to standard error, so they stay visible in a dpkg run:

_DEB_SYSTEMD_HELPER_DEBUG=1   deb-systemd-helper is-enabled example-worker.service

Scope this to the failing test or package operation. It is evidence, not service configuration. The installed program also refuses normal interactive invocation, another hint that its interface is built for package scripts.

Common traps

  • Expecting enable on every upgrade. Its one-time behaviour protects later administrator choices.
  • Starting a daemon with it. Enablement state and running state are different concerns.
  • Treating is-enabled as a health check. It reports recorded state, not process health.
  • Testing a chroot without DPKG_ROOT. That risks changing the host's package state.
  • Passing a unit the package does not own. Keep unit names aligned with the files the package ships.

Done means

  • Documented action. The maintainer script uses one, against a real shipped unit file.
  • Exit status, not health. Enablement checks read the exit status and are not mistaken for service-health checks.
  • Disposable root. State-changing tests go through DPKG_ROOT.
  • Purge in its place. purge appears only in the package purge path.
  • Debug on demand. Debug output is enabled only while collecting evidence for a failure.