Skip to content

Commit 1d32a00

Browse files
dockerfile/uki: Rework to remove kernel + initrd
Now that we can pass kernel and initrd paths to `bootc ukify`, rework our UKI Dockerfile to remove kernel + initrd from the final layer and only keep the UKI This still will not *remove* the kernel + initrd from the tarball but have whiteout instead See #2027 (comment) Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
1 parent ce8443a commit 1d32a00

6 files changed

Lines changed: 169 additions & 56 deletions

File tree

Dockerfile

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ RUN --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \
8383
# Install systemd-ukify and systemd-boot for UKIs
8484
# This also installs systemd-boot for the grub UKI case which is not ideal...
8585
if [[ "${boot_type}" == "uki" ]]; then
86-
pkgs_to_install+=(systemd-ukify)
86+
pkgs_to_install+=(systemd-ukify binutils)
8787
fi
8888

8989
if [[ ${#pkgs_to_install[@]} -gt 0 ]]; then
@@ -135,7 +135,12 @@ ARG pkgversion
135135
ARG SOURCE_DATE_EPOCH
136136
ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}
137137
# Build RPM directly from source, using cached target directory
138-
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp --mount=type=cache,target=/src/target --mount=type=cache,target=/var/roothome RPM_VERSION="${pkgversion}" /src/contrib/packaging/build-rpm
138+
RUN --network=none \
139+
--mount=type=tmpfs,target=/run \
140+
--mount=type=tmpfs,target=/tmp \
141+
--mount=type=cache,target=/src/target \
142+
--mount=type=cache,target=/var/roothome \
143+
RPM_VERSION="${pkgversion}" /src/contrib/packaging/build-rpm
139144

140145
# Build a systemd-sysext containing just the bootc binary.
141146
# Skips RPM machinery entirely for fast incremental rebuilds.
@@ -218,7 +223,7 @@ COPY --from=update-generated-from-code /src/docs/src/*.schema.json /docs/src/
218223
# ----
219224

220225
# Perform all filesystem transformations except generating the sealed UKI (if configured)
221-
FROM base as base-penultimate
226+
FROM base as base-penultimate-source
222227
ARG variant
223228
ARG bootloader
224229
ARG boot_type
@@ -234,6 +239,7 @@ if [[ "${bootloader}" == "systemd" ]]; then
234239
fi
235240

236241
if [[ "${boot_type}" == "uki" ]]; then
242+
bootc container inspect --rootfs / --json | jq -r '.kernel.version' > /var/kernel_ver
237243
cp /run/packaging/seal-uki /usr/bin/seal-uki
238244
cp /run/packaging/finalize-uki /usr/bin/finalize-uki
239245
cp /run/packaging/initialize-sealing-tools /usr/bin/initialize-sealing-tools
@@ -246,6 +252,10 @@ rm -rf /var/cache
246252
rm -rf /run/rhsm
247253

248254
EORUN
255+
256+
FROM base-penultimate-source as base-penultimate
257+
ARG boot_type
258+
249259
# Configure the rootfs
250260
ARG rootfs=""
251261
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \
@@ -260,9 +270,19 @@ RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp
260270
COPY --from=packaging /usr-extras/ /usr/
261271
# Clean up package manager caches
262272
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \
263-
--mount=type=bind,from=packaging,src=/,target=/run/packaging \
273+
--mount=type=bind,from=base-penultimate-source,src=/,target=/run/base-penultimate-src \
274+
--mount=type=bind,from=packaging,src=/,target=/run/packaging <<EORUN
264275
/run/packaging/cleanup
265276

277+
# Remove kernel + initrd if UKI
278+
if [[ "${boot_type}" == "uki" ]]; then
279+
kver=$(cat /run/base-penultimate-src/var/kernel_ver)
280+
281+
rm -v "/usr/lib/modules/$kver/vmlinuz"
282+
rm -v "/usr/lib/modules/$kver/initramfs.img"
283+
fi
284+
EORUN
285+
266286
# Generate the sealed UKI in a separate stage
267287
# This computes the composefs digest from base-penultimate and creates a signed UKI
268288
# We need our newly-built bootc for the compute-composefs-digest command
@@ -278,18 +298,29 @@ RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp
278298
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \
279299
--mount=type=secret,id=secureboot_key \
280300
--mount=type=secret,id=secureboot_cert \
301+
--mount=type=bind,from=base-penultimate-source,src=/,target=/run/base-penultimate-src \
281302
--mount=type=bind,from=packaging,src=/,target=/run/packaging \
282303
--mount=type=bind,from=base-penultimate,src=/,target=/run/target <<EORUN
283304
set -xeuo pipefail
284305

285-
allow_missing_verity=false
306+
allow_missing_verity=()
286307

287308
if [[ $filesystem == "xfs" ]]; then
288-
allow_missing_verity=true
309+
allow_missing_verity=(--allow-missing-verity)
289310
fi
290311

291312
if test "${boot_type}" = "uki"; then
292-
/run/packaging/seal-uki /run/target /out /run/secrets $allow_missing_verity $seal_state
313+
kver=$(cat "/run/base-penultimate-src/var/kernel_ver")
314+
315+
/run/packaging/seal-uki \
316+
--target /run/target \
317+
--output /out \
318+
--secrets /run/secrets \
319+
"${allow_missing_verity[@]}" \
320+
--kernel "/run/base-penultimate-src/usr/lib/modules/$kver/vmlinuz" \
321+
--kver "$kver" \
322+
--initramfs "/run/base-penultimate-src/usr/lib/modules/$kver/initramfs.img" \
323+
--seal-state $seal_state
293324
fi
294325
EORUN
295326

@@ -299,11 +330,13 @@ ARG variant
299330
ARG boot_type
300331
# Copy the sealed UKI and finalize the image (remove raw kernel, create symlinks)
301332
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \
333+
--mount=type=bind,from=base-penultimate-source,src=/,target=/run/base-penultimate-src \
302334
--mount=type=bind,from=packaging,src=/,target=/run/packaging \
303335
--mount=type=bind,from=sealed-uki,src=/,target=/run/sealed-uki <<EORUN
304336
set -xeuo pipefail
305337
if test "${boot_type}" = "uki"; then
306-
/run/packaging/finalize-uki /run/sealed-uki/out
338+
kver=$(cat "/run/base-penultimate-src/var/kernel_ver")
339+
/run/packaging/finalize-uki /run/sealed-uki/out "$kver"
307340
fi
308341
EORUN
309342
# And finally, test our linting

contrib/packaging/finalize-uki

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,8 @@ set -xeuo pipefail
2020
# Path to directory containing the generated UKI
2121
uki_src=$1
2222
shift
23-
24-
# Find the kernel version from the current system
25-
kver=$(bootc container inspect --json | jq -r '.kernel.version')
26-
if [ -z "$kver" ] || [ "$kver" = "null" ]; then
27-
echo "Error: No kernel found" >&2
28-
exit 1
29-
fi
23+
kver=$1
24+
shift
3025

3126
# Create the EFI directory structure
3227
mkdir -p /boot/EFI/Linux
@@ -36,12 +31,6 @@ mkdir -p /boot/EFI/Linux
3631
target=/boot/EFI/Linux/${kver}.efi
3732
cp "${uki_src}/${kver}.efi" "${target}"
3833

39-
# Remove the raw kernel and initramfs since we're using a UKI now.
40-
# NOTE: We intentionally keep these for now until bcvk is updated to extract
41-
# kernel/initramfs from UKIs in subdirectories. Once bcvk PR #144 is fixed
42-
# to look for .efi files in /usr/lib/modules/<kver>/, we can uncomment this.
43-
# rm -v "/usr/lib/modules/${kver}/vmlinuz" "/usr/lib/modules/${kver}/initramfs.img"
44-
4534
# NOTE: We used to create a symlink from /usr/lib/modules/${kver}/${kver}.efi to the UKI
4635
# for tooling compatibility. However, composefs-boot's find_uki_components() doesn't
4736
# handle symlinks correctly and fails with "is not a regular file". The UKI is already

contrib/packaging/seal-uki

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,82 @@
22
# Generate a sealed UKI with embedded composefs digest
33
set -xeuo pipefail
44

5-
# Path to the desired root filesystem
6-
target=$1
7-
shift
8-
# Write to this directory
9-
output=$1
10-
shift
11-
# Path to secrets directory
12-
secrets=$1
13-
shift
14-
allow_missing_verity=$1
15-
shift
16-
seal_state=$1
17-
shift
18-
19-
if [[ $seal_state == "sealed" && $allow_missing_verity == "true" ]]; then
5+
missing_verity=()
6+
7+
while [ ! -z "${1:-}" ]; do
8+
case "$1" in
9+
# Path to the desired root filesystem
10+
"--target")
11+
target="$2"
12+
shift
13+
shift
14+
;;
15+
16+
# Write to this directory
17+
"--output")
18+
output="$2"
19+
shift
20+
shift
21+
;;
22+
23+
# Path to secrets directory
24+
"--secrets")
25+
secrets="$2"
26+
shift
27+
shift
28+
;;
29+
30+
"--allow-missing-verity")
31+
missing_verity=(--allow-missing-verity)
32+
shift
33+
;;
34+
35+
"--seal-state")
36+
seal_state="$2"
37+
shift
38+
shift
39+
;;
40+
41+
# The kernel version
42+
"--kver")
43+
kver="$2"
44+
shift
45+
shift
46+
;;
47+
48+
# Path to the kernel
49+
"--kernel")
50+
kernel="$2"
51+
shift
52+
shift
53+
;;
54+
55+
# Path to the initrd
56+
"--initramfs")
57+
initramfs="$2"
58+
shift
59+
shift
60+
;;
61+
62+
* )
63+
echo "Argument $1 not understood"
64+
exit 1
65+
;;
66+
esac
67+
done
68+
69+
if [[ $seal_state == "sealed" && ${#missing_verity[@]} -gt 0 ]]; then
2070
echo "Cannot have missing verity with sealed UKI" >&2
2171
exit 1
2272
fi
2373

24-
# Find the kernel version (needed for output filename)
25-
kver=$(bootc container inspect --rootfs "${target}" --json | jq -r '.kernel.version')
26-
if [ -z "$kver" ] || [ "$kver" = "null" ]; then
27-
echo "Error: No kernel found" >&2
28-
exit 1
74+
if [[ -z $kernel || -z $initramfs || -z $kver ]]; then
75+
echo "kernel, initramfs and kver are required" >&2
76+
exit 1
2977
fi
3078

79+
kernel_params=(--kernel "$kernel" --initramfs "$initramfs" --kver "$kver")
80+
3181
mkdir -p "${output}"
3282

3383
# Baseline ukify options
@@ -45,12 +95,6 @@ fi
4595
# Baseline container ukify options
4696
containerukifyargs=(--rootfs "${target}")
4797

48-
missing_verity=()
49-
50-
if [[ $allow_missing_verity == "true" ]]; then
51-
missing_verity+=(--allow-missing-verity)
52-
fi
53-
5498
# Build the UKI using bootc container ukify
5599
# This computes the composefs digest, reads kargs from kargs.d, and invokes ukify
56-
bootc container ukify "${containerukifyargs[@]}" "${missing_verity[@]}" -- "${ukifyargs[@]}"
100+
bootc container ukify "${containerukifyargs[@]}" "${kernel_params[@]}" "${missing_verity[@]}" -- "${ukifyargs[@]}"

crates/tests-integration/src/container.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub(crate) fn test_bootc_container_inspect() -> Result<()> {
5151
.as_bool()
5252
.expect("kernel.unified should be a boolean");
5353

54+
println!("kernel: {kernel:#?}");
55+
5456
let is_uki = std::env::var("BOOTC_boot_type").is_ok_and(|var| var == "uki");
5557

5658
if let Some(variant) = std::env::var("BOOTC_variant").ok() {

tmt/tests/Dockerfile.upgrade

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ ARG filesystem=ext4
1313
FROM scratch AS packaging
1414
COPY contrib/packaging /
1515

16+
# Get kernel + initrd from the UKI
17+
FROM localhost/bootc as kernel
18+
RUN <<-EOF
19+
kver=$(bootc container inspect --rootfs / --json | jq -r '.kernel.version')
20+
echo $kver > /var/kernel_ver
21+
22+
objcopy -O binary --only-section=.initrd /boot/EFI/Linux/*.efi /boot/initramfs.img
23+
objcopy -O binary --only-section=.linux /boot/EFI/Linux/*.efi /boot/vmlinuz
24+
EOF
25+
1626
# Create the upgrade content (a simple marker file).
1727
# For UKI builds, we also remove the existing UKI so that seal-uki can
1828
# regenerate it with the correct composefs digest for this derived image.
@@ -36,16 +46,28 @@ RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp
3646
--mount=type=secret,id=secureboot_key \
3747
--mount=type=secret,id=secureboot_cert \
3848
--mount=type=bind,from=packaging,src=/,target=/run/packaging \
49+
--mount=type=bind,from=kernel,src=/,target=/run/kernel \
3950
--mount=type=bind,from=upgrade-base,src=/,target=/run/target <<EORUN
4051
set -xeuo pipefail
4152

42-
allow_missing_verity=false
43-
if [ "${filesystem}" = "xfs" ]; then
44-
allow_missing_verity=true
53+
allow_missing_verity=()
54+
55+
if [[ $filesystem == "xfs" ]]; then
56+
allow_missing_verity=(--allow-missing-verity)
4557
fi
4658

4759
if test "${boot_type}" = "uki"; then
48-
/run/packaging/seal-uki /run/target /out /run/secrets "${allow_missing_verity}" "${seal_state}"
60+
kver=$(cat /run/kernel/var/kernel_ver)
61+
62+
/run/packaging/seal-uki \
63+
--target /run/target \
64+
--output /out \
65+
--secrets /run/secrets \
66+
"${allow_missing_verity[@]}" \
67+
--kernel "/run/kernel/boot/vmlinuz" \
68+
--kver "$kver" \
69+
--initramfs "/run/kernel/boot/initramfs.img" \
70+
--seal-state $seal_state
4971
fi
5072
EORUN
5173

tmt/tests/booted/tap.nu

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,26 +89,49 @@ export def make_uki_containerfile [containerfile: string] {
8989
return $containerfile
9090
}
9191

92-
let allow_missing_verity = $st.status.booted.composefs.missingVerityAllowed
92+
let allow_missing_verity = if $st.status.booted.composefs.missingVerityAllowed {
93+
"--allow-missing-verity"
94+
} else {
95+
""
96+
}
97+
9398
# TODO: Handle sealed UKI
9499
let seal_state = "unsealed"
95100

96101
let uki_stuff = $"
102+
FROM base as kernel
103+
RUN <<-EOF
104+
kver=$\(bootc container inspect --rootfs / --json | jq -r '.kernel.version'\)
105+
echo $kver > /var/kernel_ver
106+
107+
objcopy -O binary --only-section=.initrd /boot/EFI/Linux/*.efi /boot/initramfs.img
108+
objcopy -O binary --only-section=.linux /boot/EFI/Linux/*.efi /boot/vmlinuz
109+
EOF
110+
97111
FROM base as base-final
98112
RUN rm -rf /boot/EFI/Linux/*.efi
99113
100114
FROM base as sealed-uki
101115
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \\
102116
--mount=type=bind,from=base-final,src=/,target=/run/target \\
103-
/usr/bin/seal-uki /run/target /out /run/secrets ($allow_missing_verity) ($seal_state)
117+
--mount=type=bind,from=kernel,src=/,target=/run/kernel \\
118+
/usr/bin/seal-uki \\
119+
--target /run/target \\
120+
--output /out \\
121+
--secrets /run/secrets ($allow_missing_verity) \\
122+
--kernel /run/kernel/boot/vmlinuz \\
123+
--kver $\(cat /run/kernel/var/kernel_ver\) \\
124+
--initramfs /run/kernel/boot/initramfs.img \\
125+
--seal-state ($seal_state)
104126
105127
FROM base-final
106128
107129
# Copy the sealed UKI and finalize the image remove raw kernel, create symlinks
108130
RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \\
109131
--mount=type=bind,from=sealed-uki,src=/,target=/run/sealed-uki \\
110-
/usr/bin/finalize-uki /run/sealed-uki/out
111-
"
132+
--mount=type=bind,from=kernel,src=/,target=/run/kernel \\
133+
/usr/bin/finalize-uki /run/sealed-uki/out $\(cat /run/kernel/var/kernel_ver\)
134+
" | lines | each { str trim } | str join "\n"
112135

113136
return $"($containerfile)\n($uki_stuff)"
114137
}

0 commit comments

Comments
 (0)