The filesystem hierarchy
What lives in /etc, /usr, /var, /run and /tmp.
Every Linux server arranges its files the same way, so once you know the layout you can find your way around a machine you have never logged into. This lesson walks through that tree on a fresh Ubuntu 26.04 install: where programs, configuration, logs, service data and temporary files live, which directories belong to packages and which to you, and which ones exist only in memory. That knowledge tells you where to look when something breaks, and whether a change you make will survive the next upgrade or reboot.
One tree, and the usr merge
Linux has a single directory tree that starts at /, the root directory. There are no drive letters: extra disks and partitions are attached as directories inside the tree (the storage lesson shows how). The layout follows a published standard, and man file-hierarchy describes it on your own server. Here is the top of the tree on a fresh install:
The first letter of each line is the type: d for a directory, l for a symbolic link, a pointer to another path. bin, lib and sbin are links into /usr. This is the usr merge: all programs and libraries live under /usr, and the old top-level paths remain as links so that a script calling /bin/bash still works. Ubuntu 26.04 and RHEL 10 are both merged. RHEL keeps 64-bit libraries in /usr/lib64 on every 64-bit processor, so it also has lib64 -> usr/lib64; Ubuntu has that link only on x86_64, for the program loader.
/usr holds what packages install and is best treated as read-only: /usr/bin and /usr/sbin for commands, /usr/lib for libraries and packaged default settings, /usr/share for documentation, manual pages and other data. A package upgrade may replace any file there, so never edit one. Software you build or install by hand goes in /usr/local, which the package manager leaves alone, and self-contained third-party products often use /opt. /srv is for data a server publishes, such as a website, and /boot holds the kernel and the files that start it.
/dev holds devices presented as files: disks such as /dev/vda, terminals, and /dev/null, which discards whatever is written to it. The kernel creates them, and ordinary programs read and write them like files. /mnt and /media are the usual places to attach extra filesystems by hand or, for removable media, automatically.
proc and sys show a size of 0 because the kernel generates their contents on demand, and tmp ends in t instead of x; both come up later in this lesson.
Configuration in /etc, defaults in /usr/lib
/etc holds the configuration of this particular machine, almost all of it plain text you can read with cat or less. More and more programs split their configuration: the package's defaults go under /usr/lib, and /etc holds only what the administrator, the installer or the cloud image changed. Older programs such as the SSH server still ship their main file in /etc and take changes as drop-in files beside it. Kernel settings loaded at boot show the split (-1 lists one name per line):
Every file in /usr/lib/sysctl.d came with a package. The files in /etc/sysctl.d are local: 99-cloudimg-ipv6.conf was written when the Ubuntu cloud image was built, and 99-lima.conf by the virtualisation tool that runs this lab machine. To change a setting you add your own file to /etc/sysctl.d, and a file there with the same name as a packaged one replaces it completely. The same split appears across the system: unit files in /usr/lib/systemd/system against /etc/systemd/system, and .d directories such as /etc/ssh/sshd_config.d and /etc/sudoers.d for drop-in files that add to a main file.
The split is what makes upgrades safe. A package upgrade replaces its own files under /usr/lib and leaves yours in /etc alone, and you can see at a glance what was changed on this machine. The price is that no single file tells the whole story: the effective configuration is the defaults plus every override, and the rules for combining them differ by program. The lessons on editing configuration and on systemd show the commands that print the combined result.
/etc also holds files that must stay private, such as /etc/shadow with the password hashes, which only privileged programs can read; "Users, groups and the account files" shows its permissions on Ubuntu and RHEL and what it contains.
Data that changes: /var, /home and /root
/var holds data that grows and changes while the system runs.
/var/log holds log files; its group is syslog because the logging daemon writes there, and the lesson on logs covers what is inside. /var/lib holds the persistent state of programs: the package database, systemd's records and, on a real server, a database's data files. That makes it the directory to back up. /var/cache holds data that can be deleted and rebuilt, /var/spool queues of work such as scheduled jobs and outgoing mail, and /var/tmp temporary files that must survive a reboot. lock and run are links to /run, kept for old programs.
People's files live in /home, one directory per user. The administrator's home is /root, outside /home, so root can still log in and repair the machine when /home is on a disk that failed to mount.
Ubuntu 26.04 creates home directories with mode 0750 (drwxr-x---), RHEL 10 with 0700, so on both, other users cannot look inside yours. /root is closed to ordinary users on both. The trailing dot after the RHEL permissions means the file also carries an SELinux label, RHEL's extra access-control layer.
In memory only: /run, /tmp, /proc and /sys
Some directories are not stored on disk at all. /run is a tmpfs, a filesystem kept in RAM, where services write runtime state such as their process ID files and sockets; it starts empty at every boot. On Ubuntu 26.04 /tmp is a tmpfs too, a change from earlier Ubuntu LTS releases. findmnt -T shows which filesystem holds a path:
/tmp is its own tmpfs mount, limited to half of the RAM and emptied at every reboot, while /var/tmp is an ordinary directory on the root filesystem (ext4 on this server). The options leave the size out because the kernel lists a tmpfs size only when it differs from its own default of half the memory, and on this fresh install the two are equal; df -h shows the limit, 1.5G on this machine. The terminals in later lessons come from a second lab server with more memory, whose /tmp line reads size=1994676k: the same half-of-RAM rule, but that machine's memory total has changed by a few KiB since the limit was set at boot, so the kernel no longer sees it as its default and prints it.
Files in /tmp are kept in memory, so they compete with your programs for RAM. A job that stages a multi-gigabyte dump or archive in /tmp fails when the limit is reached, or pushes a server without swap towards running out of memory. Large or long-lived temporary files belong in /var/tmp. An administrator who needs /tmp back on disk can run sudo systemctl mask tmp.mount and reboot.
Two of the tmpfs options matter for security: nosuid makes the kernel ignore the set-user-ID bit on programs stored there, and nodev ignores device files there. The lesson on special permission bits explains why that matters. On both platforms, files in /tmp that have not been used for 10 days are also deleted, and in /var/tmp after 30 days. RHEL 10 does not mount a tmpfs on /tmp:
Both temporary directories are writable by everyone, and the final t, the sticky bit, stops users from deleting or renaming each other's files there.
/tmp and /var/tmp, so never use a fixed, guessable name there such as /tmp/backup.tar: another user can create that path first. Let mktemp or mktemp -d choose a random name with private permissions, and keep anything you need tomorrow in your home directory or /var/tmp, not in /tmp. The lesson on files, directories and links shows the symbolic-link trick this protects against./proc and /sys are the kernel's live view of itself, presented as files. Nothing in them is stored anywhere; the kernel builds the content at the moment you read it, which is why their files show a size of 0.
/proc/sys holds the kernel's tunable settings (the ones the sysctl.d files set at boot), and /proc also has a directory for every running process, which the processes lesson explores. /sys describes devices: here the network interfaces, eth0 and the loopback interface lo.
Try this
Take the SSH server as an example and find its packaged unit file and its configuration: ls -l /usr/lib/systemd/system/ssh.service /etc/ssh/sshd_config. Which of the two could a package upgrade replace? Then create two empty files with touch /tmp/fhs-test /var/tmp/fhs-test, run findmnt -T on each, and decide which one would still exist after a reboot on Ubuntu 26.04 (the one on the root filesystem) and which on RHEL 10 (both). Remove them with rm when you are done.
Takeaway
Change configuration in /etc, never in /usr, and put data where its lifetime fits: /var/lib for state, /var/tmp for temporary files that must survive a reboot, /tmp for scratch that may vanish at any boot.