Skip to content

Add initramfs infrastructure #1500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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.
Expand Down
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions crates/initramfs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions crates/initramfs/bootc-root-setup.service
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions crates/initramfs/dracut/module-setup.sh
Original file line number Diff line number Diff line change
@@ -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}"
}
24 changes: 24 additions & 0 deletions crates/initramfs/src/main.rs
Original file line number Diff line number Diff line change
@@ -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}")),
}
}
13 changes: 13 additions & 0 deletions tmt/tests/booted/readonly/051-test-initramfs.nu
Original file line number Diff line number Diff line change
@@ -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