## Compress the initramfs with zstd by default on Fedora Use `zstd` to compress the initramfs for all Fedora variants by default when built with `dracut`. For more information about the change, see https://fedoraproject.org/wiki/Changes/InitrdZstdDefault. I have tested the commands available below for `initramfs-6.15.4-200.fc42.x86_64.img` on several platforms. For the Zstandard compression algorithm, the commands executed to compress images are: ```bash= sudo dracut --force --regenerate-all --parallel "--compress=zstd -3 --threads=0" sudo dracut --force --regenerate-all --parallel "--compress=zstd -5 --threads=0" sudo dracut --force --regenerate-all --parallel "--compress=zstd -10 --threads=0" sudo dracut --force --regenerate-all --parallel "--compress=zstd -15 --threads=0" sudo dracut --force --regenerate-all --parallel "--compress=zstd -19 --threads=0" ``` For the Gzip compression algorithm, the command executed to decompress the image is: `gzip --decompress --stdout > /dev/null initramfs-6.15.4-200.fc42.x86_64.img` For the Zstandard compression algorithm, the command executed to decompress the images is: `unzstd --stdout > /dev/null initramfs-6.15.4-200.fc42.x86_64.img` **Note:** The times listed in the "Mean [ms]", "Min. [ms]", and "Max. [ms]" columns in the following tables are for decompression. ### Fedora Cloud 42 on QEMU/KVM VM with 2 vCPUs and 4 GB RAM | Size [MiB] | Tool | Algorithm | Level | Mean [ms] | Min [ms] | Max [ms] | |:--- |:--- |:--- |:--- |---: |---: |---: | | 48 |`gzip`| Gzip | 9 |467.8 ± 1.5| 465.8 | 471.3 | | 47 |`zstd`| Zstandard | 3 |60.4 ± 1.2 | 58.8 | 67.1 | | 46 |`zstd`| Zstandard | 5 |62.9 ± 1.7 | 60.6 | 69.3 | | 45 |`zstd`| Zstandard | 10 |62.2 ± 1.4 | 60.2 | 67.3 | | 45 |`zstd`| Zstandard | 15 |61.8 ± 1.2 | 59.5 | 66.1 | | 43 |`zstd`| Zstandard | 19 |78.3 ± 1.2 | 76.8 | 82.8 | ### Fedora KDE 42 on bare metal machine with Intel Pentium CPU G4560 and 12 GB RAM | Size [MiB] | Tool | Algorithm | Level | Mean [ms] | Min [ms] | Max [ms] | |:--- |:--- |:--- |:--- |---: |---: |---: | | 75 |`gzip`| Gzip | 9 |807.1 ± 2.0| 805.7 | 812.0 | | 75 |`zstd`| Zstandard | 3 |134.6 ± 3.0| 131.0 | 141.4 | | 74 |`zstd`| Zstandard | 5 |141.2 ± 2.2| 136.9 | 143.6 | | 73 |`zstd`| Zstandard | 10 |146.8 ± 1.6| 144.4 | 148.9 | | 73 |`zstd`| Zstandard | 15 |148.1 ± 2.7| 145.0 | 155.1 | | 71 |`zstd`| Zstandard | 19 |177.0 ± 1.9| 174.1 | 179.5 | --- ### Testing initramfs with zstd on Fedora Atomic Desktops **Note:** Fedora Atomic Desktops bootable container images are still considered experimental. It is recommended to use a discarded or virtual machine. Install Fedora Kinoite and create the directory `~/initrd_with_zstd_by_default` and in it a `Containerfile` with the following content: ```= FROM quay.io/fedora-ostree-desktops/kinoite:42 RUN <<EORUN set -xeuo pipefail dnf --assumeyes --refresh install zstd kver=$(ls /usr/lib/modules) stock_arguments=$(lsinitrd "/lib/modules/${kver}/initramfs.img" |\ grep --extended-regexp '^Arguments: ' |\ sed 's/^Arguments: //') mkdir --parents /tmp/dracut /var/roothome bash <(/usr/bin/echo "dracut ${stock_arguments}") mv --verbose /boot/initramfs*.img "/lib/modules/${kver}/initramfs.img" dnf clean all rm --recursive --force /var/* /tmp/* bootc container lint --no-truncate EORUN ``` Build a bootable container image: `sudo podman image build --tag localhost/fedora-kinoite:42-initramfs-zstd --file ~/initrd_with_zstd_by_default/Containerfile` Switch to the built container image and reboot the system: `sudo bootc switch --apply --transport containers-storage localhost/fedora-kinoite:42-initramfs-zstd` --- ### Testing initramfs with zstd on Fedora Cloud I modified [fedora-kiwi-descriptions](https://pagure.io/fedora-kiwi-descriptions) for the `Cloud-Base-Generic` image profile to include a local repository containing the RPMs from the x86_64 build of the [Draft: Add require on zstd to use it for initrd compression](https://src.fedoraproject.org/rpms/dracut/pull-request/85) PR, and the file `initramfs-compression-test.py`, the contents of which are at the bottom of this page. --- ### Testing initramfs with zstd on Fedora IoT When I build a container image from the following Containerfile and a qcow2 image from it, the initramfs in the virtual machine is compressed using Zstandard. The `dracut-rpms` directory contains the x86_64 build of the [Draft: Add require on zstd to use it for initrd compression](https://src.fedoraproject.org/rpms/dracut/pull-request/85) PR, and the contents of `initramfs-compression-test.py` are at the bottom of this page. ```= FROM quay.io/fedora/fedora-iot:rawhide COPY initramfs-compression-test.py /usr/libexec/ COPY dracut-rpms /tmp/dracut-rpms RUN <<EORUN set -xeuo pipefail export DRACUT_NO_XATTR=1 dnf --assumeyes reinstall --allowerasing /tmp/dracut-rpms/dracut* kver=$(ls /usr/lib/modules) stock_arguments=$(lsinitrd "/lib/modules/${kver}/initramfs.img" |\ grep --extended-regexp '^Arguments: ' |\ sed 's/^Arguments: //') mkdir --parents /tmp/dracut /var/roothome bash <(/usr/bin/echo "dracut ${stock_arguments}") mv --verbose /boot/initramfs*.img "/lib/modules/${kver}/initramfs.img" dnf clean all rm --recursive --force /var/* /tmp/* /boot/* bootc container lint --no-truncate EORUN ``` --- The following Python script aims to simplify and automate to some extent the testing of initramfs compression on Fedora Linux. ```python= #! /usr/bin/env python3 import os from pathlib import Path import re import subprocess def main(): if os.getuid() != 0: raise SystemExit(f"\n Root access is required to test initramfs compression.\n") determine_initramfs_compression() def get_initramfs_paths(): initramfs_paths = [] ostree_booted = Path("/run/ostree-booted") if ostree_booted.exists(): print(f"\n Fedora Linux operates in image mode.\n") entries_dir = Path("/boot/loader/entries") for entry in entries_dir.iterdir(): ostree_conf = entry.read_text() initrd_re_compile = re.compile(r"^initrd\b.+\.img.*", re.MULTILINE) initrd_line = re.search(initrd_re_compile, ostree_conf) initramfs_path_image_mode = ostree_conf[initrd_line.start():initrd_line.end():].replace("initrd ", "/boot") initramfs_paths.append(initramfs_path_image_mode) else: print(f"\n Fedora Linux operates in package mode.\n") initramfs_paths_package_mode = list(Path("/boot").glob("initramfs*")) for initramfs_path in initramfs_paths_package_mode: initramfs_paths.append(str(initramfs_path)) return initramfs_paths def determine_initramfs_compression(): FILE_SIGNATURES = { "Gzip": r"\x1f\x8b\x08", "XZ": r"\xfd\x37\x7a\x58\x5a\x00", "Zstandard": r"\x28\xb5\x2f\xfd", } for initramfs_path in get_initramfs_paths(): extract_initramfs = subprocess.run( ["/usr/lib/dracut/skipcpio", initramfs_path], capture_output=True, check=True) for compression, file_signature in FILE_SIGNATURES.items(): if re.search(bytes(file_signature, encoding="UTF-8"), extract_initramfs.stdout[:8]): print(f" Initramfs: {Path(initramfs_path)}") print(f" Compression: {compression}\n") if __name__ == "__main__": raise SystemExit(main()) ```