Home / Alt manpages / mksquashfs(1)

  • mksquashfs(1)
  • User command
  • linux

Build and Verify a SquashFS Image with mksquashfs

You will finish with a compressed, read-only SquashFS image made from a directory, a way to inspect its contents, and a safe pattern for exclusions and appending files. The examples use the locally installed squashfs-tools 4.6.1 package, version 1:4.6.1-1build1.

Allow about fifteen minutes. You need a shell, enough free space for the source scan and output image, and the mksquashfs and unsquashfs commands. Creating an image in a directory you own does not need sudo. Reading protected source files may need elevated access, but copying permissions into an image is not a reason to run every command as root.

Safety: mksquashfs writes the destination named on its command line. Choose a new output path first. An existing SquashFS image is normally appended to, not replaced, unless you pass -noappend. Do not test against the only copy of an archive.

1. Confirm the installed tool

Check the executable and package before relying on examples. These are ordinary read-only commands:

$ command -v mksquashfs
/usr/bin/mksquashfs
$ dpkg-query -W -f='${Package} ${Version}\n' squashfs-tools
squashfs-tools 1:4.6.1-1build1
$ mksquashfs -version
mksquashfs version 4.6.1 (2023/03/25)

The local manual describes a default 128 KiB data block and gzip compression. It also lists zstd, xz, lz4, lzo and lzma as available compressor choices for this build. Defaults and supported compressors can vary between package releases, so keep this version check near scripts that depend on them.

Checkpoint

If command -v finds a different binary, stop and read that installation's manual before copying the commands below.

2. Create a small source tree

Use a disposable directory while learning. The following changes only the current user's temporary files:

$ work=$(mktemp -d)
$ mkdir -p "$work/source/docs"
$ printf 'release notes\n' > "$work/source/README.txt"
$ printf 'private draft\n' > "$work/source/docs/draft.txt"
$ printf 'built output\n' > "$work/source/output.log"
$ printf '%s\n' "$work"
/tmp/tmp.example

Replace /tmp/tmp.example in later commands with the path printed by your shell. The command syntax is positional: one or more source paths come first, followed by the destination filesystem. A directory source contributes its contents to the image root by default.

3. Build the image with an explicit destination

Create the image with the default compressor and block size:

$ mksquashfs "$work/source" "$work/archive.sqfs" -no-progress
Creating filesystem on /tmp/tmp.example/archive.sqfs, block size 131072.
...
Filesystem size ... bytes (.. Kbytes / .. Mbytes)
Filesystem size ... bytes (..% of uncompressed filesystem size)
Number of inodes ...
Number of files ...
Number of fragments ...
Number of duplicate files ...
Number of ids ...
Number of xattr ids ...

The sizes and counts depend on the source tree, so the ellipses above indicate variable output rather than literal text to paste. -no-progress keeps a progress display out of logs; it does not change the image. Without it, the tool may display a progress bar while scanning.

By default, 4.6.1 creates reproducible filesystems and stores extended attributes. Reproducible does not mean that unrelated source metadata becomes identical: file contents, modes, ownership, timestamps and xattrs still matter. For a build where timestamps must be controlled, set SOURCE_DATE_EPOCH or pass the relevant time options deliberately.

4. Inspect what was written

Use unsquashfs to list the image instead of trusting the creation summary:

$ unsquashfs -ll "$work/archive.sqfs"
drwxr-xr-x ... squashfs-root
-rw-r--r-- ... squashfs-root/README.txt
drwxr-xr-x ... squashfs-root/docs
-rw-r--r-- ... squashfs-root/docs/draft.txt
-rw-r--r-- ... squashfs-root/output.log

Owner, group, timestamps and exact spacing are host-specific. The useful check is that each expected path appears, and that no unexpected path was included. For a narrower check, ask the listing command for a particular path and inspect its exit status:

$ unsquashfs -ll "$work/archive.sqfs" | grep -F 'README.txt'
-rw-r--r-- ... squashfs-root/README.txt
$ test "$(unsquashfs -ll "$work/archive.sqfs" | grep -Fc 'README.txt')" -eq 1
$ echo 'image listing verified'
image listing verified

This does not mount anything and needs no elevated privilege. If you need to read a file, extract into a new directory with unsquashfs -d; do not extract over a live system directory by accident.

5. Exclude paths without shell expansion

Use -e followed by paths to exclude. The basic form does not enable wildcard matching:

$ mksquashfs "$work/source" "$work/public.sqfs" -no-progress -e docs/draft.txt output.log
$ unsquashfs -ll "$work/public.sqfs" | grep -E 'README.txt|draft.txt|output.log'
-rw-r--r-- ... squashfs-root/README.txt

For wildcard exclusions, add -wildcards and quote the pattern so the shell passes it to mksquashfs unchanged:

$ mksquashfs "$work/source" "$work/public.sqfs" -noappend -no-progress -wildcards -e '*.log'
$ unsquashfs -ll "$work/public.sqfs" | grep -F 'output.log' || echo 'output.log excluded'
output.log excluded

The second command uses -noappend because public.sqfs may already exist from the previous example. This option replaces the old image by creating a new filesystem at that path, so use it only when that overwrite is intentional. A failed build can leave an incomplete destination; keep the source tree and rebuild to a new filename if you need a cautious recovery path.

6. Choose compression and block size deliberately

For a general-purpose image, the defaults are a reasonable starting point. If compatibility with a reader matters, choose a compressor that the reader supports and record the choice:

$ mksquashfs "$work/source" "$work/zstd.sqfs" -no-progress -comp zstd -b 1M
$ unsquashfs -s "$work/zstd.sqfs"
Found a valid SQUASHFS 4:0 superblock on ...
Compression zstd
Block size 1048576

A larger block can improve compression for some data but changes memory and access characteristics. -comp zstd and -b 1M are image-format decisions, not cosmetic switches. If the target kernel or extraction utility is older, verify support before distributing the image. The installed manual is the authority for this host's accepted values.

7. Append only when the merge is intentional

When the destination already contains a SquashFS filesystem, mksquashfs appends new source items by default. This is useful for adding a directory, but it is easy to mistake for replacement:

$ mkdir -p "$work/additional"
$ printf 'later file\n' > "$work/additional/later.txt"
$ mksquashfs "$work/additional" "$work/archive.sqfs" -no-progress
$ unsquashfs -ll "$work/archive.sqfs" | grep -F 'later.txt'
-rw-r--r-- ... squashfs-root/later.txt

The new source is merged into the existing root. If you want it under a named directory, use -root-becomes NAME when appending, and verify the resulting path with unsquashfs -ll. Before appending to a valuable image, copy it or create a checksum so you have a recovery point:

$ cp --reflink=auto -- "$work/archive.sqfs" "$work/archive.sqfs.before-append"
$ sha256sum "$work/archive.sqfs.before-append"
...

The copy is the undo mechanism for an append. Do not delete it until the merged image has been inspected and any downstream reader has accepted it. During an abnormal interruption, mksquashfs may write a recovery file. Follow the exact recovery command printed by that run, and do not delete the recovery file while you may still need it.

Done means

  • You checked that the installed command is mksquashfs 4.6.1 from squashfs-tools.
  • You created the image at a deliberate destination without using elevated privileges unnecessarily.
  • You inspected the image with unsquashfs and confirmed expected paths.
  • You quoted wildcard exclusions and used -noappend only for an intentional rebuild.
  • You recorded non-default compression or block-size choices.
  • You made a copy before appending and know where the printed recovery instructions are if a build is interrupted.