Journal
The Linux Filesystem Hierarchy Every Developer Should Know
The Linux filesystem follows a standard hierarchy (FHS) that dates back decades. Once you internalize it, navigating any Linux server feels familiar — whether it’s Ubuntu, Arch, or Alpine in a container.
The Directories That Matter
/etc — Configuration
System-wide configuration files live here. When you edit an Nginx config, a PHP-FPM pool, or an SSH daemon setting, you’re working in /etc.
/etc/nginx/nginx.conf
/etc/php/8.3/fpm/pool.d/www.conf
/etc/ssh/sshd_config
/etc/systemd/system/myapp.service
Rule of thumb: if a program reads a config file on startup, it’s probably in /etc.
/var — Variable Data
Data that changes during operation: logs, caches, mail spools, and databases.
/var/log/ # System and application logs
/var/www/ # Traditional web root
/var/lib/mysql/ # MySQL data directory
/var/cache/ # Application caches
/var/run/ → /run/ # Runtime data (PIDs, sockets)
This is where your web apps typically get deployed on conventional setups. It’s also where logs pile up if you’re not rotating them.
/opt — Optional Packages
Third-party software that doesn’t come from your package manager. If you install a self-contained application manually, /opt is the conventional home:
/opt/mycompany/app/
/opt/lampp/
/usr — User Programs
Despite the name, this isn’t about user home directories. It contains installed programs, libraries, and documentation:
/usr/bin/ # User binaries (most CLI tools)
/usr/lib/ # Libraries
/usr/local/bin/ # Locally compiled software
/usr/share/ # Architecture-independent data
The /usr/local/ subtree mirrors /usr/ but is reserved for software you compile yourself, keeping it separate from package-managed files.
/home — User Home Directories
Each user gets a directory here. Development tools, SSH keys, shell configs, and local projects live under your home:
/home/deploy/.ssh/authorized_keys
/home/deploy/.bashrc
/home/deploy/projects/
/tmp and /run
Both are for temporary data. /tmp is cleaned on reboot (and sometimes periodically). /run is a tmpfs mounted in RAM for runtime state like PID files and sockets.
Permissions: The Quick Version
Every file has an owner, a group, and three permission sets (read, write, execute):
ls -la /var/www/
# drwxr-xr-x 3 www-data www-data 4096 Jan 15 10:00 html
The pattern is owner-group-others. Common permission sets:
| Octal | Meaning | Typical Use |
|---|---|---|
| 755 | rwxr-xr-x | Directories, executables |
| 644 | rw-r—r— | Config files, web assets |
| 600 | rw------- | SSH keys, secrets |
| 700 | rwx------ | .ssh directory |
A frequent deployment mistake is getting the owner wrong:
# Web server can't read your files
sudo chown -R www-data:www-data /var/www/mysite
sudo chmod -R 755 /var/www/mysite
sudo chmod -R 644 /var/www/mysite/*.html
Where Web Apps Live
There’s no single right answer, but these are the conventions:
- Traditional:
/var/www/mysiteowned bywww-data - Capistrano/deployer style:
/var/www/mysite/current→ symlinked release - Container world:
/appor/srvinside the image - User-space dev:
~/projects/mysite
What matters is consistency within your team and ensuring the web server user can read the files.
Finding Things
When you can’t remember where something is:
which nginx # Find binary location
whereis php # Binary, source, and man page
find /etc -name "*.conf" -mtime -7 # Recently modified configs
locate nginx.conf # Fast search using mlocate db
The hierarchy is a convention, not a cage. But following it means any Linux-literate person joining your team can navigate your server without a map.