Linux Filesystem Hierarchy: /etc, /var, /usr, /tmp
Linux doesn't scatter files randomly across your disk. The Filesystem Hierarchy Standard (FHS) defines a consistent directory structure that every major distribution follows. This standardization...
Key Insights
- The Filesystem Hierarchy Standard (FHS) separates system configuration (/etc), variable runtime data (/var), read-only program files (/usr), and temporary storage (/tmp) to enable predictable system administration across all Linux distributions
- Understanding where data lives prevents common mistakes like filling /tmp with permanent files, editing /usr/bin directly, or storing logs outside /var where rotation tools expect them
- Modern Linux systems increasingly use tmpfs for /tmp (RAM-based storage) and systemd-tmpfiles for automatic cleanup, making filesystem location choices critical for performance and data persistence
Introduction to the Filesystem Hierarchy Standard
Linux doesn’t scatter files randomly across your disk. The Filesystem Hierarchy Standard (FHS) defines a consistent directory structure that every major distribution follows. This standardization means a system administrator can move between Ubuntu, RHEL, or Arch Linux and immediately know where to find configuration files, logs, or executables.
The FHS exists because early Unix systems were chaotic. Different vendors placed files wherever they wanted. The standard emerged to solve real problems: enabling shared /usr partitions across networks, separating static from dynamic data for backup strategies, and making system administration predictable.
Let’s examine the root directory structure:
tree -L 1 /
/
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var
Notice that /bin, /lib, and /sbin are now symbolic links to their /usr counterparts on modern systems. This merge happened because the original separation (essential binaries in /bin, everything else in /usr/bin) became meaningless with large, cheap disks.
/etc - System Configuration Files
The /etc directory holds system-wide configuration files. Everything in /etc should be text-based and human-editable. This is not a suggestion—it’s a design principle. Binary configuration files violate the Unix philosophy and make system recovery difficult.
The name allegedly comes from “et cetera,” though some claim it means “editable text configuration.” Regardless of etymology, /etc contains the files that define how your system behaves.
ls -la /etc/ | head -20
Key files you’ll encounter:
# System identity
cat /etc/hostname
cat /etc/os-release
# Network configuration
cat /etc/hosts
cat /etc/resolv.conf
# User and group databases
head /etc/passwd
head /etc/group
When troubleshooting, searching /etc for configuration patterns is invaluable:
# Find all configs mentioning a specific port
grep -r "8080" /etc/ 2>/dev/null
# Locate SSH configuration
grep -r "PermitRootLogin" /etc/
# Find all systemd service files
find /etc/systemd/system -name "*.service"
Never modify files in /etc without backing them up first. Most configuration files include comments explaining each directive. Read them. The time you spend understanding /etc/ssh/sshd_config properly will save you from lockouts.
Package managers own some /etc files. When you modify a config file that a package update also wants to change, your package manager will prompt you to merge changes. This is why /etc belongs in version control for production systems.
/var - Variable Data Files
The /var directory contains files that change during normal system operation. Logs grow, caches fill, print jobs queue—all in /var. This separation allows you to mount /var on a separate partition with different backup schedules and disk quotas than static system files.
Check what’s consuming space in /var:
du -sh /var/*
1.2G /var/cache
4.5G /var/log
128K /var/mail
2.1G /var/lib
256M /var/tmp
892M /var/www
The subdirectories have distinct purposes:
/var/log stores log files. This is where you debug everything:
# Monitor system logs in real-time
tail -f /var/log/syslog
# Check authentication attempts
grep "Failed password" /var/log/auth.log
# Review kernel messages
dmesg | tail -50
journalctl -k -b # systemd alternative
/var/cache holds application cache data that can be regenerated. Deleting /var/cache should never break your system, only slow it down temporarily:
# Safe to clear when disk space is tight
du -sh /var/cache/apt/archives
apt-get clean # Removes downloaded package files
/var/tmp differs from /tmp in persistence. Files in /var/tmp survive reboots, while /tmp gets cleared. Use /var/tmp for temporary data that needs to persist across sessions.
/var/spool contains queued data: print jobs, mail, cron tasks. The name comes from “Simultaneous Peripheral Operations On-Line.”
/var/www is the conventional location for web server content, though this isn’t FHS-mandated. Many administrators prefer /srv/www instead.
One critical consideration: /var grows. Monitor it:
# Set up a simple monitoring check
df -h /var | awk 'NR==2 {print $5}' | sed 's/%//'
If that number exceeds 80%, investigate with du and consider log rotation policies.
/usr - User Programs and Data
Despite its name, /usr doesn’t mean “user home directories”—that’s /home. The /usr directory contains the Unix System Resources: read-only program files, libraries, and documentation. Think of /usr as the installed software directory.
The hierarchy within /usr mirrors the root structure:
/usr/bin contains user commands and applications:
# Find where a command lives
which python3
# /usr/bin/python3
which docker
# /usr/bin/docker
# List all executables
ls /usr/bin | wc -l
# Typically thousands of binaries
/usr/lib stores shared libraries that programs need:
# Find library dependencies
ldd /usr/bin/python3
/usr/share contains architecture-independent data: documentation, icons, fonts, and application data:
# Browse installed documentation
ls /usr/share/doc/
# Check man pages source
ls /usr/share/man/man1/ | head
/usr/local is crucial for system administrators. This is where you install software manually, outside your package manager’s control:
# Compare package-managed vs manually installed
ls /usr/bin/python*
ls /usr/local/bin/python*
# Install custom scripts here
sudo cp my-tool.sh /usr/local/bin/my-tool
sudo chmod +x /usr/local/bin/my-tool
The separation between /usr/bin and /usr/local/bin prevents package updates from overwriting your custom installations. Always use /usr/local for compiled-from-source software or organization-specific tools.
Modern systems mount /usr read-only in some configurations, enforcing its static nature. You should never need write access to /usr during normal operation—only during package installation.
/tmp - Temporary Files
The /tmp directory provides scratch space for temporary files. Applications create working files here, expecting them to disappear eventually. The key characteristics: world-writable (with sticky bit) and automatically cleaned.
Check if /tmp uses tmpfs (RAM-based storage):
df -h /tmp
Filesystem Size Used Avail Use% Mounted on
tmpfs 7.8G 324M 7.5G 5% /tmp
If you see tmpfs, /tmp lives in RAM. This is fast but volatile—reboots erase everything. If you see a regular filesystem, /tmp persists on disk but still gets cleaned periodically.
Test temporary file creation and permissions:
# Create a temp file
mktemp
# /tmp/tmp.X8kL3mQp2R
# Temp directory
mktemp -d
# /tmp/tmp.9vK2nLpQ3S
# Named pattern
mktemp /tmp/myapp.XXXXXX
# /tmp/myapp.Hk8pLm
The sticky bit on /tmp (the ’t’ in permissions) prevents users from deleting each other’s files:
ls -ld /tmp
# drwxrwxrwt 15 root root 4096 Jan 15 10:23 /tmp
Security consideration: Never assume files in /tmp are private. Other users can read them unless you set restrictive permissions:
# Create a secure temp file
tmp_file=$(mktemp)
chmod 600 "$tmp_file"
echo "sensitive data" > "$tmp_file"
The difference between /tmp and /var/tmp matters:
- /tmp: Cleared on reboot (or every 10 days on systemd systems)
- /var/tmp: Persists across reboots, cleaned after 30 days
Find and clean old temporary files:
# Find files older than 7 days
find /tmp -type f -mtime +7
# Find large files in tmp
find /tmp -type f -size +100M -exec ls -lh {} \;
# Clean old files (dangerous - verify first!)
find /tmp -type f -mtime +7 -delete
Many systems use systemd-tmpfiles for automatic cleanup:
# View tmpfiles configuration
cat /usr/lib/tmpfiles.d/tmp.conf
Practical Navigation and Best Practices
Understanding these directories enables effective system administration. Here’s how to apply this knowledge:
Check disk usage across critical directories:
df -h / /usr /var /tmp | awk '{print $6, $5, $4}' | column -t
Back up configuration systematically:
#!/bin/bash
# Simple /etc backup script
backup_dir="/backup/etc-$(date +%Y%m%d)"
mkdir -p "$backup_dir"
rsync -av --exclude='*~' /etc/ "$backup_dir/"
Audit permissions for security:
# Find world-writable files outside /tmp
find /etc /usr /var -type f -perm -002 ! -path "/var/tmp/*" ! -path "/tmp/*"
# Check for SUID binaries
find /usr -perm -4000 -ls
Monitor log growth:
# Top 10 largest log files
du -ah /var/log | sort -rh | head -10
Verify system file integrity:
# On RPM-based systems
rpm -Va
# On Debian-based systems
debsums -c
The FHS isn’t arbitrary bureaucracy. It’s decades of hard-won wisdom about separating concerns. Configuration in /etc means you can version-control your system setup. Variable data in /var means you can monitor growth and set quotas. Read-only /usr means you can share it across machines or mount it from network storage. Temporary /tmp means applications have predictable scratch space.
Respect these boundaries. Don’t store logs in /tmp. Don’t put configuration in /var. Don’t modify /usr/bin directly. Follow the standard, and your systems will be maintainable, debuggable, and comprehensible to other administrators.