1
0
mirror of https://github.com/containers/bootc.git synced 2026-02-05 06:45:13 +01:00

Add initramfs infrastructure

This adds scaffolding to install a stub binary which can
optionally be added into the initramfs;
prep for us doing real work during setup as we aim
to move to the native composefs backend.

The binary is *built* but is only installed by a
new `Makefile` target, so existing build system
users won't pick it up. Our development-only
`Dockerfile` gains a build option to use it
(and also ensures the initramfs is regenerated).

However previously we also discussed moving the fstab
logic into the initramfs:
https://github.com/bootc-dev/bootc/pull/1113

I might try doing that once this lands.

One notable thing is that even this trivial nearly-no-op
binary is still 4MB which I think is mostly due
to linking in a whole copy of prebuilt rust `std`.
In theory we could try going to `#[no_std]` but I
don't think it'll be viable once we start doing more here.
Probably most practical thing re size is `-Z build-std` + LTO.

Signed-off-by: Colin Walters <walters@verbum.org>
This commit is contained in:
Colin Walters
2025-08-07 15:16:38 -04:00
parent acba07b6fb
commit f61ba60bbc
8 changed files with 121 additions and 3 deletions

7
Cargo.lock generated
View File

@@ -185,6 +185,13 @@ dependencies = [
"tracing",
]
[[package]]
name = "bootc-initramfs-setup"
version = "0.1.0"
dependencies = [
"anyhow",
]
[[package]]
name = "bootc-internal-blockdev"
version = "0.0.0"

View File

@@ -39,6 +39,8 @@ EORUN
# bootc binaries in /out. The intention is that the target rootfs is extracted from /out
# back into a final stae (without the build deps etc) below.
FROM base as build
# Flip this on to enable initramfs code
ARG initramfs=0
# This installs our package dependencies, and we want to cache it independently of the rest.
# Basically we don't want changing a .rs file to blow out the cache of packages. So we only
# copy files necessary
@@ -59,8 +61,14 @@ COPY --from=src /src /src
WORKDIR /src
# See https://www.reddit.com/r/rust/comments/126xeyx/exploring_the_problem_of_faster_cargo_docker/
# We aren't using the full recommendations there, just the simple bits.
RUN --mount=type=cache,target=/build/target --mount=type=cache,target=/var/roothome \
make && make install-all DESTDIR=/out
RUN --mount=type=cache,target=/build/target --mount=type=cache,target=/var/roothome <<EORUN
set -xeuo pipefail
make
make install-all DESTDIR=/out
if test "${initramfs:-}" = 1; then
make install-initramfs-dracut DESTDIR=/out
fi
EORUN
# This "build" just runs our unit tests
FROM build as units
@@ -74,6 +82,10 @@ FROM base
COPY --from=build /out/ /
RUN <<EORUN
set -xeuo pipefail
if test -x /usr/lib/bootc/initramfs-setup; then
kver=$(cd /usr/lib/modules && echo *);
env DRACUT_NO_XATTR=1 dracut -vf /usr/lib/modules/$kver/initramfs.img $kver
fi
# Only in this containerfile, inject a file which signifies
# this comes from this development image. This can be used in
# tests to know we're doing upstream CI.

View File

@@ -53,9 +53,19 @@ install-ostree-hooks:
ln -sf ../../../bin/bootc $(DESTDIR)$(prefix)/libexec/libostree/ext/$$x; \
done
# Install code in the initramfs, off by default except in builds from git main right now
# Also the systemd unit hardcodes /usr so we give up the farce of supporting $(prefix)
install-initramfs:
install -D -m 0644 -t $(DESTDIR)/usr/lib/systemd/system crates/initramfs/*.service
install -D -m 0755 target/release/bootc-initramfs-setup $(DESTDIR)/usr/lib/bootc/initramfs-setup
# Install initramfs files, including dracut module
install-initramfs-dracut: install-initramfs
install -D -m 0755 -t $(DESTDIR)/usr/lib/dracut/modules.d/51bootc crates/initramfs/dracut/module-setup.sh
# Install the main binary, the ostree hooks, and the integration test suite.
install-all: install install-ostree-hooks
install -D -m 0755 target/release/tests-integration $(DESTDIR)$(prefix)/bin/bootc-integration-tests
install -D -m 0755 target/release/tests-integration $(DESTDIR)$(prefix)/bin/bootc-integration-tests
bin-archive: all
$(MAKE) install DESTDIR=tmp-install && $(TAR_REPRODUCIBLE) --zstd -C tmp-install -cf target/bootc.tar.zst . && rm tmp-install -rf

View File

@@ -0,0 +1,12 @@
[package]
name = "bootc-initramfs-setup"
version = "0.1.0"
license = "MIT OR Apache-2.0"
edition = "2021"
publish = false
[dependencies]
anyhow.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,22 @@
[Unit]
Description=bootc setup root
Documentation=man:bootc(1)
DefaultDependencies=no
# For now
ConditionKernelCommandLine=ostree
ConditionPathExists=/etc/initrd-release
After=sysroot.mount
After=ostree-prepare-root.service
Requires=sysroot.mount
Before=initrd-root-fs.target
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
ExecStart=/usr/lib/bootc/initramfs-setup setup-root
StandardInput=null
StandardOutput=journal
StandardError=journal+console
RemainAfterExit=yes

View File

@@ -0,0 +1,18 @@
#!/bin/bash
installkernel() {
instmods erofs overlay
}
check() {
require_binaries /usr/lib/bootc/initramfs-setup || return 1
}
depends() {
return 0
}
install() {
local service=bootc-root-setup.service
dracut_install /usr/lib/bootc/initramfs-setup
inst_simple "${systemdsystemunitdir}/${service}"
mkdir -p "${initdir}${systemdsystemconfdir}/initrd-root-fs.target.wants"
ln_r "${systemdsystemunitdir}/${service}" \
"${systemdsystemconfdir}/initrd-root-fs.target.wants/${service}"
}

View File

@@ -0,0 +1,24 @@
//! Code for bootc that goes into the initramfs.
//! At the current time, this is mostly just a no-op.
// SPDX-License-Identifier: Apache-2.0 OR MIT
use anyhow::Result;
fn setup_root() -> Result<()> {
let _ = std::fs::metadata("/sysroot/usr")?;
println!("setup OK");
Ok(())
}
fn main() -> Result<()> {
let v = std::env::args().collect::<Vec<_>>();
let args = match v.as_slice() {
[] => anyhow::bail!("Missing argument".to_string()),
[_, rest @ ..] => rest,
};
match args {
[] => anyhow::bail!("Missing argument".to_string()),
[s] if s == "setup-root" => setup_root(),
[o, ..] => anyhow::bail!(format!("Unknown command {o}")),
}
}

View File

@@ -0,0 +1,13 @@
use std assert
use tap.nu
tap begin "initramfs"
if (not ("/usr/lib/bootc/initramfs-setup" | path exists)) {
print "No initramfs support"
exit 0
}
journalctl -b -t bootc-root-setup.service --grep=OK
tap ok