MAKEIMG(1)

2023-03-15

NAME

makeimg - Build system images from declarative input.

SYNOPSIS

makeimg [OPTION]

DESCRIPTION

makeimg is a script to create a Linux system image from a set of input files, most notably an IMGBUILD(5) file. Currently supported targets are Arch Linux, Alpine Linux, and Debian Linux.

In rough terms, makeimg will:

Each of these steps is described in more detail below. Every step except the bootstrapping is optional.

Much like a PKGBUILD(5), an IMGBUILD will usually not just be a file, but an entire directory, most likely a git repo. The default structure is:


  <PROJECT>/
  |- files/
  |- patches/
  |- templates/
  |- IMGBUILD
  |- pacman.conf

Everything except the IMGBUILD file itself is optional. For Alpine images, instead of pacman.conf you could have a repositories file and a keys directory.

Bootstrapping

First, the base system is bootstrapped with pacstrap(8), apk(8), or debootstrap(8). The packages to be installed and some options can be defined in the IMGBUILD file.

For Arch Linux images, if a file pacman.conf exists, it is used as config for pacstrap(8)(but not copied to the new image).

For Alpine Linux images, if a file repositories and/or a directory keys exist, it is used as config for apk(8) (the repositories are not automatically copied to the new image, but apk will always copy over the keys).

Files

By default, makeimg looks for a folder files/ in the directory where it is being run. If present, all files in that folder are copied over to the image, preserving their path underneath files/. For example, the file files/etc/hostname would be copied to /etc/hostname in the image.

Files copied to the image are owned by root, their mode is preserved (see section File Modes). If a change of ownership is required it has to be performed in the provisioning step (see section Provisioning).

Patches

While the files mechanism can also be used to overwrite files that already exist in the image, it can be preferrable to apply a patch instead. Benefits could be the automatic integration of upstream changes or the breaking of the build if the upstream file changed in a way that the patch no longer applies (whereas overwriting with a potentially invalid file will always succeed).

By default, makeimg looks for a folder patches/ in the directory where it is being run. If present, makeimg will attempt to apply each file in that folder as a patch to an existing file in the image. The patch target is determined by the file name underneath patches/, not the patch header. For example, the patch patches/etc/locale.gen would always be applied to /etc/locale.gen in the image.

Templates

Templates are handled exactly like files, except that shell expansion is performed on each file. The input file is essentially treated like a heredoc, so substitution can even occur in what would seem to be single quotes. While providing ample opportunity for fun and mischief, the main intention is to provide re-usable variables as well as a primitive mechanism for hiding secrets.

Consider the following example, which could be used to render a Wireguard config:


[Interface]
Address = ${SERVER_IP}/24
ListenPort = 51820
PrivateKey = $(pass show vpn/server_key)

[Peer]
PublicKey = 1wVQaL04+Z9aLG6vhernjFVpAN0w5yGZAGSip5GgDgQ=
AllowedIPs = 10.0.0.2/32

The variable SERVER_IP could for example be centrally defined in the IMGBUILD and then used in multiple templates, making it easy to change.

If makeimg was invoked through sudo(8), it attempts to render the template as the original user ($SUDO_USER). Thus, this example should work for a pass(1) setup of a regular user. The same mechanism is implemented for doas(1).

Since rendering templates involves plenty of subshells, checking return codes is next to impossible. Instead, makeimg checks for any output to stderr during template rendering. If there is any, it assumes an error has happened. This behavior can be overridden with the -W flag if needed, but this is considered dangerous.

Note that also due to this any process executed as part of templated cannot ask for passwords by printing the prompt to stderr. For the example above, the pass keys must either already be unlocked in gpg-agent or gpg must be configured to use a graphical prompt.

The template rendering subshell sets -o nounset, so referencing undefined variables will cause an error. For command substitution, make sure a failed command causes output on stderr to detect the error.

Like copied files, the rendered file will be owned by root and the mode preserved from the input file (see section File Modes).

Provisioning

As a final step, the provision function of the IMGBUILD is called. See IMGBUILD(5) for details.

Output

The main output of makeimg is the image as described by the IMGBUILD file. The format (and hence naming) of that image depends on settings in the IMGBUILD. See IMGBUILD(5) for details.

For each generated image makeimg also generates a list of packages that are installed in the image, along with version number (the output of pacman -Q, apk list -I, or apt list --installed). This list can be used to create an inventory of packages and versions used, for example for checking for security advisories.

File Modes

File modes are important for files and templates, as the target file will be given the mode of the source file. However, file modes may not be preserved by some version control systems (e.g. git). As a mitigation, makeimg supports creating a record of all relevant file modes and using this record to set all file modes correctly in the local checkout.

First, make sure all files and templates have the desired mode. Then, run makeimg -M to create the file .makeimg.modes. Make sure to add that file to version control. Repeat this process for new files. After a fresh checkout of a repository, run makeimg -m to apply the modes from .makeimg.modes to the files on-disk.

OPTIONS

-f, --files DIR

Path to files to add to the image (default: ./files)

-p, --patches DIR

Path to patches to apply to the image (default: ./patches)

-t, --templates DIR

Path to templates to render into the image (default: ./templates)

-m, --apply-modes

Apply recorded modes to files and templates

-M, --record-modes

Record current modes of files and templates

-W, --warn-only

Do not fail on output to stderr during template rendering. Use at your own risk, see the section on template rendering above.

-h, --help

Output command line options.

SEE ALSO

IMGBUILD(5), pacstrap(8), apk(8)

AUTHORS

This project is is maintained by Conrad Hoffmann <ch@bitfehler.net>. The source code can be found at https://git.sr.ht/~bitfehler/makeimg. Bugs or patches can be submitted by email to ~bitfehler/public-inbox@lists.sr.ht.