Linux File System Hierarchy and File Permissions Explained
What lives in /etc, /var, /usr and /proc, how Linux file permissions and chmod work, plus links, inodes, disk usage and mounting file systems.
Windows gives every disk its own letter. Linux has a single directory tree that starts at /, the root directory, and every disk, USB stick and network share appears somewhere inside it. Configuration lives in plain text files under /etc, logs under /var/log, programs under /usr, and the kernel shows its own state as files under /proc and /sys. Once you know the layout, you know where to look on any distribution.
The second half of this part covers permissions: who may read, change or run each file. Most "Permission denied" errors you will ever see make sense once you can read the ten characters at the start of ls -l.
Prerequisites
- The commands from Part 3:
cd,ls,mkdir,touchandfind. - A Linux shell. The output below comes from Ubuntu 24.04.5 LTS; the layout is the same on Debian, Fedora and RHEL.
- A fresh
~/labfrom Part 3 (rm -rf ~/lab && bash ~/make-lab.sh), so your output matches.
One Tree, Starting at /
The layout follows the Filesystem Hierarchy Standard (FHS 3.0), and systemd documents the same conventions in man file-hierarchy. These are the directories you will visit most:
| Directory | What it holds |
|---|---|
/etc |
System-wide configuration, almost all of it plain text: /etc/hosts, /etc/fstab, /etc/ssh/sshd_config, /etc/systemd/ |
/home |
One directory per user, for example /home/dev. ~ is a shortcut for yours |
/root |
The home directory of the root user (not to be confused with /) |
/usr |
Installed software: /usr/bin (commands), /usr/sbin (admin commands), /usr/lib (libraries), /usr/share (docs, data) |
/usr/local |
Software you install yourself outside the package manager, so it does not clash with distribution files |
/opt |
Self-contained third-party applications, each in its own directory |
/var |
Data that changes while the system runs: /var/log (logs), /var/lib (databases, package state, container images), /var/cache, /var/spool |
/srv |
Data your server serves, for example web sites or Git repositories |
/tmp |
Temporary files that anyone may create. Do not keep anything important here |
/boot |
The kernel, the initial RAM disk and the boot loader files |
/dev |
Device files: disks (/dev/sda, /dev/nvme0n1), terminals, and /dev/null |
/proc and /sys |
Virtual file systems where the kernel exposes processes, hardware and settings |
/run |
Runtime state such as PID files and sockets, kept in memory and cleared at boot |
/mnt and /media |
Mount points: /mnt for temporary manual mounts, /media for removable media mounted by the desktop |
The Merged /usr
Older tutorials say that /bin holds essential commands and /usr/bin holds the rest. That split is gone. Fedora, RHEL, Debian 12 and later, and current Ubuntu releases have merged /usr: /bin, /sbin and /lib are symbolic links to their counterparts under /usr, as the listing above shows. /bin/ls and /usr/bin/ls are the same file. Ubuntu 24.04 also has empty /bin.usr-is-merged and /sbin.usr-is-merged directories, markers left by the transition; leave them alone.
Two more changes worth knowing: on Debian 13, /tmp is a tmpfs in memory by default, so its contents vanish at reboot; and on new Debian 13 and Fedora installs, systemd deletes files in /tmp that were not used for 10 days and files in /var/tmp after 30 days. Keep anything you need somewhere else.
Configuration Lives in /etc
Most of /etc is human-readable text, which is why so much Linux administration is "edit a file, then reload a service". Some files are links to where the package manager keeps the real file:
/etc/os-release is the standard way to find out which distribution and version you are on, on any modern system. Scripts can source it and read $ID and $VERSION_ID.
Before you edit a file in /etc, copy it (sudo cp sshd_config sshd_config.bak), and check whether the program supports a drop-in directory such as /etc/ssh/sshd_config.d/ or /etc/sysctl.d/. A small file of your own in a drop-in directory survives package upgrades and is easy to review.
The Kernel's Files: /proc, /sys and /dev
/proc and /sys take no disk space. The kernel generates their contents when you read them.
/proc/<PID>/ describes one process (Part 7 uses it), /proc/sys/ holds tunable kernel settings that sysctl changes, and /sys describes devices and drivers. In /dev, /dev/null discards everything written to it, /dev/zero returns zeros, and /dev/urandom returns random bytes. /sys/class/net/ lists the network interfaces, and /sys/block/ the disks.
Reading Permissions
Every file has an owner, a group, and three sets of permissions: one for the owner (user), one for the group, and one for everyone else (other).
The first ten characters of -rw-rw-r-- read like this:
| Position | Characters | Meaning |
|---|---|---|
| 1 | - |
File type: - regular file, d directory, l symbolic link, c or b device, p named pipe, s socket |
| 2 to 4 | rw- |
Owner (dev) can read and write |
| 5 to 7 | rw- |
Group (dev) can read and write |
| 8 to 10 | r-- |
Everyone else can read |
For a file, r lets you read it, w lets you change it, and x lets you run it as a program. For a directory the letters mean something slightly different: r lists the names in it, w creates, renames and deletes entries in it, and x lets you enter it and reach the files inside. Deleting a file needs write permission on the directory, not on the file.
Numeric (Octal) Modes
Each permission has a value: read is 4, write is 2, execute is 1. Add them up for each of the three sets:
| Number | Permissions | Typical use |
|---|---|---|
644 |
rw-r--r-- |
Normal files: you edit, others read |
600 |
rw------- |
Private files: SSH keys, files with secrets |
755 |
rwxr-xr-x |
Programs, scripts and normal directories |
700 |
rwx------ |
Private directories such as ~/.ssh |
664 / 775 |
rw-rw-r-- / rwxrwxr-x |
Files and directories a group works on together |
Changing Permissions With chmod
Symbolic mode uses u, g, o and a (all), the operators +, - and =, and the letters r, w and x. It changes only what you name, which makes it safer than a numeric mode when you are unsure of the current state.
Recursive Changes Without Breaking Things
chmod -R 755 dir makes every file executable too, and chmod -R 644 dir removes x from every directory, so nobody can enter them. Use a capital X, which adds execute only to directories (and to files that are already executable for someone):
Directories got rwxr-xr-x and the HTML and CSS files got rw-r--r--. The same result with find: find site -type d -exec chmod 755 {} + and find site -type f -exec chmod 644 {} +.
What Permission Denied Looks Like
You are not root here, so the kernel enforces every bit:
The owner of a file can always change its permissions back, even after locking themselves out. Root ignores read and write permissions entirely, which is one reason to avoid working as root.
The umask: Default Permissions for New Files
New files start from 666 and new directories from 777, minus the bits in your umask. On Ubuntu and Debian, users who have their own private group (the default) get a umask of 0002, so new files are 664 and new directories 775. Root and systems without private groups use 0022, which gives 644 and 755.
Set a umask for a service in its systemd unit (UMask=0027) rather than in a shell profile, because services do not read your profile.
Ownership: chown and chgrp
Only root can give a file to another user. Changing the group works for the owner too, as long as they belong to the new group.
sudo chown alice report.txt # new owner
sudo chown alice:developers report.txt # new owner and group
sudo chgrp developers report.txt # new group only
sudo chown -R www-data:www-data /srv/site # a whole tree
A classic mistake: you copy files into place with sudo cp, and they end up owned by root, so the service that runs as www-data cannot write to them. Check with ls -l after every sudo cp or sudo tar -x, and fix ownership with chown -R.
Special Permission Bits
Three more bits sit in front of the usual nine. In numeric form they are the extra leading digit: 4 for setuid, 2 for setgid, 1 for sticky.
- setuid (
sin the owner'sxposition) runs a program with the permissions of its owner. That is howpasswdcan write to/etc/shadowfor an ordinary user. Setuid programs are a favourite target for attackers, so audit them (Part 10). - setgid on a directory (
sin the group'sxposition) makes new files inside it inherit the directory's group instead of the creator's primary group. Use it for shared project directories. - sticky (
tin the last position) on a directory lets users delete only their own files./tmpuses it.
A shared directory for a team needs root to set its group. Here is the full recipe and the result it produces on a system where the developers group exists (example output):
sudo mkdir -p /srv/projects
sudo chgrp developers /srv/projects
sudo chmod 2775 /srv/projects
ls -ld /srv/projects
drwxrwsr-x 2 root developers 4096 Oct 23 09:00 /srv/projects
Any file a member creates there belongs to the developers group, and with the 0002 umask the whole group can edit it. Part 6 creates the group and its users.
Access Control Lists
When owner, group and other are not enough, for example when one extra user needs read access, use an access control list (ACL). ACLs work on ext4, XFS and Btrfs out of the box; install the acl package for the tools.
setfacl -m u:alice:r report.txt # give alice read access
getfacl report.txt # show all entries
setfacl -x u:alice report.txt # remove the entry again
A file with an ACL shows a + after its permissions in ls -l (-rw-rw-r--+). Use ACLs sparingly: they are easy to forget during audits.
File Types, Links and Inodes
Everything is a file, but not every file holds data. ls -l shows the type in the first column, and file looks inside to tell you what kind of data it holds:
Each file's metadata (owner, permissions, size, timestamps, and where its data is on disk) is stored in an inode. A directory entry is just a name that points to an inode. That explains the two kinds of links:
- A hard link is a second name for the same inode. Both names are equal; the data stays until the last name is removed. Hard links cannot cross file systems or point to directories.
- A symbolic link (symlink) is a small file that contains a path. It can point anywhere, including to directories and other file systems, but it breaks when the target moves.
The number after the permissions in ls -l is the link count: 2 after the hard link was created. Deployments often use symlinks, for example a current link that points to the active release directory, so switching versions is one ln -sfn command. See how to create symlinks for more.
Hidden Files
Names that start with a dot are hidden from ls and from * wildcards. Your shell and tools keep their settings in them:
You will often edit ~/.bashrc (shell settings), ~/.profile (login settings), ~/.ssh/ (SSH keys and config, Part 6) and ~/.config/ (settings of many desktop and CLI programs).
Finding Files by Owner, Permissions and Age
find can test the metadata from this part. These checks are common in audits:
On a server, sudo find / -xdev -perm -4000 -type f lists setuid programs and sudo find / -xdev -nouser finds files whose owner was deleted. -xdev keeps find on one file system, so it does not wander into /proc or network mounts.
Disk Space: df and du
df reports free space per file system, and du adds up how much space directories use.
When a disk fills up, start at the top: sudo du -xh --max-depth=1 / | sort -rh | head, then repeat inside the biggest directory. The usual suspects are /var/log, /var/lib/docker (or /var/lib/containerd), old kernels, and package caches. df -i shows inodes: a disk can run out of inodes, with plenty of space left, when something creates millions of tiny files. Part 10 covers the case where df says the disk is full but du cannot find the files.
File Systems and Mounting
A file system organises data on a disk partition. You will meet these:
- ext4: the default on Ubuntu and Debian installs. Stable and well understood.
- XFS: the default on RHEL and Fedora Server. Good with large files; it can grow but not shrink.
- Btrfs: the default on Fedora Workstation and openSUSE, with snapshots, compression and checksums.
- ZFS: snapshots, checksums and RAID in one, available on Ubuntu as an option.
- tmpfs: lives in memory, used for
/runand, on some systems,/tmp. - vfat and exFAT for USB sticks and the EFI system partition; NTFS through the kernel's
ntfs3driver.
Mounting attaches a file system to a directory, the mount point. These commands need root and a real disk, so the output is an example of a VM with one extra disk:
lsblk -f # disks, partitions, file systems and UUIDs
sudo mkfs.ext4 /dev/vdb1 # create a file system (erases the partition!)
sudo mkdir -p /mnt/data
sudo mount /dev/vdb1 /mnt/data # attach it
findmnt /mnt/data # check it is mounted
sudo umount /mnt/data # detach it (not "unmount")
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
vda
├─vda1 ext4 1.0 cloudimg-rootfs 2f6b7e4c-8d1a-4c5e-9f3b-1a2b3c4d5e6f 21.4G 23% /
└─vda15 vfat FAT32 UEFI 9C3A-21F0 98.3M 6% /boot/efi
vdb
└─vdb1 ext4 1.0 7d8e9f10-1a2b-4c3d-8e9f-0a1b2c3d4e5f
To mount a file system at every boot, add a line to /etc/fstab. Use the UUID from lsblk -f, not the device name: names such as /dev/sdb can change between boots.
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=7d8e9f10-1a2b-4c3d-8e9f-0a1b2c3d4e5f /mnt/data ext4 defaults,nofail 0 2
A wrong line in /etc/fstab can stop the machine from booting. After every edit, run sudo findmnt --verify and sudo mount -a and fix any error before you reboot. The nofail option lets the system boot even if that disk is missing, which matters on cloud servers where volumes can be detached.
Common Mistakes
chmod -R 777to "fix" a permission error. It lets every user and every compromised service change the files. Find out which user needs access, then fix the owner or group and use755/644or775/664.chmod -R 644or755on a mixed tree. Useu=rwX,go=rXor separatefind -type dandfind -type fcommands.- Wrong owner after
sudo. Files copied or extracted withsudobelong to root. Check withls -land fix withchown. - Private keys readable by others. SSH refuses keys that other users can read (
UNPROTECTED PRIVATE KEY FILE). Usechmod 600on keys andchmod 700on~/.ssh. - Editing
/etc/fstabwithout testing. Always runfindmnt --verifyandmount -afirst. - Storing data in
/tmp. It may live in memory and is cleaned automatically.
Summary
- Linux has one directory tree.
/etcholds configuration,/varchanging data and logs,/usrinstalled software,/homeyour files, and/procand/systhe kernel's view of the system. /bin,/sbinand/libare links into/usron current distributions.- Permissions come in three sets (owner, group, other) of
r,wandx;xon a directory means "may enter". chmodchanges permissions (u=rwX,go=rXfor trees),chownandchgrpchange ownership, and the umask sets defaults.- setuid, setgid and the sticky bit add special behaviour; ACLs add per-user exceptions.
- Hard links share an inode; symlinks store a path and can break.
dfanddufind where the space went; mount disks by UUID and test/etc/fstabbefore rebooting.
Next: Package Management, where you install, update and remove software with apt and dnf.
Keep Learning
- Change permissions for a folder, its subfolders and files
- List directories with their sizes
- Interview questions: Linux file permissions
- Practice octal permissions in the binary simulator
- Linux Fundamentals flashcards
Tags
Found an issue?