This also reworks the mirror specification for centos and related
distros to duplicate less code. gpgurls of the Repo() struct is also
made into a tuple instead of a list.
- Add some more information on what we're doing
- Move running modinfo and calculating dependencies out of the files()
generator so that the "Making cpio" step doesn't include running modinfo
and calculating the dependencies.
Let's run setfiles on the host instead of inside the image. To make
this work, we have to explicitly tell it to use the binary policy
from the image to check contexts against.
Rework user/mount namespace handling and tools tree
The biggest change is that instead of making bwrap() responsible
for mounting the tools tree, we do it ourselves before we build/boot
each image. We do the same for remounting the top level directories
read-only, instead of leaving it to bwrap(), we do it once at the
start of run_verb(). Because we now mess with the host system mounts
ourselves again, we also go back to unconditionally unsharing a mount
namespace, even when running as root.
With the above out of the way, there's no real reason left to run
regular executables with bwrap(), so those are moved back to be
executed using run(). The above changes also remove the need for
bwrap_cmd(), so it is merged back with bwrap() again.
One nasty caveat of overmounting /usr ourselves at the start of
execution is that some python modules are loaded dynamically and we
need to make sure this has happened before we start overmounting /usr.
Finally, this commit also gets rid of running the image build in a
subprocess. Instead, after doing the build and doing the final tools
tree mount for the image we're going to boot/qemu/ssh into, if we're
going to do an unprivleged operation, we change uid/gid to the invoking
user. This is more or less the same as running these operations unprivileged
outside of the user namespace.
For boot/shell, these only run privileged, so we check beforehand
that we're running as root, and this doesn't change after become_root(),
so since we're just root all the time, there's no need to run the image
build in a subprocess.
To keep ssh working, we have to trick it into recognizing our user in
the user namespace by overmounting /etc/passwd with a file containing
an entry for the mapped user uid.
We also unify more of the uid/gid handling in run_verb() in general.
Allow overriding the python interpreter used by mkosi
e.g. on CentOS 8 python3 is python 3.6. python 3.9 can be installed,
but it'll be installed as python3.9, so we need a way to override the
interpreter used by mkosi.
systemd on Fedora prefers to install util-linux-core instead of
util-linux which doesn't ship sulogin which makes starting
emergency.service enter an infinite loop. Let's make sure util-linux
is installed so sulogin is available in the initrd.
Add scripts support to bwrap() and use it for chrooting
The new scripts argument to bwrap() allows providing a mapping of
script names to command lines. Each of these becomes a script in a
directory that's prepended to PATH before executing the command
given to bwrap(). This allows us to make extra commands available
to scripts we execute with bwrap().
The first usage of this is to replace the extra argument which is
used to provide the extra arguments to chroot into the root directory.
Instead, we provide a chroot script and use that in the command line
we pass to bwrap() to perform the chroot.
Implement run_workspace_command() on top of bwrap()
Instead of duplicating the apivfs setup between bwrap() and
run_workspace_command(), let's make bwrap() responsible for setting
up the apivfs and implement chrooting on top of it. Specifically,
to chroot, we just run bwrap nested to do the chroot and any
additional setup before running the actual command. This is implemented
in the new chroot_cmd() function which returns the command to do the
chroot. This also sets the stage for running scripts on the host and
somehow providing the chroot_cmd() command to scripts to use themselves
to run something inside the root directory.
To keep --debug-shell working smoothly for scripts, we pass the chroot
command as a new extra argument to bwrap() so we can also apply it when
starting the debug shell.
We also rework the /etc/resolv.conf bind mounting so we don't have
to do any cleanup after the command finishes.
Replace kwargs from bwrap with individual arguments
kwargs makes it impossible for mypy to point out wrong arguments
so let's drop it in favor of individual arguments to get more out
of the type checker.
It only has to be in front of the cmd specific options, which in
our case was only --allowerasing, so since that's gone now, let's
put the command last again.
logdir= is always taken relative to the installroot. Let's leave it
at it's default value and remove any log files from the install root
after running dnf.
Beef up --kernel-command-line-extra= defaults a little bit
Let's provide a better experience out of the box when booting an image:
- Always blacklist vmw_vmci so it can't interfere with vsock
- Always pull in network-online.target
- Configure systemd-network-generator for enp0s1 and host0 if not
configured explicitly
- Use a default loglevel where only warnings or higher are logged to
the serial console by the kernel
- Set SYSTEMD_SULOGIN_FORCE=1 unless configured explicitly so users
get a shell in the initrd if something goes wrong, even if no root
password is configured
We generally don't use environment variables passed to the process,
but let's be a little more relaxed on this policy and make sure we
use any configured proxy variables so mkosi works out of the box on
servers behind a proxy.
CentOS Stream 9 is still on bwrap 0.4 which is unfortunately still
important so let's add back support for bwrap 0.4. Luckily, instead
of doing awkward template formatting, shells pass extra arguments
received when "-c" is used as arguments to the invoked command, so
we can make use of that to keep the same API for bwrap_cmd().
ubuntu: Enable universe repository by default on kinetic and later
From kinetic onwards, the usr-is-merged package is available and
has to be installed to get a proper usrmerge system but for some
reason it's in the universe repository so we enable the universe
repository by default from kinetic onwards so we can install the
usrmerge package.
Currently, when you want to build multiple projects together, you
have to make the other projects subdirectories of the one with the
mkosi config, which is inconvenient. To make this more flexible, let's
allow specifying multiple source trees and where to mount them under
/work/src so that multiple projects can be mounted in a fixed location
regardless of their location on the host.
centos: Add Special Interest Group (SIG) repositories
See https://wiki.centos.org/SpecialInterestGroup for more information
on SIGs. This commit only adds the Hyperscale SIG repositories. More can
be added later on an as-needed basis.
Protect common system directories when running with bubblewrap
Let's make sure that even when we run as root the tools we run
can't brick the system by making core system directories read-only
bind mounts when running tools with bubblewrap.
As an example of the stuff this protects again, let's say a package
installs an absolute symlink to /usr and in the finalize script a
user tries to remove everything under this symlink, they'll end up
erasing /usr from their host system. By making /usr read-only, we
prevent this from happening.
Currently, mkosi image builds can differ depending on the host they
were built from. This can happen because we execute all kinds of
binaries to build the image and depending on the host these binaries
can differ. Usually, it's different versions of tools causing issues,
but it can also be due to different build configurations, such as rpm
writing its database in a different format depending on whether it's
executed from CentOS, Fedora, or Opensuse.
To allow for more reproducibility in image builds regardless of the
host system, this commit adds a new option --tools-tree= that allows
specifying a tree in which we look up most of the programs that we
execute during an image build.
Of course, that still leaves the question of what tree should be passed
to --tools-tree=. To solve that problem, --tools-tree= can be used
together with presets, so that as the first preset, a "bootstrap" image
can be built which can then be used with --tools-tree= in later presets.
Note that we only use /usr from the given tree. If tools end up using
config files from /etc or such, we expect those tools to expose a knob
to specify a different configuration file (instead of us overmounting
/etc).
Note that in a few cases, we don't yet execute tools in the given tree:
- systemd-analyze in GenericVersion() can't be executed in the tree
because it could be executed during config parsing when we don't
know the tree to use yet.
- newuidmap/newgidmap have to be executed before we can run
bubblewrap so we can't run them in bubblewrap itself
- Figuring out the credentials is inherently tied to the host system
so we execute all scripts and tools to figure out credentials on
the host system as well
- mount because bubblewrap does not propagate mounts to the real root
so any mounts we do within bubblewrap don't survive the bubblewrap
process
- systemd-dissect for the same reason
Use stat tool to check if we're on a btrfs subsystem
Currently, we let the btrfs tool log errors when we're not on a
btrfs filesystem. Let's avoid unnecessary errors by checking if we're
on a btrfs filesystem before invoking the btrfs tool.
Drop shell workaround in bwrap() and run_workspace_command()
Let's use --perms and --chmod to fix the permissions of /tmp, /var/tmp
and /dev/shm instead of our hacky shell workaround. Let's also drop
all usage of shlex.join() in run() since it doesn't really by us anything.
Daan De Meyer [Tue, 27 Jun 2023 11:40:43 +0000 (13:40 +0200)]
Gentoo fixes
- Use boot use flag for systemd instead of gnuefi
- Add --deep to emerge invocation to fix dep resolution failures
- Use curl to download stage3 tarball so we get a progress bar
- Do not exclude dev, proc and sys directories when extracting tarball
(only exclude their contents)
- Copy pkgmngr/ directory into stage3/ directory wholesale instead of
individual files
- Various coding style fixes
- Stop using Repositories= to specify binary package repositories as it
is not its intended purpose. Instead, pass configured environment
variables to emerge so users can set PORTAGE_BINHOST instead.
Daan De Meyer [Tue, 27 Jun 2023 14:04:58 +0000 (16:04 +0200)]
Use systemd-repart's new --offline argument
When building images, we never want to use loop devices, so use
--offline=yes in that case. When booting images, we know that
systemd-nspawn requires loop devices, so require them for
systemd-repart as well using --offline=no.
Paymon MARANDI [Tue, 20 Jun 2023 15:41:05 +0000 (11:41 -0400)]
gentoo: hardcode stage3 path
2 more things:
- bring back cache_clean so we extract stage3 once. that also means
configure pkgmngr once
- add ./proc to exclusion list during extraction