A full disk is the number one enemy of server availability. This episode covers reading capacity with df, du, and free, partitioning and formatting disks, mounting them permanently via UUID-based /etc/fstab, through to an introduction to LVM with dynamic resizing without downtime.

After episode 14 where we covered systemd and managing services — systemctl, journalctl, and writing service unit files — you can now keep an application alive. But there's one disaster even the most perfect Restart=on-failure can't prevent: a full disk. A perfectly running service dies instantly when its filesystem fills up — databases stop writing, logs stop flowing, and applications "hang" in place.
In this episode, we'll open the most fundamental layer of the system: storage. You'll learn to read storage conditions with df, du, and free, recognize disk devices with lsblk and blkid, partition and format disks, mount them permanently via /etc/fstab, and get to know LVM — the technology that lets disk capacity grow without downtime. Let's begin.
df, du, and freeThe first diagnosis of every "slow server" is capacity. Three commands form the initial measuring tools: df -h for free space on filesystems, du -sh for directory sizes, and free -h for memory.
# Free space on all filesystems
df -h
# Size of the current directory (and its subdirectories)
du -sh .
du -sh /var/log/*
# Summary of memory & swap usage
free -hThe df -h output shows one line per filesystem, with the columns Filesystem, Size, Used, Avail, Use%, Mounted on. Two things that often trip people up:
Avail vs Size columns. You'll rarely see Avail = Size; filesystems reserve space for root (usually 5%) and for metadata. That's normal, not an anomaly./ directory can be non-full yet the server "hangs". Also check separate mount points — /var, /tmp, or /home can be 100% full while / looks fine. This is why df -h is always read line by line, not just the first line.Meanwhile, du -sh /var/log/* directly reveals the culprit: a giant log file or a bloated cache directory. The typical disk-full troubleshooting combination is: df -h to find the full mount → du -sh /path/* to find the wasteful directory → du -sh /path/subdir/* and so on until the cause is found.
Tip
Files still open by a process keep consuming space even after being rm'd. The classic symptom: df -h shows Use% still at 100% even though the file was "deleted". The answer is in /proc/*/fd: run lsof +L1 to find deleted-but-open files — identify the process, then restart it so the space is truly freed.
lsblk and blkidlsblk displays block devices — physical disks and their partitions — as a tree. This is the visual map you should see first before touching any disk.
lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 1M 0 part
└─sda2 8:2 0 40G 0 part /
sdb 8:16 0 10G 0 diskMeanwhile, blkid displays the identity of block devices — especially the UUID, the key to /etc/fstab:
sudo blkid/dev/sda2: UUID="3f5a2c1e-..." TYPE="ext4" PARTUUID="..."The UUID (Universally Unique Identifier) is a disk's ID card — an identity that stays the same as long as the filesystem isn't reformatted. This is why /etc/fstab is better off using UUIDs than device names (/dev/sda2): device names can change (for example, when adding a new disk, /dev/sdb can shift to /dev/sdc), while UUIDs never change. With a UUID, the mount point stays correct no matter what order the kernel names the disks.
fdisk, parted, and mkfsTo use a new disk, the steps are: partition (divide the disk into sections) then format (write a filesystem onto the partition). The most common partitioning tools are fdisk (interactive, for simple MBR/GPT) and parted (more modern, scriptable). Because fdisk is interactive, its flow is: fdisk /dev/sdb → type n (new partition) → p (primary) → Enter for defaults → w (write).
sudo fdisk /dev/sdb
# Inside the fdisk prompt:
# n → create a new partition
# p → primary type
# Enter → default partition number
# Enter → default first sector
# Enter → default last sector (use the whole disk)
# w → write changes to diskAfter the partition is created, verify with lsblk — you should see /dev/sdb1 appear. Then format the partition with mkfs. The main filesystem choices: ext4 (the Debian/Ubuntu standard, stable, most compatible) and xfs (excellent for large files, the RHEL/Fedora default).
# ext4 — Debian/Ubuntu default
sudo mkfs.ext4 /dev/sdb1
# xfs — RHEL/Rocky/Fedora default
sudo mkfs.xfs /dev/sdb1Warning
mkfs destroys all data on the partition — there's no adequate confirmation in many versions. Always double-verify that you're formatting the right device with lsblk and blkid before pressing Enter. Formatting /dev/sda (the system disk) instead of /dev/sdb (the new disk) is one of the fastest ways to lose an entire server.
mount, umount, and /etc/fstabMounting means "attaching" the filesystem of a device to a directory, so its files can be accessed. The directory where a filesystem is attached is called the mount point. Let's mount the partition we just formatted:
# Create the mount point first
sudo mkdir -p /data
# Mount the partition to the mount point
sudo mount /dev/sdb1 /data
# Verify
df -h /data
# Unmount when not needed
sudo umount /dataA manual mount only lasts until reboot. To have the filesystem auto-mounted at boot, add an entry to /etc/fstab. An fstab line format consists of six columns: device, mount point, filesystem type, options, dump, fsck order.
# <device> <mount> <type> <options> <dump> <fsck>
UUID=3f5a2c1e-... /data ext4 defaults,nofail 0 2Columns that need attention:
UUID= — the device's stable identity. Replace with the UUID from blkid.defaults — the standard option bundle (rw, suid, dev, exec, auto, nouser, async).nofail — the most important option for data disks: if the device is missing at boot, the system still continues booting. Without nofail, a missing disk will make boot hang or fail.2 — the fsck check order; root is usually 1, other data 2, and 0 to skip.Important
One wrong /etc/fstab entry can make the system unbootable — because mounting happens in the early boot phase before login. Always test a new entry with sudo mount -a (mount all fstab entries) before rebooting, and get into the habit of adding nofail to non-system mount points. If you're already locked out, boot single-user (from GRUB) and repair the fstab.
After editing /etc/fstab, always verify with mount -a then df -h. This command "tries" to mount all entries — if there's an error, it appears now, not at reboot.
Let's chain everything together in a real scenario: you add a 10GB disk to a VM, then want the data permanently mounted at /data.
# 1. Make sure the new disk is visible (sdb = 10G)
lsblk
# 2. Create a partition (n → p → Enter → Enter → w)
sudo fdisk /dev/sdb
# 3. Format the new partition
sudo mkfs.ext4 /dev/sdb1
# 4. Get the partition UUID
sudo blkid /dev/sdb1
# 5. Create the mount point
sudo mkdir -p /data
# 6. Add to /etc/fstab (line UUID=... /data ext4 defaults,nofail 0 2)
# 7. Test mounting all fstab entries
sudo mount -a
# 8. Verify
df -h /dataThis sequence is a universal template you'll use again and again in your DevOps career — from adding VM disks, attaching cloud volumes, to preparing new storage servers. Memorize the pattern, not the commands: see → partition → format → identity → mount point → fstab → verify.
There's a problem with traditional partitions: partition size is tied to the physical disk. If /data is full, you can't grow it without the hassle of repartitioning (which usually requires downtime). LVM (Logical Volume Manager) solves this by adding an abstraction layer: storage is split into Physical Volume → Volume Group → Logical Volume, and a Logical Volume can be grown/shrunk at any time, even while in use.
Imagine modular swimming pools. A Physical Volume (PV) is an individual water tank (physical disk). A Volume Group (VG) is a combination of several interconnected tanks — one big pool. A Logical Volume (LV) is a "compartment" drawn from that big pool, and you can enlarge the compartment simply by opening a valve, without dismantling the tank.
# 1. Mark the partition as a Physical Volume
sudo pvcreate /dev/sdb1
# 2. Combine into a Volume Group named vgdata
sudo vgcreate vgdata /dev/sdb1
# 3. Create an 8G Logical Volume inside the VG
sudo lvcreate -L 8G -n lvdata vgdata
# 4. Format & mount the LV like a normal partition
sudo mkfs.ext4 /dev/vgdata/lvdata
sudo mkdir -p /data
sudo mount /dev/vgdata/lvdata /dataLVM's advantage shows when storage runs low. To grow a Logical Volume without downtime, combine lvextend and resize2fs:
# Grow the LV from 8G to 12G
sudo lvextend -L 12G /dev/vgdata/lvdata
# Expand the filesystem to match the new LV size
sudo resize2fs /dev/vgdata/lvdata
# Verify — no unmount, no downtime
df -h /dataTip
The resize2fs command adjusts the ext4 filesystem size to its LV; in the RHEL family, xfs filesystems use xfs_growfs /data instead. A must-have habit: always grow the filesystem after lvextend — growing the LV without resizing the filesystem just creates "hidden" space the application can't use.
LVM also allows adding new physical disks to the same VG (vgextend), so the storage pool keeps growing without stopping anything — that's why LVM is almost always the default choice of modern Linux installers for system storage.
| Mistake | Symptom | Solution |
|---|---|---|
Wrong fstab entry / forgot nofail | Boot hangs or fails | Test with mount -a; always add nofail |
Using /dev/sdb1 in fstab | Wrong mount when the device is renamed | Use the UUID from blkid |
mkfs on the wrong device | Permanent data loss | Verify lsblk/blkid before formatting |
lvextend without resize2fs | Space grows but the filesystem doesn't | Run resize2fs / xfs_growfs |
Only df -h on / | Another full mount goes undetected | Read all lines of df -h |
rm on a file still open | df stays at 100% | Find with lsof +L1, restart the process |
| Mount without fstab | Storage disappears after reboot | Add an entry to /etc/fstab |
In this episode 15 we've touched the most fundamental yet most crucial foundation: storage. You learned to read capacity with df -h, du -sh, and free -h, map devices with lsblk and blkid, partition and format disks with fdisk/parted and mkfs.ext4/mkfs.xfs, mount them permanently through UUID-based /etc/fstab with the nofail option, run the whole add-a-new-VM-disk workflow, and get to know LVM which allows storage to grow without downtime. The most important lesson: always verify before destroying, and always test before rebooting.
With healthy storage, your journey into the system's core is one step away. In the next episode 16 we'll discuss the boot process, kernel & kernel modules — from BIOS/UEFI, GRUB, to initramfs — and how to manage kernel modules with lsmod, modprobe, and modinfo. That's where all the layers you've learned (filesystem, services, processes) unite into one beautiful sequence. See you there!