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).

Bash
$ 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:

Bash
$ 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:

Plaintext
-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 (cd into 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

Bash
# 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

Bash
# 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.

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.
Bash
# 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 777 to 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 ls configurations) with a genuinely missing file — ls -l reveals 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.