Inspect and Safely Use Linux OS Images with systemd-dissect

Someone hands you a raw disk image and asks "is this safe to boot", and systemd-dissect answers that without touching your host.

It inspects a Discoverable Disk Image, checks its partition layout, copies a file out, and mounts it read-only when you genuinely need a filesystem view.

The examples match systemd 255.4-1ubuntu8.17 from the systemd-container package installed on this machine. Give it 15 minutes, plus however long it takes to track down the image you actually want to examine. These commands accept ordinary image files and whole block devices. Swap in a real path for /path/to/image.raw, and do not substitute a partition such as /dev/sda2: the manual requires a whole block device when you pass a device node.

1. Confirm what is actually installed

Check which executable runs and note its version before you trust any output against this guide:

$ command -v systemd-dissect
/usr/bin/systemd-dissect
$ systemd-dissect --version
systemd 255 (255.4-1ubuntu8.17)

The same tool also answers to /usr/sbin/mount.ddi. That is an external helper for mount, not a separate implementation: same code, same image rules.

Checkpoint: if systemd-dissect --version comes back missing, stop and install or enable the package through your normal admin process. Do not drop an untrusted replacement into a system directory to work around it.

2. Read the image summary

Run the command with no switches and it opens the image and prints the OS metadata and partitions it recognises:

$ systemd-dissect --no-pager /path/to/image.raw

That list is not a forensic inventory, and it is not meant to be. It only shows what the tool considers part of an OS image: unknown types, duplicate types and partitions for the wrong architecture can all be left off. Reach for fdisk separately when you need every partition entry, not just the ones systemd-dissect cares about.

A DDI might be a bare filesystem image with no partition table, a GPT image following the Discoverable Partitions Specification, or a GPT or MBR image with a single partition treated as the root filesystem. It can also carry LUKS encryption or Verity integrity data. None of that means the contents are trustworthy; the summary describes structure, not intent.

3. Validate before you touch anything

Before any workflow that will actually access an image, ask systemd-dissect to check its partition arrangement and filesystem probes:

$ systemd-dissect --validate /path/to/image.raw
OK

A pass prints OK and returns status 0. It does not mount anything, set up LUKS or activate Verity, which makes it the least privileged check the tool offers. It still needs read access to the image.

Capture the status straight away when scripting it:

if systemd-dissect --validate /path/to/image.raw; then
    printf '%s\n' 'image validation passed'
else
    status=$?
    printf 'image validation failed with status %s\n' "$status" >&2
    exit "$status"
fi

Checkpoint: a non-zero result is a stop sign for an automated pipeline. Do not go on to mount or modify a file just because it happens to have a familiar suffix. Point validation at /etc, for instance, and it correctly reports that it is not an image file and returns non-zero.

4. Look inside without creating a mount

--list prints paths, --mtree produces a BSD mtree manifest, and both work on an image or a plain directory:

$ systemd-dissect --list /path/to/image.raw | sed -n '1,20p'
$ systemd-dissect --mtree /path/to/image.raw | sed -n '1,20p'

The mtree output includes inode metadata and SHA256 content digests by default, but not everything. The manual specifically excludes extended attributes, filesystem capabilities, MAC labels, file flags and Btrfs subvolume information. Treat it as a reproducible comparison aid, not a complete security attestation.

For a single file, --copy-from writes it out, or to standard output when the target is -:

$ systemd-dissect --copy-from /path/to/image.raw etc/os-release -
NAME=Example Linux
VERSION="1.0"

The source path is relative to the image root, so etc/os-release means what you would normally see as /etc/os-release. A single file keeps its mode, extended attributes and timestamps, but not its ownership; directory copies are recursive and do preserve ownership. Send output to a terminal only for text you trust; route anything binary or sensitive to a destination you have actually thought about.

5. Mount it read-only

Mounting needs elevated privileges on an ordinary host, because it creates mounts and may set up loop, encrypted or integrity-protected devices underneath. Use a dedicated empty directory and the explicit read-only flag:

$ sudo install -d -m 0755 /mnt/image-inspect
$ sudo systemd-dissect --mount --read-only /path/to/image.raw /mnt/image-inspect
$ findmnt --mountpoint /mnt/image-inspect

Read-only mode skips the tool's normal writable behaviour, and it also skips the automatic filesystem check and repair that a writable mount triggers. Expect nested filesystems in the mount when the image contains several recognised partitions.

Only inspect what you actually need:

$ sudo sed -n '1,20p' /mnt/image-inspect/etc/os-release
$ sudo find /mnt/image-inspect -maxdepth 2 -type f -print | sed -n '1,20p'

Warning: treat everything in the image as untrusted input. Do not execute programs from it, source its shell files, or take its metadata at face value. A read-only mount stops writes to the mounted filesystem; it says nothing about whether the contents are safe to run or honest about what they claim to be.

6. Unmount everything, including the nested bits

When you are done, unmount recursively rather than one filesystem at a time:

$ sudo systemd-dissect --umount /mnt/image-inspect
$ findmnt --mountpoint /mnt/image-inspect
findmnt: /mnt/image-inspect: no mount point specified.

--umount unmounts the image recursively and then removes the loop device and its partition devices. If the directory only existed for this session, -U unmounts and removes it in one go:

$ sudo systemd-dissect -U /mnt/image-inspect

Skip -U if the directory holds files you created independently of this mount. It deletes the directory after unmounting, and a careless path makes unrelated data harder to get back.

7. Know which paths actually write

--copy-to and a normal --mount can both change the image. For writes, systemd-dissect may run the relevant filesystem check in automatic fixing mode, and may grow a marked filesystem up to its GPT partition size. Check your backup and recovery plan before using either.

--in-memory makes an in-memory copy for temporary experiments, so writes never touch the original image. It costs memory and is not a substitute for a real, tested backup. When you just need a command to run against a temporary mount, --with --read-only mounts the image, changes into the temporary root, runs the child command, then unmounts:

$ sudo systemd-dissect --read-only --with /path/to/image.raw sh -c 'printf "%s\n" "$SYSTEMD_DISSECT_ROOT"; pwd; sed -n "1,5p" etc/os-release'

The environment variable names the temporary mount point, and the child command's exit status passes straight back to the caller, so a failed command inside stays visible to your script.

Done means