Home     Blog     Rss     Contact     Donate

[Debian & Derivatives] Easily Create Metapackages


There are many ways one can use to make reinstalling a system, or even redistributing modifications across multiple machines, more convenient. Using metapackages is an often overlooked way of doing just that.

Here we'll go through creating both a simple, empty metapackage which simply installs a bunch of packages as dependencies, as well as a more elaborate one containing a postinst script and some special files.

For this we'll be using the equivs-build command.

Install equivs


First, install the equivs[1] package:


# apt-get install --no-install-recommends -y equivs

Basic Template


Create a working directory and cd into it:


$ mkdir mympkg
$ cd mympkg

Next, create a control file. You can use the equivs-control command to generate a file automatically and fill out the appropriate fields while removing those not needed, or you can create the file manually.

Create automatically (substitute mypkg_name for whatever you want as the name for your metapackage):


$ equivs-control mypkg_name

Doing it manually isn't that much more complicated. For a basic package only a few fields are required.

Create/open the mypkg_name control file in your preferred text editor and add the following:


Package: mypkg_name
Version: 01
Maintainer: Your Name <your@email.example>
Architecture: amd64
Depends: pkg1,
 pkg2,
 pkg3,
 pkg4,
Description: Short description
 Long description. Don't exceed 72 characters per line.
 If you need paragraphs, separate with a dot (.), like
 this.
 .
 This is a new paragraph.

More Elaborate


This is why this post exists. Let's be honest, if all you need is to install a series of packages you could just use a basic shell script, for example.

The following mypkg_name control file example does the same as the basic one, but adds a postinst script and a few files to copy over.


Package: mypkg_name
Version: 01
Maintainer: Your Name <your@email.example>
Architecture: amd64
Depends: pkg1,
 pkg2,
 pkg3,
 pkg4,
 Postinst: postinst
 Files: file1 /path/where/file1/should/be/installed/
  file2 /path/where/file2/should/be/installed/
Description: Short description
 Long description. Don't exceed 72 characters per line.
 If you need paragraphs, separate with a dot (.), like
 this.
 .
 This is a new paragraph.

Note: All files that you want to add to your metapackage, as well as the postinst file should be in the working directory.

The postinst script


This is a shell script that will be executed at the end of the package's installation and can perform any action you want. For example, you could set special permissions to file1 and make sure it is owned by a specific user:


#!/bin/sh

set -e

chmod 600 /path/to/file1
chown someuser:someuser /path/to/file1

Speaking of file permissions, you could use it to set the permissions of various files on the system, not just the ones provided by the metapackage. For example, this bit taken from Ragnarok's security-check[2] cronjob could be used to ensure that a wireless network's interface file is only readable by root:


#!/bin/sh

set -e

for _file in $(find /etc/network/interfaces.d/ -type f); do
    if [ "$(stat -c "%a %g %G" "$_file")" != "600 0 root" ]; then
        /usr/bin/chmod 600 "$_file"
        /usr/bin/chown root:root "$_file"
        printf '%s\n' "Fixed ${_file}'s permissions."
    else
        printf '%s\n' "${_file}'s permissions are OK."
    fi
done

Or perhaps set your system's default browser (if you have more than one installed):


#!/bin/sh

set -e

update-alternatives --install /usr/bin/x-www-browser x-www-browser /usr/bin/preferred-browser 100

Likewise for your preferred editor, compiler, awk version (mawk, original-awk, gawk), etc..

You are only limited by your imagination. Take note, however, that postinst is executed as the root user, so careful not to mess things up.

If there are any specific actions you'd rather have performed only during the initial installation of your metapackage but not when it is updated, you can use an if...else statement:


#!/bin/sh

set -e

if [ -z "$2" ]; then
    # actions to be performed on install
fi

In essence, postinst is called with specific arguments (e.g. configure) and if "$2" is null, then this is an install, rather than an upgrade.

Build the package


When you're done, all that's left is using the equivs-build command to build the package, by supplying the name of the control file as an argument:


$ equivs-build mypkg_name

Caveat


The one drawback is that removing a program installed as a dependency of this metapackage will make apt want to uninstall the whole thing. So if you wanted to replace a specific program with another, you would have to rebuild your metapackage with the new dependency and reinstall, then remove the superfluous package, rather than doing just apt remove package.

Links


[1] https://manpages.debian.org/bookworm/equivs/index.html
[2] https://github.com/RagnarokOS/src/blob/master/base/etc/cron.weekly/security-check