Skip to content

Commit 64a6d1c

Browse files
committed
Use systemd-confext instead of custom /etc overlay mount
For A/B-updated /etc contents we used a custom overlay mount that provides the default files through a lowerdir loaded from /usr. Since then we upstreamed mutable systemd-confext support and now we can switch to it. This pulls in flatcar/init#138 and flatcar/bootengine#115 together with backported systemd patches that have opened or merged upstream PRs to fix --root= issues and add a refresh skip check to prevent boot disruptions due to the multiple daemon reloads and - more important - the missing atomic remount that would mean /etc is gone for a few milliseconds during boot. The skip logic works best with verity hashes and thus the default confext must be a verity extension image. User-provided confext don't work well yet unless they use verity due to the missing atomic remount and reliance on the skipping logic. We also need to look into stacking order and other mutabiliy settings. TODO: List of PRs and patch files (inc dep commits) Signed-off-by: Kai Lueke <[email protected]>
1 parent 9d481a3 commit 64a6d1c

16 files changed

+2686
-15
lines changed

build_library/build_image_util.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,8 +737,30 @@ EOF
737737
if [[ $(sudo find "${root_fs_dir}/usr/share/flatcar/etc" -size +0 ! -type d 2>/dev/null | wc -l) -gt 0 ]]; then
738738
die "Unexpected non-empty files in ${root_fs_dir}/usr/share/flatcar/etc"
739739
fi
740+
# Some backwards-compat symlinks still use this folder as target,
741+
# we can't remove it yet
740742
sudo rm -rf "${root_fs_dir}/usr/share/flatcar/etc"
741743
sudo cp -a "${root_fs_dir}/etc" "${root_fs_dir}/usr/share/flatcar/etc"
744+
# Now set up a default confext and enable it.
745+
# It's important to use dm-verity not only for stricter image policies
746+
# but also because it allows us the refresh to identify this image and
747+
# skip setting it up again in the final boot, which not only saves us
748+
# a daemon-reload during boot but also from /etc contents shortly
749+
# disappearing until systemd-sysext uses mount beneath for an atomic
750+
# remount. Instead of a temporary directory we first prepare it as
751+
# folder and then convert it to a DDI and remove the folder.
752+
sudo rm -rf "${root_fs_dir}/usr/lib/confexts/00-flatcar-default"
753+
sudo mkdir -p "${root_fs_dir}/usr/lib/confexts/00-flatcar-default"
754+
sudo cp -a "${root_fs_dir}/etc" "${root_fs_dir}/usr/lib/confexts/00-flatcar-default/etc"
755+
sudo mkdir -p "${root_fs_dir}/usr/lib/confexts/00-flatcar-default/etc/extension-release.d/"
756+
echo ID=_any | sudo tee "${root_fs_dir}/usr/lib/confexts/00-flatcar-default/etc/extension-release.d/extension-release.00-flatcar-default" > /dev/null
757+
sudo systemd-repart \
758+
--private-key="${SYSEXT_SIGNING_KEY_DIR}/sysexts.key" \
759+
--certificate="${SYSEXT_SIGNING_KEY_DIR}/sysexts.crt" \
760+
--make-ddi=confext \
761+
--copy-source="${root_fs_dir}/usr/lib/confexts/00-flatcar-default" \
762+
"${root_fs_dir}/usr/lib/confexts/00-flatcar-default.raw"
763+
sudo rm -rf "${root_fs_dir}/usr/lib/confexts/00-flatcar-default"
742764

743765
# Remove the rootfs state as it should be recreated through the
744766
# tmpfiles and may not be present on updating machines. This
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Switched `/etc/` from a custom overlayfs for A/B updates to using a systemd-confext extension providing the default contents by using systemd-confext in the mutable mode where `/etc/` gets used as upperdir [scripts#3555](https://github.com/flatcar/scripts/pull/3555)
2+
- Moved systemd-sysext image mounting into the initrd, so that system extensions can better define the behavior of the final system at boot without workarounds to apply settings late at boot. This means `.wants` symlinks for systemd units work as expected now and, therefore, we dropped the `ensure-sysext.service` workaround. We still recommend extensions to keep their workarounds, e.g., using `.upholds` instead of `.wants`, to better support live reloading. A skipping logic prevents an extension refresh late at boot but only if no changes were found. For extensions that are not stored on a custom filesystem, such as a separate `/var` partition, the new extension mounting from the initrd won't be able to load them early but they will be picked up late at boot through the extension refresh. This is another case where it's good if extensions keep workarounds for late loading.

sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-init/coreos-init-9999.ebuild

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ EGIT_REPO_URI="https://github.com/flatcar/init.git"
88
if [[ "${PV}" == 9999 ]]; then
99
KEYWORDS="~amd64 ~arm ~arm64 ~x86"
1010
else
11-
EGIT_COMMIT="8bd8a82fb22bc46ea2cf7da94d58655e102ca26d" # flatcar-master
11+
#EGIT_COMMIT="8bd8a82fb22bc46ea2cf7da94d58655e102ca26d" # flatcar-master
12+
EGIT_BRANCH="kai/default-confext"
1213
KEYWORDS="amd64 arm arm64 x86"
1314
fi
1415

sdk_container/src/third_party/coreos-overlay/coreos/config/env/sys-apps/systemd

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,19 +160,6 @@ EOF
160160
-e '/^C!* \/etc\/pam\.d/d' \
161161
-e '/^C!* \/etc\/issue/d' || die
162162

163-
(
164-
# Some OEMs prefer chronyd, so allow them to replace
165-
# systemd-timesyncd with it.
166-
insinto "$(systemd_get_systemunitdir)/systemd-timesyncd.service.d"
167-
newins - flatcar.conf <<'EOF'
168-
# Allow sysexts to ship timesyncd replacements which can have
169-
# a Conflicts=systemd-timesyncd directive that would result
170-
# in systemd-timesyncd not being started.
171-
[Unit]
172-
After=ensure-sysext.service
173-
EOF
174-
)
175-
176163
(
177164
# Allow @mount syscalls for systemd-udevd.service
178165
insinto "$(systemd_get_systemunitdir)/systemd-udevd.service.d"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
From 6f4b065b626edd8a06ff0c8028173e060b5e444b Mon Sep 17 00:00:00 2001
2+
From: Kai Lueke <[email protected]>
3+
Date: Thu, 20 Nov 2025 23:43:55 +0900
4+
Subject: [PATCH 03/10] vpick: Don't use openat directly but resolve symlinks
5+
in given root
6+
7+
With systemd-sysext --root= all symlinks should be followed relative to
8+
the given root and direct openat usage doesn't work.
9+
Change the openat call to use the chase helper function to resolve the
10+
symlink in the given root.
11+
---
12+
src/shared/vpick.c | 4 ++--
13+
1 file changed, 2 insertions(+), 2 deletions(-)
14+
15+
diff --git a/src/shared/vpick.c b/src/shared/vpick.c
16+
index b1b2d93054..dfe58cafa5 100644
17+
--- a/src/shared/vpick.c
18+
+++ b/src/shared/vpick.c
19+
@@ -471,9 +471,9 @@ static int make_choice(
20+
if (!p)
21+
return log_oom_debug();
22+
23+
- object_fd = openat(dir_fd, best_filename, O_CLOEXEC|O_PATH);
24+
+ object_fd = chase_and_openat(toplevel_fd, p, CHASE_AT_RESOLVE_IN_ROOT, O_PATH|O_CLOEXEC, NULL);
25+
if (object_fd < 0)
26+
- return log_debug_errno(errno, "Failed to open '%s/%s': %m",
27+
+ return log_debug_errno(object_fd, "Failed to open '%s/%s': %m",
28+
empty_to_root(toplevel_path), skip_leading_slash(inode_path));
29+
30+
return pin_choice(
31+
--
32+
2.52.0
33+

0 commit comments

Comments
 (0)