cmkinitramfs

Github repository PyPI package Quality assurance Documentation status Python version Python implementation

Tools to generate an initramfs from a configuration file.

Documentation is available at https://cmkinitramfs.readthedocs.io/.

About

This project provides three main executables: cmkinit, cmkcpiodir and cmkcpiolist.

cmkinit builds an init script from a configuration file.

cmkcpiodir and cmkcpiolist build an initramfs, including the init script, from the same configuration file. cmkcpiodir builds the initramfs into a directory on a filesystem, and generates the CPIO archive from it. cmkcpiolist builds a CPIO list, using the same format as Linux kernel’s gen_init_cpio utility, and generates the CPIO archive using gen_init_cpio. See the corresponding Linux kernel documentation for more information.

Installation

Compatibility

Python version: this library is compatible with Python ≥ 3.7.

Python implementation: this library is compatible with CPython and PyPy.

Dependencies

Python dependencies:

  • bin (mkcpiodir and mkcpiolist) dependencies:

    • pyelftools

  • Documentation:

    • sphinx

    • sphinx_rtd_theme

  • Tests:

    • QA:

      • flake8

      • mypy

      • tox

Other dependencies:

  • initramfs (mkcpiodir and mkcpiolist) dependencies:

    • loadkeys (kbd)

    • busybox

    • modinfo (kmod, busybox)

  • mkcpiodir dependencies:

    • find (findutils, busybox)

    • cpio (cpio, busybox)

  • mkcpiolist dependencies:

    • gen_init_cpio (linux kernel, linux-misc-apps)

Install

Install from pypi:

$ pip install cmkinitramfs

Install from source with setup.py:

$ git clone https://github.com/teapot9/cmkinitramfs.git
$ cd cmkinitramfs
$ python3 setup.py install

Install from source with pip:

$ git clone https://github.com/teapot9/cmkinitramfs.git
$ cd cmkinitramfs
$ pip3 install .

Configuration

The configuration file is in an ini format.

Each section defines a data source, the section name is the data identifier.

Some options expects a data source as input, there are several data identifier formats:

  • DATA=data-name: data defined in the section with the same name.

  • data-name: same as DATA=data-name.

  • PATH=/path/foo/bar: data at the path /path/foo/bar, this can be a directory, a file, or a block device.

  • /absolute/path: same as PATH=/absolute/path.

  • UUID=1234-5678: filesystem with UUID 1234-5678.

  • LABEL=foo: filesystem with label foo.

  • PARTUUID=1234-5678: partition with UUID 1234-5678.

  • PARTLABEL=foo: partition with label foo.

DEFAULT section

This section has default values for other sections, as well as global configuration.

  • root (mandatory): Data identifier for the data to use as new root.

  • mountpoints (optional): Comma separated list of data identifier to load in addition of rootfs.

  • keymap (optional): Boolean value defining if a keymap should be loaded. If set to no, all keymap-* configurations will be ignored. Defaults to no.

  • keymap-src (optional): Path of the keymap file to use. If not specified but keymap is yes, the converted keymap should already exists at keymap-path.

  • keymap-path (optional): Path where the binary keymap will be generated (generated from keymap-src). Defaults to /tmp/keymap.bmap.

  • keymap-dest (optional): Path of the keymap file within the initramfs. Defaults to /root/keymap.bmap.

  • init-path (optional): Path where the init script will be generated (generated from cmkinitramfs.init.mkinit()). Defaults to /tmp/init.sh.

  • files (optional): Additional files to include in the initramfs. Each item is separated by a newline. Format: source:destination (e.g. files = /root/foo:/root/bar copy the file foo in the initramfs renaming it bar). If no destination is given, the file will be copied to the same path as source in the initramfs. source can be an absolute or relative path, destination must be an absolute path within the initramfs.

  • execs (optional): Additional executables to include in the initramfs. Same format as files, except that source will also be searched in directories from the PATH environment variable.

  • libs (optional): Additional libraries to include in the initramfs. Same format as files, except that source will also be searched in directories from /etc/ld.so.conf and the LD_LIBRARY_PATH environment variable.

  • busybox (optional): Additional executables to include in the initramfs. Each item is separated by a newline. Format: exec: name of the command (basename). If busybox provides the command, they will not be added. Otherwise, the executable is searched in PATH.

  • cmkcpiodir-default-opts (optional): Options to append to the cmkcpiodir command line.

  • cmkcpiolist-default-opts (optional): Options to append to the cmkcpiolist command line.

  • modules (optional): Kernel modules to load in the initramfs. One module per line, each line with the module name followed by the module parameters (e.g. mymodule foo=bar).

  • scripts (optional): User scripts to run at a given breakpoint. One user script per line with the format breakpoint:script. The script script will be run at the breakpoint breakpoint. A list of available breakpoints is available in cmkinitramfs.init.Breakpoint. These scripts will be run wether the breakpoint is enabled or not. Example: init: ls /dev: run ls /dev after initialization.

LUKS data sections

LUKS device to open.

  • type = luks (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • source (mandatory): Data identifier of the data to unlock.

  • name (mandatory): Name to use for the luks device, this will be used by cryptsetup.

  • key (optional): Data identifier for the LUKS key.

  • header (optional): Data identifier for the LUKS header.

  • discard (optional): Enable discards. Boolean value (yes/no).

LVM data sections

LVM logical volume to load.

  • type = lvm (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • vg-name (mandatory): Volume group name.

  • lv-name (mandatory): Logical volume name.

Mount data sections

Filesystem to mount.

  • type = mount (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • source (optional): Data identifier for the filesystem to mount. If not set, it will set the source to “none” (e.g. for TMPFS).

  • mountpoint (mandatory): Path where the filesystem will be mounted.

  • filesystem (mandatory): Which filesystem to use, option passed to mount -t filesystem.

  • options (optional): Mount options, defaults to ro. Note for ZFS: if the mountpoint property is not set to legacy, the zfsutil option is required.

MD data sections

MD RAID data to load.

  • type = md (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • name (mandatory): Name of the MD RAID, this will be used by mdadm.

  • source (mandatory): New line separated data identifiers of the sources to use. Multiple block devices can be specified, or the UUID of the MD RAID.

Clone data sections

Clone a source to a destination.

  • type = clone (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • source (mandatory): Data identifier for the source of the clone.

  • destination (mandatory): Data identifier of the destination of the clone.

ZFS pool sections

Import a ZFS pool.

  • type = zfspool (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • pool (mandatory): Pool name.

  • cache (optional): Data identifier of the ZFS cache file (must be present in the initramfs).

ZFS crypt sections

Unlock an encrypted ZFS dataset.

  • type = zfscrypt (mandatory).

  • need (optional): Hard dependencies: comma separated list of data identifiers. Those dependencies are required to load and use the data.

  • load-need (optional): Load dependencies: comma separated list of data identifiers. Those dependencies are only required to load the data, they can be unloaded when the data has been successfully loaded. (e.g. A LUKS key, an archive to decompress.)

  • pool (optional): Data identifier of the parent pool (defaults to same as pool name).

  • dataset (mandatory): Name of the dataset to unlock.

  • key (optional): Data identifier of a keyfile to use.

Usage

Kernel command-line parameters

The init script will check the kernel cmdline for known parameters.

  • debug: Same as rd.debug.

  • init=<path to init>: Set the init process to run after the initramfs.

  • quiet: Same as rd.quiet.

  • rd.break=<breakpoint>: Drop into a shell at a given point. See cmkinitramfs.init.Breakpoint.

  • rd.debug: Show debugging informations.

  • rd.panic: On fatal error: cause a kernel panic rather than droping into a shell.

  • rd.quiet: Reduce log shown on console.

For more details, see cmkinitramfs.init.do_cmdline.

cmkinit

$ cmkinit --help
usage: cmkinit [-h] [--version]

Build an init script

optional arguments:
  -h, --help  show this help message and exit
  --version   show program's version number and exit

Running cmkinit will generate an init script and output it to stdout. No options are available, everything is defined in the configuration file. The CMKINITCFG environment variable may be defined to use a custom configuration file.

cmkcpiodir

$ cmkcpiodir --help
usage: cmkcpiodir [-h] [--version] [--debug] [--verbose] [--quiet]
                  [--output OUTPUT] [--binroot BINROOT] [--kernel KERNEL]
                  [--only-build-archive | --only-build-directory] [--keep]
                  [--clean] [--build-dir BUILD_DIR]

Build an initramfs using a directory.

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --debug, -d           debugging mode: non-root, implies -k
  --verbose, -v         be verbose
  --quiet, -q           be quiet (can be repeated)
  --output OUTPUT, -o OUTPUT
                        set the output of the CPIO archive
  --binroot BINROOT, -r BINROOT
                        set the root directory for binaries (executables and
                        libraries)
  --kernel KERNEL, -K KERNEL
                        set the target kernel version of the initramfs,
                        defaults to the running kernel
  --only-build-archive, -c
                        only build the CPIO archive from an existing initramfs
                        directory
  --only-build-directory, -D
                        only build the initramfs directory, implies -k
  --keep, -k            keep the created initramfs directory
  --clean, -C           overwrite temporary directory if it exists, use
                        carefully
  --build-dir BUILD_DIR, -b BUILD_DIR
                        set the location of the initramfs directory

Running cmkcpiodir will generate the initramfs in a directory, then it will create the CPIO archive from this directory. cmkcpiodir requires root privileges when run in non-debug mode, see the do_nodes options of cmkinitramfs.initramfs.Initramfs.build_to_directory().

cmkcpiolist

$ cmkcpiolist --help
usage: cmkcpiolist [-h] [--version] [--debug] [--verbose] [--quiet]
                   [--output OUTPUT] [--binroot BINROOT] [--kernel KERNEL]
                   [--only-build-archive | --only-build-list] [--keep]
                   [--cpio-list CPIO_LIST]

Build an initramfs using a CPIO list

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --debug, -d           debugging mode: non-root, implies -k
  --verbose, -v         be verbose
  --quiet, -q           be quiet (can be repeated)
  --output OUTPUT, -o OUTPUT
                        set the output of the CPIO archive
  --binroot BINROOT, -r BINROOT
                        set the root directory for binaries (executables and
                        libraries)
  --kernel KERNEL, -K KERNEL
                        set the target kernel version of the initramfs,
                        defaults to the running kernel
  --only-build-archive, -c
                        only build the CPIO archive from an existing CPIO list
  --only-build-list, -L
                        only build the CPIO list, implies -k
  --keep, -k            keep the created CPIO list
  --cpio-list CPIO_LIST, -l CPIO_LIST
                        set the location of the CPIO list

Running cmkcpiolist will generate an initramfs CPIO list in a file, then it will create the CPIO archive from this list with gen_init_cpio. cmkcpiolist does not require root privileges.

findlib

$ findlib --help
usage: findlib [-h] [--verbose] [--quiet] [--version]
               [--compatible COMPATIBLE] [--root ROOT] [--null] [--glob]
               LIB [LIB ...]

Find a library on the system

positional arguments:
  LIB                   library to search

optional arguments:
  -h, --help            show this help message and exit
  --verbose, -v         be verbose
  --quiet, -q           be quiet (can be repeated)
  --version             show program's version number and exit
  --compatible COMPATIBLE, -c COMPATIBLE
                        set a binary the library must be compatible with
  --root ROOT, -r ROOT  set the root directory to search for the library
  --null, -0            paths will be delemited by null characters instead of
                        newlines
  --glob, -g            library names are glob patterns

findlib will search the absolute path of a library on the system. It will search in directories from /etc/ld.so.conf, LD_LIBRARY_PATH, and default library paths (see cmkinitramfs.bin.find_lib() and cmkinitramfs.bin.find_lib_iter()).

Examples

Command-line interface

$ cmkcpiodir
  • Creates init script in /tmp/init.sh.

  • If enabled, builds binary keymap in /tmp/keymap.bmap.

  • Builds initramfs in /tmp/initramfs (disable this step with --only-build-archive).

  • Builds CPIO archive from /tmp/initramfs to /usr/src/initramfs.cpio (disable this step with --only-build-directory).

  • Cleanup /tmp/initramfs directory (disable with --keep).

$ cmkcpiolist
  • Creates init script in /tmp/init.sh.

  • If enabled, builds binary keymap in /tmp/keymap.bmap.

  • Builds CPIO list in /tmp/initramfs.list (disable this step with --only-build-archive).

  • Builds CPIO archive from /tmp/initramfs.list to /usr/src/initramfs.cpio (disable this step with --only-build-list).

$ findlib 'libgcc_s.so.1'
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libgcc_s.so.1
  • Searches the libgcc_s.so.1 library on the system and prints it to stdout.

$ findlib -g 'libgcc_s.*'
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libgcc_s.so.1
/lib64/libgcc_s.so.1
/lib64/libgcc_s.so.1
  • Search any library matching libgcc_s.* on the system and prints them to stdout.

Configuration

 1# cmkinitramfs.ini
 2#
 3# Example configuration file for cmkinitramfs and cmkinit
 4#
 5# This configuration uses a separate / and /usr partitions, respectively on
 6# system/root and system/usr LVM logical volumes. The LVM is on a LUKS
 7# encrypted partition. The key to unlock the LUKS partition is encrypted
 8# in the /root/key file, the header for the key file is /root/key.luks.
 9# The luks encrypted partition is on a MD RAID.
10# 
11# The resulting /init script will:
12#   - Assemble the RAID
13#   - Unlock the key /root/key with the header /root/key.luks
14#   - Unlock the main luks partition with the unlocked key
15#   - Lock the key since we don't need it anymore
16#   - Enable the system/root LV
17#   - Mount /
18#   - User script: print the content of /dev
19#   - Enable the system/usr LV
20#   - Mount /usr
21#
22
23[DEFAULT]
24root = mnt-root
25mountpoints = mnt-usr
26keymap = yes
27keymap-src = fr
28#keymap-dest = /root/keymap.bmap
29init = /sbin/openrc-init
30files = /root/key:/root/key.luks
31scripts =
32	rootfs: echo 'Content of /dev:'
33	rootfs: ls /dev
34
35[md-main]
36type = md
37need =
38load-need =
39name = mdraid
40source = UUID=xxxxxxxx-yyyy-yyyy-yyyy-zzzzzzzzzzzz
41
42[luks-key]
43type = luks
44need =
45load-need =
46source = PATH=/root/key
47name = key
48header = PATH=/root/key.luks
49
50[luks-main]
51type = luks
52need = md-main
53load-need = luks-key
54source = UUID=xxxxxxxx-yyyy-yyyy-yyyy-zzzzzzzzzzzz
55name = luks
56key = luks-key
57discard = yes
58
59[lvm-root]
60type = lvm
61need = luks-main
62load-need =
63vg-name = system
64lv-name = root
65
66[mnt-root]
67type = mount
68need = lvm-root
69load-need =
70source = UUID=xxxxxxxx-yyyy-yyyy-yyyy-zzzzzzzzzzzz
71mountpoint = /mnt/root
72filesystem = ext4
73options = ro
74
75[lvm-usr]
76type = lvm
77need = luks-main
78load-need =
79vg-name = system
80lv-name = usr
81
82[mnt-usr]
83type = mount
84need = lvm-usr
85load-need =
86source = lvm-usr
87mountpoint = /mnt/root/usr
88filesystem = ext4
89options = ro

Table of contents

Indices and tables