A disk, a filesystem, and a mount that survives a reboot
Domain 1 is 23% of XK0-006 and most of it is storage. This guide builds a block device out of a file, partitions it, puts a filesystem on it, mounts it by UUID and writes the fstab line - then checks that line before anything reboots, and does the same work on the RPM family, which defaults to a different filesystem.
System Management Guide 4 of 28 Intermediate
- PlatformsUbuntu 26.04 LTS + AlmaLinux 10.2
- Mandatory access controlAppArmor on Ubuntu, SELinux enforcing on Alma
- Firewallufw / nftables 1.1.6
- TimeAbout 26 min
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| LPLUS-A01 | 192.168.0.73 | Ubuntu 26.04 LTS | Debian-family host - apt, ufw, netplan, AppArmor | 2 Core | 4 GB | 50 GB |
| LPLUS-B01 | 192.168.0.74 | AlmaLinux 10.2 | RPM-family host - dnf, firewalld, NetworkManager, SELinux | 2 Core | 4 GB | 50 GB |
This guide includes
Use this when you are asked to add storage to a machine, or before you trust a hand-written fstab line to a reboot. This matters because a wrong line in that file stops the machine booting, and the two commands that catch it take seconds.
- reading what a machine already has, and finding there is no spare disk to practise on
- making a real block device out of a sparse file, and seeing what sparse means
- partitioning it, putting ext4 on it, and mounting it by UUID rather than device name
- writing the fstab line and verifying it, including the warning that only
findmnt --verifygives you - doing the same on the RPM family, whose default filesystem costs 35 MB before you write anything
Before you start
- the-lab-and-the-two-package-families
-
What this machine has, and what it has not
Before adding storage, look at what is there.
bash Example session lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS | head -7; echo "--- one 50 GB disk, and every byte of it already in use"NAME SIZE TYPE MOUNTPOINTSfd0 4K disksda 50G disk├─sda1 1M part├─sda2 2G part /boot└─sda3 48G part └─ubuntu--vg-ubuntu--lv 48G lvm /--- one 50 GB disk, and every byte of it already in usedf -hT / /boot | awk '{printf "%-28s %-6s %-5s %s\n", $1, $2, $3, $7}'Filesystem Type Size Mounted/dev/mapper/ubuntu--vg-ubuntu--lv ext4 48G //dev/sda2 ext4 2.0G /bootExpected resultOne 50 GB
sdawith/bootonsda2and the rest in an LVM volume, and a root filesystem of type ext4.Success conditionYou can describe a machine's storage layout in one command.
-
A block device made out of a file
512 MB that costs nothing until it is used.
bash Example session sudo truncate -s 512M /var/tmp/xk0.img && ls -lh /var/tmp/xk0.img | awk '{print $5, $9}'; du -h --apparent-size /var/tmp/xk0.img | cut -f1; du -h /var/tmp/xk0.img | cut -f1512M /var/tmp/xk0.img512M0sudo losetup -fP --show /var/tmp/xk0.img/dev/loop0lsblk /dev/loop0 -o NAME,SIZE,TYPE; echo "--- the kernel treats it as a disk, which is the only thing that matters here"NAME SIZE TYPEloop0 512M loop--- the kernel treats it as a disk, which is the only thing that matters hereExpected result
512Mfromls -lhand fromdu --apparent-size, but 0 from plaindu. Then/dev/loop0, whichlsblkreports as a 512M device of typeloop.Success conditionYou can produce a block device to practise on wherever you are.
-
A partition table, and the partition the kernel could not see
GPT, one partition, and the reason it appeared immediately.
bash Example session sudo parted -s /dev/loop0 mklabel gpt mkpart primary ext4 1MiB 100%; sudo parted -s /dev/loop0 print | tail -4 Number Start End Size File system Name Flags 1 1049kB 536MB 535MB primarylsblk /dev/loop0 -o NAME,SIZE,TYPE; echo "--- losetup -P asked the kernel to scan the table, so loop0p1 is already here"NAME SIZE TYPEloop0 512M loop└─loop0p1 510M part--- losetup -P asked the kernel to scan the table, so loop0p1 is already hereExpected resultA GPT table with one 535 MB primary partition, then
loop0p1at 510M underneathloop0in the tree.Success conditionYou can partition a device non-interactively and confirm the kernel sees the result.
-
A filesystem, and the name it will be mounted by
ext4, a label, and the identifier that does not change.
bash Example session sudo mkfs.ext4 -q -L XK0DATA /dev/loop0p1 && sudo blkid /dev/loop0p1/dev/loop0p1: LABEL="XK0DATA" UUID="0ad80a25-dfff-4792-97d7-063e30b88aa2" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="primary" PARTUUID="c4fa73b3-41ac-4c0a-bd27-6567cffca396"sudo tune2fs -l /dev/loop0p1 | grep -E "Filesystem volume name|Filesystem UUID|Block count|Reserved block count"Filesystem volume name: XK0DATAFilesystem UUID: 0ad80a25-dfff-4792-97d7-063e30b88aa2Block count: 130560Reserved block count: 6528Expected result
blkidreportingLABEL="XK0DATA", a UUID,TYPE="ext4", andtune2fsshowing 130560 blocks with 6528 reserved.Success conditionYou can create a filesystem and read back the identifiers it will be mounted by.
-
Mounting it, by UUID rather than by device name
One mount, one file written, and the proof it is really there.
bash Example session sudo mkdir -p /mnt/xk0 && sudo mount UUID=$(sudo blkid -s UUID -o value /dev/loop0p1) /mnt/xk0 && findmnt /mnt/xk0 -o TARGET,SOURCE,FSTYPE,OPTIONSTARGET SOURCE FSTYPE OPTIONS/mnt/xk0 /dev/loop0p1 ext4 rw,relatimeecho "domain 1 is 23 per cent" | sudo tee /mnt/xk0/note.txt > /dev/null; sudo df -hT /mnt/xk0 | tail -1; cat /mnt/xk0/note.txt/dev/loop0p1 ext4 462M 156K 426M 1% /mnt/xk0domain 1 is 23 per centExpected result
findmntshowing/mnt/xk0from/dev/loop0p1, type ext4 - then a 462M filesystem with 156K used, and the file read back.Success conditionYou can mount a filesystem by a name that survives a reboot, and prove it is writable.
-
The fstab line, checked before anything reboots
The file that stops a machine booting, and the two commands that check it.
bash Example session sudo cp /etc/fstab /var/tmp/fstab.bak && printf 'UUID=%s /mnt/xk0 ext4 defaults,nofail 0 2\n' $(sudo blkid -s UUID -o value /dev/loop0p1) | sudo tee -a /etc/fstab | catUUID=0ad80a25-dfff-4792-97d7-063e30b88aa2 /mnt/xk0 ext4 defaults,nofail 0 2sudo umount /mnt/xk0 && sudo mount -a && findmnt /mnt/xk0 -o TARGET,SOURCE,FSTYPE,OPTIONS; echo "mount -a exit $?"TARGET SOURCE FSTYPE OPTIONS/mnt/xk0 /dev/loop0p1 ext4 rw,relatimemount -a exit 0sudo findmnt --verify --verbose 2>&1 | tail -4 [ ] source /dev/loop0p1 exists [ ] FS type is ext4 [W] your fstab has been modified, but systemd still uses the old version; use 'systemctl daemon-reload' to reloadExpected resultThe appended line, then
mount -a exit 0with the filesystem mounted again - andfindmnt --verifyconfirming the source and type, then warning that systemd is still using the old fstab.Success conditionYou can add a persistent mount and prove the line is good without rebooting.
-
The RPM family, and the filesystem it defaults to
The same work on the other host, and the difference that matters.
bash Example session sudo truncate -s 512M /var/tmp/xk0.img && sudo losetup -fP --show /var/tmp/xk0.img && sudo mkfs.xfs -q -L XK0DATA /dev/loop0 && sudo blkid /dev/loop0/dev/loop0/dev/loop0: LABEL="XK0DATA" UUID="8a78801d-ca1e-4abd-adcd-383c939b8d49" BLOCK_SIZE="512" TYPE="xfs"sudo mkdir -p /mnt/xk0 && sudo mount /dev/loop0 /mnt/xk0 && df -hT /mnt/xk0 | tail -1; echo "--- xfs, which is what this family ships as its default"/dev/loop0 xfs 448M 35M 414M 8% /mnt/xk0--- xfs, which is what this family ships as its defaultdf -hT / | tail -1; echo "--- and the root filesystem is xfs too, where Ubuntu's was ext4"/dev/mapper/almalinux-root xfs 44G 5.1G 39G 12% /--- and the root filesystem is xfs too, where Ubuntu's was ext4Expected result
TYPE="xfs"on the loop device, a mounted filesystem showing 35M used of 448M while empty, and a root filesystem that is also xfs.Success conditionYou can do this work on either family and know what each one gives you by default.
-
Putting both machines back
Unmount, restore, detach, delete - then count what is left.
bash Example session sudo umount /mnt/xk0; sudo cp /var/tmp/fstab.bak /etc/fstab && sudo rm -f /var/tmp/fstab.bak; sudo losetup -d /dev/loop0; sudo rm -f /var/tmp/xk0.img; sudo rmdir /mnt/xk0; grep -c xk0 /etc/fstab; echo "fstab lines mentioning xk0"0fstab lines mentioning xk0losetup -a | wc -l; echo "loop devices left"; ls /var/tmp/xk0.img 2>&1 | tail -10loop devices leftls: cannot access '/var/tmp/xk0.img': No such file or directorysudo umount /mnt/xk0; sudo losetup -d /dev/loop0; sudo rm -f /var/tmp/xk0.img; sudo rmdir /mnt/xk0; losetup -a | wc -l; echo "loop devices left on the RPM host"0loop devices left on the RPM hostExpected result
0fstab lines mentioning xk0,0loop devices on either host, andNo such file or directoryfor the image.Success conditionBoth machines are exactly as they were before this page.
Troubleshooting
A new partition does not appear under
/devafterpartedorfdisk.Why: The partition table on disk changed but the kernel is still using the copy it read earlier.
Fix:
sudo partprobe /dev/sdXorsudo partx -a /dev/sdX. For a loop device, attach it withlosetup -Pso the scan happens automatically.The machine drops to emergency mode after a reboot and the console mentions a mount.
Why: A line in
/etc/fstabnames a device or UUID that is not present, and withoutnofailsystemd treats the failure as fatal.Fix:From the rescue shell,
mount -o remount,rw /, comment the line out, and reboot. Prevent it next time withnofailand by runningumountthenmount -abefore you ever reboot.A filesystem mounted from
/dev/sdb1comes back on the wrong disk after a reboot.Why: Kernel device names are assigned in discovery order and are not stable across reboots or hardware changes.
Fix:Mount by
UUID=orLABEL=.blkidprints both, andlsblk -o NAME,UUID,LABELshows them for every device at once.dfshows space free but writes fail for an ordinary user.Why: ext4 reserves 5% of blocks for root by default - 6,528 of 130,560 on the filesystem built here.
Fix:
tune2fs -m 1 /dev/sdX1lowers the reserve on a data volume, or-m 0removes it. Leave the reserve alone on the root filesystem, where it is what lets a full machine still boot and log.