.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MMDEBSTRAP 1" .TH MMDEBSTRAP 1 "2021-05-07" "perl v5.32.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mmdebstrap \- multi\-mirror Debian chroot creation .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBmmdebstrap\fR [\fB\s-1OPTION...\s0\fR] [\fI\s-1SUITE\s0\fR [\fI\s-1TARGET\s0\fR [\fI\s-1MIRROR\s0\fR...]]] .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBmmdebstrap\fR creates a Debian chroot of \fI\s-1SUITE\s0\fR into \fI\s-1TARGET\s0\fR from one or more \fI\s-1MIRROR\s0\fRs. It is meant as an alternative to the debootstrap tool (see section \fB\s-1DEBOOTSTRAP\s0\fR). In contrast to debootstrap it uses apt to resolve dependencies and is thus able to use more than one mirror and resolve more complex dependencies. .PP If no \fI\s-1MIRROR\s0\fR option is provided, is used. If \fI\s-1SUITE\s0\fR is a stable release name and no \fI\s-1MIRROR\s0\fR is specified, then mirrors for updates and security are automatically added. If a \fI\s-1MIRROR\s0\fR option starts with \*(L"deb \*(R" or \*(L"deb-src \*(R" then it is used as a one-line-style format entry for apt's sources.list inside the chroot. If a \fI\s-1MIRROR\s0\fR option contains a \*(L"://\*(R" then it is interpreted as a mirror \s-1URI\s0 and the apt line inside the chroot is assembled as \*(L"deb [arch=A] B C D\*(R" where A is the host's native architecture, B is the \fI\s-1MIRROR\s0\fR, C is the given \fI\s-1SUITE\s0\fR and D is the components given via \fB\-\-components\fR (defaults to \*(L"main\*(R"). If a \fI\s-1MIRROR\s0\fR option happens to be an existing file, then its contents are pasted into the chroot's sources.list. This can be used to supply a deb822 style sources.list. If \fI\s-1MIRROR\s0\fR is \f(CW\*(C`\-\*(C'\fR 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 any mirror contains a https \s-1URI,\s0 then the packages apt-transport-https and ca-certificates will be installed inside the chroot. If any mirror contains a tor+xxx \s-1URI,\s0 then the apt-transport-tor package will be installed inside the chroot. .PP The optional \fI\s-1TARGET\s0\fR argument can either be the path to a directory, the path to a tarball filename, the path to a squashfs image, the path to an ext2 image, a \s-1FIFO,\s0 a character special device, or \f(CW\*(C`\-\*(C'\fR. Without the \fB\-\-format\fR option, \&\fI\s-1TARGET\s0\fR will be used to choose the format. See the section \fB\s-1FORMATS\s0\fR for more information. If no \fI\s-1TARGET\s0\fR was specified or if \fI\s-1TARGET\s0\fR is \f(CW\*(C`\-\*(C'\fR, an uncompressed tarball will be sent to standard output. .PP The \fI\s-1SUITE\s0\fR may be a valid release code name (eg, sid, stretch, jessie) or a symbolic name (eg, unstable, testing, stable, oldstable). Any suite name that works with apt on the given mirror will work. If no \fI\s-1SUITE\s0\fR was specified, then a single \fI\s-1MIRROR\s0\fR \f(CW\*(C`\-\*(C'\fR is added and thus the information of the desired suite has to come from standard input as part of a valid apt sources.list file. If mmdebstrap is instructed to retrieve packages from multiple releases, then the value of the \fI\s-1SUITE\s0\fR argument will be used to determine which apt index to use for finding out the set of \f(CW\*(C`Essential:yes\*(C'\fR packages and/or the set of packages with the right priority for the selected variant. See the section \&\fB\s-1VARIANTS\s0\fR for more information. .PP All status output is printed to standard error unless \fB\-\-logfile\fR is used to redirect it to a file or \fB\-\-quiet\fR or \fB\-\-silent\fR is used to suppress any output on standard error. Help and version information will be printed to standard error with the \fB\-\-help\fR and \fB\-\-version\fR options, respectively. Otherwise, an uncompressed tarball might be sent to standard output if \&\fI\s-1TARGET\s0\fR is \f(CW\*(C`\-\*(C'\fR or if no \fI\s-1TARGET\s0\fR was specified. .SH "OPTIONS" .IX Header "OPTIONS" Options are case insensitive. Short options may be bundled. Long options require a double dash and may be abbreviated to uniqueness. .IP "\fB\-h,\-\-help\fR" 8 .IX Item "-h,--help" Print synopsis and options of this man page and exit. .IP "\fB\-\-man\fR" 8 .IX Item "--man" Show the full man page as generated from Perl \s-1POD\s0 in a pager. This requires the perldoc program from the perl-doc package. This is the same as running: .Sp .Vb 1 \& pod2man /usr/bin/mmdebstrap | man \-l \- .Ve .IP "\fB\-\-version\fR" 8 .IX Item "--version" Print the \fBmmdebstrap\fR version and exit. .IP "\fB\-\-variant\fR=\fIname\fR" 8 .IX Item "--variant=name" Choose which package set to install. Valid variant \fIname\fRs are \fBextract\fR, \&\fBcustom\fR, \fBessential\fR, \fBapt\fR, \fBrequired\fR, \fBminbase\fR, \fBbuildd\fR, \&\fBimportant\fR, \fBdebootstrap\fR, \fB\-\fR, and \fBstandard\fR. The default variant is \&\fBdebootstrap\fR. See the section \fB\s-1VARIANTS\s0\fR for more information. .IP "\fB\-\-mode\fR=\fIname\fR" 8 .IX Item "--mode=name" Choose how to perform the chroot operation and create a filesystem with ownership information different from the current user. Valid mode \fIname\fRs are \&\fBauto\fR, \fBsudo\fR, \fBroot\fR, \fBunshare\fR, \fBfakeroot\fR, \fBfakechroot\fR, \fBproot\fR and \&\fBchrootless\fR. The default mode is \fBauto\fR. See the section \fB\s-1MODES\s0\fR for more information. .IP "\fB\-\-format\fR=\fIname\fR" 8 .IX Item "--format=name" Choose the output format. Valid format \fIname\fRs are \fBauto\fR, \fBdirectory\fR, \&\fBtar\fR, \fBsquashfs\fR, and \fBext2\fR. The default format is \fBauto\fR. See the section \fB\s-1FORMATS\s0\fR for more information. .IP "\fB\-\-aptopt\fR=\fIoption\fR|\fIfile\fR" 8 .IX Item "--aptopt=option|file" Pass arbitrary \fIoption\fRs to apt. Will be permamently added to \&\fI/etc/apt/apt.conf.d/99mmdebstrap\fR inside the chroot. Use hooks for temporary configuration options. Can be specified multiple times. Each \fIoption\fR 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 \fIfile\fR, the content of the file will be appended to 99mmdebstrap verbatim. .Sp Example: This is necessary for allowing old timestamps from snapshot.debian.org .Sp .Vb 1 \& \-\-aptopt=\*(AqAcquire::Check\-Valid\-Until "false"\*(Aq .Ve .Sp Example: Settings controlling download of package description translations .Sp .Vb 2 \& \-\-aptopt=\*(AqAcquire::Languages { "environment"; "en"; }\*(Aq \& \-\-aptopt=\*(AqAcquire::Languages "none"\*(Aq .Ve .Sp Example: Enable installing Recommends (by default \fBmmdebstrap\fR doesn't) .Sp .Vb 1 \& \-\-aptopt=\*(AqApt::Install\-Recommends "true"\*(Aq .Ve .Sp Example: Configure apt-cacher or apt-cacher-ng as an apt proxy .Sp .Vb 1 \& \-\-aptopt=\*(AqAcquire::http { Proxy "http://127.0.0.1:3142"; }\*(Aq .Ve .Sp Example: For situations in which the apt sandbox user cannot access the chroot .Sp .Vb 1 \& \-\-aptopt=\*(AqAPT::Sandbox::User "root"\*(Aq .Ve .Sp Example: Minimizing the number of packages installed from experimental .Sp .Vb 3 \& \-\-aptopt=\*(AqAPT::Solver "aspcud"\*(Aq \& \-\-aptopt=\*(AqAPT::Solver::aspcud::Preferences \& "\-count(solution,APT\-Release:=/a=experimental/),\-removed,\-changed,\-new"\*(Aq .Ve .IP "\fB\-\-keyring\fR=\fIfile\fR|\fIdirectory\fR" 8 .IX Item "--keyring=file|directory" Change the default keyring to use by apt. By default, \fI/etc/apt/trusted.gpg\fR and \fI/etc/apt/trusted.gpg.d\fR are used. 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 \fBnot\fR use this option to pass multiple files and/or directories. Using the \f(CW\*(C`\-\-keyring\*(C'\fR argument in the following way is equal to keeping the default: .Sp .Vb 1 \& \-\-keyring=/etc/apt/trusted.gpg \-\-keyring=/etc/apt/trusted.gpg.d .Ve .Sp If you need to pass multiple keyrings, use the \f(CW\*(C`signed\-by\*(C'\fR option when specifying the mirror like this: .Sp .Vb 1 \& mmdebstrap mysuite out.tar "deb [signed\-by=/path/to/key.gpg] http://..." .Ve .Sp The \f(CW\*(C`signed\-by\*(C'\fR option will automatically be added to the final \&\f(CW\*(C`sources.list\*(C'\fR if the keyring required for the selected \fI\s-1SUITE\s0\fR is not yet trusted by apt. Automatically adding the \f(CW\*(C`signed\-by\*(C'\fR option in these cases requires \f(CW\*(C`gpg\*(C'\fR to be installed. If \f(CW\*(C`gpg\*(C'\fR and \f(CW\*(C`ubuntu\-archive\-keyring\*(C'\fR are installed, then you can create a Ubuntu Bionic chroot on Debian like this: .Sp .Vb 1 \& mmdebstrap bionic ubuntu\-bionic.tar .Ve .Sp The resulting chroot will have a \f(CW\*(C`source.list\*(C'\fR with a \f(CW\*(C`signed\-by\*(C'\fR option pointing to \fI/usr/share/keyrings/ubuntu\-archive\-keyring.gpg\fR. .IP "\fB\-\-dpkgopt\fR=\fIoption\fR|\fIfile\fR" 8 .IX Item "--dpkgopt=option|file" Pass arbitrary \fIoption\fRs to dpkg. Will be permanently added to \&\fI/etc/dpkg/dpkg.cfg.d/99mmdebstrap\fR inside the chroot. Use hooks for temporary configuration options. Can be specified multiple times. Each \fIoption\fR will be appended to 99mmdebstrap. If the command line argument is an existing \fIfile\fR, the content of the file will be appended to 99mmdebstrap verbatim. .Sp Example: Exclude paths to reduce chroot size .Sp .Vb 8 \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/man/*\*(Aq \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/man/man[1\-9]/*\*(Aq \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/locale/*\*(Aq \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/locale/locale.alias\*(Aq \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/doc/*\*(Aq \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/doc/*/copyright\*(Aq \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/doc/*/changelog.Debian.*\*(Aq \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/{doc,info,man,omf,help,gnome/help}/*\*(Aq .Ve .IP "\fB\-\-include\fR=\fIpkg1\fR[,\fIpkg2\fR,...]" 8 .IX Item "--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 \fBextract\fR and \fBcustom\fR 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. The \fBessential\fR variant does not include apt and thus, the include option will only work when the \fBchrootless\fR mode is selected and thus apt from the outside can be used. Package names are directly passed to apt and thus, you can use apt features like \f(CW\*(C`pkg/suite\*(C'\fR, \f(CW\*(C`pkg=version\*(C'\fR, \&\f(CW\*(C`pkg\-\*(C'\fR or use a glob or regex for \f(CW\*(C`pkg\*(C'\fR. See \fBapt\fR\|(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: .Sp .Vb 3 \& \-\-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\- .Ve .IP "\fB\-\-components\fR=\fIcomp1\fR[,\fIcomp2\fR,...]" 8 .IX Item "--components=comp1[,comp2,...]" Comma or whitespace separated list of components like main, contrib and non-free which will be used for all URI-only \fI\s-1MIRROR\s0\fR 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: .Sp .Vb 3 \& \-\-components="main contrib non\-free" \& \-\-components=main,contrib,non\-free \& \-\-comp=main \-\-comp="contrib non\-free" \-\-comp="main,non\-free" .Ve .IP "\fB\-\-architectures\fR=\fInative\fR[,\fIforeign1\fR,...]" 8 .IX Item "--architectures=native[,foreign1,...]" Comma or whitespace separated list of architectures. The first architecture is the \fInative\fR architecture inside the chroot. The remaining architectures will be added to the foreign dpkg architectures. Without this option, the \fInative\fR architecture of the chroot defaults to the native architecture of the system running \fBmmdebstrap\fR. 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: .Sp .Vb 3 \& \-\-architectures="amd64 armhf mipsel" \& \-\-architectures=amd64,armhf,mipsel \& \-\-arch=amd64 \-\-arch="armhf mipsel" \-\-arch=armhf,mipsel .Ve .IP "\fB\-\-simulate\fR, \fB\-\-dry\-run\fR" 8 .IX Item "--simulate, --dry-run" Run apt-get with \fB\-\-simulate\fR. 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 \fB\-\-simulate\fR or \fB\-\-dry\-run\fR. .IP "\fB\-\-setup\-hook\fR=\fIcommand\fR" 8 .IX Item "--setup-hook=command" Execute arbitrary \fIcommand\fRs 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 \fB\s-1HOOKS\s0\fR for more information. .Sp Example: Setup merged\-/usr via symlinks .Sp .Vb 2 \& \-\-setup\-hook=\*(Aqfor d in bin sbin lib; do ln \-s usr/$d "$1/$d"; \& mkdir \-p "$1/usr/$d"; done\*(Aq .Ve .Sp Example: Setup chroot for installing a sub-essential busybox-based chroot with \&\-\-variant=custom \&\-\-include=dpkg,busybox,libc\-bin,base\-files,base\-passwd,debianutils .Sp .Vb 6 \& \-\-setup\-hook=\*(Aqmkdir \-p "$1/bin"\*(Aq \& \-\-setup\-hook=\*(Aqfor p in awk cat chmod chown cp diff echo env grep less ln \& mkdir mount rm rmdir sed sh sleep sort touch uname; do \& ln \-s busybox "$1/bin/$p"; done\*(Aq \& \-\-setup\-hook=\*(Aqecho root:x:0:0:root:/root:/bin/sh > "$1/etc/passwd"\*(Aq \& \-\-setup\-hook=\*(Aqprintf "root:x:0:\enmail:x:8:\enutmp:x:43:\en" > "$1/etc/group"\*(Aq .Ve .IP "\fB\-\-extract\-hook\fR=\fIcommand\fR" 8 .IX Item "--extract-hook=command" Execute arbitrary \fIcommand\fRs after the Essential:yes packages have been extracted but before installing them. See section \fB\s-1HOOKS\s0\fR for more information. .Sp Example: Install busybox symlinks .Sp .Vb 1 \& \-\-extract\-hook=\*(Aqchroot "$1" busybox \-\-install \-s\*(Aq .Ve .IP "\fB\-\-essential\-hook\fR=\fIcommand\fR" 8 .IX Item "--essential-hook=command" Execute arbitrary \fIcommand\fRs after the Essential:yes packages have been installed but before installing the remaining packages. The hook is not executed for the \fBextract\fR and \fBcustom\fR variants. See section \fB\s-1HOOKS\s0\fR for more information. .Sp Example: Enable unattended upgrades .Sp .Vb 3 \& \-\-essential\-hook=\*(Aqecho unattended\-upgrades \& unattended\-upgrades/enable_auto_updates boolean true \& | chroot "$1" debconf\-set\-selections\*(Aq .Ve .Sp Example: Select Europe/Berlin as the timezone .Sp .Vb 4 \& \-\-essential\-hook=\*(Aqecho tzdata tzdata/Areas select Europe \& | chroot "$1" debconf\-set\-selections\*(Aq \& \-\-essential\-hook=\*(Aqecho tzdata tzdata/Zones/Europe select Berlin \& | chroot "$1" debconf\-set\-selections\*(Aq .Ve .IP "\fB\-\-customize\-hook\fR=\fIcommand\fR" 8 .IX Item "--customize-hook=command" Execute arbitrary \fIcommand\fRs after the chroot is set up and all packages got installed but before final cleanup actions are carried out. See section \&\fB\s-1HOOKS\s0\fR for more information. .Sp Example: Preparing a chroot for use with autopkgtest .Sp .Vb 7 \& \-\-customize\-hook=\*(Aqchroot "$1" passwd \-\-delete root\*(Aq \& \-\-customize\-hook=\*(Aqchroot "$1" useradd \-\-home\-dir /home/user \& \-\-create\-home user\*(Aq \& \-\-customize\-hook=\*(Aqchroot "$1" passwd \-\-delete user\*(Aq \& \-\-customize\-hook=\*(Aqecho host > "$1/etc/hostname"\*(Aq \& \-\-customize\-hook=\*(Aqecho "127.0.0.1 localhost host" > "$1/etc/hosts"\*(Aq \& \-\-customize\-hook=/usr/share/autopkgtest/setup\-commands/setup\-testbed .Ve .IP "\fB\-\-hook\-directory\fR=\fIdirectory\fR" 8 .IX Item "--hook-directory=directory" Execute scripts in \fIdirectory\fR with filenames starting with \f(CW\*(C`setup\*(C'\fR, \&\f(CW\*(C`extract\*(C'\fR, \f(CW\*(C`essential\*(C'\fR or \f(CW\*(C`customize\*(C'\fR, 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 \f(CW\*(C`./hooks\*(C'\fR with two scripts \&\f(CW\*(C`setup01\-foo.sh\*(C'\fR and \f(CW\*(C`setup01\-bar.sh\*(C'\fR, this call: .Sp .Vb 1 \& mmdebstrap \-\-customize=./scriptA \-\-hook\-dir=./hooks \-\-setup=./scriptB .Ve .Sp is equivalent to this call: .Sp .Vb 2 \& mmdebstrap \-\-customize=./scriptA \-\-setup=./hooks/setup01\-foo.sh \e \& \-\-setup=./hooks/setup02\-bar.sh \-\-setup=./scriptB .Ve .Sp 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. .Sp Example: Run mmdebstrap with eatmydata .Sp .Vb 1 \& \-\-hook\-dir=/usr/share/mmdebstrap/hooks/eatmydata .Ve .IP "\fB\-\-skip\fR=\fIstage\fR[,\fIstage\fR,...]" 8 .IX Item "--skip=stage[,stage,...]" \&\fBmmdebstrap\fR 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 \fB\s-1OPERATION\s0\fR for a list of possible arguments and their context. .IP "\fB\-q,\-\-quiet\fR, \fB\-s,\-\-silent\fR" 8 .IX Item "-q,--quiet, -s,--silent" Do not write anything to standard error. If used together with \fB\-\-verbose\fR or \&\fB\-\-debug\fR, only the last option will take effect. .IP "\fB\-v,\-\-verbose\fR" 8 .IX Item "-v,--verbose" Instead of progress bars, write the dpkg and apt output directly to standard error. If used together with \fB\-\-quiet\fR or \fB\-\-debug\fR, only the last option will take effect. .IP "\fB\-d,\-\-debug\fR" 8 .IX Item "-d,--debug" In addition to the output produced by \fB\-\-verbose\fR, write detailed debugging information to standard error. Errors will print a backtrace. If used together with \fB\-\-quiet\fR or \fB\-\-verbose\fR, only the last option will take effect. .IP "\fB\-\-logfile\fR=\fIfilename\fR" 8 .IX Item "--logfile=filename" Instead of writing status information to standard error, write it into the file given by \fIfilename\fR. .SH "MODES" .IX Header "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. .IP "\fBauto\fR" 8 .IX Item "auto" This mode automatically selects a fitting mode. If the effective user id is the one of the superuser, then the \fBsudo\fR mode is chosen. Otherwise, the \&\fBunshare\fR mode is picked if the system has the sysctl \&\f(CW\*(C`kernel.unprivileged_userns_clone\*(C'\fR set to \f(CW1\fR. Should that not be the case and if the fakechroot binary exists, the \fBfakechroot\fR mode is chosen. Lastly, the \fBproot\fR mode is used if the proot binary exists. .IP "\fBsudo\fR, \fBroot\fR" 8 .IX Item "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 \f(CW\*(C`SYS_CAP_ADMIN\*(C'\fR. .IP "\fBunshare\fR" 8 .IX Item "unshare" 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 should be bit-by-bit identical to a tarball created with the \fBroot\fR mode. In Debian, this mode requires the sysctl \&\f(CW\*(C`kernel.unprivileged_userns_clone\*(C'\fR being set to \f(CW1\fR. The default used to be \&\f(CW0\fR but was changed to \f(CW1\fR with linux 5.10.1 or Debian 11 (Bullseye). \&\fB\s-1SETTING THIS OPTION TO 1 HAS SECURITY IMPLICATIONS\s0\fR. Refer to .Sp A directory chroot created with this mode will end up with wrong ownership information. For correct ownership information, the directory must be accessed from a user namespace with the right subuid/subgid offset, like so: .Sp .Vb 2 \& $ lxc\-usernsexec \-\- lxc\-unshare \-s \*(AqMOUNT|PID|UTSNAME|IPC\*(Aq \-\- \e \& > /usr/sbin/chroot ./debian\-rootfs /bin/bash .Ve .Sp Or without \s-1LXC:\s0 .Sp .Vb 1 \& $ mmdebstrap \-\-unshare\-helper /usr/sbin/chroot ./debian\-rootfs /bin/bash .Ve .Sp Or, if you don't mind using superuser privileges and have systemd-nspawn available and you know your subuid/subgid offset (100000 in this example): .Sp .Vb 2 \& $ sudo systemd\-nspawn \-\-private\-users=100000 \e \& > \-\-directory=./debian\-rootfs /bin/bash .Ve .Sp 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. .IP "\fBfakeroot\fR, \fBfakechroot\fR" 8 .IX Item "fakeroot, fakechroot" This mode will exec \fBmmdebstrap\fR again under \f(CW\*(C`fakechroot fakeroot\*(C'\fR. A directory chroot created with this mode will end up with wrong permissions. If you need a directory then run \fBmmdebstrap\fR under \f(CW\*(C`fakechroot fakeroot \-s fakeroot.env\*(C'\fR and use \f(CW\*(C`fakeroot.env\*(C'\fR later when entering the chroot with \&\f(CW\*(C`fakechroot fakeroot \-i fakeroot.env chroot ...\*(C'\fR. This mode will not work if maintainer scripts are unable to handle \f(CW\*(C`LD_PRELOAD\*(C'\fR correctly like the package \fBinitramfs-tools\fR until version 0.132. This mode will also not work with a different libc inside the chroot than on the outside. Since ldconfig cannot run under fakechroot, the final system will not contain \&\fI/etc/ld.so.cache\fR. See the section \fB\s-1LIMITATIONS\s0\fR in \fB\fBfakechroot\fB\|(1)\fR. .IP "\fBproot\fR" 8 .IX Item "proot" This mode will carry out all calls to chroot with proot instead. Since ownership information is only retained while proot is still running, this will lead to wrong ownership information in the final directory (everything will be owned by the user that executed \fBmmdebstrap\fR) and tarball (everything will be owned by the root user). Extended attributes are not retained. This mode is useful if you plan to use the chroot with proot. .IP "\fBchrootless\fR" 8 .IX Item "chrootless" Uses the dpkg option \f(CW\*(C`\-\-force\-script\-chrootless\*(C'\fR to install packages into \&\fI\s-1TARGET\s0\fR without dpkg and apt inside \fI\s-1TARGET\s0\fR but using apt and dpkg from the machine running \fBmmdebstrap\fR. Maintainer scripts are run without chrooting into \fI\s-1TARGET\s0\fR and rely on their dependencies being installed on the machine running \fBmmdebstrap\fR. Unless \fBmmdebstrap\fR was run inside fakeroot, the \&\fI\s-1TARGET\s0\fR directory will be owned by the user running \fBmmdebstrap\fR. \&\fB\s-1WARNING\s0\fR: if this option is used carelessly with packages that do not support \&\f(CW\*(C`DPKG_ROOT\*(C'\fR, this mode can result in undesired changes to the system running \&\fBmmdebstrap\fR because maintainer-scripts will be run without \fB\fBchroot\fB\|(1)\fR. .SH "VARIANTS" .IX Header "VARIANTS" All package sets also include the direct and indirect hard dependencies (but not recommends) of the selected package sets. The variants \fBminbase\fR, \&\fBbuildd\fR and \fB\-\fR, resemble the package sets that debootstrap would install with the same \fI\-\-variant\fR argument. If multiple releases are passed as apt sources to \fBmmdebstrap\fR, then the release with a name matching the \fI\s-1SUITE\s0\fR argument will be used to determine the \f(CW\*(C`Essential:yes\*(C'\fR and priority values. .IP "\fBextract\fR" 8 .IX Item "extract" Installs nothing by default (not even \f(CW\*(C`Essential:yes\*(C'\fR packages). Packages given by the \f(CW\*(C`\-\-include\*(C'\fR option are extracted but will not be installed. .IP "\fBcustom\fR" 8 .IX Item "custom" Installs nothing by default (not even \f(CW\*(C`Essential:yes\*(C'\fR packages). Packages given by the \f(CW\*(C`\-\-include\*(C'\fR option will be installed. If another mode than \&\fBchrootless\fR was selected and dpkg was not part of the included package set, then this variant will fail because it cannot configure the packages. .IP "\fBessential\fR" 8 .IX Item "essential" \&\f(CW\*(C`Essential:yes\*(C'\fR packages. .IP "\fBapt\fR" 8 .IX Item "apt" The \fBessential\fR set plus apt. .IP "\fBrequired\fR, \fBminbase\fR" 8 .IX Item "required, minbase" The \fBessential\fR set plus all packages with Priority:required and apt. .IP "\fBbuildd\fR" 8 .IX Item "buildd" The \fBminbase\fR set plus build-essential. .IP "\fBimportant\fR, \fBdebootstrap\fR, \fB\-\fR" 8 .IX Item "important, debootstrap, -" The \fBrequired\fR set plus all packages with Priority:important. This is the default of debootstrap. .IP "\fBstandard\fR" 8 .IX Item "standard" The \fBimportant\fR set plus all packages with Priority:standard. .SH "FORMATS" .IX Header "FORMATS" The output format of \fBmmdebstrap\fR is specified using the \fB\-\-format\fR option. Without that option the default format is \fIauto\fR. The following formats exist: .IP "\fBauto\fR" 8 .IX Item "auto" When selecting this format (the default), the actual format will be inferred from the \fI\s-1TARGET\s0\fR positional argument. If \fI\s-1TARGET\s0\fR was not specified, then the \fBtar\fR format will be chosen. If \fI\s-1TARGET\s0\fR is an existing directory, and does not equal to \f(CW\*(C`\-\*(C'\fR, then the \fBdirectory\fR format will be chosen. If \&\fI\s-1TARGET\s0\fR ends with \f(CW\*(C`.tar\*(C'\fR or with one of the filename extensions listed in the section \fB\s-1COMPRESSION\s0\fR, or if \fI\s-1TARGET\s0\fR equals \f(CW\*(C`\-\*(C'\fR, or if \fI\s-1TARGET\s0\fR is a named pipe (fifo) or if \fI\s-1TARGET\s0\fR is a character special file like \&\fI/dev/null\fR, then the \fBtar\fR format will be chosen. If \fI\s-1TARGET\s0\fR ends with \&\f(CW\*(C`.squashfs\*(C'\fR or \f(CW\*(C`.sqfs\*(C'\fR, then the \fBsquashfs\fR format will be chosen. If <\s-1TARGET\s0> ends with \f(CW\*(C`.ext2\*(C'\fR then the \fBext2\fR format will be chosen. If none of these conditions apply, the \fBdirectory\fR format will be chosen. .IP "\fBdirectory\fR, \fBdir\fR" 8 .IX Item "directory, dir" A chroot directory will be created in \fI\s-1TARGET\s0\fR. If the directory already exists, it must either be empty or only contain an empty \f(CW\*(C`lost+found\*(C'\fR directory. The special \fI\s-1TARGET\s0\fR \f(CW\*(C`\-\*(C'\fR does not work with this format because a directory cannot be written to standard output. If you need your directory be named \f(CW\*(C`\-\*(C'\fR, then just explicitly pass the relative path to it like \fI./\-\fR. If a directory is chosen as output in any other mode than \fBsudo\fR, then its contents will have wrong ownership information and special device files will be missing. Refer to the section \fB\s-1MODES\s0\fR for more information. .IP "\fBtar\fR" 8 .IX Item "tar" A temporary chroot directory will be created in \f(CW$TMPDIR\fR or \fI/tmp\fR if \&\f(CW$TMPDIR\fR is not set. A tarball of that directory will be stored in \fI\s-1TARGET\s0\fR or sent to standard output if \fI\s-1TARGET\s0\fR was omitted or if \fI\s-1TARGET\s0\fR equals \&\f(CW\*(C`\-\*(C'\fR. If \fI\s-1TARGET\s0\fR ends with one of the filename extensions listed in the section \fB\s-1COMPRESSION\s0\fR, then a compressed tarball will be created. The tarball will be in \s-1POSIX 1003.1\-2001\s0 (pax) format and will contain extended attributes. To preserve the extended attributes, you have to pass \fB\-\-xattrs \&\-\-xattrs\-include='*'\fR to tar when extracting the tarball. .IP "\fBsquashfs\fR, \fBsqfs\fR" 8 .IX Item "squashfs, sqfs" A temporary chroot directory will be created in \f(CW$TMPDIR\fR or \fI/tmp\fR if \&\f(CW$TMPDIR\fR is not set. A tarball of that directory will be piped to the \&\f(CW\*(C`tar2sqfs\*(C'\fR utility, which will create an xz compressed squashfs image with a blocksize of 1048576 bytes in \fI\s-1TARGET\s0\fR. The special \fI\s-1TARGET\s0\fR \f(CW\*(C`\-\*(C'\fR does not work with this format because \f(CW\*(C`tar2sqfs\*(C'\fR can only write to a regular file. If you need your squashfs image be named \f(CW\*(C`\-\*(C'\fR, then just explicitly pass the relative path to it like \fI./\-\fR. Since \f(CW\*(C`tar2sqfs\*(C'\fR does not support extended attributes, the resulting image will not contain them. .IP "\fBext2\fR" 8 .IX Item "ext2" A temporary chroot directory will be created in \f(CW$TMPDIR\fR or \fI/tmp\fR if \&\f(CW$TMPDIR\fR is not set. A tarball of that directory will be piped to the \&\f(CW\*(C`genext2fs\*(C'\fR utility, which will create an ext2 image that will be approximately 90% full in \fI\s-1TARGET\s0\fR. The special \fI\s-1TARGET\s0\fR \f(CW\*(C`\-\*(C'\fR does not work with this format because \f(CW\*(C`genext2fs\*(C'\fR can only write to a regular file. If you need your ext2 image be named \f(CW\*(C`\-\*(C'\fR, then just explicitly pass the relative path to it like \fI./\-\fR. To convert the result to an ext3 image, use \f(CW\*(C`tune2fs \-O has_journal TARGET\*(C'\fR and to convert it to ext4, use \f(CW\*(C`tune2fs \-O extents,uninit_bg,dir_index,has_journal TARGET\*(C'\fR. Since \f(CW\*(C`genext2fs\*(C'\fR does not support extended attributes, the resulting image will not contain them. .SH "HOOKS" .IX Header "HOOKS" This section describes properties of the hook options \fB\-\-setup\-hook\fR, \&\fB\-\-extract\-hook\fR, \fB\-\-essential\-hook\fR and \fB\-\-customize\-hook\fR which are common to all four of them. Any information specific to each hook is documented under the specific hook options in the section \fB\s-1OPTIONS\s0\fR. .PP 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 \f(CW\*(C`copy\-in\*(C'\fR, \f(CW\*(C`copy\-out\*(C'\fR, \f(CW\*(C`tar\-in\*(C'\fR, \f(CW\*(C`tar\-out\*(C'\fR, \f(CW\*(C`upload\*(C'\fR or \&\f(CW\*(C`download\*(C'\fR followed by a space, then the hook is interpreted as a special hook. Otherwise, if \fIcommand\fR is an existing executable file from \f(CW$PATH\fR or if \fIcommand\fR does not contain any shell metacharacters, then \fIcommand\fR is directly exec-ed with the path to the chroot directory passed as the first argument. Otherwise, \fIcommand\fR is executed under \fIsh\fR and the chroot directory can be accessed via \fI\f(CI$1\fI\fR. All environment variables set by \&\fBmmdebstrap\fR (like \f(CW\*(C`APT_CONFIG\*(C'\fR, \f(CW\*(C`DEBIAN_FRONTEND\*(C'\fR, \f(CW\*(C`LC_ALL\*(C'\fR and \f(CW\*(C`PATH\*(C'\fR) are preserved. All environment variables set by the user are preserved, except for \f(CW\*(C`TMPDIR\*(C'\fR which is cleared. .PP 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 \&\fBmmdebstrap\fR invocation. The path inside the chroot must already exist. Paths outside the chroot are created as necessary. .PP In \fBfakechroot\fR and \fBproot\fR mode, \f(CW\*(C`tar\*(C'\fR, or \f(CW\*(C`sh\*(C'\fR and \f(CW\*(C`cat\*(C'\fR 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 \&\fBfakechroot\fR and \fBproot\fR mode for the \fBsetup\fR hook or for the \fBextract\fR and \&\fBcustom\fR variants if no \f(CW\*(C`tar\*(C'\fR or \f(CW\*(C`sh\*(C'\fR and \f(CW\*(C`cat\*(C'\fR is available inside the chroot. .IP "\fBcopy-out\fR \fIpathinside\fR [\fIpathinside\fR ...] \fIpathoutside\fR" 8 .IX Item "copy-out pathinside [pathinside ...] pathoutside" Recursively copies one or more files and directories recursively from \&\fIpathinside\fR inside the chroot to \fIpathoutside\fR outside of the chroot. .IP "\fBcopy-in\fR \fIpathoutside\fR [\fIpathoutside\fR ...] \fIpathinside\fR" 8 .IX Item "copy-in pathoutside [pathoutside ...] pathinside" Recursively copies one or more files and directories into the chroot into, placing them into \fIpathinside\fR inside of the chroot. .IP "\fBsync-out\fR \fIpathinside\fR \fIpathoutside\fR" 8 .IX Item "sync-out pathinside pathoutside" Recursively copy everything inside \fIpathinside\fR inside the chroot into \&\fIpathoutside\fR. In contrast to \fBcopy-out\fR, this command synchronizes the content of \fIpathinside\fR with the content of \fIpathoutside\fR without deleting anything from \fIpathoutside\fR but overwriting content as necessary. Use this command over \fBcopy-out\fR if you don't want to create a new directory outside the chroot but only update the content of an existing directory. .IP "\fBsync-in\fR \fIpathoutside\fR \fIpathinside\fR" 8 .IX Item "sync-in pathoutside pathinside" Recursively copy everything inside \fIpathoutside\fR into \fIpathinside\fR inside the chroot. In contrast to \fBcopy-in\fR, this command synchronizes the content of \&\fIpathoutside\fR with the content of \fIpathinside\fR without deleting anything from \&\fIpathinside\fR but overwriting content as necessary. Use this command over \&\fBcopy-in\fR if you don't want to create a new directory inside the chroot but only update the content of an existing directory. .IP "\fBtar-in\fR \fIoutside.tar\fR \fIpathinside\fR" 8 .IX Item "tar-in outside.tar pathinside" Unpacks a tarball \fIoutside.tar\fR from outside the chroot into a certain location \fIpathinside\fR inside the chroot. .IP "\fBtar-out\fR \fIpathinside\fR \fIoutside.tar\fR" 8 .IX Item "tar-out pathinside outside.tar" Packs the path \fIpathinside\fR from inside the chroot into a tarball, placing it into a certain location \fIoutside.tar\fR outside the chroot. .IP "\fBdownload\fR \fIfileinside\fR \fIfileoutside\fR" 8 .IX Item "download fileinside fileoutside" Copy the file given by \fIfileinside\fR from inside the chroot to outside the chroot as \fIfileoutside\fR. In contrast to \fBcopy-out\fR, this command only handles files and not directories. To copy a directory recursively out of the chroot, use \fBcopy-out\fR or \fBtar-out\fR. 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. .IP "\fBupload\fR \fIfileoutside\fR \fIfileinside\fR" 8 .IX Item "upload fileoutside fileinside" Copy the file given by \fIfileoutside\fR from outside the chroot to inside the chroot as \fIfileinside\fR. In contrast to \fBcopy-in\fR, this command only handles files and not directories. To copy a directory recursively into the chroot, use \fBcopy-in\fR or \fBtar-in\fR. 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. .SH "OPERATION" .IX Header "OPERATION" This section gives an overview of the different steps to create a chroot. .IP "\fBcheck\fR" 8 .IX Item "check" Upon startup, several checks are carried out, like: .RS 8 .IP "\(bu" 4 whether required utilities (apt, dpkg, tar) are installed .IP "\(bu" 4 which mode to use and whether prerequisites are met .IP "\(bu" 4 if you are root, check whether you have the ability to mount. This check requires the \f(CW\*(C`unshare\*(C'\fR program from the \f(CW\*(C`util\-linux\*(C'\fR package and can be disabled by using \fB\-\-skip=check/canmount\fR. .IP "\(bu" 4 whether the requested architecture can be executed (requires arch-test) using qemu binfmt_misc support. This requires arch-test and can be disabled using \fB\-\-skip=check/qemu\fR .IP "\(bu" 4 how the apt sources can be assembled from \fI\s-1SUITE\s0\fR, \fI\s-1MIRROR\s0\fR and \fB\-\-components\fR and/or from standard input as deb822 or one-line format and whether the required \s-1GPG\s0 keys exist. .IP "\(bu" 4 which output format to pick depending on the \fB\-\-format\fR argument or name of \fI\s-1TARGET\s0\fR or its type. .IP "\(bu" 4 whether the output directory is empty. This check can be disabled using \fB\-\-skip=check/empty\fR .RE .RS 8 .RE .IP "\fBsetup\fR" 8 .IX Item "setup" The following tasks are carried out: .RS 8 .IP "\(bu" 4 create required directories .IP "\(bu" 4 write out the temporary apt config file .IP "\(bu" 4 populates \fI/etc/apt/apt.conf.d/99mmdebstrap\fR and \fI/etc/dpkg/dpkg.cfg.d/99mmdebstrap\fR with config options from \fB\-\-aptopt\fR and \fB\-\-dpkgopt\fR, respectively .IP "\(bu" 4 write out \fI/etc/apt/sources.list\fR .IP "\(bu" 4 copy over \fI/etc/resolv.conf\fR and \fI/etc/hostname\fR .IP "\(bu" 4 populate \fI/dev\fR if mknod is possible .RE .RS 8 .RE .IP "\fBsetup-hook\fR" 8 .IX Item "setup-hook" Run \fB\-\-setup\-hook\fR options and all \fIsetup*\fR scripts in \fB\-\-hook\-dir\fR. .IP "\fBupdate\fR" 8 .IX Item "update" Runs \f(CW\*(C`apt\-get update\*(C'\fR using the temporary apt configuration file created in the \fBsetup\fR step. .IP "\fBdownload\fR" 8 .IX Item "download" Checks whether \fI/var/cache/apt/archives/\fR is empty. This can be disabled with \&\fB\-\-skip=download/empty\fR. In the \fBextract\fR and \fBcustom\fR variants, \f(CW\*(C`apt\-get \&\-\-download\-only install\*(C'\fR is used to download all the packages requested via the \&\fB\-\-include\fR option. The \fBapt\fR variant uses the fact that libapt treats the \&\f(CW\*(C`apt\*(C'\fR packages as implicitly essential to download only all \f(CW\*(C`Essential:yes\*(C'\fR packages plus apt using \f(CW\*(C`apt\-get \-\-download\-only dist\-upgrade\*(C'\fR. In the remaining variants, all Packages files downloaded by the \fBupdate\fR step are inspected to find the \f(CW\*(C`Essential:yes\*(C'\fR package set as well as all packages of the required priority. .IP "\fBextract\fR" 8 .IX Item "extract" Extract the downloaded packages into the rootfs. This step is not carried out in chrootless mode if the variant is not \fBextract\fR. .IP "\fBextract-hook\fR" 8 .IX Item "extract-hook" Run \fB\-\-extract\-hook\fR options and all \fIextract*\fR scripts in \fB\-\-hook\-dir\fR. .IP "\fBprepare\fR" 8 .IX Item "prepare" In \fBfakechroot\fR mode, environment variables \f(CW\*(C`LD_LIBRARY_PATH\*(C'\fR will be set up correctly. If the chroot requires the qemu-user-static binary it will be copied in. For foreign \fBfakechroot\fR environments, \f(CW\*(C`LD_LIBRARY_PATH\*(C'\fR and \&\f(CW\*(C`QEMU_LD_PREFIX\*(C'\fR are set up accordingly. This step is not carried out in >\fBextract\fR mode and neither for the \fBchrootless\fR variant. .IP "\fBessential\fR" 8 .IX Item "essential" Uses \f(CW\*(C`dpkg \-\-install\*(C'\fR to properly install all packages that have been extracted before. Removes all packages downloaded in the \fBdownload\fR step, except those which were present in \fI/var/cache/apt/archives/\fR before (if any). This can be disabled using \fB\-\-skip=essential/unlink\fR. This step is not carried out in \fBextract\fR mode. .IP "\fBessential-hook\fR" 8 .IX Item "essential-hook" Run \fB\-\-essential\-hook\fR options and all \fIessential*\fR scripts in \fB\-\-hook\-dir\fR. This step is not carried out in \fBextract\fR mode. .IP "\fBinstall\fR" 8 .IX Item "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 \fBextract\fR mode. .IP "\fBcustomize-hook\fR" 8 .IX Item "customize-hook" Run \fB\-\-customize\-hook\fR options and all \fIcustomize*\fR scripts in \fB\-\-hook\-dir\fR. This step is not carried out in \fBextract\fR mode. .IP "\fBcleanup\fR" 8 .IX Item "cleanup" Performs cleanup tasks like: .RS 8 .IP "\(bu" 4 Removes the package lists and apt cache. This can be disabled using \fB\-\-skip=cleanup/apt\fR. .IP "\(bu" 4 Remove all files that were put into the chroot for setup purposes, like \fI/etc/apt/apt.conf.d/00mmdebstrap\fR, the temporary apt config and the qemu-user-static binary. This can be disabled using \fB\-\-skip=cleanup/mmdebstrap\fR. .IP "\(bu" 4 Remove all files that make the result unreproducible, like apt and dpkg logs and caches or \fI/etc/machine\-id\fR. This can be disabled using \fB\-\-skip=cleanup/reproducible\fR .IP "\(bu" 4 Remove everything in \fI/tmp\fR inside the chroot. This can be disabled using \fB\-\-skip=cleanup/tmp\fR. .RE .RS 8 .Sp For formats other than \fBdirectory\fR, pack up the temporary chroot directory into a tarball, ext2 image or squashfs image and delete the temporary chroot directory. .RE .SH "EXAMPLES" .IX Header "EXAMPLES" Use like debootstrap: .PP .Vb 1 \& $ sudo mmdebstrap unstable ./unstable\-chroot .Ve .PP Without superuser privileges: .PP .Vb 1 \& $ mmdebstrap unstable unstable\-chroot.tar .Ve .PP With no command line arguments at all. The chroot content is entirely defined by a sources.list file on standard input. .PP .Vb 1 \& $ mmdebstrap < /etc/apt/sources.list > unstable\-chroot.tar .Ve .PP 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: .PP .Vb 1 \& $ mmdebstrap unstable | tar \-\-delete ./dev > unstable\-chroot.tar .Ve .PP Instead of a tarball, a squashfs image can be created: .PP .Vb 1 \& $ mmdebstrap unstable unstable\-chroot.squashfs .Ve .PP By default, \fBmmdebstrap\fR runs \fBtar2sqfs\fR with \f(CW\*(C`\-\-no\-skip \-\-exportable \&\-\-compressor xz \-\-block\-size 1048576\*(C'\fR. To choose a different set of options, pipe the output of \fBmmdebstrap\fR into \fBtar2sqfs\fR manually. .PP By default, debootstrapping a stable distribution will add mirrors for security and updates to the sources.list. .PP .Vb 1 \& $ mmdebstrap stable stable\-chroot.tar .Ve .PP If you don't want this behaviour, you can override it by manually specifying a mirror in various different ways: .PP .Vb 4 \& $ 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 .Ve .PP 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). .PP .Vb 9 \& $ mmdebstrap \-\-variant=essential \e \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/man/*\*(Aq \e \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/man/man[1\-9]/*\*(Aq \e \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/locale/*\*(Aq \e \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/locale/locale.alias\*(Aq \e \& \-\-dpkgopt=\*(Aqpath\-exclude=/usr/share/doc/*\*(Aq \e \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/doc/*/copyright\*(Aq \e \& \-\-dpkgopt=\*(Aqpath\-include=/usr/share/doc/*/changelog.Debian.*\*(Aq \e \& unstable debian\-unstable.tar .Ve .PP Create a bootable \s-1USB\s0 Stick that boots into a full Debian desktop: .PP .Vb 10 \& $ mmdebstrap \-\-aptopt=\*(AqApt::Install\-Recommends "true"\*(Aq \-\-customize\-hook \e \& \*(Aqchroot "$1" adduser \-\-gecos user \-\-disabled\-password user\*(Aq \e \& \-\-customize\-hook=\*(Aqecho \*(Aquser:live\*(Aq | chroot "$1" chpasswd\*(Aq \e \& \-\-customize\-hook=\*(Aqecho host > "$1/etc/hostname"\*(Aq \e \& \-\-customize\-hook=\*(Aqecho "127.0.0.1 localhost host" > "$1/etc/hosts"\*(Aq \e \& \-\-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 : \e \& part\-set\-bootable /dev/sda 1 true : mkfs ext2 /dev/sda1 : \e \& set\-label /dev/sda1 rootfs : mount /dev/sda1 / : \e \& tar\-in debian\-unstable.tar / xattrs:true : \e \& upload /usr/lib/SYSLINUX/mbr.bin /mbr.bin : \e \& copy\-file\-to\-device /mbr.bin /dev/sda size:440 : rm /mbr.bin : \e \& 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 .Ve .PP Build libdvdcss2.deb without installing installing anything or changing apt sources on the current system: .PP .Vb 5 \& $ mmdebstrap \-\-variant=apt \-\-components=main,contrib \-\-include=libdvd\-pkg \e \& \-\-customize\-hook=\*(Aqchroot $1 /usr/lib/libdvd\-pkg/b\-i_libdvdcss.sh\*(Aq \e \& | tar \-\-extract \-\-verbose \-\-strip\-components=4 \e \& \-\-wildcards \*(Aq./usr/src/libdvd\-pkg/libdvdcss2_*_*.deb\*(Aq \& $ ls libdvdcss2_*_*.deb .Ve .PP Use as replacement for autopkgtest-build-qemu and vmdb2: .PP .Vb 10 \& $ mmdebstrap \-\-variant=important \-\-include=linux\-image\-amd64 \e \& \-\-customize\-hook=\*(Aqchroot "$1" passwd \-\-delete root\*(Aq \e \& \-\-customize\-hook=\*(Aqchroot "$1" useradd \-\-home\-dir /home/user \-\-create\-home user\*(Aq \e \& \-\-customize\-hook=\*(Aqchroot "$1" passwd \-\-delete user\*(Aq \e \& \-\-customize\-hook=\*(Aqecho host > "$1/etc/hostname"\*(Aq \e \& \-\-customize\-hook=\*(Aqecho "127.0.0.1 localhost host" > "$1/etc/hosts"\*(Aq \e \& \-\-customize\-hook=/usr/share/autopkgtest/setup\-commands/setup\-testbed \e \& unstable debian\-unstable.tar \& $ cat << END > extlinux.conf \& > default linux \& > timeout 0 \& > \& > label linux \& > kernel /vmlinuz \& > append initrd=/initrd.img root=/dev/vda1 console=ttyS0 \& END \& $ guestfish \-N debian\-unstable.img=disk:8G \-\- \e \& part\-disk /dev/sda mbr : \e \& part\-set\-bootable /dev/sda 1 true : \e \& mkfs ext2 /dev/sda1 : mount /dev/sda1 / : \e \& tar\-in debian\-unstable.tar / xattrs:true : \e \& extlinux / : copy\-in extlinux.conf / : \e \& sync : umount / : shutdown \& $ qemu\-img convert \-O qcow2 debian\-unstable.img debian\-unstable.qcow2 .Ve .PP As a debootstrap wrapper to run it without superuser privileges but using Linux user namespaces instead. This fixes Debian bug #829134. .PP .Vb 3 \& $ mmdebstrap \-\-variant=custom \-\-mode=unshare \e \& \-\-setup\-hook=\*(Aqenv container=lxc debootstrap unstable "$1"\*(Aq \e \& \- debian\-debootstrap.tar .Ve .PP Build a non-Debian chroot like Ubuntu bionic: .PP .Vb 2 \& $ mmdebstrap \-\-aptopt=\*(AqDir::Etc::Trusted \& "/usr/share/keyrings/ubuntu\-keyring\-2012\-archive.gpg"\*(Aq bionic bionic.tar .Ve .PP If, for some reason, you cannot use a caching proxy like apt-cacher or apt-cacher-ng, you can use the \fBsync-in\fR and \fBsync-out\fR special hooks to synchronize a directory outside the chroot with \fI/var/cache/apt/archives\fR inside the chroot. .PP .Vb 5 \& $ mmdebstrap \-\-variant=apt \-\-skip=download/empty \-\-skip=essential/unlink \e \& \-\-setup\-hook=\*(Aqmkdir \-p ./cache "$1"/var/cache/apt/archives/\*(Aq \e \& \-\-setup\-hook=\*(Aqsync\-in ./cache /var/cache/apt/archives/\*(Aq \e \& \-\-customize\-hook=\*(Aqsync\-out /var/cache/apt/archives ./cache\*(Aq \e \& unstable /dev/null .Ve .PP Create a system that can be used with docker: .PP .Vb 5 \& $ mmdebstrap unstable | sudo docker import \- debian \& [...] \& $ sudo docker run \-it \-\-rm debian whoami \& root \& $ sudo docker rmi debian .Ve .SH "ENVIRONMENT VARIABLES" .IX Header "ENVIRONMENT VARIABLES" .ie n .IP """SOURCE_DATE_EPOCH""" 8 .el .IP "\f(CWSOURCE_DATE_EPOCH\fR" 8 .IX Item "SOURCE_DATE_EPOCH" By setting \f(CW\*(C`SOURCE_DATE_EPOCH\*(C'\fR the result will be reproducible over multiple runs with the same options and mirror content. .ie n .IP """TMPDIR""" 8 .el .IP "\f(CWTMPDIR\fR" 8 .IX Item "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 \fI/tmp\fR or the location pointed to by \f(CW\*(C`TMPDIR\*(C'\fR if that environment variable is set. .SH "DEBOOTSTRAP" .IX Header "DEBOOTSTRAP" This section lists some differences to debootstrap. .IP "\(bu" 8 More than one mirror possible .IP "\(bu" 8 Default mirrors for stable releases include updates and security mirror .IP "\(bu" 8 Multiple ways to operate as non-root: fakechroot, proot, unshare .IP "\(bu" 8 3\-6 times faster .IP "\(bu" 8 Can create a chroot with only \f(CW\*(C`Essential:yes\*(C'\fR packages and their deps .IP "\(bu" 8 Reproducible output by default if \f(CW$SOURCE_DATE_EPOCH\fR is set .IP "\(bu" 8 Can create output on filesystems with nodev set .IP "\(bu" 8 apt cache and lists are cleaned at the end .IP "\(bu" 8 foreign architecture chroots using qemu-user .PP Limitations in comparison to debootstrap: .IP "\(bu" 8 Only runs on systems with apt installed (Debian and derivatives) .IP "\(bu" 8 No \fI\s-1SCRIPT\s0\fR argument .IP "\(bu" 8 Some debootstrap options don't exist, namely: .Sp \&\fI\-\-second\-stage\fR, \fI\-\-exclude\fR, \fI\-\-resolve\-deps\fR, \fI\-\-force\-check\-gpg\fR, \&\fI\-\-merged\-usr\fR and \fI\-\-no\-merged\-usr\fR .SH "COMPRESSION" .IX Header "COMPRESSION" \&\fBmmdebstrap\fR will choose a suitable compressor for the output tarball depending on the filename extension. The following mapping from filename extension to compressor applies: .PP .Vb 10 \& 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 \-\-threads=0 \& .txz xz \-\-threads=0 \& .zst zstd .Ve .PP To change compression specific options, either use the respecitve environment variables like \fB\s-1XZ_OPT\s0\fR or send \fBmmdebstrap\fR output to your compressor of choice with a pipe. .SH "BUGS" .IX Header "BUGS" https://gitlab.mister\-muffin.de/josch/mmdebstrap/issues .PP https://bugs.debian.org/src:mmdebstrap .PP As of version 1.19.5, dpkg does not provide facilities preventing it from reading the dpkg configuration of the machine running \fBmmdebstrap\fR. Therefore, until this dpkg limitation is fixed, a default dpkg configuration is recommended on machines running \fBmmdebstrap\fR. If you are using \fBmmdebstrap\fR as the non-root user, then as a workaround you could run \f(CW\*(C`chmod 600 /etc/dpkg/dpkg.cfg.d/*\*(C'\fR so that the config files are only accessible by the root user. .PP Setting [trusted=yes] to allow signed archives without a known public key 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, \&\fBmmdebstrap\fR treats any warning from \*(L"apt-get update\*(R" as an error. Fixing this will require apt to provide a machine readable status interface. See Debian bugs #778357, #776152, #696335, and #745735. .SH "SEE ALSO" .IX Header "SEE ALSO" .Vb 1 \& debootstrap(8) .Ve