Do not fail when writing root password and /etc/shadow is missing
I had this failure when testing https://github.com/systemd/mkosi/pull/1442. But
it would happen whenever the installed system has no /etc/shadow and we want to
set the password, so it's worth fixing regardless.
Fedora plans to switch to dnf5 for F40. For now, the new binary is called
'dnf5', and the old 'dnf'. Let's try to call 'dnf5' if available. It is
generally faster. E.g.
'mkosi build' in the mkosi directory after all packages have been downloaded:
950 ms with dnf5
1350 ms with dnf
Dnf5 also doesn't download file metadata by default, so it'll be faster if
downloads are necessary too.
Let's try the new shiny to save some time on installations.
For some reason, dnf5 doesn't like it if command options are before the
command. Old dnf is fine with either order, so let's just move the command
earlier.
Package managers have the annoying quirk that they use the user
and group information from the host system instead of the user and
group information from the chroot. As a workaround, in
run_with_apivfs(), let's overmount the files from the host with the
ones from the root if they exist.
Let's also always install a distribution in 2 steps. First, we install
the package that provides passwd. Then, we install the rest of the
packages, during which passwd and related files will be overmounted.
Let's move most of the logic related to installing packages into
install_packages() for each distribution, and only keep the first
time installation stuff in install(). This allows us to move most
of the base_image checks out of the distribution specific files into
a single check in install_distribution() where if a base image is
provided, we call install_packages(). Otherwise, we call install().
Drop centos logic to rebuild database to bdb format
This image might just be a base image that's intended to be added
onto with sysexts and such. If so, we need to keep the database in
sqlite format so that it can still be written to by rpm on the host.
So let's leave the rebuilding to be done in a postinst script by the
user.
Let's not muck around with distro defaults after all. This is trivial
to fix in a postinst script and should be done there instead of by
default in mkosi.
We install minbase with debootstrap which should already be very
minimal, so if there's docs in there let's assume they're critical.
We already specify --no-install-recommends for apt which should
exclude docs packages as they're optional so there's no need for
dpkg specific overrides to exclude docs on top of that.
Instead of disabling all services on Debian, let's adopt the new
preset directive "ignore" which tells preset to ignore any matching
services (neither enable nor disable). This makes sure we don't
override any defaults set by individual Debian services. On older
systemd, preset will simply ignore any line it can't parse so this
doesn't break those systems but will only result in a harmless
warning message.
bwrap seems to run into permission errors with relative paths in
some cases so let's follow systemd best practices and convert all
config paths to absolute paths as we're parsing them.
Instead of doing everything via zypper, let's just write the repo
definition files ourselves directly. Also, to mimick what we do
with dnf, let's write the repo files outside of the root instead of
inside the root and leave installing repos inside the root up to
the user.
Instead, we just do the necessary setup for a bootable image if all
the required components are available in the image. In practice, this
means that if a user installs systemd-boot, the kernel, and dracut,
they'll get a bootable image.
Let's trim down on the default packages we install, and only install
the most basic filesystem package by default. We'll leave everything
else up to the user.
This change is important when considering mkosi's use to build system
extensions and similar, where even the default packages we have now
are too much.
rpm blocks most signals when doing a transaction. dnf doesn't block
anything. The end result is that when we do ctrl+c when dnf is running
the rpm transaction, dnf gets interrupted and exits, which means mkosi
exits and tries to remove the workspace directory on which rpm is still
operating, causing all kinds of nastiness.
Because we don't care about transaction safety since we're operating on
a chroot, let's add --die-with-parent when running bubblewrap. This makes
bubblewrap ensure cleanup of all child processes underneath it, and
because rpm can't ignore SIGKILL, it also cleans up rpm properly, fixing
the issue.
It's also useful to be able to match against stuff that isn't the
current configuration. Let's add a PathExists= match that is satisfied
when the given path exists.
This will be useful in systemd where we conditionally build a kernel if
mkosi.kernel/ exists in the top level repo directory. With this setting,
we can only install the necessary packages to build the kernel if the
mkosi.kernel/ path actually exists.
Rework configuration parsing ordering and overrides
Currently, aside from list based settings, if a setting is used
multiple times across different configuration files, the later
assignments override earlier assignments. On top of that, the CLI
arguments are parsed last and override everything from config files.
This has worked very well until now, but breaks now that we have
[Match] sections. If we override a setting using the CLI, we want
any configured [Match] sections to compare against the value specified
via the CLI. Because the CLI values are applied last, this currently
isn't the case.
Similarly, if we add 90-local.conf to override the distribution release
used for Debian, all the config files that are processed earlier will
still compare against the default release configured for Debian in
50-debian.conf. If we rename 90-local.conf to 00-local.conf, the default
release in 50-debian.conf will still override that value. Only by putting
the override after the config file that assigns the default release but
before the first config file that matches on that release can we make this
work, but depending on the configuration this might require a lot of
different override files which isn't ideal.
Also, because later values can override earlier ones, it's possible to have
[Match] sections that match against different values of the same setting
both apply, if the setting happens to be reassigned inbetween, which is not
intuitive and error prone. Ideally, [Match] settings only apply to the final
value of a setting.
To fix these problems, this commit reworks the way we order and override
settings. Instead of having later assignments override earlier ones, for
all settings aside from list settings, the first assignment is the one that
is used. All later assignments of the same setting are ignored. Along with, we
switch to parsing CLI arguments first, which means that any settings assigned
in CLI args take precedence over those configured in config files.
Because the first value is immediately the final value, any [Match] sections
will only ever see the final value. One caveat is default values for settings.
We only want to assign these at the end of parsing, if no value has been
explicitly configured, but we also want [Match] sections to apply to default
values if no value is explicitly configured. The solution to this is that if
we encounter a setting in a [Match] section and it has not been explicitly
assigned a value yet, it is assigned its default value.
For list based settings, ! now configures an ignore glob, which means that if any
later assignments try to assign values that match an ignore glob, those values
are ignored. We also prepend list values instead of appending so that list
values that are configured in a preceeding config file appear later in the final
list value than values configured in a later assignment.
Implementation wise, this commit reworks config parser functions to return the
new value that should be assigned instead of assigning it themselves. This makes
the config parsing functions slightly more generic.
Instead of messing with the internals of argparse, let's implement
proper configuration file parsing.
- Parsing classes and functions are located in a new file config.py
- Configuration settings are split up from CLI settings in a list of
the new ConfigSetting dataclass
- The CLI options for configuration settings now share the same
argparse setting which simply delegates parsing to the corresponding
configuration setting parser.
- We add support for [Match] sections to enable conditionally including
configuration files. Currently Match support is implemented for
Distribution= and Release=.
- Configuration file searching is reworked. In mkosi.conf.d/, we parse
all files ending with ".conf" and directories. If a directory is parsed,
we parse mkosi.conf, mkosi.conf.d/ and all mkosi specific paths in it.
All paths are interpreted relative to the directory that we're parsing.
Remove build phases docs as we only have a single phase these days
and update the caching section docs to take the new build overlay
approach into account.
Daan De Meyer [Thu, 30 Mar 2023 12:00:34 +0000 (14:00 +0200)]
qemu: Don't write any log messages when running qemu
The running command message can get huge depending on which credentials
you're using so let's not write it by default (can still get it with
--debug run). And the swtpm message isn't super useful either so let's
drop it as well.
Daan De Meyer [Thu, 30 Mar 2023 11:56:53 +0000 (13:56 +0200)]
qemu: Use virtconsole serial console instead of regular serial console
With --qemu-headless, qemu stops working when latest systemd is not
available because smbios provided kernel cmdline arguments are ignored.
This includes "console=ttyS0" meaning we don't get any output on the
serial console when booting in qemu.
As a workaround, let's use qemu's virtconsole instead. This means the
serial console will be available in the VM as /dev/hvc0, on which
systemd will automatically spawn a serial getty. This means we'll
eventually get a login prompt, even if latest systemd is not used.
One caveat is that EDK2 doesn't seem to support virtio-serial with
virtconsole. To get around this limitation, we keep a regular serial
console around as well, which can be used by the bootloader to log
its output.
Daan De Meyer [Wed, 29 Mar 2023 08:50:14 +0000 (10:50 +0200)]
Drop --netdev
Let's not configure systemd-networkd in mkosi, but leave this up
to users instead. As our SSH support now works on top of vsock, we
don't need this option anymore to make the SSH support work.
When booting, containers are started without a network device (trivial
to add one by adding --network-veth) and VMs are started with a network
device. We don't want one for containers so that they can just reuse the
network namespace of the host instead of having to start networkd to get
internet access within the container. For VMs, there's no disadvantage to
adding a network device, so we add one by default.
Daan De Meyer [Sun, 19 Mar 2023 11:30:45 +0000 (12:30 +0100)]
Replace --qemu-headless with --qemu-gui
We add extra kernel command line arguments that configure term and
the tty size at runtime. We start qemu in the terminal on a serial tty
by default now as well.
We introduce --qemu-gui to still allow booting qemu in a graphical
interface
We also pass the host environment to qemu and nspawn to mimick what
we do with ssh and because qemu needs the host environment to
initialize gtk properly.
Daan De Meyer [Mon, 27 Mar 2023 08:55:16 +0000 (10:55 +0200)]
Add --acl option
Let's make the usage of ACLs opt-in since they leak into the final
image if the directory output is used.
We move the call to print_output_size() so its executed inside the
user namespace, which is required because we might not have permissions
to read some of the image's directories outside the user namespace.
Luca Boccassi [Fri, 24 Mar 2023 01:04:05 +0000 (01:04 +0000)]
overlayfs: avoid userxattr if kernel version is < 5.11
userxattr was added as a mount option for overlayfs only in kernel 5.11,
so avoid it on older versions (like Debian stable):
‣ Running build script…
mount: /home/bluca/git/systemd/.mkosi.tmpzt2q0dyp/root: wrong fs type, bad option, bad superblock on overlay, missing codepage or helper program, or other error.
umount: /home/bluca/git/systemd/.mkosi.tmpzt2q0dyp/root: not mounted
Daan De Meyer [Mon, 20 Mar 2023 16:33:15 +0000 (17:33 +0100)]
SSH fixes
- Disable UsePAM to avoid a slow reverse DNS lookup
- Pass environ when runnning ssh to pass SSH_AUTH_SOCK
- Don't use a random CID, instead hash the machine name and take
the first 4 bytes as the CID
- Pull in sshd-keygen.target so the ssh key gets generated on boot.
Daan De Meyer [Sun, 19 Mar 2023 13:50:18 +0000 (14:50 +0100)]
Fix caching behavior of several functions
Follow up for cee0b1b. Forgot to add checking of state.for_cache.
Also configure_dracut() needs to stay cached since we have an option
to cache the initrd.
Daan De Meyer [Fri, 17 Mar 2023 14:45:14 +0000 (15:45 +0100)]
Reimplement Ssh option on top of VSock and credentials
SSH key generation is currently broken under unprivileged mkosi.
Instead of trying to make this work, let's rework the SSH feature
entirely.
First, we only really need the SSH option for getting additional
login shells in VMs, so if we drop the requirement that this works
for containers (which can already be accessed with machinectl), we
can use VSock instead of TUN/TAP to get rid of a ton of code.
We also have a much better way of provisioning the public key these
days, add a script "ssh.authorized_keys.root" to mkosi.credentials/
with the following contents:
```
\#!/bin/sh
ssh-add -L
```
So we don't need to do SSH key generation ourselves anymore, we can
just let the user provide their own SSH key via a credential.
Daan De Meyer [Fri, 17 Mar 2023 12:46:52 +0000 (13:46 +0100)]
centos: Add missing base features for ext4 on c8s
Accidentally only added the ext4 specific features and none of the
base features, let's make sure we add the base features as well,
especially sparse_super is important to make repart's minimize
guessing logic work properly.
Daan De Meyer [Thu, 16 Mar 2023 07:33:15 +0000 (08:33 +0100)]
Replace QemuSMBIOS option with KernelCommandLineExtra
We only really added the QemuSMBIOS option to be able to set stub
option for adding extra command line options. Let's replace it by
a less generic option to make it less verbose to use and to allow
passing the added kernel command line arguments to systemd running
in nspawn as well.
Daan De Meyer [Sun, 12 Mar 2023 17:23:01 +0000 (18:23 +0100)]
Extend credentials support
We now also read credentials from mkosi.credentials/. If a file in
mkosi.credentials/ is executable, we run the file and use its output
as the credential.
Daan De Meyer [Sun, 12 Mar 2023 15:54:00 +0000 (16:54 +0100)]
Stop mounting package caches into images when running scripts
The package manager in the container might be a very different
version than the one running on the host which could cause all
sorts of caching issues. Since we don't need the caches in the
image anymore as we run the package managers outside of the image,
let's stop mounting the cache directory into the image when running
scripts as well.