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
Tip: Always back up /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: /var should be on a separate partition or have disk quotas. A runaway log file or growing database can fill /var and 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
Warning: The /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/programname for state data, /etc/programname or /etc/programname.conf for configuration, and /var/log/programname for logs. This pattern holds for the vast majority of Linux software.