Daan De Meyer [Wed, 31 Jan 2024 13:13:37 +0000 (14:13 +0100)]
Implement CacheOnly=metadata
We make CacheOnly= take an enum but keep backwards compat with the
boolean argument as well.
CacheOnly=metadata means we'll download packages but we won't sync
repository metadata. We also enable this in the kernel-install so that
our built initrds use exactly the same package versions as the host
system.
While we're at it we rename the internal variable to cacheonly instead
of cache_only (to match dnf's --cacheonly option). We keep the user
facing stuff the same to not break backwards compat.
We also make all of our enum functions take StrEnum as argument instead
of the generic enum.Enum.
Daan De Meyer [Tue, 30 Jan 2024 13:50:42 +0000 (14:50 +0100)]
Rework package manager caching
Currently, CacheDirectory= is used for all caching, both incremental
images and package manager cache. While this works great for incremental
images, there's a few issues with using CacheDirectory= for all package
manager caching:
- By default we don't do any caching, this has to be explicitly
configured by setting CacheDirectory=mkosi.cache or telling users
to manually create mkosi.cache. This means new users might be frustrated
by their image builds downloading everything again on subsequent builds.
- By doing package manager caches per individual mkosi project, we
unnecessarily download multiple copies of the same repo metadata and
packages.
- When using incremental images, if the post-install or finalize scripts
install extra packages, these packages can trigger repository metadata
updates, which will result in the image being built from two repository
metadata snapshots, one from when the incremental image was built, the
other from the new packages installed using the refreshed repository
metadata. Even if the scripts don't trigger repository metadata updates
themselves, because the cache is shared, the repository metadata could
already have been updated during another image build.
- When using base trees, any images using the base tree might trigger a
repository metadata update as well, resulting in the same issue, where
the image is built from multiple different snapshots of the repository
metadata.
To fix the first two issues, we introduce a new setting PackageCacheDirectory=
and make its default either a system or per user cache directory depending
on how mkosi is invoked. This makes sure we cache by default and use a shared
package manager cache directory so that we do not unnecessarily download duplicate
copies of repository metadata and packages
To fix the two remaining issues, we need to make sure we only sync repository
metadata once for each image. We opt to do this at the start of each image build
and configure the package manager commands to not do any metadata syncing by
default. To make sure the repository metadata snapshot stays available for
extension images and for incremental images, we copy the repository metadata from
the shared cache into the image itself at /mkosi/cache/<subdir>. This makes sure
that even if the repository metadata in the shared cache is refreshed by another
image build it won't remove the old snapshot for incremental builds or images
intended to be used as base trees.
To make sure the actual packages downloaded during the image build are still
written into the shared package cache, in finalize_package_manager_mounts(), we
bind mounts the relevant directories from the shared package cache instead of
from /mkosi/cache/<subdir> in the image to make sure that other image builds can
take advantage of the downloaded packages.
The /mkosi/ directory is removed from the image at the end of each image build
before packaging up the result unless we're building a directory or tar image
and CleanPackageMetadata= is explicitly disabled.
The initial sync we do at the start of each image build operates on the shared
package cache directory so that repository metadata is only refreshed once and
can be reused by other image builds.
Because package managers now prevent automatic syncing by default, we have to
rework the local package repositories slightly to make sure the local package
repository is still synced whenever it is updated. We get rid of the localrepo()
functions and opt to again write the repo definitions for the local package
repository inline to keep things simple and localized.
To avoid pacman from writing packages from the local package repository to the
shared package cache directory, we configure the local repository itself as an
additional read-only cache directory, which makes sure that pacman will read cached
packages from this directory but won't write any new packages to this directory.
For zypper we disable "keeppackages" for the local package repository to prevent
those packages from getting cached.
For dnf, we don't mount in any directory from the shared package cache for the
mkosi-packages repository to make sure it stays local to the image.
Apt doesn't support any mechanism that allows us to prevent packages from the
local repository from getting cached so we allow these to be written to the
shared package cache.
We also take the opportunity to rename the mkosi-packages repo to the mkosi repo,
and rename the accompanying config files as well;
Because pacman does not employ any sort of cache key for its repository metadata,
when using the default shared package cache directory, we use a subdirectory based
on the distribution, release and architecture that we're building for to prevent
any possible conflicts in the cache directory when different pacman based distributions
use the same repo identifiers.
To avoid issues when two instances of mkosi operate on the same package cache directory,
we take an advisory BSD lock on the cache subdirectory that we're going to sync or copy.
When building the default initrd, we make sure it uses the same repository snapshot
as the associated image.
Daan De Meyer [Tue, 30 Jan 2024 14:29:18 +0000 (15:29 +0100)]
Introduce PackageManager interface
Let's start introducing a common interface for package manager
implementations. This will allow us to slowly get rid of the
functions where we do logic for each package manager because we
don't know the one that's being used. For example we add scripts
for each package manager right now which we can get rid of with a
package manager interface.
This also allows for more intuitive naming of package manager functions,
instead of invoke_dnf() we can now write Dnf.invoke().
Daan De Meyer [Fri, 26 Jan 2024 22:05:06 +0000 (23:05 +0100)]
Use shared package cache directory by default
Instead of having a separate package cache for each mkosi project,
let's default to having a shared package cache directory that can
also be configured separately from the incremental cache directory.
Daan De Meyer [Fri, 26 Jan 2024 21:50:11 +0000 (22:50 +0100)]
Drop Gentoo support
Gentoo has completely stopped working and nobody has stepped up to
maintain it. It also keeps hindering refactoring so let's remove the
gentoo support so the upcoming work is easier.
Daan De Meyer [Fri, 26 Jan 2024 12:21:23 +0000 (13:21 +0100)]
Rework local repository
Let's have each createrepo function return the repository to use to
access the local packages and let's call this function from the setup()
functions of each distribution.
Daan De Meyer [Fri, 26 Jan 2024 10:50:37 +0000 (11:50 +0100)]
pacman: Make sure we pass packages to repo-add in right order
According to https://wiki.archlinux.org/title/pacman/Tips_and_tricks,
the newest version has to be added last, so let's make sure we sort
the paths we pass to repo-add.
Daan De Meyer [Wed, 24 Jan 2024 12:21:27 +0000 (13:21 +0100)]
Update link to mkosi introduction blog post
Let's stop linking the old blog from 2017 and link the newer one
that was just published instead. The old one isn't really useful
as it uses tons of features that have been removed since.
Winterhuman [Tue, 23 Jan 2024 12:51:55 +0000 (12:51 +0000)]
man: `--debug-shell=` -> `--debug-shell`
`--debug-shell` refuses to take an argument, so the equal sign is misleading (aka. `--debug-shell=yes` errors out), so let's remove it from the `man` page.
Daan De Meyer [Mon, 22 Jan 2024 19:51:00 +0000 (20:51 +0100)]
Only use tools trees for verbs that need a build
Currently we try to use a tools tree that isn't there for verbs
that don't need a build. Let's instead opt to not use one altogether
since building an entire image just to run ssh is kind of overkill.
Daan De Meyer [Mon, 22 Jan 2024 14:17:01 +0000 (15:17 +0100)]
Allow including builtin configs
Let's make it possible to include builtin configurations using
e.g. Include=mkosi-initrd. This allows building the default initrd
or default tools tree independently whereas currently these can only
be built as part of another image.
Daan De Meyer [Mon, 22 Jan 2024 13:23:16 +0000 (14:23 +0100)]
Extract mkosi.resources once
Instead of extracting individual files and directories when we need
them, let's extract the resources once and pass the extracted path
around so that we don't have to deal with context managers every time
we want to use resources.
Daan De Meyer [Thu, 18 Jan 2024 08:56:45 +0000 (09:56 +0100)]
Don't mount /srv and /mnt read-only
It seems there are use cases where users expect to write their output
to a directory in /srv or /mnt so let's make that writable. This should
be safe as we set up a custom sandbox now so none of the tools we run
will have access to /srv and /mnt in the first place.
Daan De Meyer [Thu, 18 Jan 2024 09:24:45 +0000 (10:24 +0100)]
Don't preserve timestamps when copying skeleton/extra trees
If timestamps should be preserved, a tar archive should be used.
Timestamps in directories are very likely to be arbitrary and there's
no point in preserving them. This doesn't impact reproducible builds
as we have SourceDateEpoch= for that.