A Unified Kernel Image (UKI) is a single UEFI executable that bundles a small EFI boot stub, the Linux kernel, and optionally the initrd, kernel command line, os-release data, splash image and devicetree. Because it is one PE file, one Secure Boot signature covers all of it, and a TPM can predict its measurements, so encrypted disks can unlock across kernel updates.
This guide goes one level deeper than our posts on Secure Boot with your own keys and what each TPM 2.0 PCR measures. Those posts cover key enrollment and the firmware PCRs. This one follows the Linux side: what goes into a UKI, how systemd-stub measures it, how systemd-boot finds it, and how to build, sign, install and check one. Every section name, PCR number, option and path comes from the UAPI Group specifications, the systemd 262 manual pages, the kernel documentation and distribution documents listed under Sources. Where a detail depends on your distribution or systemd version, we say so.
Key takeaways
- A UKI is a PE/COFF file whose sections carry the kernel (
.linux, the only required section) and optional extras such as.initrd,.cmdline,.osrel,.uname,.splash,.dtb,.ucode,.sbat,.pcrsigand.pcrpkey. The UAPI.5 specification fixes the order of those sections so measurements are predictable. - In the common shim plus GRUB chain, the kernel is signature checked but the initrd is loaded as a separate file and the command line comes from a configuration file. A UKI moves both inside the signed binary.
- With Secure Boot on and an embedded
.cmdline, systemd-stub ignores any command line passed to it, so boot menu edits do nothing. - systemd-stub measures each UKI section name and its contents into PCR 11. Because PCR 11 only reflects static parts of the image,
systemd-measurecan calculate the expected value ahead of time and sign it, andukifyembeds that signature in the.pcrsigsection. systemd-cryptenroll --tpm2-public-key=binds a LUKS volume to "any UKI signed by this PCR key" instead of to one literal hash, so a new signed kernel unlocks the disk without re-enrollment.- Addons, credentials and system extensions let you change a UKI's command line, initrd or configuration without rebuilding it. Addons must pass Secure Boot checks; credentials and extensions are measured into PCRs 12 and 13 and protected by TPM encryption or dm-verity.
- Distribution support varies. Fedora's change proposals added UKIs for virtual machines, direct shim to UKI boot and a UEFI cloud image variant; Arch documents local UKI builds with mkinitcpio, kernel-install or ukify; Debian and Ubuntu package ukify but keep shim plus GRUB as the default. Host-specific initrds, out of tree modules and custom command lines remain the hard cases.
What is a Unified Kernel Image, and what does it bundle?
The UAPI.5 specification, version 1.0, defines a UKI as a UEFI boot stub, a Linux kernel image, an optional initrd and further resources combined in one UEFI PE file. It can be started directly by the UEFI firmware, which the specification says is useful in cloud and confidential computing environments, or through a boot loader that offers a menu of kernel versions.
The file format is plain PE/COFF, the same executable format UEFI firmware already loads. The specification says UKIs should set the PE optional header Subsystem field to 0x0A, which is IMAGE_SUBSYSTEM_EFI_APPLICATION. The stub is the code that actually runs. It finds the other resources inside its own executable, loads the kernel and initrd, and jumps into the kernel. systemd-stub is the reference implementation, shipped on disk as linuxx64.efi.stub, linuxia32.efi.stub and linuxaa64.efi.stub under /usr/lib/systemd/boot/efi/.
The sections, in canonical order
The specification lists the sections below and says this "specifies the canonical order of sections". Items are never reordered and new sections are only added at the end, because the order is what makes PCR measurements predictable.
| Section | Contents | Required? | Notes from the spec and systemd-stub |
|---|---|---|---|
.linux | The Linux kernel | Yes, the only required section | Everything else is optional |
.osrel | Contents of the target OS's /etc/os-release | No | Used for boot menu titles and version ordering |
.cmdline | Kernel command line | No | If absent, the loader may allow local overrides |
.initrd | The initrd | No | Can be built from several cpio archives concatenated |
.ucode | Microcode initrd | No | Handed to the kernel before any other initrd; must not be compressed |
.splash | Splash image | No | Windows BMP format, shown before the kernel starts |
.dtb | Compiled devicetree | No | For systems that need one |
.dtbauto | One or more devicetrees | No | First match against firmware devicetree or .hwids overrides .dtb |
.efifw | Firmware image blob | No | Matched by .hwids and firmware ID, used at next reset |
.hwids | Hardware ID table (HWID or CHID) | No | Matched against SMBIOS data |
.uname | uname -r of the kernel | No | Menu display and ordering; also used to match addons |
.sbat | SBAT revocation metadata (CSV) | No | Format defined by the shim project |
.pcrsig | JSON with expected PCR 11 values and signatures | No | Not measured, since it describes the measurement result |
.pcrpkey | PEM public key for the PCR signatures | No | The key the booted system binds secrets to |
All of these are singletons, appearing at most once, except .dtbauto and .efifw, which may repeat. Multi-profile UKIs, covered later, add a .profile separator that lets each set repeat once per profile.
The specification also notes that boot menus can impose extra requirements. For example, systemd-boot may only list kernels that carry an .osrel section, because that is where it reads the title and version.
Where UKIs live on disk
There are two locations to keep apart.
- Where the package manager installs a distribution-built UKI. UAPI.5 says these go in
/usr/lib/modules/$UNAME/, where$UNAMEisuname -rof the kernel inside, with a filename that sorts correctly under the UAPI version format specification. Auxiliary resources that apply to every UKI go in/usr/lib/modules/uki.extra.d/, and resources for one UKI go in/usr/lib/modules/$UNAME/$UKI.efi.extra.d/. Addons end in.addon.efi, system extensions in.sysext.rawand configuration extensions in.confext.raw. - Where the boot loader looks. The Boot Loader Specification calls a UKI a "Type #2" entry and places them in
/EFI/Linux/on the EFI System Partition (ESP) or the Extended Boot Loader partition (XBOOTLDR).kernel-installwithlayout=ukicopies a UKI to$BOOT/EFI/Linux/ENTRY-TOKEN-KERNEL-VERSION.efi, and copies any.extra.d/directory next to it.
UKI, EFI stub kernel and plain bzImage: what is the difference?
The Linux kernel has had its own EFI stub for years. The kernel documentation explains that with CONFIG_EFI_STUB, an x86 or ARM kernel image can present itself as a PE/COFF image, so firmware loads it as an EFI program. On arm64 the stub is linked into the kernel Image itself. The kernel docs put it this way: since the EFI boot stub does a boot loader's job, "in a certain sense it IS the boot loader."
The kernel's own stub takes its command line from whoever starts it, and its only stub-specific parameter is initrd=, an absolute, backslash-separated path from the root of the ESP. A UKI wraps that kernel inside systemd-stub, which adds the embedded resources, measurement, addons and companion files. The kernel inside a UKI is still built with CONFIG_EFI_STUB.
Why does a UKI help Secure Boot?
UEFI Secure Boot verifies signatures on PE executables that the firmware loads. That covers the boot loader and, through shim's protocol, the kernel. It does not cover data files that a boot loader reads off disk.
In the familiar shim plus GRUB chain the result is a gap. Fedora's first UKI change proposal states it directly: with a UKI, the Secure Boot signature covers everything including the initrd, which is not the case when the initrd is loaded as a separate file from /boot. The kernel command line has the same problem. It sits in a GRUB configuration file, and GRUB offers an editor at boot. Someone who can write to /boot, or who has a keyboard in front of the machine, can change the initrd or the command line without breaking any signature.
That matters because the initrd decides how the root file system is found and unlocked, and the command line can switch off protections or point init at a different program. An attacker does not need to touch the signed kernel to change what the system does.
A UKI closes the gap in three ways.
- One signature over everything. UAPI.5 says that because UKIs are regular UEFI PE files, a single Secure Boot signature protects every embedded resource at once, and their combination. Standard tools such as sbsigntool and pesign sign them.
- A locked command line. The systemd-stub manual says that if Secure Boot is enabled and the
.cmdlinesection is present, any command line passed to the EFI binary as an invocation parameter is ignored. To allow overrides you must either disable Secure Boot or leave.cmdlineout of the image. If an override is accepted, it is measured into PCR 12. - Atomic updates. UAPI.5 points out that the ESP is a vFAT file system with weak data safety guarantees. Because a UKI is one file, the kernel, initrd and command line update together, so a crash cannot leave a new kernel paired with an old initrd.
There is a cost. A distribution-built UKI carries a generic initrd and command line, so anything host specific has to move into a locally signed UKI, a signed addon, encrypted credentials or discoverable partitions. The distribution section below covers those pressure points.
How does systemd-boot find and boot UKIs, and how does it compare with GRUB plus shim?
systemd-boot (sd-boot) is described in its manual as "a simple UEFI boot manager." It supports UEFI only. It reads its configuration and boot entries from the ESP, usually mounted at /efi/, /boot/ or /boot/efi/, and from XBOOTLDR if one exists. Everything it boots must sit on one of those two partitions, because firmware can only read FAT.
At each boot it assembles a menu from these sources, in the manual's words:
- Type #1 entries: text files in
/loader/entries/that describe a kernel and initrd, or any other EFI program. - Type #2 entries: UKIs in
/EFI/Linux/on the ESP and XBOOTLDR. - The Windows boot manager and the macOS boot manager, if installed.
- The EFI shell, if installed.
- A "Reboot Into Firmware Interface" entry, if the firmware supports it.
- Secure Boot key enrollment, if the firmware is in setup mode and key files are provided on the ESP.
There is no menu entry to write for a UKI. Drop a UKI into /EFI/Linux/ and it appears, titled and ordered from its .osrel and .uname data. That is the main practical difference from a GRUB menu, which is generated from scripts into grub.cfg.
Other features in the systemd-boot manual that matter for UKIs:
- Boot counting and automatic fallback. A UKI file name can carry a tries counter (for example
foo+3-0.efi). systemd-boot decrements it,systemd-bless-boot.servicemarks a boot good, and entries that run out of tries are skipped. A bad kernel update falls back to the previous one. - Boot loader interface.
systemctl reboot --boot-loader-entry=reboots into a chosen entry. - Secure Boot enrollment. When the firmware is in setup mode, systemd-boot can enroll Secure Boot variables from files on the ESP, and with the
secure-boot-enrolloption inloader.confit can do so automatically. The loader.conf manual warns that this option can soft-brick a device if used improperly, so test it on hardware you can recover, and read the own keys guide first. - A command line editor you can switch off. The menu's editor is enabled by default. The loader.conf manual says it "should be disabled if the machine can be accessed by unauthorized persons", with
editor no. - TPM measurement of its own configuration. The UAPI PCR registry lists systemd-boot measuring the
loader.confit used into PCR 5 and the kernel command line into PCR 12.
How GRUB plus shim differs
The shim plus GRUB chain is what most mainstream distributions ship for Secure Boot on general purpose hardware. Shim is a small first stage loader signed so that firmware with the common third party certificate trusts it. It carries the distribution's own certificate, verifies GRUB and then the kernel, and supports Machine Owner Keys (MOK) that a local administrator can enroll. Our post on why Windows updates can break Linux dual boot covers shim's SBAT revocation in detail.
The UAPI PCR registry shows how the two chains measure differently:
| Measured by | PCR | What |
|---|---|---|
| shim | 4 | The PE binary it chain loads |
| shim | 7 | Most of its non-MOK certificates and SBAT data |
| shim | 14 | MOK certificates and hashes |
| GRUB | 8 | Commands and the kernel command line |
| GRUB | 9 | Every file it reads, including the kernel |
| Linux kernel | 9 | All initrds passed to it through the newer LOAD_FILE2 protocol |
| systemd-boot | 5 | The loader.conf it used |
| systemd-boot | 12 | The kernel command line |
| systemd-stub | 11 | All UKI sections |
| systemd-stub | 12 | Command line overrides, credentials, addons, confexts |
| systemd-stub | 13 | System extension images for the initrd |
The difference that matters for disk unlock is predictability. GRUB's PCR 8 records every command it runs, which changes when grub.cfg is regenerated. PCR 9 records every file read. Those values are hard to calculate before a reboot. PCR 11 under systemd-stub only reflects the static content of one signed file, so it can be calculated, and signed, at build time.
UKIs and shim are not mutually exclusive either. systemd-stub accepts addons signed by keys in shim's own database or MOK list, and Fedora's second UKI proposal has shim load a UKI directly, with no GRUB or systemd-boot in between.
When to stay on GRUB
GRUB still does things systemd-boot does not. It reads many file systems, so kernels can live outside the ESP, it runs on BIOS machines, and it has a scripting language for unusual setups. Fedora's first proposal notes experimental GRUB patches to boot UKIs on x86_64 BIOS for hybrid cloud images. If your fleet depends on any of that, a staged move is more realistic than a switch. When GRUB itself breaks, our GRUB rescue and reinstall guide walks through recovery.
How do systemd-stub and systemd-measure predict PCR 11?
PCRs are registers that can only be extended, never written. Extending PCR n with data replaces its value with the hash of the old value concatenated with the hash of the new data. Start from zero, extend in a known order with known inputs, and you get a known result. Change anything, including the order, and the result changes. The TPM PCR post covers the mechanics and the event log.
What systemd-stub measures
UAPI.5 specifies the measurement precisely. The stub measures the sections in the listed order, starting from .linux. For each section it makes two measurements into PCR 11, both logged with the event type EV_IPL:
- The section name in ASCII, including one trailing NUL byte.
- The section's binary contents.
So the sequence is interleaved: .linux name, .linux data, .osrel name, .osrel data, and so on. Absent sections are skipped. .pcrsig is not measured, because it holds signatures over the result. If several .dtbauto sections exist, only the one actually used is measured.
The systemd-stub manual adds that nothing else uses PCR 11 at that stage, so its value can be calculated in advance with little effort. The UAPI PCR registry recommends PCR 11 for binding TPM policies to a specific kernel image, optionally with its embedded initrd, and to a boot phase.
Boot phases also go into PCR 11
PCR 11 is shared deliberately. After the stub, systemd-pcrphase measures boot phase strings into the same register as the system enters the initrd, leaves it, reaches sysinit and reaches ready. So a policy can say "unseal the root volume key only while still in the initrd." Once the system leaves the initrd, PCR 11 moves on and a process in the running system cannot ask the TPM for that key again. The ukify manual's examples sign the enter-initrd phase with an initrd key and the later phases with a separate system key.
How the prediction is calculated and signed
systemd-measure is described in its manual as a tool to "pre-calculate and sign expected TPM2 PCR 11 values for booted unified kernel images." Its manual marks it experimental. It has four commands:
| Command | What it does | Added in |
|---|---|---|
status | Shows the local TPM's current PCR 11 values (the default) | systemd 252 |
calculate | Predicts PCR 11 from component files, starting from a zero PCR | systemd 252 |
sign | Predicts and signs with an RSA key pair, writing JSON | systemd 252 |
policy-digest | Predicts and prints the TPM policy digest so it can be signed offline | systemd 258 |
Inputs are passed with --linux=, --osrel=, --cmdline=, --initrd=, --ucode=, --splash=, --dtb=, --uname=, --sbat=, --pcrpkey=, and, since systemd 257, --profile=, --dtbauto= and --hwids=. Only --linux= is mandatory. --bank= selects hash banks and defaults to sha1, sha256, sha384 and sha512. The manual warns that some operating systems disable SHA1 signatures, in which case signing for that bank fails. It also notes that sign needs a TPM present even though the result does not depend on any particular TPM.
The manual says you usually should not call it directly. ukify runs it during build when PCR keys are configured and embeds the output in .pcrsig. UAPI.5 defines that JSON: one object per hash bank, each holding an array of entries with pcrs (here, [11]), pkfp (the SHA-256 fingerprint of the signing public key in DER form), pol (the expected policy hash) and sig (the base64 signature).
How the booted system uses the signature
When a UKI carries .pcrsig and .pcrpkey, systemd-stub passes them to the kernel in a generated cpio archive as /.extra/tpm2-pcr-signature.json and /.extra/tpm2-pcr-public-key.pem, which a tmpfiles rule usually copies to /run/systemd/. systemd-cryptsetup@.service, systemd-cryptenroll and systemd-creds pick them up from there.
The binding happens once, at enrollment. systemd-cryptenroll --tpm2-public-key=PATH binds a LUKS slot to a signed PCR policy rather than to literal PCR values; if no key is passed, the manual says tpm2-pcr-public-key.pem is picked up from /etc/systemd/, /run/systemd/ or /usr/lib/systemd/. The manual frames the benefit: a vendor can ship a signed policy with each update, so secrets decrypt "when running any kernel+initrd signed by the vendor."
Why this survives kernel updates
Compare the two ways to seal a disk key:
| Approach | What the TPM checks at unlock | What happens on a kernel update |
|---|---|---|
Literal PCR binding (--tpm2-pcrs=) | PCR values equal the ones recorded at enrollment | Values change; the TPM refuses; you type the recovery key and re-enroll |
Signed PCR policy (--tpm2-public-key=) | PCR 11 equals a value signed by the trusted key | The new UKI carries a fresh signature for its own PCR 11; unlock works |
pcrlock policy (--tpm2-pcrlock=) | PCRs match any of the predicted variants stored in an NV index | Re-run prediction and update the NV policy before reboot |
The signed approach moves trust from "this exact kernel" to "any kernel the holder of this key built." That is a real trade. Whoever holds the PCR private key can produce a UKI that unlocks your disks, so treat it like the Secure Boot signing key. The ukify example of separate initrd and system keys exists so the more sensitive key, the one that unlocks the root volume in the initrd, can be held more tightly.
A worked example of the hashing
The following Python shows the shape of the calculation on toy data. Use systemd-measure for real values; it matches exactly how the stub reads each section.
import hashlib
def extend(pcr: bytes, data: bytes) -> bytes:
# TPM extend: new = H(old || H(data))
return hashlib.sha256(pcr + hashlib.sha256(data).digest()).digest()
pcr11 = bytes(32) # PCR 11 starts at all zeros
sections = [
(".linux", b"<kernel image bytes>"),
(".osrel", b'ID=example\nVERSION_ID=1\n'),
(".cmdline", b"quiet rw"),
(".initrd", b"<initrd bytes>"),
]
for name, data in sections:
pcr11 = extend(pcr11, name.encode() + b"\x00") # name with trailing NUL
pcr11 = extend(pcr11, data) # then the contents
print(pcr11.hex())
Change quiet rw to quiet rw init=/bin/sh and the final value changes, so a signed policy for the original image no longer matches. Swap the order of .cmdline and .initrd and it also changes, which is why UAPI.5 fixes the order.
systemd-pcrlock: predicting more than PCR 11
systemd-pcrlock, also marked experimental and added in systemd 255, solves a wider problem. It reads the firmware event log (/sys/kernel/security/tpm0/binary_bios_measurements), the userspace log (/run/log/systemd/tpm2-measure.log), the current PCR values and a set of .pcrlock component definition files. It matches log records to components, and for each PCR where every record is accounted for it predicts future values, allowing several variants per component, for example two kernel versions at once. It turns the prediction into a TPM policy of PolicyPCR and PolicyOR terms and stores it in a TPM NV index. Disk encryption is then bound with PolicyAuthorizeNV through systemd-cryptenroll --tpm2-pcrlock= or systemd-repart.
The manual notes this needs a TPM implementing PolicyAuthorizeNV, meaning TPM 2.0 specification version 1.38 or newer. Its lock-* commands, such as lock-firmware-code, lock-secureboot-policy, lock-gpt and lock-uki, write component definitions.
The two approaches fit together. Signed PCR 11 policies cover "which kernel"; pcrlock can additionally cover firmware, Secure Boot state and partition table.
Which PCRs a UKI boot touches
The systemd-stub manual warns that the same data can be measured more than once: the firmware measures the whole UKI as a PE image into PCR 4, the stub measures its sections into PCR 11, and the kernel measures every initrd it receives into PCR 9. An embedded initrd therefore appears in PCRs 4, 9 and 11, and credentials from companion files in PCRs 9 and 12. The stub records the PCRs it used in EFI variables (StubPcrKernelImage, normally 11; StubPcrKernelParameters, normally 12; StubPcrInitRDSysExts, normally 13), and systemd-pcrosseparator.service extends PCRs 0 to 7, 9 and 12 to 14 with the word os-separator when userspace first sees the TPM, so firmware and OS measurements stay distinguishable.
Everything before the UKI still counts. The registry lists firmware code in PCR 0, configuration in PCR 1, and option ROMs on pluggable hardware in PCR 2, which our PCI option ROMs post covers in depth. A UKI needs UEFI services to start, so on a machine running coreboot it depends on a UEFI payload such as edk2.
What are addons, credentials and extensions, and what can change without re-signing?
A distribution-signed UKI is identical on every machine. Real machines still need local settings. systemd-stub offers four ways to supply them, each with a different trust model. It looks for "companion files" next to the UKI in a directory named after it: for foo.efi, the directory is foo.efi.extra.d/. Boot counters in the file name are ignored, so foo+3-0.efi still uses foo.efi.extra.d/. Global versions live under /loader/ on the ESP.
PE addons
UAPI.5 defines addons as ordinary PE UEFI binaries, authenticated through normal Secure Boot logic, that carry one or more of .cmdline, .dtb, .dtbauto, .ucode or .initrd. They must not contain .linux, which is how they are told apart from UKIs. They may contain a .text section so that running one by mistake prints a friendly message.
Rules from the specification and the systemd-stub manual:
- Addons are applied sorted by file name. Command lines are appended in order: the UKI's own
.cmdline, then global addons in/loader/addons/, then UKI-specific addons infoo.efi.extra.d/. - Microcode addons go in reverse order, because the kernel's microcode loader stops at the first matching file name.
- With Secure Boot on, addons are checked against the UEFI db, shim's db or shim's MOK list, and only loaded if they pass.
- If both the addon and the UKI have
.unamesections, the addon is rejected unless they match exactly. That pins an addon to one kernel build. - Addon data is measured into PCR 12.
The systemd-stub manual is candid about one weakness: "the filename is not protected by the PE signature." Someone with write access to the ESP could rename signed addons to change their order, which matters if options are order dependent. Its advice is to watch PCR 12 values through an attestation service and revoke misused addons.
For revocation, the manual recommends always adding an .sbat section to signed addons, so they can be revoked by an SBAT policy update instead of a DBX or MOKX entry. ukify adds a default SBAT entry to addons if you do not pass one. The shim project's SBAT document explains why that matters: revoking images one hash at a time fills the firmware's limited dbx storage, so SBAT attaches component names and generation numbers to each binary and revokes everything below a minimum generation with one small policy update.
Credentials
Files ending in .cred in foo.efi.extra.d/ or /loader/credentials/ are packed into a cpio archive at /.extra/credentials/ or /.extra/global_credentials/ in the initrd and measured into PCR 12. They are not signed. The protection is encryption: the systemd-stub manual says they should be encrypted and authenticated through the TPM with systemd-creds encrypt -T. A credential sealed that way only decrypts on the machine and in the boot state it was sealed for. Fedora's proposal names credentials as one way to supply secrets and configuration that used to be baked into a host-specific initrd, for example for iSCSI root.
System and configuration extensions
*.sysext.raw files are disk images that extend /usr in the initrd, measured into PCR 13. *.confext.raw files extend /etc, measured into PCR 12. The manual says they should be signed dm-verity images, so the kernel checks every block as it is read.
Summary: what you can change, and how
| Change you want | Re-sign the UKI? | Mechanism | Trust check | PCR |
|---|---|---|---|---|
| Kernel, embedded initrd, embedded command line | Yes | Rebuild with ukify | Secure Boot signature on the UKI | 11 |
| Add a command line option on one machine | No | Signed addon with .cmdline | Secure Boot (db, shim db or MOK) | 12 |
| Add a driver or file to early boot | No | Signed addon with .initrd, or a sysext | Secure Boot, or dm-verity signature | 12 or 13 |
| Ship a secret or setting to the initrd | No | Encrypted credential | TPM sealing with systemd-creds | 12 |
| Override the command line at the boot menu | Not possible with Secure Boot on and .cmdline present | Edit in systemd-boot | Ignored by the stub | 12 if accepted |
| Pick a recovery or factory reset mode | No, if built in | Multi-profile UKI | Covered by the UKI signature | 11, profile number into 12 |
What are multi-profile UKIs?
UAPI.5 defines an optional extension where one UKI holds several profiles, separated by .profile sections. Sections before the first .profile form the base, and each profile can override any base section. Prefixing the stub's arguments with @1 selects profile 1; with no selector, @0 is used. The selector is stripped before the command line reaches the kernel. Only the selected profile's sections plus the base are measured into PCR 11, and the systemd-stub manual says a non-zero profile number is measured into PCR 12.
The specification's example has three profiles: regular boot, factory reset (systemd.unit=factory-reset.target) and Storage Target Mode. A .profile section can carry ID= and TITLE= for the boot menu, and the specification recommends a separate .pcrsig per profile. This is how you offer a recovery or debug command line without unlocking edits: put it inside the signed image.
Step by step: build a UKI, sign it, install it and check the measurements
The walkthrough below uses systemd's own tools, following the ukify, kernel-install and systemd-measure manuals. Paths follow those manuals. Your distribution may use different kernel and initrd paths, and package names vary (on Arch, ukify is in systemd-ukify).
Warning: these steps change how your machine boots. Keep a working boot entry, a live USB and your LUKS recovery key on hand before you start. Do not delete your current boot loader until the new path has booted successfully several times.
Step 1: Check what you have
# Is the system booted in UEFI mode, and is Secure Boot on?
bootctl status
# Which TPM is present, and which PCR banks are active?
systemd-analyze has-tpm2
systemd-analyze pcrs
# Find the ESP and XBOOTLDR mount points
bootctl --print-esp-path
bootctl --print-boot-path
bootctl status shows the firmware, Secure Boot state, the current boot loader and the ESP. Note how much free space the ESP has. A UKI with an embedded initrd is often tens of megabytes, and you will want room for at least two.
Step 2: Create signing keys
Keep keys off the ESP. The ukify manual's example puts them in /etc/kernel/ and /etc/systemd/, readable only by root.
sudo tee /etc/kernel/uki.conf >/dev/null <<'EOF'
[UKI]
SecureBootPrivateKey=/etc/kernel/secureboot-private-key.pem
SecureBootCertificate=/etc/kernel/secureboot-certificate.pem
[PCRSignature:initrd]
Phases=enter-initrd
PCRPrivateKey=/etc/systemd/tpm2-pcr-initrd-private-key.pem
PCRPublicKey=/etc/systemd/tpm2-pcr-initrd-public-key.pem
[PCRSignature:system]
Phases=enter-initrd:leave-initrd enter-initrd:leave-initrd:sysinit
enter-initrd:leave-initrd:sysinit:ready
PCRPrivateKey=/etc/systemd/tpm2-pcr-private-key-system.pem
PCRPublicKey=/etc/systemd/tpm2-pcr-public-key-system.pem
EOF
sudo ukify genkey --config=/etc/kernel/uki.conf
ukify genkey writes the Secure Boot private key and certificate and both PCR key pairs. The Secure Boot certificate must then be trusted by firmware: either enroll it in db with your own keys, as our own keys guide describes, or enroll it as a MOK if you boot through shim. In a production setting, keep these keys in a hardware token or an offline signing host; ukify supports --signing-engine= and --signing-provider= for that, and systemd-measure policy-digest exists so PCR policies can be signed offline.
Step 3: Build a UKI by hand
KVER=$(uname -r)
sudo ukify build \
--linux=/usr/lib/modules/$KVER/vmlinuz \
--initrd=/boot/initramfs-$KVER.img \
--cmdline='root=UUID=<your-root-uuid> rw quiet' \
--os-release=@/etc/os-release \
--uname=$KVER \
--config=/etc/kernel/uki.conf \
--output=/tmp/test-$KVER.efi
Replace the kernel and initrd paths with your distribution's. If your root partition uses discoverable partition type GUIDs, you can leave root= out entirely. ukify signs with sbsign by default; --signtool= also accepts pesign and systemd-sbsign. With PCR keys configured it calls systemd-measure and embeds .pcrsig and .pcrpkey.
The manual's minimal example, with only --linux, --initrd and --cmdline, produces an unsigned vmlinuz.unsigned.efi; with a Secure Boot key it names the output with .signed.efi unless you pass --output.
Step 4: Inspect it
ukify inspect /tmp/test-$KVER.efi
ukify inspect --json=short /tmp/test-$KVER.efi
sbverify --list /tmp/test-$KVER.efi
ukify inspect lists the sections and their contents. Check that .cmdline says what you expect, that .uname matches, and that .pcrsig and .pcrpkey are present if you configured PCR keys. sbverify --list shows the Authenticode signature.
Step 5: Test boot it in a virtual machine first
The ukify manual shows that QEMU with OVMF firmware can boot a UKI directly through -kernel:
qemu-kvm \
-drive if=pflash,format=qcow2,readonly=on,file=/usr/share/edk2/ovmf/OVMF_CODE_4M.qcow2 \
-kernel /tmp/test-$KVER.efi
The firmware path differs between distributions. This catches a broken initrd or command line before you touch the real ESP.
Step 6: Install systemd-boot and the UKI with kernel-install
Warning:
bootctl installwrites to the ESP and adds a UEFI boot entry. Before running it, confirm the ESP path and device withbootctl --print-esp-pathandfindmnt "$(bootctl --print-esp-path)", and make sure you are not pointing at a removable disk or another operating system's partition. It does not remove GRUB, but it may change the default boot order.
# Confirm the ESP device first
findmnt "$(bootctl --print-esp-path)"
sudo bootctl install
# Tell kernel-install to produce UKIs with ukify
echo 'layout=uki' | sudo tee /etc/kernel/install.conf
echo 'uki_generator=ukify' | sudo tee -a /etc/kernel/install.conf
sudo cp /proc/cmdline /etc/kernel/cmdline # then edit: remove BOOT_IMAGE= and initrd= items
sudo kernel-install add "$KVER" /usr/lib/modules/$KVER/vmlinuz
ls "$(bootctl --print-boot-path)"/EFI/Linux/
bootctl list
With layout=uki, the 60-ukify.install plugin builds the UKI using /etc/kernel/uki.conf and 90-uki-copy.install copies it to $BOOT/EFI/Linux/ENTRY-TOKEN-KERNEL-VERSION.efi, according to the kernel-install manual. The Arch wiki warns not to set the command line in uki.conf, where it is ignored; kernel-install takes it from /etc/kernel/cmdline. Check the generated command line before rebooting.
Step 7: Check the measurements after reboot
# Which PCRs did the stub use? (EFI variables, read by bootctl)
bootctl status | grep -iE 'stub|measured|tpm'
# Compare the live PCR 11 with what the tool expects
/usr/lib/systemd/systemd-measure status
/usr/lib/systemd/systemd-measure calculate \
--linux=/usr/lib/modules/$KVER/vmlinuz \
--initrd=/boot/initramfs-$KVER.img \
--cmdline=/etc/kernel/cmdline \
--osrel=/etc/os-release \
--uname=<(echo -n $KVER) --bank=sha256
# The firmware and stub events, from the event log
sudo /usr/lib/systemd/systemd-pcrlock log
sudo tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements | less
Note that after the system finishes booting, PCR 11 has also absorbed the boot phase strings, so status will not equal the plain calculate output. That is expected. systemd-pcrlock log matches each event to a component and shows which PCRs are fully recognized. tpm2_eventlog, from tpm2-tools, prints the raw firmware event log, where you will see one EV_IPL pair per UKI section in PCR 11.
Step 8: Bind disk unlock to the signed policy
Warning: this adds a key slot to a LUKS volume. Confirm the device with
lsblk -fandcryptsetup luksDump /dev/<your-luks-partition>first, and make sure you have a working passphrase or recovery key slot before adding a TPM slot.
lsblk -f
sudo cryptsetup luksDump /dev/nvme0n1p3 # replace with your LUKS partition
sudo systemd-cryptenroll /dev/nvme0n1p3 --recovery-key
sudo systemd-cryptenroll /dev/nvme0n1p3 \
--tpm2-device=auto \
--tpm2-public-key=/etc/systemd/tpm2-pcr-public-key-system.pem \
--tpm2-pcrs=7 --tpm2-with-pin=yes
This binds unlock to "PCR 11 signed by the system key" and additionally to the literal value of PCR 7, the Secure Boot state. The cryptenroll manual says --tpm2-public-key-pcrs= defaults to 11 when not given, which binds the policy to any UKI that comes with a valid PCR signature. --tpm2-with-pin=yes adds a PIN, which the manual says is hardened with Argon2id before it reaches the TPM. Add tpm2-device=auto to the volume's line in /etc/crypttab, rebuild the UKI so the initrd picks up the change, and test with the recovery key ready.
How do mainstream distributions support UKIs, and what breaks?
Support depends on the distribution, and the documentation moves quickly. What follows describes each project's own documents as fetched on 23 October 2026.
Fedora
Fedora's "Unified Kernel Support Phase 1" change targeted Fedora Linux 38. It moved initrd generation from the installed machine to the kernel package build, shipping the result inside a UKI in an optional sub-package (kernel-uki-virt) aimed at virtual machines, where the driver set is small and well defined. The proposal says removing support for non-UKI kernels is "NOT planed" (sic).
"Phase 2" targeted Fedora Linux 40. It added booting UKIs directly from shim, with no GRUB or systemd-boot involved, enabled UKIs on aarch64, and added a UEFI-only cloud image variant using UKIs that the page calls suitable for confidential VMs.
Arch Linux
The Arch wiki documents several ways to build UKIs locally: mkinitcpio presets (default_uki= and fallback_uki=, renamed from PRESET_efi_image in November 2022 according to the wiki), kernel-install with layout=uki and systemd-ukify, dracut, and ukify directly. Because Arch builds the UKI on the machine, it also signs it locally with whatever key the owner enrolled. That is the opposite trade from Fedora's centrally built images: full local flexibility, with key custody on the machine.
Ubuntu and Debian
UKI support is less settled here, and we could not find a current first party guide. Ubuntu's wiki page for unified kernel images returned an empty page when we fetched it, after the project's wiki migration, and Debian's wiki blocked scripted access. What we could confirm is packaging. The Debian archive carries systemd-ukify in main, including a 257.13 build for Debian 13 and 262 builds in the development suites. The Ubuntu archive carries systemd-ukify in the universe component, with builds from 257.4 through 261.3 in the pool on 23 October 2026. Universe means community maintained rather than covered by Canonical's main archive support, which matters if you plan a production rollout. Both distributions' installers still set up shim plus GRUB for Secure Boot, so on either one a UKI setup is something you build with the steps above and maintain yourself.
What breaks, and how to work around it
Fedora's Phase 1 proposal names the cases that depend on a host-specific initrd or command line:
- Optional initrd modules. Features that need optional dracut modules require an initrd rebuild to enable them. A shared UKI cannot carry every option. Workarounds: build the UKI locally, or deliver extras as signed
.initrdaddons or sysext images. - Configuration or secrets baked into the initrd, such as iSCSI root. Workaround: encrypted credentials from the ESP.
- Configuration on the kernel command line, the root file system being the most important. Workaround: discoverable partitions remove the need for
root=; signed.cmdlineaddons cover the rest.
Three more practical breakages come up often:
- Out of tree kernel modules (DKMS and similar). Modules built on the machine are not in a distribution-built initrd. If one is needed in early boot, for storage or early graphics, you need a locally built UKI or a signed initrd addon. Module signing rules under Secure Boot still apply; check your distribution's documentation.
- Custom command lines. With Secure Boot on and
.cmdlineembedded, nothing typed at the menu takes effect. Plan debug and recovery options as profiles or signed addons in advance. - Dual boot and ESP size. UKIs with embedded initrds live on the ESP or XBOOTLDR. An ESP created small by another operating system's installer can fill up after two or three kernels. The Boot Loader Specification's answer is an XBOOTLDR partition, which systemd-boot also searches for
/EFI/Linux/. systemd-boot lists the Windows boot manager automatically if it is on the same ESP. Keep firmware boot entries for both systems so you are not dependent on one menu, and read our dual boot and SBAT post before mixing shim and your own keys.
Comparison: GRUB plus shim, systemd-boot plus UKI, and direct EFI stub boot
| Aspect | GRUB plus shim | systemd-boot plus UKI | Direct EFI stub boot (firmware or shim loads a kernel or UKI) |
|---|---|---|---|
| What Secure Boot signs | shim, GRUB and the kernel | systemd-boot and the UKI, which includes initrd and command line | The kernel or UKI only |
| initrd covered by signature | No, separate file | Yes, if embedded | Yes for a UKI; no for a bare stub kernel with initrd= |
| Command line protected | No, from grub.cfg and editable at boot | Yes, edits ignored when Secure Boot is on and .cmdline exists | Yes for a UKI with .cmdline; no for a bare stub kernel |
| Main measurement PCRs | 4, 7, 8, 9, 14 | 4, 5, 11, 12, 13 | 4 and 11 (UKI) or 4 and 9 |
| Predictable unlock policy | Hard; PCR 8 and 9 change with config and files | Yes; signed PCR 11 policies | Yes for a UKI |
| Boot menu | Generated grub.cfg, scripting | Auto-discovered entries, boot counting | Firmware boot menu only |
| Recovery | Rescue shell, many file systems | Fallback to older entries, profiles, EFI shell entry | Firmware menu, a second boot entry |
| File systems for kernels | Many | FAT on ESP or XBOOTLDR only | FAT on the ESP only |
| Firmware | UEFI and BIOS, several architectures | UEFI only | UEFI only |
| Local key management | Distribution keys plus MOK | Own keys in db, or MOK through shim | Own keys in db, or MOK through shim |
| Distribution support | Default on most general purpose distributions | Supported, opt in on most; documented on Arch and Fedora | Fedora cloud images via shim; VMs and appliances |
There is no universal winner. For a laptop with full disk encryption where you control the keys, systemd-boot plus UKI gives the strongest binding between what booted and what unlocks. For a server fleet on mixed firmware, GRUB plus shim is still the safe default. For VMs and confidential computing, direct UKI boot is the simplest path, which is where Fedora started.
Timeline
Release dates for systemd come from the project's GitHub release records; the "added in version" facts come from each tool's manual.
| Date | Change | Source |
|---|---|---|
| 31 Oct 2022 | systemd 252: systemd-measure with status, calculate and sign | systemd-measure manual; GitHub release |
| November 2022 | Arch mkinitcpio PRESET_efi_image options renamed PRESET_uki | ArchWiki |
| Fedora Linux 38 cycle | UKI Phase 1 targeted: kernel-uki-virt sub-package for VMs | Fedora change page |
| 15 Feb 2023 | systemd 253: kernel-install layout=uki | kernel-install manual; GitHub release |
| 28 Jul 2023 | systemd 254: ukify config files, --signtool, kernel-install uki_generator= | ukify and kernel-install manuals; GitHub release |
| 6 Dec 2023 | systemd 255: systemd-pcrlock | systemd-pcrlock manual; GitHub release |
| Fedora Linux 40 cycle | UKI Phase 2 targeted: shim boots UKIs directly, aarch64, UEFI cloud image | Fedora change page |
| 10 Dec 2024 | systemd 257: profile, .dtbauto and .hwids inputs for systemd-measure | systemd-measure manual; GitHub release |
| 17 Sep 2025 | systemd 258: systemd-measure policy-digest for offline signing | systemd-measure manual; GitHub release |
| 22 Sep 2026 | systemd 262: the manual pages used for this guide | freedesktop.org; GitHub release |
Common mistakes
- Signing the UKI but leaving
.cmdlineout "for flexibility". Without an embedded command line, the stub accepts one from the boot loader, measured into PCR 12. Anyone who can edit the boot entry controlsinit=and similar options. If you need flexibility, use profiles or signed addons. - Binding LUKS to literal PCR 11 values. It works until the next kernel update, then every machine asks for a recovery key. Use
--tpm2-public-key=for PCR 11, or pcrlock. - Binding to too few PCRs. PCR 11 says which kernel booted, not whether Secure Boot was on. Pair it with PCR 7, or a pcrlock policy, so a machine with Secure Boot disabled does not unlock.
- Storing signing keys on the ESP or in a world readable directory. The PCR signing key can unlock disks indirectly. Keep it with the Secure Boot key, ideally on a token or offline host.
- Forgetting the recovery key. Enroll a recovery key with
systemd-cryptenroll --recovery-keybefore adding TPM slots, and store it away from the machine. - Running out of ESP space. Distribution-sized ESPs can hold only a few UKIs. Check free space before enabling UKIs, and consider XBOOTLDR.
- Shipping addons without SBAT. Without an
.sbatsection, the only way to revoke a signed addon is a DBX or MOKX entry. Let ukify add SBAT, or set your own. - Leaving the systemd-boot editor available on shared machines. With Secure Boot and an embedded command line edits are ignored, but on Type #1 entries they are not. Set
editor noinloader.confwhere the console is not trusted.
FAQ
What is a unified kernel image in Linux?
It is a single UEFI executable that contains an EFI boot stub, the Linux kernel and, optionally, the initrd, kernel command line, os-release data, splash image, devicetree and SBAT data, each in its own PE section. The UAPI.5 specification defines the format and systemd-stub is the reference stub.
Is a UKI more secure than GRUB?
It closes specific gaps. In the shim plus GRUB chain the initrd and command line are not covered by a signature. In a UKI they are, and the stub ignores command line overrides when Secure Boot is on and .cmdline is embedded. A UKI does not fix weak keys, a disabled Secure Boot or an unpatched kernel.
Why does my TPM ask for the recovery key after every kernel update?
Your LUKS slot is probably bound to literal PCR values. A new kernel changes them. Re-enroll with systemd-cryptenroll --tpm2-public-key= so unlock depends on a signed PCR 11 policy carried in each new UKI, or use systemd-pcrlock to predict the new values before you reboot.
Which PCR does systemd-stub measure the kernel into?
PCR 11, for every UKI section from .linux onward. The firmware also measures the whole UKI into PCR 4, and the kernel measures the initrds it receives into PCR 9. Command line overrides, credentials and addons go into PCR 12, and system extensions into PCR 13.
Can I change kernel parameters on a UKI without rebuilding it?
Yes, with a signed PE addon that carries a .cmdline section. Put it in foo.efi.extra.d/ for one UKI or /loader/addons/ on the ESP for all of them. With Secure Boot on, it must be signed by a key in db, shim's db or MOK. It is measured into PCR 12.
How do I build a unified kernel image with ukify?
Run ukify build --linux=<kernel> --initrd=<initrd> --cmdline='<options>'. Add --secureboot-private-key= and --secureboot-certificate= to sign it, and --pcr-private-key= with --pcr-public-key= to embed a signed PCR 11 policy. Use ukify inspect to check the result.
Does a UKI work with DKMS kernel modules?
A distribution-built UKI contains a generic initrd, so locally built modules are not in it. Modules loaded after the root file system mounts keep working as before, subject to your distribution's module signing rules under Secure Boot. Modules needed in early boot require a locally built UKI or a signed initrd addon.
What is the difference between systemd-measure and systemd-pcrlock?
systemd-measure predicts and signs PCR 11 for one UKI, and the signature travels inside the UKI. systemd-pcrlock predicts many PCRs from the event log and component files and stores the allowed values in a TPM NV index. Both are marked experimental in their manuals.
Where Safeguard fits
Safeguard does not build, sign, measure or scan UKIs, boot loaders or firmware, and it does not manage TPMs or disk encryption. The fit is indirect: the scripts and container images that build UKIs in a pipeline are ordinary software projects with open source dependencies. Safeguard can scan those repositories and container images for known vulnerabilities with safeguard scan --dir . or --image, show which projects contain a given component version, and apply policies and gates before the pipeline signs anything.
Measured boot proves that the kernel and initrd you signed are the ones that ran. It says nothing about whether the packages inside that initrd, or the tools that built it, carried known vulnerabilities, so supply chain hygiene still applies to every component you sign. The section below is the same remediation guidance we publish with every post, and it applies to the open source dependencies and container images in your build and signing pipeline rather than to the boot chain itself.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The demos below show Safeguard on ordinary software projects, not on kernel images or boot chains. They apply to the repositories around a UKI rollout: the build container that runs ukify, the signing and kernel-install scripts, and any tooling you maintain for PCR policy signing.
The first demo is a real Safeguard CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repository, and it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. It ends with /permissions, /model and /scan. The same loop suits a boot tooling repository where every change should be reviewed.
Click through it at your own pace, or open it full screen.
Signing hosts for Secure Boot and PCR keys are usually kept off the general network. The local runner demo shows how to set up the runner on your own machine, approve it with its device code, and then scan from the terminal. A runner on a build host can scan the build tree and containers that live there without sending keys anywhere.
Click through it at your own pace, or open it full screen.
If your team uses Claude, the third demo shows how to connect Claude to the Safeguard MCP server with OAuth and choose which tools Claude can use. An engineer can then ask about known vulnerabilities in the projects that hold your UKI build and signing tooling, using only the tools you allowed.
Click through it at your own pace, or open it full screen.
To try it on your own repositories, download Safeguard and follow the CLI documentation.
Quick check
Secure Boot is on and your UKI has an embedded .cmdline. You press e in systemd-boot and add init=/bin/sh. What happens?
The edit is ignored. The systemd-stub manual says that with Secure Boot enabled and a .cmdline section present, command lines passed to the UKI are not used. The embedded command line is what the kernel receives.
Why can systemd-measure predict PCR 11 but not PCR 8 under GRUB?
PCR 11 under systemd-stub only receives the names and contents of the UKI's sections in a fixed order, all known at build time. GRUB measures every command it runs and the command line into PCR 8, which change whenever its configuration is regenerated.
Sources
- UAPI Group: UAPI.5 Unified Kernel Images (UKI)
- UAPI Group: UAPI.1 Boot Loader Specification
- UAPI Group: UAPI.7 Linux TPM PCR Registry
- systemd manual: ukify(1)
- systemd manual: systemd-stub(7)
- systemd manual: systemd-boot(7)
- systemd manual: systemd-measure(1)
- systemd manual: systemd-pcrlock(8)
- systemd manual: systemd-cryptenroll(1)
- systemd manual: kernel-install(8)
- Linux kernel documentation: The EFI Boot Stub
- shim project: SBAT
- Fedora: Changes/Unified Kernel Support Phase 1
- Fedora: Changes/Unified Kernel Support Phase 2
- ArchWiki: Unified kernel image
- ArchWiki: systemd-boot
- systemd manual: loader.conf(5)
- systemd manual: bootctl(1)
- systemd manual: systemd-analyze(1)
- systemd GitHub releases (release dates for v252 to v262)
- Debian archive: systemd source package pool
- Ubuntu archive: systemd universe pool
Last reviewed: 23 October 2026. systemd-measure and systemd-pcrlock are marked experimental, and distribution UKI support changes between releases; check the manuals for your systemd version and your distribution's documentation before rolling out.