Some Linux-based computer systems require an initramfs to boot properly. This guide covers the concepts of the initramfs as well as how to properly create and manage initramfs instances.
Systems with exotic drivers or setups, or encrypted file systems need initramfs so the Linux kernel is capable of handing over control to the init binary on their system.
Linux boot process
Once the Linux kernel has control over the system (which it gets after being loaded by the boot loader), it prepares its memory structures and drivers. It then hands over control to an application (usually init) whose task is to further prepare the system and make sure that, at the end of the boot process, all necessary services are running and the user is able to log on. The init application does that by launching, among other services, the udev daemon who will further load up and prepare the system based on the detected devices. When udev is launched, all remaining file systems that have not been mounted are mounted, and the remainder of services is started.
For systems where all necessary files and tools reside on the same file system, the init application can perfectly control the further boot process. But when multiple file systems are defined (or more exotic installations are done), this might become a bit more tricky:
- When the /usr partition is on a separate file system, tools and drivers that have files stored within /usr cannot be used unless /usr is available. If those tools are needed to make /usr available, then we cannot boot up the system.
- If the root file system is encrypted, then the Linux kernel will not be able to find the init application, resulting in an unbootable system.
The solution for this problem has long since been to use an initrd (initial root device).
The initial root disk
The initrd is an in-memory disk structure (ramdisk) that contains the necessary tools and scripts to mount the needed file systems before control is handed over to the init application on the root file system. The Linux kernel triggers the setup script (usually called linuxrc but that name is not mandatory) on this root disk, which prepares the system, switches to the real root file system and then calls init.
Although the initrd method is all that is needed, it had a few drawbacks:
- It is a full-fledged block device, requiring the overhead of an entire file system; it has a fixed size. Choosing an initrd that is too small and all needed scripts cannot fit. Make it too big and memory will be wasted.
- Because it is a real, static device it consumes cache memory in the Linux kernel and is prone to the memory and file management methods in use (such as paging), this makes initrd greater in memory consumption.
To resolve these issues the initramfs was created.
The initial ram file system
An initramfs is an initial ram file system based on tmpfs (a size-flexible, in-memory lightweight file system), which also did not use a separate block device (so no caching was done and all overhead mentioned earlier disappears). Just like the initrd, it contains the tools and scripts needed to mount the file systems before the init binary on the real root file system is called. These tools can be decryption abstraction layers (for encrypted file systems), logical volume managers, software raid, bluetooth driver based file system loaders, etc.
The content of the initramfs is made by creating a cpio archive. cpio is an old (but proven) file archiver solution (and its resulting archive files are called cpio files). cpio is definitely comparable to the tar archiver. The choice of cpio here was because it was easier to implement (code-wise) and supported device files which tar did not support at the time.
All files, tools, libraries, configuration settings (if applicable), etc. are put into the cpio archive. This archive is then compressed using the gzip utility and stored alongside the Linux kernel. The boot loader will then offer it to the Linux kernel at boot time so the kernel knows an initramfs is needed.
Once detected, the Linux kernel will create a tmpfs file system, extract the contents of the archive on it, and then launch the init script located in the root of the tmpfs file system. This script then mounts the real root file system (after making sure it can mount it, for instance by loading additional modules, preparing an encryption abstraction layer, etc.) as well as vital other file systems (such as /usr and /var ).
Once the root file system and the other vital file systems are mounted, the init script from the initramfs will switch the root towards the real root file system and finally call the /sbin/init binary on that system to continue the boot process.
Creating an initramfs
Introduction and bootloader configuration
To create an initramfs, it is important to know what additional drivers, scripts, and tools will be needed to boot the system.
The root disk and root filesystem needs to be accessible
In practice, this usually means CONFIG_SATA_AHCI or CONFIG_BLK_DEV_NVME (for the disk), and CONFIG_EXT4_FS (the filesystem) should ideally be built-in [=y] to the kernel; otherwise having these as modules [=m] will require these modules to be loaded by the initramfs first so booting can continue.
If LVM is used, then LVM tools will be needed in the initramfs.
If software RAID is used, mdadm utilities will be needed, or DMRAID, etc... ZFS and BTRFS would also require consideration here.
Several automated tools exist that help users create initramfs (compressed cpio archives) for their system. Most commonly used are dracut and genkernel. Those who want total control can easily create personal, custom initramfs images as well manually.
Once created, the bootloader configuration will need to be adjusted to inform it an initramfs is to be used.
Usually this is done by re-generating the config file grub-mkconfig -o /boot/grub/grub.cfg
For instance, if the initramfs file is stored as /boot/initramfs-5.15.32-gentoo-r1.img, then afterwards, the GRUB configuration in /boot/grub/grub.cfg would look somewhat like the following:
title Gentoo Linux 5.15.32-r1
Gentoo's kernel building utility, Genkernel, can be used to generate an initramfs. genkernel expects that both the kernel and initramfs are built by it, although in some cases, an initramfs built by genkernel with the kernel built by another method may work (but is discouraged).
To use genkernel for generating an initramfs, it is recommended all necessary drivers and code that is needed to mount the / root and /usr file systems be included as built-in in the kernel (not as modules). If these are built-in, genkernel can be called with the
If modules are required in the initramfs, call genkernel as follows:
genkernel --install initramfs
Depending on the system, one or more of the following options may be needed:
|Add support for
LABEL= settings in /etc/fstab
|Add support for fake hardware RAID.
|Add in firmware code found on the system.
|Add in GnuPG support.
|Add support for iSCSI.
|Add support for LUKS encryption containers.
|Add support for LVM.
|Add support for software RAID.
|Add support for multiple I/O access towards a SAN.
|Add support for ZFS.
When finished, the resulting initramfs file will be stored in /boot.
The Dracut utility is created for the sole purpose of managing initramfs files.
To install the Dracut utility, run:
emerge --ask sys-kernel/dracut
The next step is to configure dracut by editing /etc/dracut.conf.
Once configured, create an initramfs by calling dracut as follows:
The resulting image supports generic system boots based on the configuration in /etc/dracut.conf. It is also possible to generate an initramfs specifically tailored to an individual system (which dracut tries to detect the needed tools, drivers, etc. from the existing system). If the modules and drivers are built into the kernel (not as separate modules and references to the firmware), then the
--no-kernel option can be added:
dracut --host-only --no-kernel
For more information, check out the dracut and dracut.cmdline manual pages:
- Initramfs — is used to prepare Linux systems during boot before the init process starts.
- Initramfs - make your own
- Custom Initramfs — the successor of initrd. It provides early userspace which can do things the kernel can't easily do by itself during the boot process.
- Early Userspace Mounting — how to build a custom minimal initramfs that checks the /usr filesystem and pre-mounts /usr.
- The ramfs-rootfs-initramfs.txt file within the Linux kernel documentation.