File System and Permissions
The Directory Tree
Linux uses a single hierarchical root (/). The Filesystem Hierarchy Standard (FHS) defines common layout:
| Path | Purpose |
|---|---|
/ |
Root of the filesystem |
/home |
User home directories |
/root |
root user’s home |
/etc |
System configuration |
/var |
Variable data (logs, caches, spool) |
/tmp |
Temporary files (sticky bit; often cleared on reboot) |
/usr |
User programs, libraries, documentation |
/opt |
Optional third-party software |
/bin, /sbin |
Essential binaries (often symlinks to /usr/bin) |
/dev |
Device files |
/proc, /sys |
Kernel and hardware interfaces |
cd /var/log
ls -la
tree -L 2 /etc 2>/dev/null || find /etc -maxdepth 2 -type d
Paths and Navigation
pwd # absolute path of cwd
cd /etc/nginx # absolute
cd ../sites-available # relative (.. = parent)
readlink -f ./symlink # resolve canonical path
realpath config.conf # same, if installed
Absolute paths start with /. Relative paths start from the current directory. Use absolute paths in scripts and systemd units to avoid ambiguity.
File Types and Metadata
ls -lah
# First char: - file, d directory, l symlink, c/b device, p pipe, s socket
file /bin/bash
stat /etc/passwd # inode, blocks, timestamps
ls -i file.txt # inode number
Timestamps: atime (access), mtime (modification), ctime (metadata change). Use touch -d to set mtime for testing.
Permissions Model
Each file has an owner, group, and mode (rwx for user, group, others):
ls -l /etc/shadow
# -rw-r----- 1 root shadow → owner rw, group r, others none
| Symbol | Octal | On files | On directories |
|---|---|---|---|
| r | 4 | Read content | List directory entries |
| w | 2 | Modify content | Create/delete files |
| x | 1 | Execute | Traverse (cd into) |
chmod 644 document.txt # rw-r--r--
chmod 755 script.sh # rwxr-xr-x
chmod u+x,g-w script.sh # symbolic mode
chmod -R g+rX docs/ # X = execute on dirs only
chown alice:developers app/
chown -R www-data:www-data /var/www/html
chgrp deploy /opt/app/config.yml
Special Permission Bits
| Bit | File effect | Directory effect |
|---|---|---|
| setuid (4) | Run as file owner | — |
| setgid (2) | Run as file group | New files inherit group |
| sticky (1) | — | Only owner deletes own files (/tmp) |
ls -ld /tmp # drwxrwxrwt — sticky bit
chmod u+s /usr/bin/passwd # setuid example
find / -perm -4000 -type f 2>/dev/null # find setuid binaries
Audit setuid binaries regularly — they are privilege escalation targets.
umask
Default permissions for new files and directories:
umask # e.g. 0022
umask 027 # stricter: group rwx, others none
# New file: 666 - umask; new dir: 777 - umask
# umask 022 → files 644, dirs 755
Set umask in /etc/profile, /etc/bash.bashrc, or PAM (/etc/login.defs).
Access Control Lists (ACLs)
When owner/group/others are insufficient:
# Install ACL tools (Debian/Ubuntu)
sudo apt install acl
getfacl project/shared/
setfacl -m u:bob:rw project/shared/file.txt
setfacl -m g:developers:rwx project/shared/
setfacl -d -m g:developers:rwx project/shared/ # default ACL for new files
Links
ln -s /etc/nginx/nginx.conf ~/nginx.conf # symbolic (soft) link
ln file hardlink # hard link (same inode)
# Find broken symlinks
find /opt -type l ! -exec test -e {} \; -print
Hard links cannot cross filesystems or link directories (usually). Symlinks can point anywhere but break if target moves.
Best Practices
| Practice | Reason |
|---|---|
| Never chmod 777 in production | World-writable = any user can modify |
| Run services as non-root users | Limits blast radius |
| Use group permissions for shared teams | Avoids overly broad “others” access |
| Separate secrets with mode 600 | Only owner reads |
chmod 600 ~/.ssh/id_ed25519
chmod 700 ~/.ssh
Common Mistakes
| Mistake | Consequence |
|---|---|
chmod -R 777 to “fix” permissions |
Security hole; masks real ownership issues |
| Running web server as root | Remote code execution = full system compromise |
| Ignoring directory execute bit | Cannot cd even with read permission |
| Editing files as root that should be owned by service user | Service cannot write after restart |
Troubleshooting
Permission denied despite chmod:
namei -l /path/to/file # trace path permissions at each level
# Every directory in path needs execute (x) for traversal
Disk full but df shows space:
# Deleted file still held open by process
lsof +L1
# Truncate or restart process holding deleted file
Production Scenario
A deployment user deploy must write to /var/www/app owned by www-data:
sudo groupadd webteam
sudo usermod -aG webteam deploy
sudo usermod -aG webteam www-data
sudo chgrp -R webteam /var/www/app
sudo chmod -R g+rws /var/www/app # setgid for group inheritance
New files inherit webteam group; both deploy and nginx can read/write without world permissions.
Understanding permissions prevents the most common production mistakes: world-writable configs, services running as root, and broken deployment permissions.