The Filesystem Hierarchy Standard

Every Linux system organizes its files into a single tree that starts at one root directory, written as /. Unlike Windows, there is no C: or D: drive letter — every disk, partition, USB stick, and even non-storage things like running processes and hardware devices are attached (“mounted”) somewhere inside that one tree. The Filesystem Hierarchy Standard (FHS) is the specification that says which directory should hold which kind of file, so that any Linux distribution, any package manager, and any script can predict where to find (or put) something. Understanding it is what lets you read a path like /var/log/nginx/error.log and immediately know what it contains before you even open it.

Overview: What the FHS Is and How It Works

The FHS is maintained by the Linux Foundation and describes a standard directory layout that Debian, Ubuntu, Fedora, RHEL, and nearly every other mainstream distribution follow (with small variations). It exists because early Unix systems grew organically, and different vendors put similar files in different places — which made it painful to write software, packages, or documentation that worked everywhere. The FHS fixed that by defining, for example, that system-wide configuration always lives under /etc, that variable data that changes at runtime (logs, caches, mail spools) lives under /var, and that user home directories live under /home.

Under the hood, the Linux kernel treats almost everything as a file: regular documents, directories, hardware devices (/dev/sda), even running processes (exposed through /proc) are all accessed through the same file-based interface. The root filesystem / is the first filesystem the kernel mounts during boot. Every other filesystem — a second disk partition, a USB drive, a network share — is attached to an empty directory somewhere inside that tree through a process called mounting. Once mounted, the contents of that separate filesystem simply appear to live inside the directory you mounted it on, called the mount point. This is why /home and / can physically be two different disks, or why /boot is sometimes its own small partition, yet from a user’s perspective they all just look like folders in one tree.

When you type a path like /etc/hosts, the kernel resolves it by walking the tree one directory entry at a time starting from the root: it looks up etc inside /, then looks up hosts inside that etc directory. A relative path like logs/today.log is resolved starting from your shell’s current working directory instead of the root. Modern distributions (including current Ubuntu and Fedora) also use a “merged /usr” layout, where directories like /bin, /sbin, and /lib are actually symbolic links pointing into /usr/bin, /usr/sbin, and /usr/lib. That consolidation happened for technical reasons (making early boot and read-only root filesystems simpler), but the FHS names still work exactly as documented — you can keep using /bin/bash and it will resolve correctly through the symlink.

The Standard Top-Level Directories

Here are the directories you will see directly under / on almost any Linux system, and what each one is for:

Directory Purpose
/bin Essential user command binaries needed by all users (ls, cp, bash), usable even in single-user/recovery mode. On modern distros this is a symlink to /usr/bin.
/boot Files needed to boot the system: the Linux kernel image, initramfs, and bootloader configuration (GRUB).
/dev Device files representing hardware and virtual devices (/dev/sda for a disk, /dev/null, /dev/tty). Managed dynamically by the kernel’s udev subsystem.
/etc System-wide configuration files, always plain text and editable (/etc/passwd, /etc/ssh/sshd_config, /etc/hosts).
/home Personal directories for regular users, e.g. /home/alice. Each user’s files, settings, and downloads live here.
/lib Shared library files needed by the binaries in /bin and /sbin. Also usually a symlink to /usr/lib.
/media Mount points for removable media, like USB drives or CDs, typically auto-mounted here by the desktop environment.
/mnt A conventional, temporary place for an administrator to manually mount a filesystem.
/opt Optional, self-contained third-party software packages that don’t follow the normal /usr layout, e.g. /opt/google/chrome.
/proc A virtual filesystem, generated live by the kernel, exposing information about running processes and kernel parameters. Nothing here exists on disk.
/root The home directory for the root (superuser) account — not to be confused with /, the root of the whole tree.
/run Runtime data since the last boot: process IDs, sockets, lock files. Cleared on every reboot.
/sbin System binaries mainly used by the administrator, like fdisk or iptables. Also usually a symlink to /usr/sbin.
/srv Data served by this system, such as files for a web server or FTP server.
/sys Another virtual, kernel-generated filesystem exposing device and driver information, used heavily by udev and hardware tools.
/tmp Temporary files that any user or program may write to. Often cleared automatically on reboot — never assume it’s permanent.
/usr The bulk of installed software: user programs, libraries, documentation, and (under /usr/local) software installed manually outside the package manager.
/var “Variable” data that changes while the system runs: logs (/var/log), package caches, mail spools, and databases.

Syntax

The FHS isn’t a command you type — it’s a layout you explore with ordinary tools. The commands below are the ones you’ll reach for most:

  • ls -l / — list the top-level directories and their permissions.
  • df -h — show every mounted filesystem, its size, and where it’s mounted (-h means “human-readable” sizes like 20G instead of raw bytes).
  • findmnt — show mounted filesystems as a tree, matching the directory structure.
  • du -sh path — summarize how much disk space a directory is using.
  • man hier — the manual page that documents the FHS directly on your own system.

The general shape of a disk-usage lookup is:

df -h <mount-point>

Examples

Example 1: Listing the top-level directories

ls -l /

Output:

drwxr-xr-x   2 root root  4096 Jul 12 09:14 bin -> usr/bin
drwxr-xr-x   3 root root  4096 Jun 02 08:01 boot
drwxr-xr-x  19 root root  3860 Aug 04 07:30 dev
drwxr-xr-x  95 root root  4096 Aug 03 22:11 etc
drwxr-xr-x   4 root root  4096 Jun 02 08:20 home
lrwxrwxrwx   1 root root     7 Jun 02 07:55 lib -> usr/lib
drwx------   2 root root 16384 Jun 02 07:55 lost+found
drwxr-xr-x   2 root root  4096 Feb 03 12:00 media
drwxr-xr-x   2 root root  4096 Feb 03 12:00 mnt
drwxr-xr-x   3 root root  4096 Jul 20 15:44 opt
dr-xr-xr-x 213 root root     0 Aug 04 00:00 proc
drwx------   4 root root  4096 Aug 01 10:02 root
drwxr-xr-x  25 root root   760 Aug 04 07:30 run
drwxr-xr-x   2 root root 12288 Jul 12 09:14 sbin -> usr/sbin
drwxr-xr-x   2 root root  4096 Feb 03 12:00 srv
dr-xr-xr-x  13 root root     0 Aug 04 00:00 sys
drwxrwxrwt  12 root root  4096 Aug 04 09:10 tmp
drwxr-xr-x  14 root root  4096 Jun 02 07:55 usr
drwxr-xr-x  13 root root  4096 Jul 30 18:22 var

Notice the l at the start of the lib line and the -> arrows on bin and sbin: those are symbolic links, confirming the merged-/usr layout described above. The d at the start of most other lines means “this is a directory.” /tmp‘s permissions end in t (the sticky bit) — it’s world-writable, but that bit stops one user from deleting another user’s files inside it.

Example 2: Seeing which physical filesystems back which directories

df -h

Output:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        30G   12G   17G  42% /
/dev/sda1       512M   88M  424M  18% /boot
/dev/sdb1       200G  140G   50G  74% /home
tmpfs           3.9G     0  3.9G   0% /dev/shm

This shows that although /, /boot, and /home all appear as ordinary folders in one tree, they are actually three separate physical partitions (sda2, sda1, sdb1) mounted at those points. That’s a common real-world setup: giving /home its own partition means you can reinstall the operating system on / without touching user files.

Example 3: Finding files inside a standard directory

find /var/log -maxdepth 1 -name "*.log"

Output:

/var/log/alternatives.log
/var/log/dpkg.log
/var/log/auth.log
/var/log/syslog.log

Because the FHS guarantees that log files live under /var/log, you never have to guess where an application writes its logs — you can search that one location instead of scanning the whole disk.

How It Works Step by Step

When a Linux machine boots, the sequence that builds the filesystem tree looks like this:

  • 1. The bootloader (usually GRUB) loads the kernel and an initial RAM filesystem (initramfs) into memory, using files it finds under /boot.
  • 2. The kernel starts, mounts the real root filesystem (the partition configured to hold /) read-only at first, then switches it to read-write once checks pass.
  • 3. The kernel creates the virtual filesystems /proc and /sys on the fly — these were never written to disk; they’re generated in memory to expose live kernel and hardware state as if they were files.
  • 4. The init system (typically systemd) reads mount configuration from /etc/fstab and mounts every other configured filesystem — /boot, /home, swap, network shares — onto their designated directories.
  • 5. Once everything is mounted, any path you type, like /etc/hosts, is resolved by the kernel walking that single unified tree, transparently crossing from one physical (or virtual) filesystem into another wherever a mount point sits.

Common Mistakes

Mistake 1: Treating /tmp as permanent storage

It’s tempting to stash working data in /tmp because it’s always writable, but many distributions clear it automatically on every reboot (via systemd-tmpfiles or a startup script).

#!/usr/bin/env bash
echo "important state" > /tmp/myapp-state.txt

If the machine reboots, that file can silently vanish. Store data you actually need to keep somewhere under the user’s home directory or /var instead:

#!/usr/bin/env bash
set -euo pipefail
state_dir="$HOME/.local/state/myapp"
mkdir -p "$state_dir"
echo "important state" > "$state_dir/state.txt"

Mistake 2: Installing your own software into /usr/bin

Copying a personal or third-party script straight into /usr/bin mixes it in with files owned by your distribution’s package manager, so a future apt upgrade could overwrite or conflict with it.

sudo cp myscript /usr/bin/myscript

The FHS reserves /usr/local/bin exactly for this case: software installed manually, outside the package manager, that should never collide with distro-managed files.

sudo cp myscript /usr/local/bin/myscript
sudo chmod +x /usr/local/bin/myscript

Mistake 3: Writing application logs into a root-owned directory

If you install an app under /opt/myapp (owned by root) and then try to have it write its own logs next to itself while running as a normal user, it will fail:

myapp >> /opt/myapp/logs/output.log

Output:

bash: /opt/myapp/logs/output.log: Permission denied

Logs belong under /var/log, in a directory created with the right ownership up front:

sudo mkdir -p /var/log/myapp
sudo chown "$USER":"$USER" /var/log/myapp
myapp >> /var/log/myapp/output.log

Best Practices

  • Put system-wide configuration you hand-edit in /etc, never inside /usr.
  • Use /usr/local (or /opt for large self-contained packages) for anything installed outside your distribution’s package manager.
  • Never assume /tmp survives a reboot; treat it as scratch space only.
  • Write logs to /var/log, not next to the program’s binaries.
  • Keep personal files under your own /home/<user> directory, not system directories that require sudo to edit.
  • Before manually editing a file under /etc, make a backup copy — a typo in something like /etc/fstab can prevent the system from booting.
  • Use df -h or findmnt to check what’s actually mounted before assuming a directory has plenty of free space — /home being full doesn’t mean / is full, and vice versa.

Practice Exercises

  • 1. Run ls -l / on your own machine and identify which top-level entries are symbolic links rather than real directories. What do they point to?
  • 2. Run df -h and note how many separate filesystems are mounted, and which directories they’re mounted on. Is /home on the same filesystem as /?
  • 3. Pick an installed command-line tool (for example curl) and use which curl followed by ls -l on the result to figure out whether it actually lives in /bin, /usr/bin, or somewhere symlinked between the two.

Summary

  • Linux has one unified file tree rooted at /; separate disks and partitions are attached into it via mount points.
  • The Filesystem Hierarchy Standard defines what each top-level directory is for, so paths are predictable across distributions.
  • /etc holds configuration, /var holds changing runtime data like logs, /home holds user files, and /usr holds the bulk of installed software.
  • /proc and /sys are virtual filesystems generated live by the kernel, not stored on disk.
  • On modern distros, /bin, /sbin, and /lib are symlinks into their /usr equivalents (the “merged /usr” layout).
  • Use /usr/local for manually installed software so it never collides with your package manager, and never treat /tmp as permanent storage.