Hello again. In the preceding lesson, you packaged gateway-agent so that Buildroot installs it through the normal cross-build and target-rootfs process. That package now becomes a useful test payload: it should appear and run regardless of whether the generated root filesystem is writable ext4 or read-only SquashFS.
This lesson produces both formats from the same Buildroot configuration, boots each one on ARM64 QEMU, and separates three often-confused properties:
- Mutability: whether the running system can persist changes inside the root filesystem.
- Image size: the storage capacity consumed by the deployed artifact, not merely its apparent size on the host filesystem.
- Recovery behavior: what each filesystem can and cannot protect after an unexpected reset or power loss.
For the gateway prototype, this comparison establishes why a production design normally separates immutable operating-system content from deliberately managed persistent state.
Two filesystem formats, two operational models
A Buildroot root filesystem image is the packaged representation of output/target. Buildroot first assembles the target directory tree, including BusyBox, libraries, /etc configuration, device nodes, and your installed gateway-agent. It then creates each selected filesystem image from that common content.
The resulting images contain essentially the same software but embody different policies.
ext4: a writable filesystem
An ext4 image contains a conventional Linux filesystem with metadata structures and typically a journal. When mounted read-write, applications can create, delete, and modify files in the root filesystem. This is convenient during development:
- edit
/etcdirectly; - create logs or test data;
- install files interactively;
- reboot and retain changes.
That convenience has a systems cost. The deployed ext4 partition must include spare capacity, metadata, and journal space. More importantly, runtime state accumulates in the same place as the operating-system image unless you intentionally partition or mount it elsewhere.
The ext4 journal improves filesystem metadata consistency after an unclean shutdown. On the next mount, the kernel can replay or discard incomplete journal transactions. But this is not a guarantee that an application’s latest data is valid. A file update may still be absent, truncated, or semantically inconsistent unless the application uses an appropriate persistence protocol, including fsync() where required.
SquashFS: a compressed read-only filesystem
SquashFS is an image created once and then mounted read-only. Because no normal write operation can alter it, its contents remain fixed throughout operation. It is a strong fit for an appliance-like system whose executable software, libraries, and baseline configuration should not drift in the field.
Squashfs 4.0 Filesystem — The Linux Kernel documentation
Read the Linux Kernel documentation, “Squashfs 4.0 Filesystem,” to ground the lab in the filesystem’s actual design: compressed storage and intentional read-only operation.
In the opening overview before Section 1, read the overview. Focus on the fact that SquashFS compresses both file data and filesystem metadata, and is intended for constrained embedded storage. Then read Section 2, “Using Squashfs,” beginning with the creation note. Buildroot performs this image-creation step for you.
SquashFS can use several compression algorithms. Compression reduces flash or eMMC capacity needs, but decompression consumes CPU during filesystem reads. For this lab, use XZ because it makes the space-saving effect apparent in a small system image. In a product, choose compression based on measured boot time, application-start latency, storage capacity, and CPU budget—not on the smallest output alone.
Neither filesystem format alone provides cryptographic integrity:
- ext4 journaling does not prove that content is authentic.
- SquashFS read-only behavior does not prove that the original image was authentic or unmodified before boot.
- A later module will bind a read-only root filesystem to authenticated boot metadata with
dm-verity, and the OTA module will use A/B slots to make updates recoverable.
Configure Buildroot to generate both images
Return to the same Buildroot checkout and external tree used for gateway-agent. Confirm the external tree path first:
export BR2_EXTERNAL="$HOME/work/gateway-br2-external"
Open Buildroot configuration:
make BR2_EXTERNAL="$BR2_EXTERNAL" menuconfig
Navigate to Filesystem images. The exact submenu wording varies slightly with Buildroot release, but select both of the following:
Filesystem images
[*] ext2/3/4 root filesystem
ext2/3/4 variant: ext4
[*] squashfs root filesystem
Compression method: xz
The image below shows the relevant Buildroot menu area. In this lab, rather than selecting only the tar archive shown in the screenshot, enable both the ext4 and SquashFS filesystem-image entries.

Buildroot’s ext2/3/4 image generator generally needs an image size. Leave the existing value if it is already suitable for your QEMU configuration; otherwise choose a modest value such as 64M for this minimal system. This number is the logical capacity of the ext4 filesystem, not a measurement of the software content. It must be large enough for the root tree and future writes.
Save the configuration, then build:
make BR2_EXTERNAL="$BR2_EXTERNAL"
After a successful build, inspect the generated outputs:
ls -lh output/images/rootfs.ext4 output/images/rootfs.squashfs
file output/images/rootfs.ext4 output/images/rootfs.squashfs
Expected interpretations from file are:
rootfs.ext4is an ext4 filesystem image.rootfs.squashfsis a SquashFS filesystem image.
Before trying to mount either image as root, ensure the kernel has both filesystem drivers built in, not built as modules. A module cannot be loaded until after the root filesystem has mounted.
grep -E 'CONFIG_(EXT4_FS|SQUASHFS|SQUASHFS_XZ)=' \
output/build/linux-*/.config
For this XZ-based exercise, look for:
CONFIG_EXT4_FS=y
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XZ=y
If a needed setting is absent or shown as =m, open the kernel configuration:
make linux-menuconfig
In the kernel configuration, enable:
- File systems
The Extended 4 filesystem - File systems
Miscellaneous filesystems
SquashFS 4.0
XZ decompression support
Save the configuration. If your Buildroot setup uses a maintained kernel defconfig, update that defconfig according to its established workflow before treating the change as permanent. For this lab, rebuild the kernel and image after saving:
make linux-rebuild
Measure the artifacts correctly
Run the following before booting the writable ext4 test image:
for image in output/images/rootfs.ext4 output/images/rootfs.squashfs; do
printf '\n%s\n' "$image"
stat -c 'logical size: %s bytes; allocated host blocks: %b blocks of 512 bytes' "$image"
du -h "$image"
done
Interpret these values carefully:
| Measurement | Meaning | Why it matters |
|---|---|---|
stat logical size | The apparent length of the image file | This is close to the capacity required when writing a raw image to a fixed partition. |
Allocated host blocks / du | Space currently consumed on the Ubuntu host filesystem | An ext4 image may be sparse, so this can be much smaller than its logical size. |
| SquashFS file size | The compressed filesystem payload size | This is normally close to the storage required by the raw SquashFS image itself. |
Do not conclude that ext4 “uses less space” simply because its sparse file consumes few blocks on the development SSD. If a flasher writes that image byte-for-byte to a raw eMMC partition, the logical image capacity is what matters. Conversely, do not assume a SquashFS image will always be smaller by a fixed ratio; the outcome depends on the content and compression algorithm.
Record the following evidence in your private implementation repository:
sha256sum output/images/rootfs.ext4 output/images/rootfs.squashfs
The hashes identify the exact artifacts used in your boot comparison. They are safe to include in a sanitized public showcase later, whereas signing keys, private certificates, and production storage maps will not be.
Boot the ext4 image as a writable root filesystem
Use a disposable copy for the ext4 mutability test. This preserves the Buildroot-produced artifact for later comparison.
cp --reflink=auto \
output/images/rootfs.ext4 \
output/images/rootfs-ext4-lab.img
EXT4_IMAGE="output/images/rootfs-ext4-lab.img"
The following command assumes the ARM64 QEMU virt machine setup used in the earlier minimal-system lab. It presents the image as a virtio block device, which Linux normally names /dev/vda.
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-m 512M \
-nographic \
-kernel output/images/Image \
-drive if=none,file="$EXT4_IMAGE",format=raw,id=rootfs0 \
-device virtio-blk-device,drive=rootfs0 \
-append "console=ttyAMA0 root=/dev/vda rootfstype=ext4 rootwait rw"
After the BusyBox shell appears, inspect the mounted root filesystem:
cat /proc/mounts | grep ' / '
The root mount should identify ext4 and include rw. Now make a deliberately harmless change:
printf 'ext4 persistence probe\n' > /etc/gateway-write-probe
sync
cat /etc/gateway-write-probe
/usr/sbin/gateway-agent
The expected application output remains:
gateway-agent: prototype application installed
Exit QEMU using Ctrl-A, then X. Boot the same rootfs-ext4-lab.img again with the same QEMU command and verify that the probe remains:
cat /etc/gateway-write-probe
This verifies the defining ext4 behavior: a write to the root filesystem can persist across reboot.
The following QEMU boot console is representative of the evidence you should learn to read. The key lines are the kernel’s root-filesystem mount and the subsequent transition into userspace.

When you finish, remove the probe from the disposable copy if desired:
rm /etc/gateway-write-probe
sync
For this lab, the valuable observation is not merely that ext4 accepts a write. It is that every write changes the deployable system partition unless the product architecture redirects mutable state elsewhere.
Boot SquashFS as a read-only root filesystem
Now boot the compressed image. The kernel command line changes in two deliberate ways:
rootfstype=squashfstells the kernel what filesystem driver must mount the root device.rodocuments and enforces the intended read-only root mount.
qemu-system-aarch64 \
-M virt \
-cpu cortex-a53 \
-m 512M \
-nographic \
-kernel output/images/Image \
-drive if=none,file=output/images/rootfs.squashfs,format=raw,id=rootfs0 \
-device virtio-blk-device,drive=rootfs0 \
-append "console=ttyAMA0 root=/dev/vda rootfstype=squashfs rootwait ro"
At the target shell, inspect the root mount and run the packaged application:
cat /proc/mounts | grep ' / '
/usr/sbin/gateway-agent
Then attempt the same root-filesystem write:
touch /etc/squashfs-write-probe
It should fail with a message equivalent to:
Read-only file system
That failure is desired. It prevents configuration drift and prevents a running process from silently changing the root operating-system image.
A functioning gateway still needs writable locations for temporary files, persistent configuration, log retention, credentials, and update state. A read-only root filesystem does not create those locations automatically. To see the distinction, mount temporary volatile storage at /tmp:
mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs /tmp
printf 'volatile runtime state\n' > /tmp/runtime-probe
cat /tmp/runtime-probe
/tmp/runtime-probe is writable because it resides in RAM-backed tmpfs, not in SquashFS. It disappears at reboot. This is the beginning of a crucial product rule:
Immutable software belongs in the read-only system image; each category of mutable state needs an explicit, reviewed storage location and retention policy.
Do not treat tmpfs as a substitute for persistent configuration or security credentials. It is suitable for disposable runtime state. In later modules, you will define a persistent data partition, read-only root operation, A/B slots, and rollback-controlled updates.
Diagnose the likely boot failures
If either image fails before the login prompt, first identify which layer failed rather than changing settings at random.
| Symptom in serial output | Likely cause | First check |
|---|---|---|
VFS: Cannot open root device or an unknown block-device error | QEMU drive was not attached as expected, or root=/dev/vda is wrong | Confirm the -drive and virtio-blk-device arguments; inspect whether the kernel reports vda |
No filesystem could mount root | The filesystem driver or selected decompressor is absent from the kernel | Check CONFIG_EXT4_FS=y, CONFIG_SQUASHFS=y, and the compression-specific SquashFS setting |
System mounts root but says it cannot execute /sbin/init | Root image content or dynamic-loader setup is incomplete | Inspect output/target/sbin/init and use the earlier boot-failure workflow |
| No boot messages at all | Console argument does not match QEMU’s ARM PL011 serial device | Use console=ttyAMA0 with the virt machine |
| SquashFS boot succeeds but writes fail | Expected behavior | Mount an intentional writable volume, such as tmpfs or a separate data partition; do not remount the system image read-write |
The correct response to a SquashFS write failure is architectural, not a permissive remount command. A system image intended to be immutable should remain immutable.
Compare the formats as a gateway architect
The following table captures the decision at the level that matters for an automotive or industrial gateway.
| Dimension | ext4 root filesystem | SquashFS root filesystem |
|---|---|---|
| Normal rootfs writes | Supported when mounted rw | Rejected by design |
| Storage layout | Fixed-capacity filesystem with filesystem metadata and journal | Compact compressed image |
| Apparent host size | May be sparse and misleadingly small on the development host | Usually close to its actual compressed payload size |
| Runtime change persistence | Easy, including accidental changes | Impossible inside the root image |
| Power-loss behavior | Journal helps restore filesystem metadata consistency; application data still needs correct durability handling | No runtime metadata changes and no journal replay; an interrupted update must be handled outside the image |
| Software drift | Possible through direct rootfs changes | Strongly constrained |
| Product update style | Can encourage file-level mutation, which is difficult to audit and roll back | Naturally supports replace-the-image updates, especially with A/B slots |
| Integrity guarantee | None by filesystem type alone | None by filesystem type alone; read-only does not equal cryptographically verified |
| Best immediate use | Development, diagnostics, and systems that intentionally require a writable root | Immutable production base, paired with explicit writable state and authenticated updates |
A practical sequence for this gateway project is:
- Use ext4 during early bring-up, when rapid inspection and experimentation are valuable.
- Measure the real image sizes and startup behavior rather than selecting a format from intuition.
- Move toward SquashFS for the immutable product root filesystem.
- Keep logs, gateway configuration, certificates, update metadata, and operational data out of the immutable system image.
- Add verified boot, root-hash verification, and dual-slot update logic before claiming resilience against tampering or interrupted updates.
Key takeaways
You generated two Buildroot filesystem images from the same target root tree, then booted them independently:
- ext4 mounted read-write and retained a test file across reboot.
- SquashFS mounted read-only, compressed the target filesystem, and rejected writes to the root image.
- The ext4 image’s configured logical capacity is the relevant deployment-space figure; host sparse-file allocation can be misleading.
- ext4 journaling improves recovery of filesystem metadata but does not guarantee application-level data correctness after sudden power loss.
- SquashFS prevents ordinary runtime mutation, but it is not itself a secure-boot or integrity-verification mechanism.
Next, you will write an architecture decision record comparing Buildroot and Yocto for a ten-year automotive or industrial gateway lifecycle, using evidence from this Buildroot prototype rather than treating either build system as universally superior.
Can't find a good explanation? Sign up and we'll make it for you
Sign up