Skip to content

Phase 1 · FOUNDATIONS

The Linux filesystem: where everything lives

Day 2 of 90 ~50 min 0/20 in phase Builds on Day 1

By the end of today

  • Map the Linux filesystem tree and name what each top dir holds
  • Tell an absolute path from a relative one, and / from ~
  • Know where config and logs live: /etc versus /var

The Linux filesystem: one tree, rooted at /

Section 1 of 5 · ~3 min

On Windows you have C:\ and D:\ — separate drives with separate letters. Linux has no drive letters. Everything lives in one single tree, and the top of that tree is /, called root. Plug in a USB stick or mount a network share and it does not become “E:” — it gets mounted into a folder somewhere under /. One tree, always.

That tree is not random. Almost every Linux distribution follows the Filesystem Hierarchy Standard (FHS), which fixes what goes where. Learn it once and you can walk an Ubuntu server, a Red Hat box, or a Docker container blindfolded. Here are the directories you will touch constantly:

  • /etc — system-wide configuration. Plain text files that tell programs how to behave: /etc/ssh/sshd_config, /etc/hosts, /etc/os-release. You edit /etc deliberately; nothing should be writing here on its own.
  • /var — data that varies as the machine runs. The big one is /var/log (every log you will ever grep), plus caches, spools and databases. When a disk fills up at 3 a.m., /var is your first suspect.
  • /home — one folder per human user (/home/pushkar): your files, your configs, your playground. The root user is the exception — its home is /root.
  • /usr — installed software: programs, libraries, and their read-only data. Most commands you run live in /usr/bin.
  • /bin, /sbin — core commands. On modern Ubuntu these are just symlinks into /usr/bin and /usr/sbin (the “usr-merge”), so do not be surprised when /bin and /usr/bin look identical.
  • /tmp — scratch space anyone can write to, wiped on reboot. Never keep anything you care about here.
  • /proc — not real files at all. The kernel invents these on the fly to expose live process and system info; cat /proc/cpuinfo reads straight from the running kernel.
The Linux filesystem tree: a single root / with the top-level directories /etc, /var, /home, /usr, /bin, /tmp and /proc hanging beneath it. / /etc config /var logs + state /home users /usr programs /bin commands /tmp scratch /proc kernel
One root, one tree — every top-level directory has a job the FHS assigns it.

Two more ideas make the tree usable. First, absolute vs relative paths. An absolute path starts from / and means the same thing anywhere: /var/log/syslog. A relative path is read from wherever you are standing right now — log/syslog means “the log folder inside my current directory.” pwd (“print working directory”) tells you where “here” is. Scripts should prefer absolute paths, because a cron job or CI runner starts in a different place than your terminal.

Second, / versus ~. / is the very top of the whole system. ~ is a shortcut for your home directory — /home/pushkar for you, /root for the root user. cd / climbs to the top; cd ~ (or just cd) drops you home. The difference is life-or-death: rm -rf aimed at / destroys the machine; aimed at ~ it only wrecks your own files.

Real world: Picture a large government office where every kind of paper has exactly one room: rule-books and policies in the records room, the day’s incoming applications in the mail room, each clerk’s own drawer for personal files, shared stationery in the store room. Nobody wonders where a document goes — the building’s layout decides it. The Linux filesystem is that building: /etc is the rule-book room, /var is the mail room where fresh paperwork piles up, /home holds each user’s desk, and the FHS is the rule that every office follows the same floor plan.

A named example makes it concrete. When you apt install nginx, nginx’s Debian package drops its config into /etc/nginx/ and writes access logs to /var/log/nginx/ — on Ubuntu, Debian, or any FHS-compliant distro. That is why a runbook that says “check /var/log/nginx/error.log” works on a server you have never touched: the standard, not the machine, decides where things land.

Knowing the tree is the difference between poking around and hoping, and walking onto any server to head straight for the file you need.

Hands-On Lab

Section 2 of 5 · ~3 min

Budget about 20 minutes. Open your WSL2 Ubuntu 24.04 terminal (if you have not set up WSL2 yet, do Day 0 first — macOS and Linux users can follow along in their built-in terminal). Type each command yourself and read every line of output; today the goal is to walk the tree, not to memorise it.

# 1. What hangs off the root of the tree? Every top-level FHS directory.
ls /
# Output (a WSL2 noble box; a plain cloud VM omits the *.usr-is-merged markers and init):
# bin  bin.usr-is-merged  boot  dev  etc  home  init  lib  lib.usr-is-merged  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  sbin.usr-is-merged  snap  srv  sys  tmp  usr  var
# 2. Same listing, but -F marks each entry's type: @ = symlink, / = directory, * = executable.
#    bin, lib, sbin and lib64 are @ symlinks (the usr-merge), init* is the WSL2 launcher, and the *.usr-is-merged dirs are usr-merge markers.
ls -F /
# Output:
# bin@  bin.usr-is-merged/  boot/  dev/  etc/  home/  init*  lib@  lib.usr-is-merged/  lib64@  lost+found/  media/  mnt/  opt/  proc/  root/  run/  sbin@  sbin.usr-is-merged/  snap/  srv/  sys/  tmp/  usr/  var/
# 3. Walk into the "config room" and skim what real configuration looks like.
cd /etc && ls
# Output (trimmed — /etc holds ~150 entries):
# adduser.conf  apt          bash.bashrc  cron.d   fstab    group    hostname  hosts
# os-release    passwd       profile      ssh      sudoers  systemd  ...
# 4. Read the file that names the distro and version — note the hyphen, not an underscore.
cat /etc/os-release
# Output (trimmed; your point release — 24.04.1, .2, .3 … — will differ):
# PRETTY_NAME="Ubuntu 24.04.2 LTS"
# NAME="Ubuntu"
# VERSION_ID="24.04"
# VERSION_CODENAME=noble
# ID=ubuntu
# 5. Where do logs live? /var/log — your first stop on almost any incident.
ls /var/log
# Output (trimmed — a stock box holds ~40 entries: auth.log, kern.log, syslog.1, …):
# alternatives.log  apt  btmp  dpkg.log  journal  lastlog  syslog  wtmp
# 6. Watch the tail of a real log. dpkg.log records every package change and is world-readable.
tail -n 3 /var/log/dpkg.log
# Output (your dates, versions and packages will differ):
# 2026-07-08 10:32:01 status installed libc6:amd64 2.39-0ubuntu8.3
# 2026-07-08 10:32:02 status installed base-files:amd64 13ubuntu10.2
# 2026-07-08 10:32:02 status installed bash:amd64 5.2.21-2ubuntu4
# 7. List your home INCLUDING the hidden dotfiles: -a shows them, -l goes long.
ls -la ~
# Output (dates and sizes will differ):
# total 20
# drwxr-xr-x 2 pushkar pushkar 4096 Jul  8 10:41 .
# drwxr-xr-x 3 root    root    4096 Jul  8 10:35 ..
# -rw------- 1 pushkar pushkar   35 Jul  8 10:41 .bash_history
# -rw-r--r-- 1 pushkar pushkar  220 Jul  8 10:35 .bash_logout
# -rw-r--r-- 1 pushkar pushkar 3792 Jul  8 10:35 .bashrc
# -rw-r--r-- 1 pushkar pushkar  828 Jul  8 10:35 .profile
# 8. After all that, where is "here"? We ran cd /etc back in step 3 and never left.
pwd
# Output:
# /etc
# 9. A bare cd (no argument) drops you straight back to your home — the ~ shortcut.
cd
pwd
# Output:
# /home/pushkar
# 10. Prove /proc is not on disk: the kernel invents these files live, on read.
cat /proc/cpuinfo | head
# Output (your CPU will differ — this is generated fresh by the running kernel):
# processor       : 0
# vendor_id       : GenuineIntel
# cpu family      : 6
# model           : 140
# model name      : Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
# stepping        : 1
# microcode       : 0xffffffff
# cpu MHz         : 2803.200
# cache size      : 12288 KB
# physical id     : 0

Before you close the terminal, trace the path you just walked out loud: from / at the top, into /etc for config, over to /var/log for logs, home to ~ for your own files, and into /proc for the kernel’s live view — that mental map is what lets you land on any server and head straight for the file you need.

Common Errors & Fixes

Section 3 of 5 · ~2 min

These three trip up almost everyone in their first week on the tree. Read the error text slowly — learning to parse it is the actual skill.

Common error: Curiosity about a locked system file — running cat /etc/shadow as a normal user — prints:

cat: /etc/shadow: Permission denied

Why: /etc/shadow stores password hashes, so it is deliberately readable only by root (-rw-r-----, owner root, group shadow). A normal user like pushkar is not in that group and is refused. Linux enforces this per file — no exception for the curious.

Fix: You rarely need to read it at all; if you genuinely do, borrow root’s rights for one command with sudo cat /etc/shadow. What sudo does — and why you should not prefix everything with it — is Day 5.

How you’d spot it in prod: Permission denied in a service or CI log almost always means the process runs as a user without rights on that path. Check who owns the file and who the process runs as before reaching for sudo — the fix is usually ownership, not privilege.

Common error: Reaching for the distro file but typing an underscore — cat /etc/os_release — prints:

cat: /etc/os_release: No such file or directory

Why: The real file is os-release, with a hyphen. The shell is completely literal: it looked for a file spelled exactly os_release, found none, and said so. It does not guess the nearest match.

Fix: Retype with the hyphen: cat /etc/os-release. Better habit — type /etc/os then press Tab and let completion fill in the real name, so the typo is caught before you hit Enter.

How you’d spot it in prod: No such file or directory on a path you “know” exists is nearly always a typo, the wrong directory, or a relative path resolved from somewhere unexpected. Confirm with ls on the parent directory and check pwd before assuming the file is actually gone.

Common error: Coming from Windows and treating paths as case-insensitive — cd /Etc — prints:

bash: cd: /Etc: No such file or directory

Why: Linux filesystems are case-sensitive: /Etc, /etc and /ETC are three different names, and only /etc exists. Windows (C:\) treats them as the same thing, which is why this catches almost every newcomer arriving through WSL.

Fix: Use the exact lowercase name: cd /etc. Tab-completion helps here too — it only completes the casing that actually exists on disk.

How you’d spot it in prod: Case bugs love to hide until deployment — a file referenced as Config.yaml in code but saved as config.yaml works on a Windows or macOS laptop, then fails on the Linux server or in CI. Match case exactly everywhere, including in scripts and Dockerfiles.

The Linux Filesystem Interview Questions

Section 4 of 5 · ~1 min

Cover the answers below and say your own version out loud first — name what /etc, /var and ~ are before you reveal each answer. Recalling before revealing is what makes these stick when an interviewer asks them cold. The four questions and answers render right after this note.

Go Deeper

Section 5 of 5 · ~1 min

Optional extras if you have ~30 more minutes today:

  • 5 min — Run man hier in your terminal. It is the built-in manual page describing the whole filesystem hierarchy, straight from your own machine.
  • 10 min — Skim the Filesystem Hierarchy Standard (Linux Foundation) — you do not need to memorise it, just see that the tree really is a written spec.
  • 15 min — Read the “Introduction to Linux” section of the Linux for DevOps guide for how these directories fit the wider server-side picture.
What is the difference between /etc and /var? Both

/etc holds system-wide configuration — plain text files that tell programs how to behave, like /etc/ssh/sshd_config or /etc/os-release. It is meant to be static and edited deliberately; nothing should write to it during normal running. /var is the opposite: data that varies while the system runs — logs in /var/log, caches, spool queues, databases. The rule I use is simple: config you set lives in /etc, state the machine generates lives in /var. That matters for backups and containers — you treat the two very differently, and you rarely bake /var into an image because it fills up at runtime.

What is the difference between an absolute and a relative path? Both

An absolute path starts from the root of the filesystem — it begins with a slash, like /var/log/syslog, and means the same thing no matter where you are standing. A relative path is resolved from your current directory: log/syslog means 'the log folder inside wherever I am right now.' You check where 'here' is with pwd. In DevOps this bites people constantly — a script using relative paths works when you run it by hand from your home directory, then fails in a cron job or CI runner that starts somewhere else. The safe habit is absolute paths in scripts, relative paths only for quick interactive work.

Where do logs live on a Linux server, and how do you find them? Service

On most Linux servers logs live under /var/log. System and boot messages sit in /var/log/syslog; authentication and sudo attempts in /var/log/auth.log; individual services often get their own file or folder, like /var/log/nginx/. My first move on an unfamiliar box is ls /var/log to see what is there, then tail -f a file to watch it live. On modern Ubuntu, systemd services also log to the journal, which you read with journalctl rather than a flat file — that is Day 10. Knowing logs live in /var also explains a classic outage: /var fills up, logs can no longer be written, and services start failing for no obvious reason.

What is the difference between / and ~? Both

/ is the root of the entire filesystem — the single top of the tree that everything else hangs off. ~ is a shortcut for your home directory, which for me is /home/pushkar; for the root user it is /root. So cd / takes you to the very top, while cd ~ (or just cd with no argument) takes you home. People mix these up early and it is a meaningful slip: a destructive command like rm -rf aimed at / is a catastrophe, aimed at ~ it merely wrecks your own files. Interviewers like this one because it quietly checks whether you understand the difference between the whole system and your little corner of it.

Quick check

Which directory holds system-wide configuration that should rarely change at runtime?

A script using a relative path works when you run it by hand, but fails in a cron job. Why?

Mark Day 2 complete

You know the map now — tomorrow you learn to move through it, copying, renaming and deleting files without a safety net.

Stuck on today’s lab? Ask in Mission 90 Q&A