Documentsbluefin
Systemd Mount Configuration
Systemd Mount Configuration
Type
Topic
Status
Published
Created
Jul 3, 2026
Updated
Jul 3, 2026

Systemd Mount Configuration#

Bluefin is built on bootc with an ostree/composefs backend, which makes the root filesystem read-only by default. Persistent state lives in /etc (mutable, 3-way merged on upgrades) and /var (persists across deployments). For secondary drives and extra mount points, two mechanisms are available: entries in /etc/fstab (which systemd auto-converts to native mount units at boot) or hand-authored .mount unit files.

Critical constraint: When composefs is enabled (the Bluefin default), you cannot use /etc/fstab or a .mount unit to remount /. Use the rootflags= kernel argument instead.

How systemd Processes Mounts#

systemd-fstab-generator(8) runs early at boot — before unit files are loaded — and translates each /etc/fstab entry into a transient .mount (or .swap) unit . Native .mount unit files in /etc/systemd/system/ or /usr/lib/systemd/system/ take precedence over fstab-generated ones .

Naming Convention#

Unit filenames mirror the mount point path with slashes replaced by dashes and the .mount suffix appended. Example: /var/datavar-data.mount. Escaping follows systemd.unit(5) rules .

fstab Field → Mount Unit Mapping#

fstab fieldUnit optionPurpose
fs_specWhat=Device, UUID, or label
fs_fileWhere=Absolute mount point path
fs_vfstypeType=Filesystem type (xfs, ext4, btrfs…)
fs_mntopsOptions=Comma-separated mount options

Useful x-systemd.* fstab Options#

OptionEffect
x-systemd.automountCreate a companion automount unit (on-demand mount)
x-systemd.device-timeout=How long to wait for the device to appear
x-systemd.mount-timeout=How long to wait for the mount command
x-systemd.makefsFormat the device if it carries no filesystem signature
x-systemd.growfsGrow the filesystem to fill its partition
x-systemd.requires=Add Requires=/After= dependency on another unit
nofailBoot continues even if mount fails (Wants= only, no ordering)
noautoDo not add as dependency of local-fs.target (manual mount)
_netdevTreat as network mount; order after network-online.target

Persistent Drive Configuration on Bluefin#

Because /etc persists and is 3-way-merged on upgrades , /etc/fstab and /etc/systemd/system/*.mount are valid locations for persistent non-root mount configuration. /var is shared across all deployments, making it the natural base for data directories (e.g. /var/data).

ApproachWhen to useHow
/etc/systemd/system/<name>.mountMost cases — tooling-friendly, declarativeWrite unit file, systemctl enable, systemctl start
/etc/fstabSimple, human-managed mountsAdd entry; auto-converted at boot
systemd.mount-extra= kernel argInstall-time injection or immutable configbootc install ... --karg "systemd.mount-extra=UUID=:/data:xfs:defaults"

Injecting Mounts Before First Boot#

When provisioning via bootc install to-existing-root, find the new deployment directory and write the unit there before rebooting :

DEPLOY_PATH=$(ostree admin --sysroot=/target --print-current-dir)

cat > "${DEPLOY_PATH}/etc/systemd/system/var-data.mount" <<EOF
[Unit]
Description=Data drive

[Mount]
What=/dev/disk/by-uuid/<UUID>
Where=/var/data
Type=xfs
Options=defaults

[Install]
WantedBy=local-fs.target
EOF

systemctl --root="${DEPLOY_PATH}" enable var-data.mount

Alternatively, inject via kernel argument at install time — no file editing required :

bootc install to-existing-root \
  --karg "systemd.mount-extra=UUID=<uuid>:/var/data:xfs:defaults"

The systemd.mount-extra syntax is source:path:type:options.

Native .mount Unit File Format#

Mount units must live at a path matching the escaped mount point . Place persistent user-managed units in /etc/systemd/system/; image-baked units go in /usr/lib/systemd/system/.

# /etc/systemd/system/var-data.mount
[Unit]
Description=External data drive

[Mount]
What=/dev/disk/by-uuid/xxxx-yyyy
Where=/var/data
Type=xfs
Options=defaults,noatime
TimeoutSec=30

[Install]
WantedBy=local-fs.target

Key [Mount] Options#

OptionRequiredNotes
What=YesDevice node, UUID=, or label
Where=YesAbsolute path; must match unit filename
Type=NoFilesystem type
Options=NoComma-separated mount options
TimeoutSec=NoDefault from DefaultTimeoutStartSec= in system.conf
DirectoryMode=NoMode for auto-created mount point dir (default 0755)
SloppyOptions=NoIgnore unknown mount options (yes/no)
LazyUnmount=NoDetach filesystem even if busy

Enable and start with:

systemctl enable --now var-data.mount

Constraints and Reference#

ConstraintDetail
No / in fstab/mount unitscomposefs handles root; use rootflags= karg instead
/var content from image is copy-on-first-deployLike Docker VOLUME; changes to /var in subsequent image updates are NOT applied
/etc/fstab for root is legacybootc direction is to migrate away from fstab root entries toward kernel arguments
SELinux labels on new toplevel dirsCustom mount points may get default_t; may need SELinux file context entries
Unit file precedence/etc/systemd/system/ overrides /usr/lib/systemd/system/; both override fstab-generated units