Shrink root filesystem with initramfs hook
Note
This guide is verified on a Raspberry Pi 5 booting from NVMe running Debian 13. The principles apply to other Debian-based systems, but device names (e.g., /dev/sys, /dev/mmcblk0) will vary.
While expanding a filesystem on Linux is a common and straightforward task (often handled automatically by scripts like raspi-config), shrinking a root filesystem is significantly more complex. The primary challenge is that you cannot shrink an ext4 filesystem while it is mounted, and the root filesystem is mounted almost immediately during the boot process.
This tutorial demonstrates how to perform this operation safely by using a custom initramfs hook. This allows us to intercept the boot process in the local-premount stage—after hardware detection but before the root filesystem is mounted—to perform file system and partition resizing operations.
Overview of the Process
flowchart TD
A["Prepare System"] -->|"Create Hook & Script"| B["/etc/initramfs-tools/..."]
B -->|"update-initramfs -u"| C["New Initrd Image"]
C -->|"Add 'shrink_me' to cmdline"| D["Reboot"]
D -->|"Boot Process (local-premount)"| E{"Check for 'shrink_me'"}
E -- Yes --> F["Run Resize Script"]
E -- No --> G["Normal Boot"]
F -->|"e2fsck & resize2fs"| H["Resize Filesystem"]
H -->|"sfdisk"| I["Resize Partition"]
I -->|"Continue Boot"| J["Verify Size"] - Create a Hook Script: To ensure necessary tools (
resize2fs,e2fsck,sfdisk) are included in the initramfs image. - Create the Resize Script: A script that runs during boot to perform the actual resizing.
- Update Initramfs: Generate the new boot image.
- Trigger the Resize: Reboot with a specific kernel command line argument.
Prepare the System
First, identify your root partition and disk.
In this example: - Disk:/dev/nvme0n1 - Partition: /dev/nvme0n1p2 (Partition 2) Ensure your initramfs configuration allows loading modules needed for your storage. For NVMe drives, we explicitly add the modules. Add nvme modules to /etc/initramfs-tools/modules:
Ensure auto_initramfs is enabled in your firmware config:
Create the Initramfs Hook
We need a hook script to copy the binary tools into the initramfs image. Create /etc/initramfs-tools/hooks/resize_tools with the following content:
Make it executable:
Create the Resize Script
Create the script that will actually run during the boot process at /etc/initramfs-tools/scripts/local-premount/shrink_root.
Warning
Hardcoded Values: This script has hardcoded values for the device (/dev/nvme0n1p2) and the target sizes (68G for filesystem, 70G for partition). You MUST edit these to match your requirements.
When shrinking, always resize the filesystem to be slightly smaller than the target partition size to avoid data corruption. In this example: FS = 68G, Partition = 70G.
Make it executable:
Update Initramfs
Regenerate your initramfs images to include the new scripts and tools.
Trigger the Resize
To trigger the script, we need to add the shrink_me parameter to the kernel command line.
Edit /boot/firmware/cmdline.txt and append shrink_me to the end of the line (make sure it's on the same line, separated by a space). Example content of /boot/firmware/cmdline.txt:
Reboot and Verify
Reboot your Raspberry Pi.
You can monitor the process if you have a serial console or display attached. Look for the FS-RESIZE messages in the boot logs.
After the system comes back online:
-
Check the new size:
-
Remove the trigger from
/boot/firmware/cmdline.txtto prevent it from running again (though the script is safe to run as resize2fs does nothing if size matches). -
Clean up by removing the hook and script files and running
update-initramfs -uagain.