Linux Filesystem Hierarchy Explained: Understanding /etc, /var, /opt and More
Every file on a Linux system has its place, and that place is defined by the Filesystem Hierarchy Standard (FHS). Understanding where things go and why is fundamental to effective Linux administration. When a service fails, you need to know where to find its logs. When you deploy an application, you need to know where to put its binaries, configuration, and data. When you troubleshoot a kernel issue, you need to navigate /proc and /sys with confidence.
This guide walks through every major directory in the Linux filesystem, explains its purpose with concrete examples, and covers the virtual filesystems that expose kernel state to userspace.
The Root Filesystem Overview
| Directory | Purpose | Typical Contents |
|---|---|---|
/ |
Root of the filesystem | Everything |
/bin |
Essential user binaries | ls, cp, mv, bash, cat |
/sbin |
Essential system binaries | init, ip, mount, fdisk |
/etc |
System configuration | Config files for all services |
/var |
Variable data | Logs, caches, spools, databases |
/tmp |
Temporary files | Files cleared on reboot |
/usr |
User system resources | Applications, libraries, docs |
/home |
User home directories | Personal files and configs |
/opt |
Optional/third-party software | Self-contained applications |
/proc |
Process/kernel information | Virtual files (runtime kernel data) |
/sys |
Kernel device/driver info | Virtual files (hardware/driver data) |
/dev |
Device files | Block/character devices |
/run |
Runtime data | PID files, sockets (tmpfs) |
/mnt |
Temporary mount points | Manually mounted filesystems |
/media |
Removable media | Auto-mounted USB, CD-ROM |
/srv |
Service data | Web server files, FTP data |
/boot |
Boot loader files | Kernel, initramfs, GRUB |
/etc -- System Configuration
The /etc directory (historically "et cetera", now often read as "editable text configuration") contains system-wide configuration files. Almost every service on Linux stores its configuration here:
# Key configuration files
/etc/hostname # System hostname
/etc/hosts # Static hostname resolution
/etc/resolv.conf # DNS resolver configuration
/etc/fstab # Filesystem mount table
/etc/passwd # User account information
/etc/shadow # Encrypted user passwords
/etc/group # Group definitions
/etc/sudoers # Sudo access control
/etc/ssh/sshd_config # SSH daemon configuration
/etc/systemd/ # systemd configuration
/etc/sysctl.d/ # Kernel parameter overrides
/etc/pacman.conf # Pacman configuration (Arch)
/etc/apt/ # APT configuration (Debian/Ubuntu)
Modern practice uses .d directories for drop-in configuration fragments:
# Instead of editing a monolithic config file:
/etc/sysctl.conf
# Use drop-in directory for modular configuration:
/etc/sysctl.d/10-network.conf
/etc/sysctl.d/20-security.conf
/etc/sysctl.d/99-custom.conf
# Files are processed in alphabetical order
# Higher numbers override lower numbers
/etc before making changes. A simple tar czf /root/etc-backup-$(date +%Y%m%d).tar.gz /etc can save hours of troubleshooting if a configuration change breaks something.
/var -- Variable Data
The /var directory holds data that changes during normal system operation. It is one of the most important directories to understand for server administration:
/var/log/ # System and application logs
/var/log/syslog # General system log (Debian)
/var/log/messages # General system log (RHEL)
/var/log/auth.log # Authentication log
/var/log/kern.log # Kernel log
/var/log/journal/ # systemd journal (binary)
/var/lib/ # Application state data
/var/lib/docker/ # Docker images, containers, volumes
/var/lib/postgresql/ # PostgreSQL databases
/var/lib/mysql/ # MySQL/MariaDB databases
/var/lib/pacman/ # Pacman package database (Arch)
/var/lib/dpkg/ # dpkg database (Debian)
/var/cache/ # Application cache data
/var/cache/pacman/pkg/ # Downloaded packages (Arch)
/var/cache/apt/archives/ # Downloaded .deb files (Debian)
/var/spool/ # Queued data waiting to be processed
/var/spool/cron/ # User crontabs
/var/spool/mail/ # User mailboxes
/var/run -> /run # Symlink to /run (runtime data)
/var/tmp/ # Temporary files preserved between reboots
Important:
/varshould be on a separate partition or have disk quotas. A runaway log file or growing database can fill/varand bring down your entire system if it shares a partition with/.
/usr -- User System Resources
Despite its name, /usr is not for user files. It stands for "Unix System Resources" and contains the bulk of the operating system:
/usr/bin/ # Most user commands
/usr/bin/python3 # Python interpreter
/usr/bin/git # Git version control
/usr/bin/docker # Docker CLI
/usr/sbin/ # System administration commands
/usr/sbin/sshd # SSH daemon
/usr/sbin/nftables # Firewall
/usr/sbin/useradd # User management
/usr/lib/ # Libraries for /usr/bin and /usr/sbin
/usr/lib64/ # 64-bit libraries (some distros)
/usr/include/ # C/C++ header files
/usr/share/ # Architecture-independent data
/usr/share/man/ # Manual pages
/usr/share/doc/ # Documentation
/usr/share/zoneinfo/ # Timezone data
/usr/local/ # Locally installed software
/usr/local/bin/ # Local binaries
/usr/local/lib/ # Local libraries
/usr/local/etc/ # Local configuration
On modern systems (Arch, Fedora, and recent Debian), /bin is a symlink to /usr/bin and /sbin is a symlink to /usr/sbin. This is known as the usr merge:
# On merged systems:
ls -la /bin
# lrwxrwxrwx 1 root root 7 /bin -> usr/bin
ls -la /sbin
# lrwxrwxrwx 1 root root 8 /sbin -> usr/sbin
/opt -- Optional Software
/opt is designed for self-contained, third-party software packages that do not follow the standard /usr directory layout:
/opt/
/opt/google/chrome/ # Google Chrome
/opt/containerd/ # containerd runtime
/opt/mycompany/myapp/ # Custom company application
/opt/mycompany/myapp/bin/
/opt/mycompany/myapp/lib/
/opt/mycompany/myapp/etc/
Use /opt when your application is a single self-contained package. Use /usr/local when the application follows the traditional bin/lib/share layout. This is particularly relevant for Docker deployments and custom Go binaries:
# A Go binary with its configuration
/opt/usulnet/
/opt/usulnet/bin/usulnet
/opt/usulnet/config.yaml
# vs. a traditionally installed tool
/usr/local/bin/usulnet
/proc -- The Process Virtual Filesystem
/proc is a virtual filesystem that does not exist on disk. It is generated by the kernel at runtime and provides a window into the kernel's view of the system:
# Per-process information (replace PID with actual process ID)
/proc/[PID]/cmdline # Command that started the process
/proc/[PID]/environ # Environment variables
/proc/[PID]/fd/ # Open file descriptors
/proc/[PID]/maps # Memory mappings
/proc/[PID]/status # Process status (memory, threads, etc.)
/proc/[PID]/cgroup # Cgroup membership (important for containers)
/proc/[PID]/limits # Resource limits
# System-wide information
/proc/cpuinfo # CPU details
/proc/meminfo # Memory usage details
/proc/loadavg # System load averages
/proc/uptime # System uptime
/proc/version # Kernel version
/proc/filesystems # Supported filesystems
/proc/mounts # Currently mounted filesystems
/proc/net/ # Network statistics
# Kernel tunable parameters
/proc/sys/ # Writable kernel parameters (sysctl)
/proc/sys/net/ # Network parameters
/proc/sys/vm/ # Virtual memory parameters
/proc/sys/kernel/ # Kernel parameters
/proc/sys/fs/ # Filesystem parameters
Reading from /proc is how most monitoring tools work:
# How much memory is available?
cat /proc/meminfo | grep MemAvailable
# MemAvailable: 12345678 kB
# What is the system load?
cat /proc/loadavg
# 0.45 0.62 0.71 2/456 12345
# How many file descriptors is a process using?
ls /proc/$(pidof sshd)/fd | wc -l
# What are the current kernel network parameters?
cat /proc/sys/net/core/somaxconn
# 4096
# Modify a kernel parameter at runtime
echo 65535 > /proc/sys/net/core/somaxconn
/sys -- The Sysfs Virtual Filesystem
/sys exposes the kernel's device model. While /proc is process-oriented, /sys is device-and-driver oriented:
/sys/class/ # Devices organized by class
/sys/class/net/ # Network interfaces
/sys/class/block/ # Block devices (disks)
/sys/class/thermal/ # Thermal zones
/sys/block/ # Block device information
/sys/block/sda/ # Disk sda details
/sys/block/sda/queue/scheduler # I/O scheduler
/sys/devices/ # All devices in the system
/sys/fs/ # Filesystem-specific information
/sys/fs/cgroup/ # Cgroup filesystem (container resource control)
/sys/kernel/ # Kernel configuration
/sys/module/ # Loaded kernel modules
# Check the current I/O scheduler for a disk
cat /sys/block/sda/queue/scheduler
# [mq-deadline] kyber none
# Change I/O scheduler
echo "kyber" > /sys/block/sda/queue/scheduler
# Check disk rotational status (0 = SSD, 1 = HDD)
cat /sys/block/sda/queue/rotational
# Read CPU temperature
cat /sys/class/thermal/thermal_zone0/temp
# 45000 (divide by 1000 for Celsius: 45.0°C)
# Check network interface speed
cat /sys/class/net/eth0/speed
# 1000 (Mbps)
/dev -- Device Files
/dev contains device files that represent hardware and virtual devices. It is managed by udev:
/dev/sda # First SATA/SCSI disk
/dev/sda1 # First partition on sda
/dev/nvme0n1 # First NVMe SSD
/dev/null # Discards all data written to it
/dev/zero # Provides infinite null bytes
/dev/random # Cryptographic random number generator
/dev/urandom # Non-blocking random number generator
/dev/tty # Current terminal
/dev/pts/ # Pseudo-terminal devices (SSH sessions)
/dev/loop0 # Loop devices (for mounting images)
/dev/mapper/ # Device mapper (LVM, LUKS)
# List all block devices with details
lsblk -f
# Check device permissions
ls -la /dev/sda
# Docker uses device files for direct device access
# docker run --device=/dev/sda:/dev/sda ...
/tmp vs /run -- Temporary Data
These two directories serve similar but distinct purposes:
| Feature | /tmp |
/run |
|---|---|---|
| Purpose | General temporary files | Runtime state for services |
| Backed by | tmpfs (RAM) on most distros | Always tmpfs (RAM) |
| Cleared on reboot | Yes | Yes |
| Sticky bit | Yes (users can only delete own files) | No |
| Typical contents | Compilation artifacts, session data | PID files, sockets, lock files |
| Who writes | Any user or process | System services (root) |
# Check what is using /run
ls -la /run/
# docker.sock, sshd.pid, systemd/, user/, etc.
# Check tmpfs usage
df -h /tmp /run
# tmpfs 2.0G 12M 2.0G 1% /tmp
# tmpfs 2.0G 1.8M 2.0G 1% /run
/boot -- Boot Files
/boot/
vmlinuz-linux # Compressed Linux kernel
initramfs-linux.img # Initial RAM filesystem
initramfs-linux-fallback.img # Fallback initramfs
loader/ # systemd-boot configuration (Arch)
grub/ # GRUB bootloader (Debian/Ubuntu/RHEL)
EFI/ # EFI boot entries
/boot partition is often small (256-512 MB). On Arch Linux, keep old kernels pruned or you will run out of space. Use paccache -rk 2 regularly and consider the linux-lts kernel as a fallback.
/srv -- Service Data
/srv is intended for data served by the system. The FHS suggests it for web servers, FTP, and similar services:
/srv/
/srv/http/ # Web server document root
/srv/ftp/ # FTP server files
/srv/docker/ # Docker project files (alternative to /opt)
In practice, many organizations use /var/www for web content or /opt for application data instead of /srv. The important thing is consistency within your organization.
Where Docker Stores Its Data
Understanding the filesystem hierarchy is critical for Docker administration. Docker stores data across several locations:
/var/lib/docker/ # Docker root directory
/var/lib/docker/overlay2/ # Image and container layers
/var/lib/docker/volumes/ # Named volumes
/var/lib/docker/containers/ # Container metadata and logs
/var/lib/docker/image/ # Image metadata
/var/lib/docker/network/ # Network configuration
/var/lib/docker/buildkit/ # BuildKit cache
/etc/docker/daemon.json # Docker daemon configuration
/run/docker.sock # Docker API socket
/usr/bin/docker # Docker CLI binary
/usr/bin/dockerd # Docker daemon binary
When managing Docker hosts with usulnet, understanding these paths helps you configure backups, monitor disk usage, and troubleshoot container issues effectively.
Rule of thumb: If you need to find where a program stores its data, check
/var/lib/programnamefor state data,/etc/programnameor/etc/programname.conffor configuration, and/var/log/programnamefor logs. This pattern holds for the vast majority of Linux software.