BDEBSTRAP(1)

🌸 BDEBSTRAP(1) β€” bdebstrap’s Manual 🌸

okay bestie, sit down, hydrate, because this is the manual page for bdebstrap and she is long. Pull up a chair. 🫢


πŸ’– NAME πŸ’–

bdebstrap β€” a YAML config based multi-mirror Debian chroot creation tool. yes she makes chroots. yes she does it from YAML. no she is not sorry. πŸ’…


✨ SYNOPSIS ✨

bdebstrap [-h|--help] [-c|--config CONFIG] [-n|--name NAME] [-e|--env
ENV] [-s|--simulate|--dry-run] [-b|--output-base-dir OUTPUT_BASE_DIR]
[-o|--output OUTPUT] [-q|--quiet|--silent|-v|--verbose|--debug]
[-f|--force] [-t|--tmpdir TMPDIR] [--variant
{extract,custom,essential,apt,required,minbase,buildd,important,debootstrap,-,standard}]
[--mode {auto,sudo,root,unshare,fakeroot,fakechroot,chrootless}]
[--format {auto,directory,dir,tar,squashfs,sqfs,ext2,null}] [--aptopt
APTOPT] [--keyring KEYRING] [--dpkgopt DPKGOPT] [--hostname HOSTNAME]
[--install-recommends] [--packages|--include PACKAGES] [--components
COMPONENTS] [--architectures ARCHITECTURES] [--hook-dir DIRECTORY]
[--setup-hook COMMAND] [--extract-hook COMMAND] [--essential-hook
COMMAND] [--customize-hook COMMAND] [--cleanup-hook COMMAND] [--skip
STAGE] [--suite SUITE] [--target TARGET] [--mirrors MIRRORS] [SUITE
[TARGET [MIRROR...]]]

that's the whole vibe in one code block, periodt. πŸŽ€


πŸ¦‹ DESCRIPTION πŸ¦‹

so like, bdebstrap creates a Debian chroot of SUITE into TARGET from one or more MIRRORs, and then it drops some meta-data into the OUTPUT directory. and what's in there? two things, bestie:

  • a config.yaml containing the configuration for the build β€” super useful for rebuilds, so you can recreate the exact same thing later πŸ”
  • a manifest listing all installed packages and versions πŸ“‹

and here's a cute little detail: if TARGET is just a filename and does not include the path, then it gets placed in the OUTPUT directory as well. 🏠

bdebstrap extends mmdebstrap and makes it configurable via YAML configuration files, so you can do way more complex builds without losing your whole mind. 🧚

now, the config parameters β€” you can pass them to bdebstrap as command line arguments, or you can put them in one or more configuration YAML files. either way works. πŸ’–

when you have multiple YAML files, their content gets merged by:

  • appending lists βž•
  • recursively merging maps πŸ—ΊοΈ

and any arguments you specify on the command line take precedence over values provided in the YAML configuration file. command line wins, always. main character energy. πŸ‘‘

the final merged parameters get stored in the output directory as config.yaml. so everything you built is documented, and future-you can thank past-you. 🫢


πŸŽ€ OPTIONS πŸŽ€

  • -h, --help β€” shows a help message and dips. bye! πŸ‘‹
  • -c CONFIG, --config CONFIG β€” Configuration YAML file. the expected structure of this file is described down in YAML CONFIGURATION below. this parameter can be specified multiple times, and the content of the YAML files gets merged by appending lists and recursively merging maps. stack 'em up. πŸ“š
  • -n NAME, --name NAME β€” the name of the generated golden image. ✨ if no output directory is specified, the golden image gets placed in OUTPUT_BASE_DIR/NAME. golden. iconic. no notes.
  • -e ENV, --env ENV β€” adds an additional environment variable. these environment variables get set when the hooks are called. πŸ”§
  • -s, --simulate, --dry-run β€” runs apt-get with --simulate. only the package cache gets initialized; no binary packages are downloaded or installed. use this to quickly check whether a package selection within a certain suite and variant can in principle be installed, as far as their dependencies go. πŸ•΅οΈ
    • if the output is a tarball, then no output is produced.
    • if the output is a directory, then the directory will be left populated with the skeleton files and directories necessary for apt to run in it.
  • -b OUTPUT_BASE_DIR, --output-base-dir OUTPUT_BASE_DIR β€” output base directory. by default it is the current directory. πŸ“
  • -o OUTPUT, --output OUTPUT β€” output directory (default: output-base-dir/name). πŸ“‚
  • -q, --quiet, --silent β€” do not write anything to standard error except errors. 🀫 if used together with --verbose or --debug, only the last option takes effect. last one wins, that's the rule.
  • -v, --verbose β€” writes informational messages (about configuration files, environment variables, mmdebstrap call, etc.) to standard error. instead of progress bars, mmdebstrap writes the dpkg and apt output directly to standard error. πŸ—£οΈ if used together with --quiet or --debug, only the last option takes effect.
  • --debug β€” in addition to the output produced by --verbose, writes detailed debugging information to standard error. errors of mmdebstrap will print a backtrace. πŸ› if used together with --quiet or --verbose, only the last option takes effect.
  • -f, --force β€” removes the existing output directory before creating a new one. πŸ’₯ out with the old.
  • -t TMPDIR, --tmpdir TMPDIR β€” temporary directory for building the image (default: /tmp). 🌑️
  • --variant {extract,custom,essential,apt,required,minbase,buildd,important,debootstrap,-,standard} β€” choose which package set to install. πŸ“¦
  • --mode {auto,sudo,root,unshare,fakeroot,fakechroot,chrootless} β€” choose how to perform the chroot operation and create a filesystem with ownership information different from the current user. πŸͺ„
  • --format {auto,directory,dir,tar,squashfs,sqfs,ext2,null} β€” choose the output format. 🎁
  • --aptopt APTOPT β€” pass arbitrary options or configuration files to apt. 🧠
  • --keyring KEYRING β€” change the default keyring to use by apt. πŸ”‘
  • --dpkgopt DPKGOPT β€” pass arbitrary options or configuration files to dpkg. 🧰
  • --hostname HOSTNAME β€” write the given HOSTNAME into /etc/hostname in the target chroot. 🏷️
  • --install-recommends β€” consider recommended packages as a dependency for installing. πŸ’• (she's needy but in a good way)
  • --packages PACKAGES, --include PACKAGES β€” a comma or whitespace separated list of packages which will be installed in addition to the packages installed by the specified variant. βž•πŸ“¦
  • --components COMPONENTS β€” a comma or whitespace separated list of components like main, contrib and non-free which will be used for all URI-only MIRROR arguments. 🧩
  • --architectures ARCHITECTURES β€” a comma or whitespace separated list of architectures. the first architecture is the native architecture inside the chroot. πŸ—οΈ
  • --hook-dir DIRECTORY β€” execute scripts in DIRECTORY with filenames starting with β€œsetup”, β€œextract”, β€œessential” or β€œcustomize”, at the respective stages during an mmdebstrap run. the files must be marked executable. their extension is ignored. subdirectories are not traversed. this option is a short-hand for specifying the remaining four hook options individually for each file in the directory. if there are more than one script for a stage, then they are added alphabetically. πŸ”€ this is useful when a user wants to run the same hooks frequently. this option can be specified multiple times. πŸͺ
  • --setup-hook COMMAND β€” execute arbitrary COMMAND right after initial setup (directory creation, configuration of apt and dpkg, ...) but before any packages are downloaded or installed. at that point, the chroot directory does not contain any executables and thus cannot be chroot-ed into. 🚧 this option can be specified multiple times.
  • --extract-hook COMMAND β€” execute arbitrary COMMAND after the Essential:yes packages have been installed but before installing them. 😭 yes bestie, that's literally what the manpage says, installed but before installing them β€” i'm just the messenger, iykyk. this option can be specified multiple times.
  • --essential-hook COMMAND β€” execute arbitrary COMMAND after the Essential:yes packages have been installed, but before installing the remaining packages. 🧱 this option can be specified multiple times.
  • --customize-hook COMMAND β€” execute arbitrary COMMAND after the chroot is set up and all packages got installed, but before final cleanup actions are carried out. 🎨 this option can be specified multiple times.
  • --cleanup-hook COMMAND β€” execute arbitrary COMMAND after all customize hooks have been executed. 🧹 this option can be specified multiple times.
  • --skip STAGE β€” a comma or whitespace separated list of actions and safety checks to skip. πŸ™ˆ this option can be specified multiple times.
  • --suite SUITE, SUITE β€” the suite may be a valid release code name (eg, sid, stretch, jessie) or a symbolic name (eg, unstable, testing, stable, oldstable). 🌈
  • --target TARGET, TARGET β€” the optional target argument can either be the path to a directory, the path to a tarball filename, the path to a squashfs image or -. 🎯
  • --mirrors MIRRORS, MIRRORS β€” comma separated list of mirrors. if no mirror option is provided, http://deb.debian.org/debian is used. πŸͺž default slay.

πŸ’– YAML CONFIGURATION πŸ’–

Okay bestie, this is where the YAML gets its whole personality. This section describes the expected data-structure hierarchy of the YAML configuration file(s) πŸ“„. The top-level structure is expected to be a mapping. The top-level mapping may contain following keys πŸ‘‡


env

Mapping of environment variable names to their values 🌱. Environment variables can be overridden by specifying them with --env using the same name. These environment variables are set before calling the hooks πŸͺ.

name

String. The name of the generated golden image πŸ‘‘. Can be overridden by --name.

mmdebstrap

Mapping. The values in here get passed straight to mmdebstrap(1) 🫢. Following keys might be specified:

aptopts

List of arbitrary options or configuration files (string) to apt πŸ“¦. Additional apt options can be specified with --aptopt.

architectures

List of architectures (string) πŸ—οΈ. The first architecture is the native architecture inside the chroot. Additional architectures can be specified with --architectures.

components

List of components (string) like main, contrib and non-free which will be used for all URI-only MIRROR arguments 🧩. Additional components can be specified with --components.

dpkgopts

List of arbitrary options or configuration files (string) to dpkg 🎁. Additional dpkg options can be specified with --dpkgopt.

format

Choose the output format πŸ“Ό. It needs to be one of auto, directory, dir, tar, squashfs, sqfs, ext2, null. See mmdebstrap(1) for details. Can be overridden by --format.

hostname

String. If specified, write the given hostname into /etc/hostname in the target chroot 🏷️. Heads up: this parameter does not exist in mmdebstrap and is implemented as a customize hook for mmdebstrap πŸͺ„. Can be overridden by --hostname.

install-recommends

Boolean. If set to True, the APT option Apt::Install-Recommends set to true is passed to mmdebstrap via --aptopt βœ…. Can be overridden by --install-recommends.

keyrings

List of default keyring to use by apt πŸ”‘. Additional keyring files can be specified with --keyring.

mirrors

List of mirrors (string) πŸͺž. Additional mirrors can be specified with --mirrors.

mode

Choose how to perform the chroot operation and create a filesystem with ownership information different from the current user 🧚. It needs to be one of auto, sudo, root, unshare, fakeroot, fakechroot, or chrootless. See mmdebstrap(1) for details. Can be overridden by --mode.

packages

List of packages (string) which will be installed in addition to the packages installed by the specified variant πŸ“. Additional packages can be specified with --packages or --include. This setting is passed to mmdebstrap using the --include parameter.

hook-dirs

List of hook directories (string) πŸ“‚. Execute scripts in the specified directories with filenames starting with setup, extract, essential or customize, at the respective stages during an mmdebstrap run. The files must be marked executable πŸ”“. Their extension is ignored. Subdirectories are not traversed. This option is a short-hand for specifying the remaining four hook options individually for each file in the directory. If there are more than one script for a stage, then they are added alphabetically πŸ”€. This is useful in cases where a user wants to run the same hooks frequently πŸ’…. Additional hook directories can be specified with --hook-dir.

setup-hooks

List of setup hooks (string) πŸ› οΈ. Execute arbitrary commands right after initial setup (directory creation, configuration of apt and dpkg, ...) but before any packages are downloaded or installed. At that point, the chroot directory does not contain any executables and thus cannot be chroot-ed into 😭. See HOOKS in mmdebstrap(1) for more information and examples. Additional setup hooks can be specified with --setup-hook.

extract-hooks

List of extract hooks (string) 🧲. Execute arbitrary commands after the Essential:yes packages have been installed but before installing them. See HOOKS in mmdebstrap(1) for more information and examples. Additional extract hooks can be specified with --extract-hook.

essential-hooks

List of essential hooks (string) ⭐. Execute arbitrary commands after the Essential:yes packages have been installed, but before installing the remaining packages. See HOOKS in mmdebstrap(1) for more information and examples. Additional essential hooks can be specified with --essential-hook.

customize-hooks

List of customize hooks (string) 🎨. Execute arbitrary commands after the chroot is set up and all packages got installed but before final cleanup actions are carried out 🧹. See HOOKS in mmdebstrap(1) for more information and examples. Additional customize hooks can be specified with --customize-hook.

cleanup-hooks

List of cleanup hooks (string) 🫧. Cleanup hooks are just hooks that are run directly after all other customize hooks. See customize-hooks above. Additional cleanup hooks can be specified with --cleanup-hook.

skip

List of stages to skip (string) ⏭️. mmdebstrap tries hard to implement sensible defaults and will try to stop you before shooting yourself in the foot πŸ¦ΆπŸ”«. This option is for when you are sure you know what you are doing and allows one to skip certain actions and safety checks. See section OPERATION in mmdebstrap(1) for a list of possible arguments and their context. Additional stages to skip can be specified with --skip.

suite

String. The suite may be a valid release code name (eg, sid, stretch, jessie) or a symbolic name (eg, unstable, testing, stable, oldstable) 🌈. Can be overridden by --suite.

target

String. The target argument can either be the path to a directory, the path to a tarball filename, the path to a squashfs image or - πŸ“. Can be overridden by --target.

variant

Choose which package set to install πŸŽ’. It needs to be one of extract, custom, essential, apt, required, minbase, buildd, important, debootstrap, -, standard. See mmdebstrap(1) for details. Can be overridden by --variant.


πŸͺ HOOKS πŸͺ

bdebstrap enhances the hooks provided by mmdebstrap 🫢. Hooks can use the environment variables specified via the env configuration option or the --env parameter. bdebstrap sets following environment variables by default to be consumed by the hooks:

BDEBSTRAP_HOOKS

Path to the hooks provided by bdebstrap πŸ“.

BDEBSTRAP_NAME

Name of the generated golden image which is set via the name configuration option or the --name parameter πŸ‘‘.

BDEBSTRAP_OUTPUT_DIR

Path of a temporary directory inside the chroot πŸ“€. Files and directories that are placed inside this directory will be copied out of the image into the output directory. This temporary directory will be removed in a final cleanup hook 🫧.


Following hook scripts are shipped with bdebstrap 🎁:

disable-units

Disable services / systemd units πŸš«βš™οΈ.

enable-units

Enable services / systemd units βœ…βš™οΈ.


Example usage for the hook scripts, bestie, look at this πŸ₯Ή:

---
mmdebstrap:
  customize-hooks:
    - $BDEBSTRAP_HOOKS/disable-units "$1" apt-daily.timer cron
    - $BDEBSTRAP_HOOKS/enable-units "$1" systemd-timesyncd
  suite: bullseye
  target: root.tar
  variant: important

🌈 EXAMPLES 🌈

okay bestie this is the part where it all comes together, the demo, the main character moment, the slay ✨ three whole scenarios, all of them real, all of them copy-pasteable.


πŸ’– Minimal Debian unstable tarball πŸ’–

this one's the starter pack, the lil baby example. super small YAML config, and boom, you have a minimal Debian unstable tarball. imagine the config below is living its best life in unstable.yaml:

---
mmdebstrap:
  keyrings:
    - /usr/share/keyrings/debian-archive-keyring.gpg
  mode: unshare
  suite: unstable
  target: root.tar.xz
  variant: minbase

then you just... run it?? and the tarball appears like magic, no cap:

$ bdebstrap -c unstable.yaml --name example1
$ ls example1/
config.yaml  manifest  root.tar.xz

literally three files. it's giving efficiency. πŸ’…


πŸ¦‹ Debian live system πŸ¦‹

okay THIS one, this is the glow-up. we're building a full Debian 11 (bullseye) live system, and it's honestly iconic. say the config below is chillin' in live.yaml:

---
mmdebstrap:
  architectures:
    - amd64
  cleanup-hooks:
    - cp /dev/null "$1/etc/hostname"
    - if test -f "$1/etc/resolv.conf"; then cp /dev/null "$1/etc/resolv.conf"; fi
  customize-hooks:
    - cp --preserve=timestamps -v "$1"/boot/vmlinu* "$1${BDEBSTRAP_OUTPUT_DIR?}/vmlinuz"
    - cp --preserve=timestamps -v "$1"/boot/initrd.img* "$1${BDEBSTRAP_OUTPUT_DIR?}/initrd.img"
    - mkdir -p "$1/root/.ssh"
    - upload ~/.ssh/id_rsa.pub /root/.ssh/authorized_keys
  keyrings:
    - /usr/share/keyrings/debian-archive-keyring.gpg
  mode: unshare
  packages:
    - init
    - iproute2
    - less
    - libpam-systemd
    - linux-image-cloud-amd64
    - live-boot
    - locales
    - openssh-server
  suite: bullseye
  target: root.squashfs
  variant: minbase
heads up bestie: this whole example is assuming ~/.ssh/id_rsa.pub actually exists on your machine, because it's getting copied into the image at /root/.ssh/authorized_keys so you can SSH in with your own SSH key. no key, no entry, and we'd be sad 😭

and the squashfs image gets generated like this:

$ bdebstrap -c live.yaml --name example2
$ ls example2/
config.yaml  initrd.img  manifest  root.squashfs  vmlinuz

see how the kernel and initrd got yanked out of the squashfs image? that's the customize hooks doing their little dance ✨ β€” it's so QEMU can use them directly. and to launch this image locally with QEMU, the root.squashfs image needs to be served up by an HTTP server:

$ python3 -m http.server -b localhost --directory example2 8080

that command exposes the generated image over HTTP on localhost, port 8080. then QEMU can be started, passing the TCP traffic on port 8080 through to the webserver:

$ cd example2
$ qemu-system-x86_64 -machine accel=kvm -m 1G -device virtio-net-pci,netdev=net0 -monitor vc \
    -netdev user,id=net0,hostfwd=tcp::2222-:22,guestfwd=tcp:10.0.2.252:8080-tcp:localhost:8080,hostname=debian-live \
    -kernel ./vmlinuz -initrd ./initrd.img -append "boot=live fetch=http://10.0.2.252:8080/root.squashfs quiet"

and if you want the output to actually print on the terminal you launched it from? add -nographic -serial stdio to the QEMU command line, and toss console=ttyS0 into the -append parameter. πŸŽ€

once the virtual machine is up and running, you can get in over SSH:

$ ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -p 2222 root@localhost

πŸ‘‘ SEE ALSO πŸ‘‘

mmdebstrap(1), debootstrap(8)


🌸 AUTHOR 🌸

Benjamin Drung bdrung@posteo.de


and that's the whole page bestie, you made it to the end, we're so proud of you 🫢 this was bdebstrap, source/version bdebstrap dated 2023-12-02, from the BDEBSTRAP(1) manual. go build something cute. periodt. πŸ’–βœ¨

πŸ“¦ where this page comes from