Skip to main content
RunBook Academy

LinuxXV · /etc/fstab and Mount ManagementMount units

Mount units by hand, and verifying a mount change before you reboot

Advanced⏱ ~15 minbashsystemctlsystemd-analyzesystemd-escapefindmnt

What you'll learn

  • Decide between an fstab line and a hand-written .mount unit
  • Name a mount unit correctly with systemd-escape and know why the name is not cosmetic
  • Translate fstab-only options into their unit equivalents
  • Verify a unit with systemd-analyze verify and read its exit status honestly
  • Test a mount transiently with systemd-mount before making it persistent

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-11

Not yet marked complete on this device.

Everything in /etc/fstab becomes a .mount unit anyway. The generator does the translation and drops the result in /run/systemd/generator/. Writing the unit yourself skips the translation - which buys you things fstab cannot express, and costs you options that only exist on the fstab side.

The other half of this lesson is the part that gets skipped: a mount change is untested until the host reboots, and there is a short list of checks that catch everything except the timing.

When the unit form is worth it

fstab is one file, shared by every team that touches the host, edited by hand, and read only at boot and on daemon-reload. It is the right place for the base filesystems of the machine.

A .mount unit is a file of its own, which means it can be shipped by configuration management alongside the service that needs it, removed with that service, and given dependencies that fstab has no column for:

You needfstab.mount unit
Order the mount after a specific servicex-systemd.after= (workable)After= (direct)
Refuse to mount unless a condition holdsnot availableConditionPathExists=, ConditionKernelCommandLine=
Ship the mount with the application, not with the hostnoyes - one file, one owner
Bound the wait for the devicex-systemd.device-timeout=explicit After=/Requires= on the .device unit
Bound the mount attemptx-systemd.mount-timeout=TimeoutSec=

The unit, and the name that is not cosmetic

man 5 systemd.mount states the rule flatly: mount units must be named after the mount point directories they control, using systemd’s path escaping. Do not compute the name in your head.

Read-only / Safederive the unit name
$ systemd-escape -p --suffix=mount /var/lib/postgresql/16/main
var-lib-postgresql-16-main.mount
# /etc/systemd/system/srv-data.mount
[Unit]
Description=Application data volume
Documentation=man:systemd.mount(5)
After=iscsi.service
Requires=iscsi.service

[Mount]
What=/dev/disk/by-uuid/8f2c1b7a-3d4e-4f50-a611-2b3c4d5e6f70
Where=/srv/data
Type=xfs
Options=noatime,nodev,nosuid
TimeoutSec=45s

[Install]
WantedBy=remote-fs.target

Four things in that file are load-bearing:

  1. Where= must match the unit filename. systemd refuses to load the unit otherwise; the check below shows exactly what the refusal looks like.
  2. What= should be a stable path. /dev/disk/by-uuid/... or /dev/disk/by-id/..., never /dev/sdb1 - the same rule as fstab, for the same reason.
  3. TimeoutSec= is the unit-side equivalent of x-systemd.mount-timeout=. man 5 systemd.mount says both x-systemd.mount-timeout= and x-systemd.device-timeout= are ignored when they appear in a unit’s Options= line, so copying an fstab option string into a unit quietly drops them.
  4. [Install] WantedBy= is what makes it start at boot. Leave it out and the unit works perfectly when you start it by hand and never starts on its own.

Verifying before the reboot

systemd-analyze verify loads a unit file exactly as systemd would, plus everything it references, and reports what it finds. It runs against a file path, so you can check a unit before it is installed anywhere.

Read-only / Safecatch a misspelt directive
$ systemd-analyze verify /etc/systemd/system/srv-data.mount
/etc/systemd/system/srv-data.mount:10: Unknown key 'TimeoutSecs' in section [Mount], ignoring.
Read-only / Safecatch a wrong unit name
$ systemd-analyze verify /etc/systemd/system/data.mount
data.mount: Where= setting doesn't match unit name. Refusing.
Unit data.mount has a bad unit file setting.

The full pre-reboot sequence

  1. systemd-analyze verify on the unit file, or sudo findmnt --verify --verbose for an fstab change. Catches syntax, unknown directives, bad unit names, missing mount points.
  2. sudo systemctl daemon-reload. Without this, systemd is still working from the previous version of the file - and for an fstab change, from the previous run of the generator.
  3. systemctl cat srv-data.mount. Read back what systemd now believes, not what you wrote. The options, the After= lines and the TimeoutSec must all be there.
  4. sudo systemctl start srv-data.mount, then findmnt /srv/data. Proves the mount works now, with the network up and every device enumerated.
  5. systemctl is-enabled srv-data.mount. Proves it will be started at the next boot rather than only by hand.
  6. Reboot, inside a window, with console access. This is the only step that can catch a timing failure, and it is the step that is always skipped.

Steps 1 to 5 eliminate the syntax class of failure completely. They eliminate none of the timing class - a device that enumerates late, a filer that is slow to answer, a mount whose parent is not yet mounted. Only a boot exercises those, because only at boot is the system in the state where they happen.

Automount units

An .automount unit is a separate file that sits in front of a .mount unit of the same name. Enable and start the .automount; the .mount is triggered on first access.

# /etc/systemd/system/srv-archive.automount
[Unit]
Description=On-demand archive share

[Automount]
Where=/srv/archive
TimeoutIdleSec=600

[Install]
WantedBy=remote-fs.target

The .mount unit with the same name must still exist - the automount only supplies the trigger. Enable the .automount, not the .mount; enabling both means the filesystem is mounted at boot and has an idle trigger, which is not what anyone intends.

sudo systemctl enable --now srv-archive.automount
systemctl list-units --type=automount

Knowledge check

Knowledge check · 4 questions

  1. Q1. You copy an fstab option string, including x-systemd.mount-timeout=30, into the Options= line of a hand-written .mount unit. What happens?

  2. Q2. A zero exit status from systemd-analyze verify means the unit file contains no problems.

  3. Q3. Which checks can be run on a live host and will catch a defective mount change before the reboot? Select all that apply.

  4. Q4. An fstab line and a hand-written unit both describe /srv/data, with different options. Which one takes effect, and why?

Passing score: 75%. Answers are checked in this browser.