File System and Permissions
The Linux filesystem hierarchy, reading and changing permissions, and symbolic vs hard links.
The filesystem hierarchy
Unlike Windows, Linux has no drive letters (C:\, D:\) — everything lives under a single root directory, written /. Every disk, partition, or network share gets mounted at some point inside this one tree rather than getting its own top-level letter. The layout is standardized (the Filesystem Hierarchy Standard, FHS) so tools and admins can rely on consistent locations across distributions:
| Path | Purpose |
|---|---|
/ |
The root of the entire filesystem tree. |
/bin, /usr/bin |
Essential user command binaries (ls, cat, bash). |
/sbin, /usr/sbin |
System administration binaries, typically requiring root (fdisk, iptables). |
/etc |
System-wide configuration files — nginx configs, passwd, cron jobs, package manager sources. |
/var |
Variable data that changes at runtime — logs (/var/log), databases, mail queues, package caches. |
/home |
Personal directories for regular users, e.g. /home/deploy. |
/root |
The home directory for the root (superuser) account specifically — not to be confused with /. |
/tmp |
Temporary files, often cleared on reboot. |
/opt |
Optional, self-contained third-party software. |
/usr |
The bulk of installed user programs, libraries, and documentation. |
/proc, /sys |
Virtual filesystems exposing kernel and process information (not real files on disk). |
/dev |
Device files representing hardware (/dev/sda, /dev/null). |
As a backend engineer, the two you'll touch constantly are /etc (where you'll edit an app's or a service's configuration) and /var/log (where you'll go first when something breaks in production).
$ ls /etc/nginx/
nginx.conf sites-available sites-enabled conf.d
$ tail -n 5 /var/log/syslog
Understanding ls -l output
Running ls -l (long format) is the single most common way to inspect permissions:
$ ls -l /var/www/app
-rw-r--r-- 1 deploy deploy 1204 Aug 20 09:14 .env
-rwxr-xr-x 1 deploy deploy 8912 Aug 20 09:14 deploy.sh
drwxr-xr-x 4 deploy deploy 4096 Aug 20 09:12 storage
Reading one line left to right:
-rwxr-xr-x 1 deploy deploy 8912 Aug 20 09:14 deploy.sh
│└┬┘└┬┘└┬┘ │ │ │
│ │ │ │ │ │ └── group owner
│ │ │ │ │ └── user (owner)
│ │ │ │ └── number of hard links
│ │ │ └── permissions for OTHER (everyone else)
│ │ └── permissions for GROUP
│ └── permissions for OWNER (the user)
└── file type: - regular file, d directory, l symbolic link
Each permission triad (rwx) is checked for a different actor:
- Owner — the specific user who owns the file.
- Group — any user who belongs to the file's group.
- Other — everyone else on the system.
And each triad has three possible flags:
r(read) — on a file: view its contents. On a directory: list its contents.w(write) — on a file: modify or delete its contents. On a directory: create, delete, or rename entries inside it.x(execute) — on a file: run it as a program/script. On a directory: enter it (cdinto it) or access files inside by exact name.
A directory with r but not x is a common trap: you can list filenames with ls, but you can't actually cd into it or open any file inside by path.
Reading permissions as numbers (octal)
Each triad can also be expressed as a single digit by summing bit values: r=4, w=2, x=1.
| Symbolic | Calculation | Octal |
|---|---|---|
rwx |
4+2+1 | 7 |
rw- |
4+2+0 | 6 |
r-x |
4+0+1 | 5 |
r-- |
4+0+0 | 4 |
So rwxr-xr-x is 755 (owner: 7, group: 5, other: 5), and rw-r--r-- is 644 — the most common permission set for regular application files.
Changing permissions with chmod
# Symbolic form: add execute for the owner
$ chmod u+x deploy.sh
# Remove write access for group and other
$ chmod go-w config.php
# Octal form: owner=read/write/execute, group=read/execute, other=read/execute
$ chmod 755 deploy.sh
# Apply recursively to a whole directory tree
$ chmod -R 644 storage/logs
A good rule of thumb: never make a file world-writable (chmod 777) just to "make an error go away" — it means literally any user on the system can overwrite it. Diagnose why a process can't write (usually the wrong owner, not insufficiently broad permissions) instead.
Changing ownership with chown
# Change the owning user
$ chown deploy app.log
# Change both user and group (user:group)
$ chown deploy:www-data app.log
# Change only the group
$ chown :www-data storage/
# Recursively change ownership of a directory tree
$ chown -R deploy:deploy /var/www/app
chown almost always requires root privileges (sudo chown ...) since you're changing who is recorded as owning the file, not just what the current owner is allowed to do.
Symbolic vs. hard links
Both let one file be reachable from multiple names, but they work very differently:
- A hard link is a second directory entry pointing at the exact same underlying data (inode) as the original. Both names are equal — deleting the "original" leaves the data intact as long as one hard link remains. Hard links can't span filesystems/partitions and can't point at directories.
- A symbolic link (symlink) is a small special file that just stores a path to another file. It's more like a Windows shortcut — if the target is deleted or moved, the symlink breaks ("dangling"). Symlinks can point across filesystems and at directories.
# Create a hard link
$ ln original.txt hardlink.txt
# Create a symbolic link
$ ln -s /var/www/app/current /var/www/app/releases/latest
$ ls -l /var/www/app/releases/latest
lrwxrwxrwx 1 deploy deploy 20 Aug 20 09:14 latest -> /var/www/app/current
That l at the very start of the ls -l line (instead of - or d) identifies a symlink, and the -> target shows what it points to. Symlinks like this are exactly how tools like Capistrano-style zero-downtime deploys work: a current symlink is atomically re-pointed at a new release directory.
Common mistakes
- Using
chmod 777to fix a permission error instead of finding out which user/group actually needs access — it's a security hole, not a fix. - Forgetting that directories need the execute bit (
x) to be entered, even if you only want to read files inside them. - Confusing a symlink pointing at a deleted target (which shows as broken/red in many
lsconfigurations) with a genuinely missing file —ls -lreveals the target path so you can tell immediately.
Interview questions
Q: What do the r, w, and x bits mean on a directory, as opposed to a file?
On a file, r means you can read its contents, w means you can modify it, and x means you can execute it as a program. On a directory, r means you can list its contents (ls), w means you can create/delete/rename entries inside it, and x means you can actually enter it or access a file inside by exact path — without x, r alone lets you see filenames but not touch anything inside.
Q: What's the difference between a hard link and a symbolic link? A hard link is another directory entry pointing at the same underlying data on disk (same inode) — the two names are functionally equivalent, and the data survives as long as any hard link to it exists. A symbolic link is a separate small file that just stores a path to another file; it can cross filesystems and point at directories, but breaks if the target is moved or deleted.
Q: What does chmod 644 mean for a file?
The owner gets read and write (6 = 4+2), and both the group and everyone else get read-only (4). This is the standard permission set for a regular file like a config file or a source file that shouldn't be executable or writable by anyone but its owner.