Ubuntu .deb package maintainer scripts, hooks, triggers, tips & tricks

Maintainer scripts, triggers, and flowcharts

Please familiarize yourself with

https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html

and the associated flowcharts at

https://www.debian.org/doc/debian-policy/ap-flowcharts.html

Also note documentation on dpkg-triggers, see
https://manpages.ubuntu.com/manpages/jammy/en/man5/deb-triggers.5.html

And associated documentation

How to raise reboot required notification?

On all Ubuntu flavours update-notifier-common is a seeded package. It provides integration hooks to other packages to raise awarness that a reboot is required for updates to take effect. This is normally done for packages that cannot be restarted as part of the package upgrade - or have too many processes running as user instances that cannot be tracked with apt upgrades. Example of such packages are linux kernels, dbus, libss1.1, libc6 and others.

General pattern in the package is to add debian/mypackage.postinst with the following snippet

# [ -n "$2"  ] means package upgrade, see maintainer scripts policy above
# [ -z "$2" ] means initial install-only, see maintainer scripts policy above
# adjust checks as needed

if [ "$1" = configure ] && [ -z "$2" ]; then
        # trigger an update notification that recommends a reboot
        # (used by unattended-upgrades etc.)
        touch /var/run/reboot-required || true

        if ! grep -Fqsx mypackage /run/reboot-required.pkgs; then
            echo mypackage >> /run/reboot-required.pkgs || true
        fi

        # same thing for the older update-notifier interface
        [ -x /usr/share/update-notifier/notify-reboot-required ] && \
            /usr/share/update-notifier/notify-reboot-required || true
    fi

This will result in GUI popup notifying desktop users that a reboot is required, MOTD is updated for Ubuntu Server users, at the end of the apt call it is mentioned that a reboot is required, and many other monitoring solutions would also flag up the machine as reboot required (e.g. Canonical Landscape).

The above snippet should be guarded with any checks needed to ensure that reboot is actually required, for example only when system is modified in a way that actually requires reboot. If the state of the system is fine as is, please do not needless raise such flag. For example, some packages only raise this flag upon initial package installation ([ "$1" = configure ] && [ -z "$2" ]) or only upon upgrades ([ "$1" = configure ] && [ -n "$2" ]) or only when specific conditions are met or change.

Similarly this reboot required notification can be raised in other maintainer scripts, for example in postrm after the package removal.

How to update bootloader kernel commandline?

In general it is best to update kernel command line options only for things that are needed or desired, and user is aware of that they are opting into them. For example installing kdump-tools package configures and modifies the bootloader to allow for it to work. Similarly when opting into optimised kernels (Public Cloud specific kernel, FIPS certified kernel, Realtime Kernel) the system is configured to use that particular kernel flavour by default.

Using grub

The package can ship a conffile at /etc/default/grub.d/mypackage or generate such file on the fly in postinst. Shipping it as conffile, will allow end users to customize the file and preserve their changes (for example comment options out). If it is always generated customizations will be erased, but in such cases please add a comment that file is automatically generated / managed by mypackage.

Below is a conffile example of shipping grub customization

cat debian/mypackage.install
debian/grub.d etc/default/

cat debian/grub.d/mypackage
GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT mypackage=arg"

cat debian/mypackage.postinst
if command -v update-grub > /dev/null && [ -e /boot/grub/grub.cfg ]; then
	update-grub
fi
cat debian/mypackage.postrm
if command -v update-grub > /dev/null && [ -e /boot/grub/grub.cfg ]; then
	update-grub
fi

This will ensure that mypackage=arg is activated on systems that use grub bootloader, without any effect or errors on systems that don’t use grub.

Using u-boot-menu

TODO

Using nullboot

TODO

Using sipl

TODO

How to get triggered whenever kernel upgrades?

Ubuntu kernels upon installation, upgrade, removal trigger execution of hooks from /etc/kernel. Normally packages ship hooks there in postinst.d directory to regenerating specific things that are needed for the new kernel abis that are yet to be booted. Good examples are bootloaders, generating initrd, recompiling dkms modules, and doing any other updates that are coupled with exact kernel ABIs. These have to be coded very gracefully, as they can be triggered at different points of the apt upgrade transaction, can be triggered multiple times, and upon failure could prevent kernel upgrades. Also these are executed during system installation & image preparation, thus often these are guarded with calls to systemd-detect-virt --quiet --container to ensure they do not execute in a chroot/container which often happens during VM image preparation. (E.g. systemd-detect-virt).

But it is a useful place to precompile anything that needs to be correct and active on the next boot against the future kernel.

3 Likes