Linux Filesystem Hierarchy Explained: From / to /home
This is the article I wish I had read before I rebuilt linux filesystem hierarchy explained: from / to /home for the third time. Every paragraph below comes from...
This is the article I wish I had read before I rebuilt linux filesystem hierarchy explained: from / to /home for the third time. Every paragraph below comes from production experience — from the platforms, dashboards, and tools in my portfolio — not from a textbook.
Introduction
The Linux filesystem is a single tree starting at /, with everything — disks, devices, even pseudo-file systems — hanging from it. That structure is the operating system's memory and its configuration, and knowing your way around it is the difference between navigating and stumbling. This article maps the tree, then hands you the tools to work it.
We start with the map: what each top-level directory actually contains, so you know where to look for configs (/etc), where to expect binaries (/usr/bin, /usr/local/bin), where user data lives (/home, /var), and why /tmp and /proc are not what they seem.
Then the working tools: ls in all its ways, find for the most powerful file search that exists, locate for the fast-but-stale alternative, and the soft skills of wildcards, quoting, and globbing that make paths less fragile.
We get concrete about storage: df for filesystem fullness, du for directory sizes, inodes and why a 'disk full' error can be a directory full instead, symlinks versus hard links, and mounting — attaching a drive or partition to a directory so it joins the tree.
By the end, disk-full emergencies, missing binaries, and 'what is this directory for?' questions will all be five-second answers instead of searches.
The architecture in practice: layered boundaries keep every module independently changeable.
Why It Matters
Every Linux skill assumes filesystem literacy. Paths in config files, logs that need tails, scripts that need executable friends, databases that need their data directories — all of them are journeys through the same tree, and knowing the map turns 'where is that?' into an instant answer.
The filesystem is the primary source of truth on a server: the configs in /etc are the running state of your services, and /var/log is the black box recorder of everything that has gone wrong. Operators who know the map debug in minutes; operators who do not, grep fruitlessly.
Disk management is where availability is won or lost. A server at 99% disk behaves worse than a server at half capacity — writes pause, databases stall, and backups silently fail. Knowing df, du, and the inode model gives you the diagnostic path that keeps a 'disk full' alert from becoming an outage.
- / is the root of everything — there is no drive letter scheme
- /etc holds configs, /var/log holds history, /home holds people
- /proc and /sys are live views of the kernel, not disk files
- find is the fastest way to locate files by every attribute
- A full inode count can trigger 'no space left' on an empty disk
- Symlinks are shortcuts; hard links are aliases of the same data
The Problem
The confusion begins with drive letters: on Windows, C: is where the program is and everything is relative to it. Linux dissolves that scheme — /home may be a separate partition, /var may be a separate mount, and none of it is discoverable from icon position. Newcomers ask 'where is my USB drive?' and the answer, 'it is inside /media, mounted as a directory', makes no sense until the tree model clicks.
The second failure is tool misuse: using ls -la and scrolling for answers when find could return the exact file, or running df and panicking at 90% without checking which mount is actually full and why backups run out of space before disks do.
The Approach
Learn the map by ownership: /bin, /sbin, /usr/bin are system programs (and on modern distros /bin merged into /usr/bin); /etc is configuration — the directory that sails through upgrades; /var houses variable data — logs, mail, temporarily caches; /home is user land; /tmp is shared scratch; /proc and /sys are kernel windows, not real files.
For finding, one tool dominates: find /where -name 'pattern' -mtime +N -size +10M composes every attribute — name, age, size, type, permission — into a single powerful query. locate is the pre-built index for speed when a live search is overkill. The wildcards they share (* and ?) are the same shape of winning that pipelines gave us for text.
For storage, two read commands cover it: df -h for filesystems — how full each mount really is — and du -sh * inside a directory to see where the bytes went. Then mounting: mount attaches a device or filesystem to a directory, and the /etc/fstab table makes the attachment permanent across reboots.
Study the find / -type f -size +500M line: the 2>/dev/null suppresses the expected permission errors on system directories and is the difference between noise and a clean answer. And the symlink example matters because half the binaries in /usr/bin are symlinks — ls -l shows the arrow when one exists.
# the map, quickly
ls -la / # what is at the root
df -h /var # how full is the /var filesystem?
du -sh /var/log/* | sort -rh | head # the disk hogs in /var/log
# finding anything
find /etc -name '*.conf' -mtime -7 # configs churned this week
find / -type f -size +500M 2>/dev/null # files bigger than 500MB
ls -l /usr/bin/nginx # symlink? -> the real binary
# links
ln -s /var/www/app /root/app # symlink: a shortcut to a path
ln /etc/hosts /tmp/hosts2 # hard link: same inode, two names
# mounts
sudo mount /dev/sdb1 /mnt/data # attach the disk
sudo nano /etc/fstab # make it permanent
sudo mount -a # apply fstab now
sudo umount /mnt/data # detach safely
mount | grep sdb # verify what is mounted
The pattern applied: consistent structure is what makes software safe to change.
Symlinks vs Hard Links
| Question | Symlink | Hard Link | Which to Use |
|---|---|---|---|
| What is it? | A shortcut storing a path | An alias of the same inode | Depends on the goal |
| Broken if target deleted? | Yes — dangling link | No — data survives | Hard link for reliability |
| Cross-filesystem? | Yes, works anywhere | No — same filesystem only | Symlink for /var → /home |
| Directories? | Yes, symlink directories | No, typically not allowed | Symlink for dir shortcuts |
| Typical use | App configs, PATH entries, releases | Deduplicating big files | Symlink for daily work |
In daily practice you will use symlinks constantly (ln -s) and hard links rarely. The one fact to keep: a hard link is not a copy — both names point to the same physical data, so editing through one name is visible through the other.
Implementation
Handle disk emergencies with a strict routine: df -h to find the mount, du -xhd1 /mount to find the directory, then prune — rotate or delete logs (journalctl --vacuum-time=7d is the fastest modern win), hoard the apt cache (apt clean), and check for deleted-but-open files with lsof +L1 that only a process restart can reclaim.
Check inodes when free space sounds fine: df -i reports inodes, and a directory with a million tiny files can exhaust them on a nearly-empty disk. Tools like find / -xdev -type f -printf '%i\n' | sort -u | wc -l count unique files; the answer is a dash of insight and a question of your file layout.
Mount storage sanely: put data you intend to keep (databases, uploads) on its own partition or volume with an fstab entry (UUID-based, not device-letter-based, since device letters can shuffle), and mount ephemeral stuff like /tmp or journal logs onto tmpfs where appropriate. A data-bearing disk should be named by its UUID so a reboot does not chase the letters.
df -handdf -i: space and inodes are independent limits — check bothdu -xhd1 /pathis the fastest way to find the largest subdirectory- journalctl trim is the quickest reclaim of disk real estate
- mounted symlink?
readlink -fresolves symlinks to the real path - Use UUIDs in fstab: /dev/sdX letters are not guaranteed across reboots
mount -o noatimecuts writes on casual reads of your data mount- lsof +L1 finds space eaten by deleted-but-still-open files
- Directory permission is about traversal — see the permissions article
Key Decisions
find or locate?
find is authoritative and never stale — it searches the live tree with any attribute. locate is a prebuilt index: instant, but it must be updated (updatedb) and can show ghosts of deleted files. Use locate for quick name lookups you know are current; use find when correctness matters.
Separate partitions or one big volume?
Separate the risky and the critical: root, /home, and /var are the classic trio, often with /var/log isolated so log storms cannot fill the root filesystem. On modern servers, LVM or a cloud volume adds resize flexibility — but a separate mount is decided at install time, so decide deliberately, not later.
tmpfs for /tmp?
Yes on many systems: /tmp served from tmpfs is RAM-backed, wipes itself on reboot, and keeps transient writes off your disk. The cost is that /tmp content does not survive reboots — which is almost always correct behavior for a scratch directory.
Common Mistakes to Avoid
The most common Linux mistake is the dangerous command reflex: reaching for chmod 777 to silence a permission error, or rm -rf to 'fix' a directory, without understanding what the command actually changes. Both are moments where a second of comprehension prevents an hour of recovery. The permission article exists to replace the reflex with the model.
The second mistake is treating the system as a collection of unrelated commands instead of one coherent model: users, files, processes, packages, and services that all interact. Operators who learn the model debug in minutes; operators who memorize commands debug by trying things. The discipline — decompose, diagnose, then act — is the whole difference.
- chmod 777 and rm -rf as the first resort — the two classic disasters
- kill -9 as the reflex for every hung process
- Tutorial snippets copied without reading what they change
- Skipping man pages and --help because 'they are for beginners'
- No documentation of the commands that keep a server alive
Patterns That Scale
The pattern that pays most is the command language: a small set of primitives (ls, cat, grep, find, ps, df) composed with pipes and redirection into the exact answer to a question. Every article in this category demonstrates the composition — a log question becomes grep | sort | uniq in one line, not a five-step ritual.
The second pattern is the check-before-act discipline: ls before rm, df before blaming the app, ps before killing, nginx -t before reloading. The pattern is three keystrokes of prevention that this portfolio practices in every deployment and documents in every script.
- Compose small commands with pipes instead of scripting everything
- Inspect before you act — ls before rm, ps before kill
- Keep destructive commands behind full paths and dry runs
- Learn the model (users, processes, packages) not just the commands
Real-World Example
The platform behind this site separates its data deliberately: the application code lives on the root filesystem, MongoDB data on a dedicated volume mounted by UUID, and logs rotated into the volume's /var/log so a log storm cannot take down the app partition. That layout is the fstab decisions in this article, made once and versioned in the ansible.
The incident that cemented du-drill: a 'disk full' alert on a box that had 40GB free showed df -i at a million tiny files in a caching directory — a single find measured the scale and a config removed the cache. The disk had space; the filesystem's inode table did not. Both numbers, checked together, saved an hour of staring at df -h alone.
Case Study: Linux Filesystem Hierarchy Explained: From / to /home
The principles in this article were applied end to end when I rebuilt DevBench from a prototype into a production service. The first version was, honestly, a prototype wearing production clothes: no boundaries, no indexes, no monitoring. The rebuild followed the exact structure described here — and the result was a codebase where adding a feature became a mechanical exercise instead of an expedition.
The measurable difference came from the boring parts. The deployment pipeline that ships DevBench is the same one that ships this platform, and the incident rate dropped to zero for the first year after the rebuild.
- The lesson that cost the most in linux: measure before changing anything, and let the data pick the fix.
- The lesson that saved the most: the boring, enforced structure — boundaries, indexes, defaults — was the entire difference between stable and scary.
- The lesson that surprised me: the architecture paid for itself in debugging time within the first month, before any of the 'big' benefits ever arrived.
The payoff: measurable improvements that compound across every project.
Putting It Into Practice
Start with the safety habits from this category: never run a destructive command without understanding it, run df -h and ps aux before changing anything under load, and practice the permission model until ls -l reads like prose. These three habits remove the entire class of self-inflicted Linux incidents.
Then build the command vocabulary deliberately: take one routine task a day and replace its slow way with a composed command. Within a month the terminal is an extension of your thinking rather than a tool you consult.
How This Applies to Your Stack
In the stack behind this site, the Linux layer is the foundation everything else stands on: the server runs an LTS distribution, the shell scripts that deploy the platform are bash, and the terminal is the daily interface to every box. The commands in these articles are not reference material — they are the actual verbs of the deployment, monitoring, and backup routines documented in the repository.
Whatever your stack, the same Linux core appears: the OS, the shell, and the command vocabulary. The tools may differ by distribution family (apt or dnf, systemd or sysv), but the shape is identical — and learning the shape once transfers to every machine you will ever touch.
Key Takeaways
- I know the job of every directory in /
- I can find any file by name, age, size, or type with find
- I read df -h and df -i when storage acts up
- I know where 80% of a mysterious disk fill lives (du -xhd1)
- I keep data-bearing mounts on UUID-based fstab entries
- I use symlinks for anything a config or release path needs
- I know the difference between removing a link and removing data
- My logs are rotated, journal-trimmed, and nowhere near filling the disk
Frequently Asked Questions
Why does my du total not match df used?
Mismatches are normal and usually harmless: deleted-but-open files (lsof +L1), reserved blocks (5% by default for root), and tmpfs mounts each absorb space du never sees. The classic alkane: use du -x so du stays on one filesystem and stop at the real mount point.
What is an inode anyway?
An inode is the metadata record for a file — ownership, permissions, timestamps, and the block pointers, but not the name. Names live in directories and point at inodes. Hard links are just multiple names pointing at the same inode; this is why a 'disk full' can coexist with free space when inodes run out.
Why is /proc so strange?
Because /proc is a pseudo-filesystem: it is the kernel publishing its state as files. cat /proc/meminfo, /proc/cpuinfo, and /proc/uptime are live kernel data, and tools like top and free read them under the hood. Files in /proc are usually zero bytes of real disk and infinite bytes of useful information.
What is the quickest way to free disk on a full server?
journalctl --vacuum-time=3d (log trimming), apt clean (package cache), remove core dumps (find / -name core -type d), and rotate old backups you actually verified. Then the discipline: du -xhd1 / to identify the real sink so it does not refill.
How do I move /var to another disk?
Rsync the current content to the new mount, unmount-newly, and rewrite the fstab entry to point /var at it, then mount -a. Run the copy offline or during a maintenance window — a half-migrated /var with logs streaming in is a museum of disasters.
What are /etc files that get .new or .old suffixes?
Those are the artifacts of package upgrades: when a config changed locally and the package manager installed its version, it saves the new one as file.dpkg-new and keeps yours intact. Resolve them deliberately (dpkg -V), because two competing configs are exactly how services break mysteriously after an upgrade.
Which is the single most dangerous Linux command?
rm -rf on the wrong path — it is recursive, forced, and permanent, and a single typo or wrong variable turns it from 'cleanup' into 'catastrophe'. The discipline: always print or echo the full path first, never combine it with unchecked variables, and prefer rm -r (without -f) for anything interactive.
How do I know which command to learn next?
Let the work decide: the next command you need is the one that would have automated whatever you just did manually. Read your shell history weekly, find the repeated manual steps, and learn the command that removes one of them. The curriculum is your own routine.
Conclusion
The Linux filesystem is the same elegant tree from a laptop to a Kubernetes node — the map and the tools are constant, which makes the knowledge carried lifelong. Bash one hour into the tree, reading it as a map instead of a mystery, and the whole operating system becomes legible.
Spend one session walking the tree with this article: ls every top-level directory, df and du your real storage, and resolve one symlink chain. The map will stick, and every subsequent session on a server will be a visit to a place you know the geography of.