Skip to content

Filesystem Hierarchy

Linux uses one directory tree rooted at /, with each top-level directory reserved for a kind of data: configuration, logs, binaries, runtime state. The layout follows the Filesystem Hierarchy Standard (FHS) and systemd's file-hierarchy(7), so the same paths work on every distribution.

Track: Core · Interview weight: High


Must-Know Facts

Fact Value Verify with
One tree Disks, partitions and network shares are mounted into /; no drive letters findmnt
/etc Host-specific configuration, plain text ls /etc
/var Data that changes: logs, caches, spools, databases ls /var
/var/log Log files ls /var/log
/var/lib Persistent application state (package databases, Docker, databases) ls /var/lib
/usr Installed software, read-only in normal operation du -sh /usr
usrmerge /bin, /sbin, /lib, /lib64 are symlinks into /usr ls -l /bin
/usr/local, /opt Software installed outside the package manager ls /usr/local
/tmp vs /var/tmp Both world-writable with the sticky bit; /var/tmp survives reboots and is cleaned less often, or never ls -ld /tmp /var/tmp
/run tmpfs for runtime data (PID files, sockets); emptied at boot findmnt /run
/proc, /sys Virtual filesystems exposing kernel and device state findmnt /proc
/dev Device files, created by the kernel and udev ls -l /dev/null
/boot Kernel, initramfs, bootloader files ls /boot
/root vs /home Root's home (mode 700) vs regular users' homes ls -ld /root /home
References man 7 hier, man 7 file-hierarchy man -w 7 hier

Top-Level Directories

Directory Holds Example
/ Root of the tree
/bin, /sbin Links to /usr/bin, /usr/sbin ls, ip
/boot Kernels, initramfs, GRUB vmlinuz-*, grub2/grub.cfg
/dev Device nodes /dev/sda, /dev/null
/etc Configuration /etc/ssh/sshd_config, /etc/fstab
/home User home directories /home/amor
/lib, /lib64 Links to shared libraries and kernel modules in /usr libc.so.6
/media, /mnt Mount points for removable media / temporary mounts /mnt/backup
/opt Self-contained third-party software /opt/google/chrome
/proc Processes and kernel tunables /proc/cpuinfo, /proc/sys
/root Root user's home /root/.bashrc
/run Runtime state since boot /run/sshd.pid, /run/docker.sock
/srv Data served by the host /srv/www, /srv/nfs
/sys Devices, drivers, cgroups /sys/class/net, /sys/fs/cgroup
/tmp Short-lived temporary files Build scratch files
/usr Programs, libraries, documentation /usr/bin, /usr/share/man
/var Variable data /var/log, /var/lib, /var/spool

usrmerge

Both families moved /bin, /sbin and /lib into /usr and left symlinks behind, so /bin/bash and /usr/bin/bash are the same file.

ls -l / | grep -E ' (bin|sbin|lib|lib64)( |$)'

Output:

lrwxrwxrwx   1 root root     7 Apr 22  2024 bin -> usr/bin
lrwxrwxrwx   1 root root     7 Apr 22  2024 lib -> usr/lib
lrwxrwxrwx   1 root root     9 Apr 22  2024 lib64 -> usr/lib64
lrwxrwxrwx   1 root root     8 Apr 22  2024 sbin -> usr/sbin

A read-only or separately snapshotted /usr now contains every system binary, which image-based systems (RHEL image mode, Fedora CoreOS) rely on.


Virtual Filesystems

Several top-level paths are not on disk. The kernel generates their contents on read.

for d in / /boot /tmp /var/tmp /run /dev /dev/shm /proc /sys; do findmnt -n -o TARGET,FSTYPE -T "$d"; done | sort -u

Output:

/      ext4
/dev   devtmpfs
/dev/shm tmpfs
/proc  proc
/run   tmpfs
/sys   sysfs

On this machine /boot, /tmp and /var/tmp belong to the root filesystem, so they do not appear as separate mounts.

Filesystem Mounted on Backed by Survives reboot
proc /proc Kernel process table No (generated)
sysfs /sys Kernel device model No (generated)
devtmpfs /dev Kernel device list No
tmpfs /run, /dev/shm, often /tmp RAM and swap No

Files in a tmpfs use memory

A large file written to /dev/shm, /run or a tmpfs /tmp consumes RAM and counts against memory limits. df -h /run shows the size cap (by default half of RAM for /dev/shm).


/tmp and /var/tmp

ls -ld /tmp /var/tmp /run /root /home

Output:

drwxr-xr-x  4 root root 4096 Aug 29 18:08 /home
drwx------  5 root root 4096 Aug 29 18:08 /root
drwxr-xr-x 15 root root  440 Sep 16 13:24 /run
drwxrwxrwt 12 root root 4096 Sep 16 13:50 /tmp
drwxrwxrwt  5 root root 4096 Sep 16 13:41 /var/tmp

The trailing t is the sticky bit: anyone can create files, but only the owner can delete them. systemd-tmpfiles-clean.timer removes old files daily, following the rules in tmpfiles.d:

grep -v '^#' /usr/lib/tmpfiles.d/tmp.conf | grep .
systemctl is-enabled tmp.mount

Output:

q /tmp 1777 root root 10d
q /var/tmp 1777 root root 30d
disabled
grep -v '^#' /usr/lib/tmpfiles.d/tmp.conf | grep .

Output:

D /tmp 1777 root root 30d

D also empties /tmp at every boot. Ubuntu ships the /var/tmp line commented out (#q /var/tmp 1777 root root 30d), so files in /var/tmp never age out by default.

Files older than the age column (10d, 30d) are removed. tmp.mount disabled means /tmp is on disk here; when it is enabled, /tmp is a tmpfs and empties at every reboot.


Where a Service Keeps Its Files

A package spreads one service across the tree by purpose:

rpm -ql openssh-server | grep -E '^/(etc/ssh/sshd_config|usr/sbin/sshd|usr/lib/systemd/system/sshd.service|usr/share/man/man8/sshd.8)'

Output:

/etc/ssh/sshd_config
/etc/ssh/sshd_config.d
/etc/ssh/sshd_config.d/40-redhat-crypto-policies.conf
/etc/ssh/sshd_config.d/50-redhat.conf
/usr/lib/systemd/system/sshd.service
/usr/sbin/sshd
/usr/share/man/man8/sshd.8.gz
dpkg -L openssh-server | grep -E '^/(etc/ssh/sshd_config|usr/sbin/sshd|usr/lib/systemd/system/ssh.service|usr/share/man/man8/sshd)'
dpkg -S /etc/ssh/sshd_config

Output:

/etc/ssh/sshd_config.d
/usr/lib/systemd/system/ssh.service
/usr/sbin/sshd
/usr/share/man/man8/sshd.8.gz
dpkg-query: no path found matching pattern /etc/ssh/sshd_config

Ubuntu generates sshd_config from a template during installation, so no package owns it.

Kind of file Location Example for nginx
Binary /usr/sbin, /usr/bin /usr/sbin/nginx
Configuration /etc/<app> /etc/nginx/nginx.conf
Vendor unit file /usr/lib/systemd/system nginx.service
Admin unit override /etc/systemd/system nginx.service.d/override.conf
Logs /var/log/<app> /var/log/nginx/access.log
State and caches /var/lib/<app>, /var/cache/<app> /var/lib/nginx
Runtime files /run/<app> /run/nginx.pid
Served content /srv, /var/www /usr/share/nginx/html (RHEL default)

systemd-path prints the canonical locations:

systemd-path | grep -E '^(system-configuration|system-state-private|system-state-logs|system-runtime|system-shared|temporary|temporary-large|system-binaries|user-configuration):'

Output:

temporary: /tmp
temporary-large: /var/tmp
system-binaries: /usr/bin
system-shared: /usr/share
system-configuration: /etc
system-runtime: /run
system-state-private: /var/lib
system-state-logs: /var/log
user-configuration: /home/laborant/.config

Back up /etc and /var/lib, not /usr

/usr can be reinstalled from packages. Host identity and data live in /etc, /var/lib, /home, /srv and /opt, which is what a backup or migration plan must cover.


Space by Directory

sudo du -xsh /usr /var /etc /opt
ls /var

Output:

1.6G    /usr
88M /var
2.9M    /etc
24K /opt
backups
cache
lib
local
lock
log
mail
opt
run
spool
tmp

/var is the directory that grows. Servers often give /var or /var/log their own filesystem, so runaway logs cannot fill /.


Common Errors

No space left on device while df -h / shows free space

Cause: the write went to a different filesystem (a small /var, /tmp or /boot), or the filesystem ran out of inodes.

Fix: df -h <path> and df -i <path> for the exact directory being written.

dpkg-query: no path found matching pattern /etc/ssh/sshd_config

Cause: the file is created by a maintainer script, so the package database does not list it.

Fix: find the package through its directory (dpkg -S /etc/ssh/sshd_config.d) or through debsums -c.


Interview Checkpoints

L1: What is the difference between /etc, /var and /usr?

Say first: /etc holds configuration, /var holds data that changes at runtime, and /usr holds installed programs and libraries that change only on updates.

Proof: ls /etc/ssh, ls /var/log, rpm -qf /usr/sbin/sshd.

Follow-up: Which of them do you need to back up?

L1: What is the difference between /tmp and /var/tmp?

Say first: both are world-writable with the sticky bit; /tmp is for short-lived files and may be a tmpfs, while /var/tmp persists across reboots and is cleaned less often.

Proof: grep -v '^#' /usr/lib/tmpfiles.d/tmp.conf

Follow-up: What does the sticky bit prevent?

L1: What are /proc and /sys?

Say first: virtual filesystems generated by the kernel: /proc exposes processes and tunables, /sys exposes devices, drivers and cgroups.

Proof: findmnt -T /proc, cat /proc/loadavg, ls /sys/class/net.

Follow-up: Why does du -sh /proc report nothing useful?

L2: Find where a service keeps its configuration, logs and unit file.

Say first: ask the package manager, then systemd.

Proof: rpm -ql openssh-server or dpkg -L openssh-server; systemctl cat sshd.

Follow-up: Which files in that list are safe to edit, and which are overwritten on update?

L2: Where should a manually installed binary go, and why?

Say first: /usr/local/bin for a single binary, /opt/<app> for a self-contained bundle; the package manager never touches either.

Proof: echo $PATH contains /usr/local/bin before /usr/bin.

Follow-up: Why not /usr/bin?

L3: The root filesystem is full on a web server.

Say first: find which directory grew, starting with /var, and whether it is a separate filesystem.

Proof: df -h, then sudo du -xh --max-depth=1 / | sort -h, then du inside /var/log and /var/lib.

Follow-up: How would you prevent a repeat? (A separate /var/log, log rotation, journal size limits.)

L3: An application loses its PID and socket files after every reboot.

Say first: it writes them to /run, which is a tmpfs recreated at boot.

Proof: findmnt /run shows tmpfs; the unit needs RuntimeDirectory= or a tmpfiles.d entry to recreate its directory.

Follow-up: Where should data that must survive a reboot go?

L4: Why did distributions merge /bin into /usr/bin?

Say first: splitting early-boot tools from /usr stopped making sense once an initramfs mounts /usr before switching root; merging lets /usr be one read-only, snapshottable unit.

Proof: ls -l /bin shows bin -> usr/bin on RHEL since version 7 and on Ubuntu installs since 19.04.

Don't say: "To save disk space."


Captured on Rocky Linux 10.2 and Ubuntu 24.04.4 LTS (iximiuz Labs microVMs, kernel 6.1.167), 2026-09.