I mounted filesystems reliably by referencing UUIDs in /etc/fstab instead of device names, then validated mounts without rebooting. UUID-based entries kept boot mounts correct even after disks were reordered or added.

Objective & Context

Device names like /dev/sdb are not stable across reboots; UUIDs are. This lab mounts manually, then persists with UUID fstab entries and validates safely, the durable-storage step the LVM and server labs depend on.

Learning Objectives

  • Mount and unmount filesystems manually with mount/umount.
  • Read stable device identifiers with blkid.
  • Write correct fstab entries with UUID, options, dump, and pass fields.
  • Validate fstab changes with mount -a and findmnt before rebooting.
  • Diagnose boot failures caused by bad fstab entries.

Environment & Prerequisites

Prerequisites

  • Linux with util-linux (mount, blkid, findmnt are preinstalled).
  • A spare formatted device or loop file to practice on.
  • Root access to edit /etc/fstab and mount.
  • A backup or snapshot before touching fstab on a real system.

Step-by-Step Execution

1. Read the device UUID

blkid /dev/sdb1

Expected output:

/dev/sdb1: UUID="a1b2c3d4-..." BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="..."

What this teaches: blkid reads the filesystem's stored UUID, which never changes when disks are reordered. Device names like /dev/sdb are enumeration order and can shift across reboots.

2. Add a UUID fstab entry [ROOT REQUIRED]

UUID=$(blkid -s UUID -o value /dev/sdb1) && sudo mkdir -p /mnt/data && echo "UUID=$UUID /mnt/data ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab

Expected output:

UUID=a1b2c3d4-... /mnt/data ext4 defaults,noatime 0 2

What this teaches: fstab fields are device, mountpoint, type, options, dump, pass. noatime skips access-time writes for speed; pass 2 orders fsck after the root filesystem. Two gotchas are handled here: the mount point must exist or mount fails (mkdir -p creates it), and a bare sudo echo ... >> /etc/fstab does not work because the shell performs the >> redirection as your user before sudo runs, so piping into sudo tee -a does the privileged append correctly.

3. Validate without rebooting

mount -a && findmnt /mnt/data

Expected output:

TARGET   SOURCE     FSTYPE OPTIONS
/mnt/data /dev/sdb1 ext4   rw,noatime

What this teaches: mount -a mounts everything in fstab that is not noauto, catching syntax errors now instead of at 3 AM boot; findmnt confirms the live mount matches the intended source and options.

How It Works

Mounting grafts a filesystem into the single directory tree at a mount point. The kernel's mount table maps paths to devices, and /etc/fstab is the declarative list the boot process applies. Because device enumeration order is not stable, fstab should identify filesystems by UUID or label, identifiers stored in the filesystem itself.

Each fstab line is six fields with distinct jobs: what to mount, where, which filesystem type, mount options, whether dump backs it up (usually 0), and the fsck pass order (root is 1, others 2, 0 to skip). Options like defaults, noatime, and nofail tune behavior; nofail is what keeps a missing USB disk from hanging the boot.

Validation without rebooting is the professional habit: mount -a replays fstab against the running system, and findmnt renders the live mount table as a tree for verification. Combined with a pre-edit backup of fstab, this makes storage changes boring, which is exactly what you want.

Validation & Testing

Run mount -a to confirm the fstab entry is valid (no errors), then verify with findmnt. On modern systems you can also run findmnt --verify, which parses fstab and checks every entry (device exists, mount point exists, filesystem type known) without mounting anything, a safe pre-flight check before mount -a touches the live system. Pass criteria: the filesystem mounts via UUID, survives a simulated device reorder, and mount -a reports no errors that would block boot.

Troubleshooting

SymptomLikely causeFix
Boot drops to emergency shellfstab references a device that is not presentComment the line or add nofail, then systemctl default to continue booting
mount: can't find UUIDTypo in the UUID or the device was reformattedRe-run blkid and correct the entry; UUIDs change on reformat
Wrong filesystem type errorTYPE field does not match the actual formatCheck blkid TYPE= and set the fstab field to match (or auto)
Mount succeeds but options ignoredOptions field misspelled or unsupported by the fsVerify with findmnt -o OPTIONS and check the filesystem's man page
Device busy on umountA process holds files open under the mountFind it with lsof +D /mnt/point, stop it, then umount
Duplicate mount entriesSame mountpoint listed twice after repeated appendsKeep one canonical line; comment or remove the stale duplicate
Advanced: Troubleshooting
  • Boot hangs on bad fstab: add nofail for non-critical mounts and always test with mount -a first.
  • Wrong device after reboot: use UUID or LABEL, never /dev/sdX.
  • Permission/owner issues: set mount options or post-mount chown as needed.

Key Results

  • Made boot mounts resilient to device renaming via UUIDs.
  • Validated fstab safely with mount -a before reboot.
  • Applied noatime/nofail options for performance and safety.
  • Confirmed mounts with findmnt rather than assumptions.

Key Takeaways

  • Identify filesystems by UUID, never by /dev/sdX names.
  • Know the six fstab fields and what each controls.
  • nofail keeps missing disks from hanging the boot.
  • mount -a plus findmnt validates without rebooting.
  • Back up /etc/fstab before every edit.
  • Pass number 1 is for the root filesystem and 2 for everything else; 0 skips the check.
  • Use x-systemd.mount-timeout to cap how long boot waits on network storage.

Practice Challenges

Challenge 1: nofail rescue

Goal: deliberately add a bogus UUID entry with and without nofail, reboot a test VM, and observe the difference in boot behavior.

Hint: snapshot first.

Challenge 2: Bind mount lab

Goal: use a bind mount to expose /srv/data at /var/www/data, persist it in fstab, and explain why the fstab line looks different.

Hint: the type field is none and the option is bind.