The Linux Filesystem Hierarchy
When you first open a terminal on an Ubuntu server, the directory tree can look like a maze of cryptic folders — /etc, /var, /usr, /proc. But this layout is not random. Linux follows a published convention called the Filesystem Hierarchy Standard (FHS) — an agreed-upon map that says “this kind of file goes in that directory.” Once you learn the map, you always know where to find config, logs, and programs on any Linux machine. This is one of the highest-leverage things a new DevOps engineer can memorize, because it turns “where did that file go?” into a reflex.
Everything starts at the root (/)
In Linux there are no drive letters like C: or D: from Windows. There is a single tree, and the very top is called the root directory, written as / (just a forward slash). Every other folder and file lives somewhere underneath it. Even extra disks and USB drives get “mounted” (attached) into this one tree, usually under /mnt or /media.
Do not confuse the root directory (
/) with the root user (the all-powerful admin account). They share a name but are different things. The root user’s home folder is/root, which is separate from/.
You can see the top-level layout with ls:
ls -l /
Output:
drwxr-xr-x 2 root root 4096 Jun 10 09:14 bin
drwxr-xr-x 4 root root 4096 Jun 10 09:14 boot
drwxr-xr-x 19 root root 3940 Jun 15 08:01 dev
drwxr-xr-x 132 root root 12288 Jun 15 07:55 etc
drwxr-xr-x 3 root root 4096 Jun 10 09:20 home
drwxr-xr-x 14 root root 4096 Jun 10 09:14 usr
drwxr-xr-x 13 root root 4096 Jun 10 09:14 var
The directory map you need to know
Here are the directories you will touch most often as a DevOps engineer, and what each one is for.
| Directory | What it holds | Real Ubuntu example |
|---|---|---|
/etc | System-wide configuration files (text files that control how programs behave) | /etc/nginx/sites-available/, /etc/ssh/sshd_config |
/var | Variable data — files that grow and change while the system runs | /var/log/, /var/www/, /var/lib/ |
/var/log | Log files — records of what services did and any errors | /var/log/nginx/error.log, /var/log/syslog |
/home | Personal folders for normal users | /home/deploy, /home/ubuntu |
/root | Home folder for the root user (admin) | /root |
/usr | Installed programs and their files (read-only application data) | /usr/bin/python3, /usr/share/ |
/usr/bin | Most user commands and programs | /usr/bin/git, /usr/bin/curl |
/usr/local | Software you install manually (not via apt) | /usr/local/bin/ |
/bin, /sbin | Core commands needed early at boot (now symlinks into /usr) | /bin/ls, /sbin/reboot |
/tmp | Temporary files — wiped on reboot | scratch files, build artifacts |
/opt | Optional, self-contained third-party software | /opt/some-vendor-app |
/dev | Device files representing hardware (disks, terminals) | /dev/sda, /dev/null |
/proc, /sys | Virtual folders exposing live kernel and process info | /proc/cpuinfo, /proc/meminfo |
/mnt, /media | Mount points for extra or removable drives | /mnt/data, /media/usb |
/boot | Files needed to boot the machine (the kernel) | /boot/vmlinuz-... |
The four you will live in day to day are /etc (config), /var/log (logs), /usr/bin (commands), and /home (your files). Learn those first.
/etc — where configuration lives
If you ever ask “how do I change a setting for this service?”, the answer almost always lives in /etc. The name historically meant “et cetera,” but today think of it as “Editable Text Configuration.” These are plain text files you edit with sudo, then restart the service to apply.
For example, to edit the Nginx web server config (Nginx is “a web server / reverse proxy — a program that serves web pages and forwards requests to your app”):
sudo nano /etc/nginx/sites-available/default
sudo systemctl restart nginx
PostgreSQL (a popular open-source database) keeps its config here too:
ls /etc/postgresql/16/main/
Output:
conf.d environment pg_hba.conf pg_ident.conf postgresql.conf start.conf
When to use it: whenever you need to change how an installed service behaves. When NOT to: do not put your own application data or logs here — /etc is for config only.
/var/log — where you debug
When something breaks, the first move is to read the logs in /var/log. Variable data means data that changes over time, and logs are the perfect example — they grow constantly.
sudo tail -f /var/log/nginx/error.log
tail -f shows the end of a file and keeps printing new lines as they appear, which is perfect for watching errors live. For services managed by systemd (Ubuntu’s service manager that starts and supervises programs), use journalctl instead:
sudo journalctl -u nginx --since "10 minutes ago"
Output:
Jun 15 08:31:02 web01 systemd[1]: Started nginx.service - A high performance web server.
Jun 15 08:31:04 web01 nginx[8821]: 2026/06/15 08:31:04 [error] connect() failed
/usr vs /usr/local vs /opt — where programs go
This trips up beginners, so here is the rule of thumb.
| Location | Use it for | Who manages it |
|---|---|---|
/usr/bin, /usr/lib | Software installed by apt | The package manager — don’t edit by hand |
/usr/local/bin | Software you compiled or installed manually | You |
/opt | Big self-contained vendor apps that bundle everything | The vendor / you |
So when you sudo apt install git, the binary lands in /usr/bin/git. When you download a standalone tool yourself, put it in /usr/local/bin so it doesn’t clash with apt-managed files. You can confirm where a command lives:
which git
Output:
/usr/bin/git
Best Practices
- Edit config in
/etcwithsudo, then restart the service withsystemctl restart <name>so the change takes effect. - Check
/var/log(orjournalctl) first when debugging — the answer is usually already written down there. - Never store important data in
/tmp; it is wiped on every reboot. - Put manually installed binaries in
/usr/local/bin, not/usr/bin, so apt updates don’t overwrite them. - Leave
/proc,/sys, and/devalone unless you know exactly what you’re doing — they are virtual and reflect live system state. - Keep your web app’s files in
/var/www, and your own work in your/homefolder — not scattered across the root tree. - Use
df -hto see which disks are mounted where, so you understand how the single tree maps to real hardware.