[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Presenting DPKG_ROOT



Hi,

in 2016 we filed our first DPKG_ROOT patch #824594 against base-files. The dpkg
version at the time just had included support for the DPKG_ROOT variable being
set for maintainer scripts and we were excited to try out this new feature for
creating foreign architecture chroots. At the time we thought that no
discussion on d-devel was necessary before filing the bug because we knew only
10 source packages had to add DPKG_ROOT to their maintainer scripts and because
doing so would not affect any normal installation.

In hindsight, this was a mistake. We should've brought it up on d-devel and
explained our idea first before starting to file our bugs with patches. Luckily
in this very first bug, Santiago pushed back and requested to first see that
our concept really works before applying anything. This was excellent advice
and resulted in a CI job on salsa that regularly checks that Debian unstable
with our patches produces bit-by-bit identical chroots created with DPKG_ROOT
compared to chroots created the normal way. This proof of our method working
exactly as intended convinced Santiago and probably many other maintainers that
applied our patches to their source packages.

Today, six years later, all but two of our patches have been applied. The
transition is nearly complete.

So why are we (Helmut and me) writing you now that things are already done?

Firstly to apologize for having misjudged the situation in the past years. We
should've communicated DPKG_ROOT to all of d-devel at the very beginning to
allow for project wide discussion but decided not to do so. For that mistake we
are sorry.

Secondly, while we of course are hoping for a blessing of our contributions in
hindsight, we wanted to ask whether we maybe missed anything that makes our
DPKG_ROOT approach inferior to other ways to solve this problem. We also wanted
to ask about the scope of DPKG_ROOT. So what exactly is the problem we are
trying to solve?

In the very early days of a new architecture, emulation support is either not
available at all or too buggy to be useful for any practical purposes.  After
having cross-built the initial package set, these packages need to be installed
to create a chroot that can then be used to continue building packages natively
on the new architecture, completing the early bootstrap process. But creating
that chroot requires package maintainer scripts to be run but we cannot emulate
the new architecture to run any of its binaries. So how was this done in the
past? By performing the tasks that are usually carried out by package
maintainer scripts manually. We wanted to find a way that would allow for an
automatic creation of a foreign architecture chroot without being able to run
any of the binaries in it.

To solve this problem, since dpkg 1.18.10 (old-old-stable) the variable
`DPKG_ROOT` is set to the empty string in all maintainer script invocations.
All, except when dpkg is run with `--force-script-chrootless` and `--root` set
to a chroot directory path which will be stored in the `DPKG_ROOT` environment
variable. This is a “force” option because if set, dpkg will not do a chroot
call into the new chroot before calling the maintainer script, thus causing
undesired changes in the outer system instead. By installing packages in a way
that avoids the chroot call, maintainer scripts will run the tools from outside
the chroot instead of the foreign architecture tools inside the chroot.  These
tools need to know where they need to operate on and they use the value of the
`DPKG_ROOT` variable to get this information.

As of today, tools like dpkg-divert, dpkg-maintscript-helper,
deb-systemd-helper, or update-shells understand the `DPKG_ROOT` variable and
will do the right thing.  Maintainer script snippets as they are generated by
debhelper also already respect `DPKG_ROOT`. Where we need package-specific
patches is when maintainer scripts call general purpose tools like mv, cp,
chown or chmod, where it doesn’t make sense to let them support `DPKG_ROOT`
because those tools are not limited to be used in maintainer scripts. Source
packages in the Essential:yes and build-essential set that require changes
involving the `DPKG_ROOT` variable in their maintainer scripts are:

base-files, base-passwd, coreutils, dash, debianutils, dpkg, gcc-defaults,
glibc, pam, shadow

Usually, patches look like this:

https://bugs.debian.org/cgi-bin/bugreport.cgi?att=1;bug=983565;filename=coreutils_8.32-4.1.debdiff;msg=5

So if before the maintainer script ran `rm /usr/bin/touch` then it now runs `rm
"$DPKG_ROOT/usr/bin/touch"`. Since the `DPKG_ROOT` variable is usually empty,
this change will be a NO-OP in normal installations and only affects setups
that explicitly called dpkg in the way described above. Another way to support
`DPKG_ROOT` is to remove maintainer scripts altogether and replace them by
declarative methods, which was done in case of the transition from add-shell
and remove-shell to update-shells:
https://lists.debian.org/YMJTIrKQbjDjyZbP@alf.mars

We test our changes to source packages in a continuous integration environment
on salsa which regularly applies all remaining patches, rebuilds the package
and then creates a chroot tarball from them. This allows us to verify that
Debian unstable with our set of patches is able to create a foreign
architecture chroot tarball with `dpkg --force-script-chrootless` that is
bit-by-bit identical to a chroot tarball created the usual way:

https://salsa.debian.org/helmutg/dpkg-root-demo/-/jobs

As of today, we only are patching four source packages for all of this to work.
Most bugs we reported against source packages have been integrated as well with
only four remaining open bugs:

https://bugs.debian.org/cgi-bin/pkgreport.cgi?users=debian-dpkg@lists.debian.org;tag=dpkg-root-support

We will continue to report bugs with patches if any changes to the involved
package set breaks the `DPKG_ROOT` use-case. Our CI environment will make sure
that any such breakage will not go unnoticed.

Since the main driver for `DPKG_ROOT` is early architecture bootstraps where
foreign architecture emulation is not possible, these changes are limited to
the package set surrounding `Essential:yes` and `build-essential`. Since
`DPKG_ROOT` support is only needed for the initial bootstrap of a chroot
tarball, package upgrades are also out of scope right now.

Helmut's debconf22 talk goes into more detail about above concepts:
https://debconf22.debconf.org/talks/23-what-is-dpkg_root-and-what-is-it-not/

What do you think? Is this the right solution to the problem? A few more bits
about DPKG_ROOT as well as alternative solution proposals (including rejected
ones) can be found on this wiki page:

https://wiki.debian.org/Teams/Dpkg/Spec/InstallBootstrap#Proposal:_chrootless_maintscripts

So lets come back to our question of scope: Right now, our DPKG_ROOT patches
are limited to Essential:yes, build-essential, apt and systemd. We also
restrict the mechanism to initial installations only and upgrades are not
supported. We also currently require that the system (and its tools) on the
outside must be the same as the chroot that is being created with DPKG_ROOT. As
far as enabling very early architecture bootstrap goes, this solves the
problem.

So what do you think? Is this okay? Is there a better solution?

Thanks!

cheers, Helmut & josch

Attachment: signature.asc
Description: signature


Reply to: