Provided by: mmdebstrap_1.5.4-2_all bug

NAME

       mmdebstrap - multi-mirror Debian chroot creation

SYNOPSIS

       mmdebstrap [OPTION...] [SUITE [TARGET [MIRROR...]]]

DESCRIPTION

       mmdebstrap creates a Debian chroot of SUITE into TARGET from one or more MIRRORs. It is
       meant as an alternative to the debootstrap tool (see section DEBOOTSTRAP). In contrast to
       debootstrap it uses apt to resolve dependencies and is thus able to use more than one
       mirror and resolve more complex dependency relationships. See section OPERATION for an
       overview of how mmdebstrap works internally.

       The SUITE option may either be a valid release code name (eg, sid, bookworm, trixie) or a
       symbolic name (eg, unstable, testing, stable, oldstable). Any suite name that works with
       apt on the given mirror will work. The SUITE option is optional if no TARGET and no MIRROR
       option is provided.  If SUITE is missing, then the information of the desired suite has to
       come from standard input as part of a valid apt sources.list file or be set up via hooks.
       The value of the SUITE argument will be used to determine which apt index to use for
       finding out the set of "Essential:yes" packages and/or the set of packages with the right
       priority for the selected variant. This functionality can be disabled by choosing the
       empty string for SUITE. See the section VARIANTS for more information.

       The TARGET option may either be the path to a directory, the path to a tarball filename,
       the path to a squashfs image, the path to an ext2 or ext4 image, a FIFO, a character
       special device, or "-".  The TARGET option is optional if no MIRROR option is provided. If
       TARGET is missing or if TARGET is "-", an uncompressed tarball will be sent to standard
       output.  Without the --format option, TARGET will be used to choose the format.  See the
       section FORMATS for more information.

       The MIRROR option may either be provided as a URI, in apt one-line format, as a path to a
       file in apt's one-line or deb822-format, or "-".  If no MIRROR option is provided, then
       <http://deb.debian.org/debian> is used as the default. If SUITE does not refer to
       "unstable" or "testing", then SUITE-updates and SUITE-security mirrors are automatically
       added. If a MIRROR option starts with "deb " or "deb-src " then it is used as a one-line
       format entry for apt's sources.list inside the chroot. If a MIRROR option contains a "://"
       then it is interpreted as a mirror URI and the apt line inside the chroot is assembled as
       "deb [arch=A] B C D" where A is the host's native architecture, B is the MIRROR, C is the
       given SUITE and D is the components given via --components (defaults to "main"). If a
       MIRROR option happens to be an existing file, then its contents are written into the
       chroot's sources.list (if the first MIRROR is a file in one-line format) or into the
       chroot's sources.list.d directory, named with the extension .list or .sources, depending
       on whether the file is in one-line or deb822 format, respectively.  If MIRROR is "-" then
       standard input is pasted into the chroot's sources.list.  More than one mirror can be
       specified and are appended to the chroot's sources.list in the given order. If you specify
       a https or tor MIRROR and you want the chroot to be able to update itself, don't forget to
       also install the ca-certificates package, the apt-transport-https package for apt versions
       less than 1.5 and/or the apt-transport-tor package using the --include option, as
       necessary.

       All status output is printed to standard error unless --logfile is used to redirect it to
       a file or --quiet or --silent is used to suppress any output on standard error. Help and
       version information will be printed to standard error with the --help and --version
       options, respectively.  Otherwise, an uncompressed tarball might be sent to standard
       output if TARGET is "-" or if no TARGET was specified.

OPTIONS

       Options are case insensitive. Short options may be bundled. Long options require a double
       dash and may be abbreviated to uniqueness. Options can be placed anywhere on the command
       line, even before or mixed with the SUITE, TARGET, and MIRROR arguments. A double dash
       "--" can be used to stop interpreting command line arguments as options to allow SUITE,
       TARGET and MIRROR arguments that start with a single or double dash. Option order only
       matters for options that can be passed multiple times as documented below.

       -h,--help
               Print synopsis and options of this man page and exit.

       --man   Show the full man page as generated from Perl POD in a pager. This requires the
               perldoc program from the perl-doc package. This is the same as running:

                   pod2man /usr/bin/mmdebstrap | man -l -

       --version
               Print the mmdebstrap version and exit.

       --variant=name
               Choose which package set to install. Valid variant names are extract, custom,
               essential, apt, required, minbase, buildd, important, debootstrap, -, and
               standard. The default variant is debootstrap. See the section VARIANTS for more
               information.

       --mode=name
               Choose how to perform the chroot operation and create a filesystem with ownership
               information different from the current user. Valid mode names are auto, sudo,
               root, unshare, fakeroot, fakechroot and chrootless.  The default mode is auto. See
               the section MODES for more information.

       --format=name
               Choose the output format. Valid format names are auto, directory, tar, squashfs,
               ext2, ext4 and null. The default format is auto. See the section FORMATS for more
               information.

       --aptopt=option|file
               Pass arbitrary options to apt. Will be permamently added to
               /etc/apt/apt.conf.d/99mmdebstrap inside the chroot. Use hooks for temporary
               configuration options. Can be specified multiple times. Each option will be
               appended to 99mmdebstrap. A semicolon will be added at the end of the option if
               necessary. If the command line argument is an existing file, the content of the
               file will be appended to 99mmdebstrap verbatim.

               Example: This is necessary for allowing old timestamps from snapshot.debian.org

                   --aptopt='Acquire::Check-Valid-Until "false"'
                   --aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"'

               Example: Settings controlling download of package description translations

                   --aptopt='Acquire::Languages { "environment"; "en"; }'
                   --aptopt='Acquire::Languages "none"'

               Example: Enable installing Recommends (by default mmdebstrap doesn't)

                   --aptopt='Apt::Install-Recommends "true"'

               Example: Configure apt-cacher or apt-cacher-ng as an apt proxy

                   --aptopt='Acquire::http { Proxy "http://127.0.0.1:3142"; }'

               Example: For situations in which the apt sandbox user cannot access the chroot

                   --aptopt='APT::Sandbox::User "root"'

               Example: Minimizing the number of packages installed from experimental

                   --aptopt='APT::Solver "aspcud"'
                   --aptopt='APT::Solver::aspcud::Preferences
                      "-count(solution,APT-Release:=/a=experimental/),-removed,-changed,-new"'

       --keyring=file|directory
               Change the default keyring to use by apt during the initial setup. This is similar
               to setting Dir::Etc::Trusted and Dir::Etc::TrustedParts using --aptopt except that
               the latter setting will be permanently stored in the chroot while the keyrings
               passed via --keyring will only be visible to apt as run by mmdebstrap. Do not use
               --keyring if apt inside the chroot needs to know about your keys after the initial
               chroot creation by mmdebstrap.  This option is mainly intended for users who use
               mmdebstrap as a deboostrap drop-in replacement. As such, it is probably not what
               you want to use if you use mmdebstrap with more than a single mirror unless you
               pass it a directory containing all the keyrings you need.

               By default, the local setting of Dir::Etc::Trusted and Dir::Etc::TrustedParts are
               used to choose the keyring used by apt as run by mmdebstrap. These two locations
               are set to /etc/apt/trusted.gpg and /etc/apt/trusted.gpg.d by default. Depending
               on whether a file or directory is passed to this option, the former and latter
               default can be changed, respectively.  Since apt only supports a single keyring
               file and directory, respectively, you can not use this option to pass multiple
               files and/or directories. Using the "--keyring" argument in the following way is
               equal to keeping the default:

                   --keyring=/etc/apt/trusted.gpg --keyring=/etc/apt/trusted.gpg.d

               If you need to pass multiple keyrings, use the "signed-by" option when specifying
               the mirror like this:

                   mmdebstrap mysuite out.tar "deb [signed-by=/path/to/key.gpg] http://..."

               Another reason to use "signed-by" instead of --keyring is if apt inside the chroot
               needs to know by what key the repository is signed even after the initial chroot
               creation.

               The "signed-by" option will automatically be added to the final "sources.list" if
               the keyring required for the selected SUITE is not yet trusted by apt.
               Automatically adding the "signed-by" option in these cases requires "gpg" to be
               installed. If "gpg" and "ubuntu-archive-keyring" are installed, then you can
               create a Ubuntu Bionic chroot on Debian like this:

                   mmdebstrap bionic ubuntu-bionic.tar

               The resulting chroot will have a "source.list" with a "signed-by" option pointing
               to /usr/share/keyrings/ubuntu-archive-keyring.gpg.

               You do not need to use --keyring or "signed-by" if you placed the keys that apt
               needs to know about into /etc/apt/trusted.gpg.d in the --setup-hook (which is
               before "apt update" runs), for example by using the copy-in special hook. You also
               need to copy your keys into the chroot explicitly if the key you passed via
               "signed-by" points to a location that is not otherwise populated during chroot
               creation (for example by installing a keyring package).

       --dpkgopt=option|file
               Pass arbitrary options to dpkg. Will be permanently added to
               /etc/dpkg/dpkg.cfg.d/99mmdebstrap inside the chroot. Use hooks for temporary
               configuration options. Can be specified multiple times. Each option will be
               appended to 99mmdebstrap. If the command line argument is an existing file, the
               content of the file will be appended to 99mmdebstrap verbatim.

               Example: Exclude paths to reduce chroot size

                   --dpkgopt='path-exclude=/usr/share/man/*'
                   --dpkgopt='path-include=/usr/share/man/man[1-9]/*'
                   --dpkgopt='path-exclude=/usr/share/locale/*'
                   --dpkgopt='path-include=/usr/share/locale/locale.alias'
                   --dpkgopt='path-exclude=/usr/share/doc/*'
                   --dpkgopt='path-include=/usr/share/doc/*/copyright'
                   --dpkgopt='path-include=/usr/share/doc/*/changelog.Debian.*'

       --include=pkg1[,pkg2,...]
               Comma or whitespace separated list of packages which will be installed in addition
               to the packages installed by the specified variant. The direct and indirect hard
               dependencies will also be installed. The behaviour of this option depends on the
               selected variant. The extract and custom variants install no packages by default,
               so for these variants, the packages specified by this option will be the only ones
               that get either extracted or installed by dpkg, respectively.  For all other
               variants, apt is used to install the additional packages. Package names are
               directly passed to apt and thus, you can use apt features like "pkg/suite",
               "pkg=version", "pkg-", use a glob or regex for "pkg", use apt patterns or pass a
               path to a .deb package file (see below for notes concerning passing the path to a
               .deb package file in unshare mode). See apt(8) for the supported syntax.

               The option can be specified multiple times and the packages are concatenated in
               the order in which they are given on the command line. If later list items are
               repeated, then they get dropped so that the resulting package list is free of
               duplicates. So the following are equivalent:

                   --include="pkg1/stable pkg2=1.0 pkg3-"
                   --include=pkg1/stable,pkg2=1.0,pkg3-,,,

                   --incl=pkg1/stable --incl="pkg2=1.0 pkg3-" --incl=pkg2=1.0,pkg3-
               Since the list of packages is separated by comma or whitespace, it is not possible
               to mix apt patterns or .deb package file paths containing either commas or
               whitespace with normal package names. If you do, your patterns and paths will be
               split by comma and whitespace as well and become useless. To pass such a pattern
               or package file path, put them into their own --include option. If the argument to
               --include starts with an apt pattern or with a file path, then it will not be
               split:

                   --include="?or(?priority(required), ?priority(important))"
                   --include="./path/to/deb with spaces/and,commas/foo.deb"

               Specifically, all arguments to --include that start with a "?", "!", "~", "(",
               "/", "./" or "../" are not split and treated as single arguments to apt. To add
               more packages, use multiple --include options. To disable this detection of
               patterns and paths, start the argument to --include with a comma or whitespace.

               If you pass the path to a .deb package file using --include, mmdebstrap will
               ensure that the path exists. If the path is a relative path, it will internally by
               converted to an absolute path. Since apt (outside the chroot) passes paths to dpkg
               (on the inside) verbatim, you have to make the .deb package available under the
               same path inside the chroot as well or otherwise dpkg inside the chroot will be
               unable to access it. This can be achieved using a setup-hook. A hook that
               automatically makes the contents of "file://" mirrors as well as .deb packages
               given with --include available inside the chroot is provided by mmdebstrap as
               --hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount. This hook takes care
               of copying all relevant file to their correct locations and cleans up those files
               at the end. In unshare mode, the .deb package paths have to be accessible by the
               unshared user as well. This means that the package itself likely must be made
               world-readable and all directory components on the path to it world-executable.

       --components=comp1[,comp2,...]
               Comma or whitespace separated list of components like main, contrib, non-free and
               non-free-firmware which will be used for all URI-only MIRROR arguments.  The
               option can be specified multiple times and the components are concatenated in the
               order in which they are given on the command line. If later list items are
               repeated, then they get dropped so that the resulting component list is free of
               duplicates. So the following are equivalent:

                   --components="main contrib non-free non-free-firmware"
                   --components=main,contrib,non-free,non-free-firmware
                   --comp=main --comp="contrib non-free" --comp="main,non-free-firmware"

       --architectures=native[,foreign1,...]
               Comma or whitespace separated list of architectures. The first architecture is the
               native architecture inside the chroot. The remaining architectures will be added
               to the foreign dpkg architectures. Without this option, the native architecture of
               the chroot defaults to the native architecture of the system running mmdebstrap.
               The option can be specified multiple times and values are concatenated. If later
               list items are repeated, then they get dropped so that the resulting list is free
               of duplicates. So the following are equivalent:

                   --architectures="amd64 armhf mipsel"
                   --architectures=amd64,armhf,mipsel
                   --arch=amd64 --arch="armhf mipsel" --arch=armhf,mipsel

       --simulate, --dry-run
               Run apt-get with --simulate. Only the package cache is initialized but no binary
               packages are downloaded or installed. Use this option 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. No hooks
               are executed in with --simulate or --dry-run.

       --setup-hook=command
               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 section HOOKS for more information.

               Example: add additional apt sources entries on top of the default ones:

                   --setup-hook='echo "deb http..." > "$1"/etc/apt/sources.list.d/custom.list'

               Example: Setup chroot for installing a sub-essential busybox-based chroot with
               --variant=custom
               --include=dpkg,busybox,libc-bin,base-files,base-passwd,debianutils

                   --setup-hook='mkdir -p "$1/bin"'
                   --setup-hook='for p in awk cat chmod chown cp diff echo env grep less ln
                       mkdir mount rm rmdir sed sh sleep sort touch uname mktemp; do
                       ln -s busybox "$1/bin/$p"; done'
                   --setup-hook='echo root:x:0:0:root:/root:/bin/sh > "$1/etc/passwd"'
                   --setup-hook='printf "root:x:0:\nmail:x:8:\nutmp:x:43:\n" > "$1/etc/group"'

               For a more elegant way for setting up a sub-essential busybox-based chroot, see
               the --hook-dir option below.

       --extract-hook=command
               Execute arbitrary commands after the Essential:yes packages have been extracted
               but before installing them. See section HOOKS for more information.

               Example: Install busybox symlinks

                   --extract-hook='chroot "$1" /bin/busybox --install -s'

       --essential-hook=command
               Execute arbitrary commands after the Essential:yes packages have been installed
               but before installing the remaining packages. The hook is not executed for the
               extract and custom variants. See section HOOKS for more information.

               Example: Enable unattended upgrades

                   --essential-hook='echo unattended-upgrades
                       unattended-upgrades/enable_auto_updates boolean true
                       | chroot "$1" debconf-set-selections'

               Example: Select Europe/Berlin as the timezone

                   --essential-hook='echo tzdata tzdata/Areas select Europe
                       | chroot "$1" debconf-set-selections'
                   --essential-hook='echo tzdata tzdata/Zones/Europe select Berlin
                       | chroot "$1" debconf-set-selections'

       --customize-hook=command
               Execute arbitrary commands after the chroot is set up and all packages got
               installed but before final cleanup actions are carried out. See section HOOKS for
               more information.

               Example: Add a user without a password

                   --customize-hook='chroot "$1" useradd --home-dir /home/user
                       --create-home user'
                   --customize-hook='chroot "$1" passwd --delete user'

               Example: set up /etc/hostname and /etc/hosts

                   --customize-hook='echo host > "$1/etc/hostname"'
                   --customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"'

               Example: to mimic debootstrap behaviour, mmdebstrap copies from the host.  Remove
               them in a --customize-hook to make the chroot reproducible across multiple hosts:

                   --customize-hook='rm "$1"/etc/resolv.conf'
                   --customize-hook='rm "$1"/etc/hostname'

       --hook-directory=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 in cases,
               where a user wants to run the same hooks frequently. For example, given a
               directory "./hooks" with two scripts "setup01-foo.sh" and "setup02-bar.sh", this
               call:

                   mmdebstrap --customize=./scriptA --hook-dir=./hooks --setup=./scriptB

               is equivalent to this call:

                   mmdebstrap --customize=./scriptA --setup=./hooks/setup01-foo.sh \
                       --setup=./hooks/setup02-bar.sh --setup=./scriptB

               The option can be specified multiple times and scripts are added to the respective
               hooks in the order the options are given on the command line. Thus, if the scripts
               in two directories depend upon each other, the scripts must be placed into a
               common directory and be named such that they get added in the correct order.

               Example 1: Run mmdebstrap with eatmydata

                   --hook-dir=/usr/share/mmdebstrap/hooks/eatmydata

               Example 2: Setup chroot for installing a sub-essential busybox-based chroot

                   --hook-dir=/usr/share/mmdebstrap/hooks/busybox

               Example 3: Automatically mount all directories referenced by "file://" mirrors
               into the chroot

                   --hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount

       --skip=stage[,stage,...]
               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 for a list of possible arguments and their context. The
               option can be specified multiple times or you can separate multiple values by
               comma or whitespace.

       -q,--quiet, -s,--silent
               Do not write anything to standard error. If used together with --verbose or
               --debug, only the last option will take effect.

       -v,--verbose
               Instead of progress bars, write the dpkg and apt output directly to standard
               error. If used together with --quiet or --debug, only the last option will take
               effect.

       -d,--debug
               In addition to the output produced by --verbose, write detailed debugging
               information to standard error. Errors will print a backtrace. If used together
               with --quiet or --verbose, only the last option will take effect.

       --logfile=filename
               Instead of writing status information to standard error, write it into the file
               given by filename.

MODES

       Creating a Debian chroot requires not only permissions for running chroot but also the
       ability to create files owned by the superuser. The selected mode decides which way this
       is achieved.

       auto    This mode automatically selects a fitting mode. If the effective user id is the
               one of the superuser, then the sudo mode is chosen. Otherwise, the unshare mode is
               picked if /etc/subuid and /etc/subgid are set up correctly. Should that not be the
               case and if the fakechroot binary exists, the fakechroot mode is chosen.

       sudo, root
               This mode directly executes chroot and is the same mode of operation as is used by
               debootstrap. It is the only mode that can directly create a directory chroot with
               the right permissions. If the chroot directory is not accessible by the _apt user,
               then apt sandboxing will be automatically disabled. This mode needs to be able to
               mount and thus requires "CAP_SYS_ADMIN".

       unshare When used as a normal (not root) user, this mode uses Linux user namespaces to
               allow unprivileged use of chroot and creation of files that appear to be owned by
               the superuser inside the unshared namespace. A tarball created in this mode will
               be bit-by-bit identical to a tarball created with the root mode. With this mode,
               the only binaries that will run as the root user will be newuidmap(1) and
               newgidmap(1) via their setuid bit. Running those successfully requires /etc/subuid
               and /etc/subgid to have an entry for your username. This entry was usually created
               by adduser(8) already.

               The unshared user will not automatically have access to the same files as you do.
               This is intentional and an additional security against unintended changes to your
               files that could theoretically result from running mmdebstrap and package
               maintainer scripts. To copy files in and out of the chroot, either use globally
               readable or writable directories or use special hooks like copy-in and copy-out.

               Besides the user namespace, the mount, pid (process ids), uts (hostname) and ipc
               namespaces will be unshared as well. See the man pages of namespaces(7) and
               unshare(2) as well as the manual pages they are linking to.

               A directory chroot created with this mode will end up with wrong ownership
               information (seen from outside the unshared user namespace). For correct ownership
               information, the directory must be accessed from a user namespace with the right
               subuid/subgid offset, like so:

                   $ lxc-usernsexec -- lxc-unshare -s 'MOUNT|PID|UTSNAME|IPC' -- \
                   > /usr/sbin/chroot ./debian-rootfs /bin/bash

               Or without LXC:

                   $ mmdebstrap --unshare-helper /usr/sbin/chroot ./debian-rootfs /bin/bash

               Or without mmdebstrap:

                   $ unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps -- \
                   > /usr/sbin/chroot ./debian-rootfs /bin/bash

               The above uses "--map-auto" to map the block of user/group ids for the effective
               user/group to a block starting at user/group ID 0. We also want to map the current
               effective user/group ID into the subuid/subgid range using "--map-user" and
               "--map-group", respectively. But if that uid/gid overlaps with the respective
               range, a "hole" will be removed from the mapping by the unshare(1) utility and the
               remaining uid/gid values will get shifted. Thus, we map the current effective
               user/group ID to the highest possible uid/gid, putting them at the end. Since that
               means that the user/group will be "nobody" and not "root" inside the namespace,
               "--keep-caps" propagate permitted capabilities into the ambient set and thus give
               the user "CAP_DAC_OVERRIDE" and other capabilities that it would've had. The
               following does NOT work:

                   $ unshare --map-root-user --map-auto ...            # or equavalient:
                   $ unshare --map-user=0 --map-group=0 --map-users=auto --map-groups=auto ...

               Using the format of lxc-usernsexec(1), these options will result in the following
               mapping:

                   0:$UID:1 + 1:$SUBUIDBASE:65535

               So a hole is punched in the automatically mapped range at the very beginning to
               make space for the user id of the current user as root inside the namespace and
               the remaining uids are shifted. With "--map-user=65536" the mapping is as follows
               and places the current user at the end of the range, preventing any shifting:

                   0:$SUBUIDBASE:65536 + 65536:$UID:1

               Lastly, if you don't mind using superuser privileges and have systemd-nspawn
               available and you know your subuid/subgid offset (100000 in this example):

                   $ sudo systemd-nspawn --private-users=100000 \
                   > --directory=./debian-rootfs /bin/bash

               A directory created in unshare mode cannot be removed the normal way.  Instead,
               use something like this:

                   $ unshare --map-root-user --map-auto rm -rf ./debian-rootfs

               The above unshare(1) command will map user and group ids into different ranges
               compared to the mapping used by mmdebstrap (effectively shifting them one up) but
               it will provide the required capabilities for the removal operation.

               If this mode is used as the root user, the user namespace is not unshared (but the
               mount namespace and other still are) and created directories will have correct
               ownership information. This is also useful in cases where the root user wants the
               benefits of an unshared mount namespace to prevent accidentally messing up the
               system.

       fakeroot, fakechroot
               This mode will exec mmdebstrap again under "fakechroot fakeroot". A directory
               chroot created with this mode will end up with wrong permissions. If you need a
               directory then run mmdebstrap under "fakechroot fakeroot -s fakeroot.env" and use
               "fakeroot.env" later when entering the chroot with "fakechroot fakeroot -i
               fakeroot.env chroot ...". This mode will not work if maintainer scripts are unable
               to handle "LD_PRELOAD" correctly like the package initramfs-tools until version
               0.132. This mode will also not work with a different libc inside the chroot than
               on the outside. See the section LIMITATIONS in fakechroot(1).

       chrootless
               Uses the dpkg option "--force-script-chrootless" to install packages into TARGET
               without dpkg and apt inside TARGET but using apt and dpkg from the machine running
               mmdebstrap. Maintainer scripts are run without chrooting into TARGET and rely on
               their dependencies being installed on the machine running mmdebstrap. Only very
               few packages support this mode. Namely, as of 2022, not all essential packages
               support it.  See https://wiki.debian.org/Teams/Dpkg/Spec/InstallBootstrap or the
               dpkg-root-support usertag of debian-dpkg@lists.debian.org in the Debian bug
               tracking system. WARNING: if this option is used carelessly with packages that do
               not support "DPKG_ROOT", this mode can result in undesired changes to the system
               running mmdebstrap because maintainer-scripts will be run without chroot(1). Make
               sure to run this mode without superuser privileges and/or inside a throw-away
               chroot environment like so:

                   mmdebstrap --variant=apt --include=mmdebstrap \
                       --customize-hook='chroot "$1" mmdebstrap --mode=chrootless
                                         --variant=apt unstable chrootless.tar' \
                       --customize-hook='copy-out chrootless.tar .' unstable /dev/null

VARIANTS

       All package sets also include the direct and indirect hard dependencies (but not
       recommends) of the selected package sets. The variants minbase, buildd and -, resemble the
       package sets that debootstrap would install with the same --variant argument. The release
       with a name matching the SUITE argument as well as the native architecture will be used to
       determine the "Essential:yes" and priority values. To select packages with matching
       priority from any suite, specify the empty string for SUITE. The default variant is
       debootstrap.

       extract Installs nothing by default (not even "Essential:yes" packages). Packages given by
               the "--include" option are extracted but will not be installed.

       custom  Installs nothing by default (not even "Essential:yes" packages). Packages given by
               the "--include" option will be installed.  If another mode than chrootless was
               selected and dpkg was not part of the included package set, then this variant will
               fail because it cannot configure the packages.

       essential
               "Essential:yes" packages. If SUITE is a non-empty string, then only packages from
               the archive with suite or codename matching SUITE will be considered for selection
               of "Essential:yes" packages.

       apt     The essential set plus apt.  It is roughly equivalent to running mmdebstrap with

                   --variant=essential --include="apt"

       buildd  The essential set plus apt and build-essential.  It is roughly equivalent to
               running mmdebstrap with

                   --variant=essential --include="apt,build-essential"

       required, minbase
               The essential set plus all packages with Priority:required.  It is roughly
               equivalent to running mmdebstrap with

                   --variant=essential --include="?priority(required)"

       important, debootstrap, -
               The required set plus all packages with Priority:important. This is the default of
               debootstrap. It is roughly equivalent to running mmdebstrap with

                   --variant=essential --include="~prequired|~pimportant"

       standard
               The important set plus all packages with Priority:standard.  It is roughly
               equivalent to running mmdebstrap with

                   --variant=essential --include="~prequired|~pimportant|~pstandard"

FORMATS

       The output format of mmdebstrap is specified using the --format option.  Without that
       option the default format is auto. The following formats exist:

       auto    When selecting this format (the default), the actual format will be inferred from
               the TARGET positional argument. If TARGET was not specified, then the tar format
               will be chosen. If TARGET happens to be /dev/null or if standard output is
               /dev/null, then the null format will be chosen. If TARGET is an existing
               directory, and does not equal to "-", then the directory format will be chosen. If
               TARGET ends with ".tar" or with one of the filename extensions listed in the
               section COMPRESSION, or if TARGET equals "-", or if TARGET is a named pipe (fifo)
               or if TARGET is a character special file, then the tar format will be chosen. If
               TARGET ends with ".squashfs" or ".sqfs", then the squashfs format will be chosen.
               If TARGET ends with ".ext2" then the ext2 format will be chosen. If TARGET ends
               with ".ext4" then the ext4 format will be chosen. If none of these conditions
               apply, the directory format will be chosen.

       directory, dir
               A chroot directory will be created in TARGET.  If the directory already exists, it
               must either be empty or only contain an empty "lost+found" directory.  The special
               TARGET "-" does not work with this format because a directory cannot be written to
               standard output. If you need your directory be named "-", then just explicitly
               pass the relative path to it like ./-.  If a directory is chosen as output in any
               other mode than sudo, then its contents will have wrong ownership information and
               special device files will be missing. Refer to the section MODES for more
               information.

       tar     A temporary chroot directory will be created in $TMPDIR or /tmp if $TMPDIR is not
               set. A tarball of that directory will be stored in TARGET or sent to standard
               output if TARGET was omitted or if TARGET equals "-".  If TARGET ends with one of
               the filename extensions listed in the section COMPRESSION, then a compressed
               tarball will be created. The tarball will be in POSIX 1003.1-2001 (pax) format and
               will contain extended attributes.  To preserve the extended attributes, you have
               to pass --xattrs --xattrs-include='*' to tar when extracting the tarball.

       squashfs, sqfs
               A temporary chroot directory will be created in $TMPDIR or /tmp if $TMPDIR is not
               set. A tarball of that directory will be piped to the "tar2sqfs" utility, which
               will create an xz compressed squashfs image with a blocksize of 1048576 bytes in
               TARGET.  The special TARGET "-" does not work with this format because "tar2sqfs"
               can only write to a regular file. If you need your squashfs image be named "-",
               then just explicitly pass the relative path to it like ./-. The "tar2sqfs" tool
               only supports a limited set of extended attribute prefixes. Therefore, extended
               attributes are disabled in the resulting image. If you need them, create a tarball
               first and remove the extended attributes from its pax headers. Refer to the
               EXAMPLES section for how to achieve this.

       ext2    A temporary chroot directory will be created in $TMPDIR or /tmp if $TMPDIR is not
               set. A tarball of that directory will be piped to the "genext2fs" utility, which
               will create an ext2 image that will be approximately 90% full in TARGET.  The
               special TARGET "-" does not work with this format because "genext2fs" can only
               write to a regular file. If you need your ext2 image be named "-", then just
               explicitly pass the relative path to it like ./-. To convert the result to an ext3
               image, use "tune2fs -O has_journal TARGET" and to convert it to ext4, use "tune2fs
               -O extents,uninit_bg,dir_index,has_journal TARGET".

               CAUTION: the ext2 format does not support timestamps beyond 2038 January 19, does
               not support sub-second precision timestamps and does not support extended
               attributes. Its inode size of 128 prevents adding these features with tune2fs
               later on.

       ext4    A temporary chroot directory will be created in $TMPDIR or /tmp if $TMPDIR is not
               set. A tarball of that directory will be piped to the "mke2fs" utility, which will
               create an ext4 image that will be approximately 90% full in TARGET. The special
               TARGET "-" does not work with this format because "mke2fs" can only write to a
               regular file. If you need your ext4 image be named "-", then just explicitly pass
               the relative path to it like ./-.  If "SOURCE_DATE_EPOCH" is set, the filesystem
               UUID and hash_seed will be set to a UUID derived from SOURCE_DATE_EPOCH to create
               reproducible images.

       null    A temporary chroot directory will be created in $TMPDIR or /tmp if $TMPDIR is not
               set. After the bootstrap is complete, the temporary chroot will be deleted without
               being part of the output. This is most useful when the desired artifact is
               generated inside the chroot and it is transferred using special hooks such as
               sync-out. It is also useful in situations where only the exit code or stdout or
               stderr of a process run in a hook is of interest.

HOOKS

       This section describes properties of the hook options --setup-hook, --extract-hook,
       --essential-hook and --customize-hook which are common to all four of them. Any
       information specific to each hook is documented under the specific hook options in the
       section OPTIONS.

       The options can be specified multiple times and the commands are executed in the order in
       which they are given on the command line. There are four different types of hook option
       arguments. If the argument passed to the hook option starts with "copy-in", "copy-out",
       "tar-in", "tar-out", "upload" or "download" followed by a space, then the hook is
       interpreted as a special hook. Otherwise, if command is an existing executable file from
       $PATH or if command does not contain any shell metacharacters, then command is directly
       exec-ed with the path to the chroot directory passed as the first argument. Otherwise,
       command is executed under sh and the chroot directory can be accessed via $1. Background
       (daemon) processes spawned in a hook are not guaranteed to persist beyond the hook that
       created them.

       Most environment variables set by mmdebstrap (like "DEBIAN_FRONTEND", "LC_ALL" and "PATH")
       are preserved.  Most notably, "APT_CONFIG" is being unset. If you need the path to
       "APT_CONFIG" as written by mmdebstrap it can be found in the "MMDEBSTRAP_APT_CONFIG"
       environment variable. All environment variables set by the user are preserved, except for
       "TMPDIR" which is cleared.  See section TMPDIR. Furthermore, "MMDEBSTRAP_MODE" will store
       the mode set by --mode, "MMDEBSTRAP_FORMAT" stores the format chosen by --format,
       "MMDEBSTRAP_HOOK" stores which hook is currently run (setup, extract, essential,
       customize), "MMDEBSTRAP_ARGV0" stores the name of the binary with which mmdebstrap was
       executed and "MMDEBSTRAP_VERBOSITY" stores the numerical verbosity level (0 for no output,
       1 for normal, 2 for verbose and 3 for debug output). The "MMDEBSTRAP_INCLUDE" variable
       stores the list of packages, apt patterns or file paths given by the --include option,
       separated by a comma and with commas and percent signs in the option values urlencoded. If
       SUITE name was supplied, it's stored in "MMDEBSTRAP_SUITE".

       In special hooks, the paths inside the chroot are relative to the root directory of the
       chroot.  The path on the outside is relative to current directory of the original
       mmdebstrap invocation. The path inside the chroot must already exist. Paths outside the
       chroot are created as necessary.

       In fakechroot mode, "tar", or "sh" and "cat" have to be run inside the chroot or
       otherwise, symlinks will be wrongly resolved and/or permissions will be off. This means
       that the special hooks might fail in fakechroot mode for the setup hook or for the extract
       and custom variants if no "tar" or "sh" and "cat" is available inside the chroot.

       copy-out pathinside [pathinside ...] pathoutside
               Recursively copies one or more files and directories recursively from pathinside
               inside the chroot to pathoutside outside of the chroot.

       copy-in pathoutside [pathoutside ...] pathinside
               Recursively copies one or more files and directories into the chroot into, placing
               them into pathinside inside of the chroot.

       sync-out pathinside pathoutside
               Recursively copy everything inside pathinside inside the chroot into pathoutside.
               In contrast to copy-out, this command synchronizes the content of pathinside with
               the content of pathoutside without deleting anything from pathoutside but
               overwriting content as necessary. Use this command over copy-out if you don't want
               to create a new directory outside the chroot but only update the content of an
               existing directory.

       sync-in pathoutside pathinside
               Recursively copy everything inside pathoutside into pathinside inside the chroot.
               In contrast to copy-in, this command synchronizes the content of pathoutside with
               the content of pathinside without deleting anything from pathinside but
               overwriting content as necessary. Use this command over copy-in if you don't want
               to create a new directory inside the chroot but only update the content of an
               existing directory.

       tar-in outside.tar pathinside
               Unpacks a tarball outside.tar from outside the chroot into a certain location
               pathinside inside the chroot. In unshare mode, device nodes cannot be created. To
               ignore device nodes in tarballs, use --skip=tar-in/mknod.

       tar-out pathinside outside.tar
               Packs the path pathinside from inside the chroot into a tarball, placing it into a
               certain location outside.tar outside the chroot. To emulate behaviour of "cp" and
               to provide control over the path which gets put into the tarball, a chdir() is
               performed to the dirname() of pathinside and then the basename() of pathinside is
               packaged as a tarball. For example, if pathinside is "/boot/." then first a
               chdir() into "/boot" will be performed before packing up the contents of "."
               inside "/boot".

       download fileinside fileoutside
               Copy the file given by fileinside from inside the chroot to outside the chroot as
               fileoutside. In contrast to copy-out, this command only handles files and not
               directories. To copy a directory recursively out of the chroot, use copy-out or
               tar-out. Its advantage is, that by being able to specify the full path on the
               outside, including the filename, the file on the outside can have a different name
               from the file on the inside. In contrast to copy-out and tar-out, this command
               follows symlinks.

       upload fileoutside fileinside
               Copy the file given by fileoutside from outside the chroot to inside the chroot as
               fileinside. In contrast to copy-in, this command only handles files and not
               directories. To copy a directory recursively into the chroot, use copy-in or tar-
               in. Its advantage is, that by being able to specify the full path on the inside,
               including the filename, the file on the inside can have a different name from the
               file on the outside. In contrast to copy-in and tar-in, permission and ownership
               information will not be retained.

OPERATION

       This section gives an overview of the different steps to create a chroot. At its core,
       what mmdebstrap does can be put into a 14 line shell script:

           mkdir -p "$2/etc/apt" "$2/var/cache" "$2/var/lib"
           cat << END > "$2/apt.conf"
           Apt::Architecture "$(dpkg --print-architecture)";
           Apt::Architectures "$(dpkg --print-architecture)";
           Dir "$(cd "$2" && pwd)";
           Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; printf "$v")";
           Dir::Etc::TrustedParts "$(eval "$(apt-config shell v Dir::Etc::TrustedParts/d)"; printf "$v")";
           END
           echo "deb http://deb.debian.org/debian/ $1 main" > "$2/etc/apt/sources.list"
           APT_CONFIG="$2/apt.conf" apt-get update
           APT_CONFIG="$2/apt.conf" apt-get --yes --download-only install '?essential'
           for f in "$2"/var/cache/apt/archives/*.deb; do dpkg-deb --extract "$f" "$2"; done
           chroot "$2" sh -c "dpkg --install --force-depends /var/cache/apt/archives/*.deb"

       The additional complexity of mmdebstrap is to support operation without superuser
       privileges, bit-by-bit reproducible output, hooks and foreign architecture support.

       The remainder of this section explains what mmdebstrap does step-by-step.

       check   Upon startup, several checks are carried out, like:

               •   whether required utilities (apt, dpkg, tar) are installed

               •   which mode to use and whether prerequisites are met

               •   do not allow chrootless mode as root (without fakeroot) unless inside a
                   chroot. This check can be disabled using --skip=check/chrootless

               •   whether the requested architecture can be executed (requires arch-test) using
                   qemu binfmt_misc support. This requires arch-test and can be disabled using
                   --skip=check/qemu

               •   how the apt sources can be assembled from SUITE, MIRROR and --components
                   and/or from standard input as deb822 or one-line format and whether the
                   required GPG keys exist.

               •   which output format to pick depending on the --format argument or name of
                   TARGET or its type.

               •   whether the output directory is empty. This check can be disabled using
                   --skip=check/empty

               •   whether adding a "signed-by" to "apt/sources.list" is necessary. This requires
                   gpg and can be disabled using --skip=check/signed-by

       setup   The following tasks are carried out unless --skip=setup is used:

               •   create required directories

               •   write out the temporary apt config file

               •   populates /etc/apt/apt.conf.d/99mmdebstrap and
                   /etc/dpkg/dpkg.cfg.d/99mmdebstrap with config options from --aptopt and
                   --dpkgopt, respectively

               •   write out /etc/apt/sources.list

               •   copy over /etc/resolv.conf and /etc/hostname

               •   populate /dev if mknod is possible

       setup-hook
               Run --setup-hook options and all setup* scripts in --hook-dir.

       update  Runs "apt-get update" using the temporary apt configuration file created in the
               setup step. This can be disabled using --skip=update.

       download
               In the extract and custom variants, "apt-get install" is used to download all the
               packages requested via the --include option. In the remaining variants, apt
               patterns are used to find the "Essential:yes" packages from the native
               architecture.  If SUITE is a non-empty string, then only packages from the archive
               with suite or codename matching SUITE will be considered for selection of
               "Essential:yes" packages.

       mount   Mount relevant device nodes, /proc and /sys into the chroot and unmount them
               afterwards. This can be disabled using --skip=chroot/mount or specifically by
               --skip=chroot/mount/dev, --skip=chroot/mount/proc and --skip=chroot/mount/sys,
               respectively. mmdebstrap will disable running services by temporarily moving
               /usr/sbin/policy-rc.d and /usr/sbin/start-stop-daemon if they exist. This can be
               disabled with --skip=chroot/policy-rc.d and --skip=chroot/start-stop-daemon,
               respectively.

       extract Extract the downloaded packages into the rootfs.

       prepare In fakechroot mode, environment variables "LD_LIBRARY_PATH" will be set up
               correctly. For foreign fakechroot environments, "LD_LIBRARY_PATH" and
               "QEMU_LD_PREFIX" are set up accordingly. This step is not carried out in extract
               mode and neither for the chrootless variant.

       extract-hook
               Run --extract-hook options and all extract* scripts in --hook-dir.

       essential
               Uses "dpkg --install" to properly install all packages that have been extracted
               before. Removes all packages downloaded in the download step, except those which
               were present in /var/cache/apt/archives/ before (if any).  This can be disabled
               using --skip=essential/unlink. This step is not carried out in extract mode.

       essential-hook
               Run --essential-hook options and all essential* scripts in --hook-dir.  This step
               is not carried out in extract mode.

       install Install the apt package into the chroot, if necessary and then run apt from inside
               the chroot to install all remaining packages. This step is not carried out in
               extract mode.

       customize-hook
               Run --customize-hook options and all customize* scripts in --hook-dir.  This step
               is not carried out in extract mode.

       unmount Unmount everything that was mounted during the mount stage and restores
               /usr/sbin/policy-rc.d and /usr/sbin/start-stop-daemon if necessary.

       zombie-reaping
               Wait for (reap) still running processes (background processes or zombie
               processes), unless --skip=zombie-reaping is used.

       cleanup Performs cleanup tasks, unless --skip=cleanup is used:

               •   Removes the package lists (unless --skip=cleanup/apt/lists) and apt cache
                   (unless --skip=cleanup/apt/cache). Both removals can be disabled by using
                   --skip=cleanup/apt.

               •   Remove all files that were put into the chroot for setup purposes, like
                   /etc/apt/apt.conf.d/00mmdebstrap and the temporary apt config. This can be
                   disabled using --skip=cleanup/mmdebstrap.

               •   Remove files that make the result unreproducible and write the empty string to
                   /etc/machine-id if it exists. This can be disabled using
                   --skip=cleanup/reproducible. Note that this will not remove files that make
                   the result unreproducible on machines with differing /etc/resolv.conf or
                   /etc/hostname. Use a --customize-hook to make those two files reproducible
                   across multiple hosts. See section "SOURCE_DATE_EPOCH" for more information.
                   The following files will be removed:

                   •   /var/log/dpkg.log/var/log/apt/history.log/var/log/apt/term.log/var/log/alternatives.log/var/cache/ldconfig/aux-cache/var/log/apt/eipp.log.xz/var/lib/dbus/machine-id

               •   Remove everything in /run inside the chroot. This can be disabled using
                   --skip=cleanup/run.

               •   Remove everything in /tmp inside the chroot. This can be disabled using
                   --skip=cleanup/tmp.

       output  For formats other than directory, pack up the temporary chroot directory into a
               tarball, ext2 image, ext4 image or squashfs image and delete the temporary chroot
               directory.

               If --skip=output/dev is added, the resulting chroot will not contain the device
               nodes, directories and symlinks that debootstrap creates but just an empty /dev as
               created by base-files.

               If --skip=output/mknod is added, the resulting chroot will not contain device
               nodes (neither block nor character special devices). This is useful if the chroot
               tarball is to be exatracted in environments where mknod does not function like in
               unshared user namespaces.

EXAMPLES

       Use like debootstrap:

           $ sudo mmdebstrap unstable ./unstable-chroot

       Without superuser privileges:

           $ mmdebstrap unstable unstable-chroot.tar

       With no command line arguments at all. The chroot content is entirely defined by a
       sources.list file on standard input.

           $ mmdebstrap < /etc/apt/sources.list > unstable-chroot.tar

       Since the tarball is output on stdout, members of it can be excluded using tar on-the-fly.
       For example the /dev directory can be removed from the final tarbal in cases where it is
       to be extracted by a non-root user who cannot create device nodes:

           $ mmdebstrap unstable | tar --delete ./dev > unstable-chroot.tar

       Create a tarball for use with "sbuild --chroot-mode=unshare":

           $ mmdebstrap --variant=buildd unstable ~/.cache/sbuild/unstable-amd64.tar

       Create a buildd tarball for EOL distro:

           $ mmdebstrap --include=apt --variant=buildd --aptopt \
               'Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"' \
               --aptopt='Acquire::Check-Valid-Until "false"' \
               --keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg \
               --hook-dir=/usr/share/mmdebstrap/hooks/maybe-jessie-or-older \
               jessie ~/.cache/sbuild/jessie-arm64.tar \
               http://archive.debian.org/debian

       Instead of a tarball, a squashfs image can be created:

           $ mmdebstrap unstable unstable-chroot.squashfs

       By default, mmdebstrap runs tar2sqfs with "--no-skip --exportable --compressor xz
       --block-size 1048576". To choose a different set of options, and to filter out all
       extended attributes not supported by tar2sqfs, pipe the output of mmdebstrap into tar2sqfs
       manually like so:

           $ mmdebstrap unstable \
               | mmtarfilter --pax-exclude='*' \
                   --pax-include='SCHILY.xattr.user.*' \
                   --pax-include='SCHILY.xattr.trusted.*' \
                   --pax-include='SCHILY.xattr.security.*' \
               | tar2sqfs --quiet --no-skip --force --exportable --compressor xz \
                   --block-size 1048576 unstable-chroot.squashfs

       By default, debootstrapping a stable distribution will add mirrors for security and
       updates to the sources.list.

           $ mmdebstrap stable stable-chroot.tar

       If you don't want this behaviour, you can override it by manually specifying a mirror in
       various different ways:

           $ mmdebstrap stable stable-chroot.tar http://deb.debian.org/debian
           $ mmdebstrap stable stable-chroot.tar "deb http://deb.debian.org/debian stable main"
           $ mmdebstrap stable stable-chroot.tar /path/to/sources.list
           $ mmdebstrap stable stable-chroot.tar - < /path/to/sources.list

       Drop locales (but not the symlink to the locale name alias database), translated manual
       packages (but not the untranslated ones), and documentation (but not copyright and Debian
       changelog).

           $ mmdebstrap --variant=essential \
               --dpkgopt='path-exclude=/usr/share/man/*' \
               --dpkgopt='path-include=/usr/share/man/man[1-9]/*' \
               --dpkgopt='path-exclude=/usr/share/locale/*' \
               --dpkgopt='path-include=/usr/share/locale/locale.alias' \
               --dpkgopt='path-exclude=/usr/share/doc/*' \
               --dpkgopt='path-include=/usr/share/doc/*/copyright' \
               --dpkgopt='path-include=/usr/share/doc/*/changelog.Debian.*' \
               unstable debian-unstable.tar

       Create a bootable USB Stick that boots into a full Debian desktop:

           $ mmdebstrap --aptopt='Apt::Install-Recommends "true"' --customize-hook \
               'chroot "$1" adduser --comment user --disabled-password user' \
               --customize-hook='echo 'user:live' | chroot "$1" chpasswd' \
               --customize-hook='echo host > "$1/etc/hostname"' \
               --customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"' \
               --include=linux-image-amd64,task-desktop unstable debian-unstable.tar
           $ cat << END > extlinux.conf
           > default linux
           > timeout 0
           >
           > label linux
           > kernel /vmlinuz
           > append initrd=/initrd.img root=LABEL=rootfs
           END
           # You can use $(sudo blockdev --getsize64 /dev/sdXXX) to get the right
           # image size for the target medium in bytes
           $ guestfish -N debian-unstable.img=disk:8G -- \
               part-disk /dev/sda mbr : \
               part-set-bootable /dev/sda 1 true : \
               mkfs ext4 /dev/sda1 : \
               set-label /dev/sda1 rootfs : \
               mount /dev/sda1 / : \
               tar-in debian-unstable.tar / xattrs:true : \
               upload /usr/lib/EXTLINUX/mbr.bin /boot/mbr.bin : \
               copy-file-to-device /boot/mbr.bin /dev/sda size:440 : \
               extlinux / : copy-in extlinux.conf / : sync : umount / : shutdown
           $ qemu-system-x86_64 -m 1G -enable-kvm debian-unstable.img
           $ sudo dd if=debian-unstable.img of=/dev/sdXXX status=progress

       On architectures without extlinux you can also boot using grub2:

           $ mmdebstrap --include=linux-image-amd64,grub2,systemd-sysv unstable fs.tar
           $ guestfish -N debian-unstable.img=disk:2G -- \
               part-disk /dev/sda mbr : \
               part-set-bootable /dev/sda 1 true : \
               mkfs ext4 /dev/sda1 : \
               set-label /dev/sda1 rootfs : \
               mount /dev/sda1 / : \
               tar-in fs.tar / xattrs:true : \
               command "grub-install /dev/sda" : \
               command update-grub : \
               sync : umount / : shutdown
           $ qemu-system-x86_64 -m 1G -enable-kvm debian-unstable.img

       Build libdvdcss2.deb without installing installing anything or changing apt sources on the
       current system:

           $ mmdebstrap --variant=apt --components=main,contrib --include=libdvd-pkg \
               --customize-hook='chroot $1 /usr/lib/libdvd-pkg/b-i_libdvdcss.sh' \
               | tar --extract --verbose --strip-components=4 \
                   --wildcards './usr/src/libdvd-pkg/libdvdcss2_*_*.deb'
           $ ls libdvdcss2_*_*.deb

       Use as replacement for autopkgtest-build-qemu and vmdb2 for all architectures supporting
       EFI booting (amd64, arm64, armhf, i386, riscv64), use a convenience wrapper around
       mmdebstrap:

           $ mmdebstrap-autopkgtest-build-qemu unstable ./autopkgtest.img

       Use as replacement for autopkgtest-build-qemu and vmdb2 on architectures supporting
       extlinux (amd64 and i386):

           $ mmdebstrap --variant=important --include=linux-image-amd64 \
               --customize-hook='chroot "$1" passwd --delete root' \
               --customize-hook='chroot "$1" useradd --home-dir /home/user --create-home user' \
               --customize-hook='chroot "$1" passwd --delete user' \
               --customize-hook='echo host > "$1/etc/hostname"' \
               --customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"' \
               --customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed \
               unstable debian-unstable.tar
           $ cat << END > extlinux.conf
           > default linux
           > timeout 0
           >
           > label linux
           > kernel /vmlinuz
           > append initrd=/initrd.img root=/dev/vda1 rw console=ttyS0
           END
           $ guestfish -N debian-unstable.img=disk:8G -- \
               part-disk /dev/sda mbr : \
               part-set-bootable /dev/sda 1 true : \
               mkfs ext4 /dev/sda1 : mount /dev/sda1 / : \
               tar-in debian-unstable.tar / xattrs:true : \
               upload /usr/lib/EXTLINUX/mbr.bin /boot/mbr.bin : \
               copy-file-to-device /boot/mbr.bin /dev/sda size:440 : \
               extlinux / : copy-in extlinux.conf / : sync : umount / : shutdown
           $ qemu-img convert -O qcow2 debian-unstable.img debian-unstable.qcow2

       As a debootstrap wrapper to run it without superuser privileges but using Linux user
       namespaces instead. This fixes Debian bug #829134.

           $ mmdebstrap --variant=custom --mode=unshare \
               --setup-hook='debootstrap unstable "$1"' \
               - debian-debootstrap.tar

       Build a non-Debian chroot like Ubuntu bionic:

           $ mmdebstrap --aptopt='Dir::Etc::Trusted
              "/usr/share/keyrings/ubuntu-keyring-2012-archive.gpg"' bionic bionic.tar

       If, for some reason, you cannot use a caching proxy like apt-cacher or apt-cacher-ng, you
       can use the sync-in and sync-out special hooks to synchronize a directory outside the
       chroot with /var/cache/apt/archives inside the chroot.

           $ mmdebstrap --variant=apt --skip=essential/unlink \
               --setup-hook='mkdir -p ./cache "$1"/var/cache/apt/archives/' \
               --setup-hook='sync-in ./cache /var/cache/apt/archives/' \
               --customize-hook='sync-out /var/cache/apt/archives ./cache' \
               unstable /dev/null

       Instead of copying potentially large amounts of data with sync-in you can also use a bind-
       mount in combination with a "file://" mirror to make packages from the outside available
       inside the chroot:

           $ mmdebstrap --variant=apt --skip=essential/unlink \
               --setup-hook='mkdir "$1/tmp/mirror"' \
               --setup-hook='mount -o ro,bind /tmp/mirror "$1/tmp/mirror"' \
               --customize-hook='sync-out /var/cache/apt/archives ./cache' \
               --customize-hook='umount "$1/tmp/mirror"; rmdir "$1/tmp/mirror";' \
               unstable /dev/null file:///tmp/mirror http://deb.debian.org/debian

       To automatically mount all directories referenced by "file://" mirrors into the chroot you
       can use a hook:

           $ mmdebstrap --variant=apt \
               --hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount \
               unstable /dev/null file:///tmp/mirror1 file:///tmp/mirror2

       Create a system that can be used with docker:

           $ mmdebstrap unstable | sudo docker import - debian
           [...]
           $ sudo docker run -it --rm debian whoami
           root
           $ sudo docker rmi debian

       Create and boot a qemu virtual machine for an arbitrary architecture using the debvm-
       create wrapper script around mmdebstrap:

           $ debvm-create -r stable -- --architecture=riscv64
           $ debvm-run

       Create a system that can be used with podman:

           $ mmdebstrap unstable | podman import - debian
           [...]
           $ podman run --network=none -it --rm debian whoami
           root
           $ podman rmi debian

       As a docker/podman replacement:

           $ mmdebstrap unstable chroot.tar
           [...]
           $ mmdebstrap --variant=custom --skip=update,tar-in/mknod \
               --setup-hook='tar-in chroot.tar /' \
               --customize-hook='chroot "$1" whoami' unstable /dev/null
           [...]
           root
           $ rm chroot.tar

       You can re-use a chroot tarball created with mmdebstrap for further refinement.  Say you
       want to create a minimal chroot and a chroot with more packages installed, then instead of
       downloading and installing the essential packages twice you can instead build on top of
       the already present minimal chroot:

           $ mmdebstrap --variant=apt unstable chroot.tar
           $ mmdebstrap --variant=custom --skip=update,setup,cleanup,tar-in/mknod \
               --setup-hook='tar-in chroot.tar /' \
               --customize-hook='chroot "$1" apt-get install --yes pkg1 pkg2' \
               '' chroot-full.tar

ENVIRONMENT VARIABLES

       "SOURCE_DATE_EPOCH"
               By setting "SOURCE_DATE_EPOCH" the result will be reproducible across multiple
               runs with the same options and mirror content. Note that for debootstrap
               compatibility, mmdebstrap will copy the host's /etc/resolv.conf and /etc/hostname
               into the chroot. This means that the mmdebstrap output will differ if it is run on
               machines with differing /etc/resolv.conf and /etc/hostname contents. To make the
               result reproducible across different hosts, you need to manually either delete
               both files from the output:

                   $ mmdebstrap --customize-hook='rm "$1"/etc/resolv.conf' \
                                --customize-hook='rm "$1"/etc/hostname' ...

               or fill them with reproducible content:

                   $ mmdebstrap --customize-hook='echo nameserver X > "$1"/etc/resolv.conf' \
                                --customize-hook='echo host > "$1"/etc/hostname' ...

       "TMPDIR"
               When creating a tarball, a temporary directory is populated with the rootfs before
               the tarball is packed. The location of that temporary directory will be in /tmp or
               the location pointed to by "TMPDIR" if that environment variable is set. Setting
               "TMPDIR" to a different directory than /tmp is useful if you have /tmp on a tmpfs
               that is too small for your rootfs.

               If you set "TMPDIR" in unshare mode, then the unshared user must be able to access
               the directory. This means that the directory itself must be world-writable and all
               its ancestors must be at least world-executable.

               Since "TMPDIR" is only valid outside the chroot, the variable is being unset when
               running hook scripts. If you need a valid temporary directory in a hook, consider
               using /tmp inside your target directory.

DEBOOTSTRAP

       This section lists some differences to debootstrap.

       •       More than one mirror possible

       •       Default mirrors for stable releases include updates and security mirror

       •       Multiple ways to operate as non-root: fakechroot and unshare

       •       twice as fast

       •       Can create a chroot with only "Essential:yes" packages and their deps

       •       Reproducible output by default if $SOURCE_DATE_EPOCH is set

       •       Can create output on filesystems with nodev set

       •       apt cache and lists are cleaned at the end

       •       foreign architecture chroots using qemu-user

       Limitations in comparison to debootstrap:

       •       Only runs on systems with apt installed (Debian and derivatives)

       •       No SCRIPT argument (use hooks instead)

       •       Some debootstrap options don't exist, namely:

               --second-stage, --exclude, --resolve-deps, --force-check-gpg, --merged-usr,
               --no-merged-usr and --cache-dir.

MERGED-/USR

       mmdebstrap will create a merged-/usr chroot or not depending on whether packages setting
       up merged-/usr (i.e. the usrmerge package) are installed or not. In Debian, the essential
       package init-system-helpers depends on the usrmerge package, starting with Debian 12
       (Bookworm).

       Before Debian 12 (Bookworm), to force mmdebstrap to create a chroot with merged-/usr using
       symlinks, either explicitly install the usrmerge package:

           --include=usrmerge

       or setup merged-/usr using the debootstrap-method which takes care of the architecture
       specific symlinks and installs the usr-is-merged package.

           --hook-dir=/usr/share/mmdebstrap/hooks/merged-usr

       To force mmdebstrap to create a chroot without merged-/usr even after the Debian 12
       (Bookworm) release, you can use the following hook:

           --hook-dir=/usr/share/mmdebstrap/hooks/no-merged-usr

       This will write "this system will not be supported in the future" into
       /etc/unsupported-skip-usrmerge-conversion inside the chroot and install the usr-is-merged
       package to avoid the installation of the usrmerge package and its dependencies.

       If you are using mmdebstrap in a setup where you do not know upfront whether the chroot
       you are creating should be merged-/usr or not and you want to avoid installation of the
       usrmerge package and it's dependencies, you can use:

           --hook-dir=/usr/share/mmdebstrap/hooks/maybe-merged-usr

       That hook will use the availability of the usr-is-merged package to decide whether to call
       the merged-usr hook or not.

COMPRESSION

       mmdebstrap will choose a suitable compressor for the output tarball depending on the
       filename extension. The following mapping from filename extension to compressor applies:

        extension compressor
        --------------------
        .tar      none
        .gz       gzip
        .tgz      gzip
        .taz      gzip
        .Z        compress
        .taZ      compress
        .bz2      bzip2
        .tbz      bzip2
        .tbz2     bzip2
        .tz2      bzip2
        .lz       lzip
        .lzma     lzma
        .tlz      lzma
        .lzo      lzop
        .lz4      lz4
        .xz       xz
        .txz      xz
        .zst      zstd

       To change compression specific options, either use the respecitve environment variables
       like XZ_OPT or send mmdebstrap output to your compressor of choice with a pipe.

WRAPPERS

   debvm
       debvm helps create and run virtual machines for various Debian releases and architectures.
       The tool debvm-create can be used to create a virtual machine image and the tool debvm-run
       can be used to run such a machine image. Their purpose primarily is testing software using
       qemu as a containment technology.  These are relatively thin wrappers around mmdebstrap
       and qemu.

   bdebstrap
       bdebstrap is a YAML config based multi-mirror Debian chroot creation tool.  bdebstrap is
       an alternative to debootstrap and a wrapper around mmdebstrap to support YAML based
       configuration files. It inherits all benefits from mmdebstrap. The support for
       configuration allows storing all customization in a YAML file instead of having to use a
       very long one-liner call to mmdebstrap. It also layering multiple customizations on top of
       each other, e.g. to support flavors of an image.

BUGS

       https://gitlab.mister-muffin.de/josch/mmdebstrap/issues

       https://bugs.debian.org/src:mmdebstrap

       As of version 1.20.9, dpkg does not provide facilities preventing it from reading the dpkg
       configuration of the machine running mmdebstrap.  Therefore, until this dpkg limitation is
       fixed, a default dpkg configuration is recommended on machines running mmdebstrap. If you
       are using mmdebstrap as the non-root user, then as a workaround you could run "chmod 600
       /etc/dpkg/dpkg.cfg.d/*" so that the config files are only accessible by the root user. See
       Debian bug #808203.

       With apt versions before 2.1.16, setting "[trusted=yes]" or
       "Acquire::AllowInsecureRepositories "1"" to allow signed archives without a known public
       key or unsigned archives will fail because of a gpg warning in the apt output. Since apt
       does not communicate its status via any other means than human readable strings, and
       because mmdebstrap wants to treat transient network errors as errors, mmdebstrap treats
       any warning from "apt-get update" as an error.

SEE ALSO

       debootstrap(8), debvm(1), bdebstrap(1)