[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