File permissions are a cornerstone of Unix and Linux security. Every file and directory has an associated set of permissions that control who can read, write, and execute it. The chmod command changes these permissions, and understanding how it works is essential for system administrators, developers, and anyone deploying applications on Linux servers.
Unix permissions are defined for three categories of users:
Each category has three permission types:
| Permission | Symbol | Numeric Value | Effect on Files | Effect on Directories |
|---|---|---|---|---|
| Read | r | 4 | View file contents | List directory contents |
| Write | w | 2 | Modify file contents | Create/delete files in dir |
| Execute | x | 1 | Run as a program | Enter (cd into) directory |
The most common way to express permissions is as a three-digit octal number. Each digit is the sum of the permission values for owner, group, and others:
Permission: rwx r-x r-x
Breakdown: 4+2+1 4+0+1 4+0+1
Numeric: 7 5 5
Result: 755
Permission: rw- r-- r--
Breakdown: 4+2+0 4+0+0 4+0+0
Numeric: 6 4 4
Result: 644
Symbolic notation uses letters and operators to modify permissions:
# Add execute permission for owner
chmod u+x script.sh
# Remove write permission for group and others
chmod go-w file.txt
# Set exact permissions for all
chmod a=rw file.txt
# Add execute for owner, read for group
chmod u+x,g+r script.sh
| Numeric | Symbolic | Use Case |
|---|---|---|
755 | rwxr-xr-x | Executable scripts, directories, web server root |
644 | rw-r--r-- | Regular files (HTML, CSS, images, configs) |
600 | rw------- | Private files (SSH keys, credentials, .env) |
700 | rwx------ | Private scripts, user home directories |
775 | rwxrwxr-x | Shared directories (group collaboration) |
664 | rw-rw-r-- | Shared files (group can edit) |
444 | r--r--r-- | Read-only files (protection from changes) |
777 | rwxrwxrwx | Wide open — AVOID in production |
# HTML, CSS, JS, images - readable by web server
chmod 644 /var/www/html/*.html
chmod 644 /var/www/html/css/*.css
# Directories - web server needs to enter them
chmod 755 /var/www/html/
chmod 755 /var/www/html/css/
# Upload directory - web server needs to write
chmod 775 /var/www/html/uploads/
chown www-data:www-data /var/www/html/uploads/
# SSH requires strict permissions or it will refuse to use the keys
chmod 700 ~/.ssh/
chmod 600 ~/.ssh/id_rsa # Private key (MUST be 600)
chmod 644 ~/.ssh/id_rsa.pub # Public key
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/config
# Make a script executable
chmod 755 deploy.sh
chmod 755 /usr/local/bin/backup.sh
# Cron jobs reference (see the full guide):
# /blog/cron-expression-guide
Learn about scheduling these scripts with cron expressions.
# Common Docker permission fix
chmod -R 755 /app/
chown -R node:node /app/
# Database data directories
chmod 700 /var/lib/postgresql/data/
The umask determines the default permissions for newly created files and directories. It is a "mask" that removes permissions:
# Check current umask
umask
# Output: 0022
# How umask works:
# New file default: 666 (rw-rw-rw-)
# umask: 022 (----w--w-)
# Result: 644 (rw-r--r--)
# New directory default: 777 (rwxrwxrwx)
# umask: 022 (----w--w-)
# Result: 755 (rwxr-xr-x)
# Set a more restrictive umask
umask 077 # New files: 600, new dirs: 700
| Permission | Numeric | Symbol | Effect |
|---|---|---|---|
| SUID | 4000 | s on owner x | Execute as file owner (e.g., passwd) |
| SGID | 2000 | s on group x | Execute as file group / inherit group on dirs |
| Sticky bit | 1000 | t on others x | Only owner can delete files in dir (e.g., /tmp) |
# SUID example (passwd command)
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59976 ... /usr/bin/passwd
# Sticky bit on /tmp
ls -ld /tmp
drwxrwxrwt 15 root root 4096 ... /tmp
# Set SGID on a shared directory
chmod 2775 /shared/project/
# Set directories to 755 and files to 644 recursively
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# AVOID: chmod -R 777 (security disaster)
# This gives everyone full access to everything
777 gives every user on the system read, write, and execute permissions. On a web server, this means any process (including a compromised one) can modify your files. Always use the minimum permissions necessary.
600 (owner read/write only). Environment files contain secrets and should never be readable by other users or the web server group. Generate strong values with the Password Generator.
Use ls -la to see symbolic permissions, or stat -c "%a %n" filename for numeric output.
SSH enforces strict permission requirements. Your private key must be 600, your .ssh directory must be 700, and your home directory must not be writable by others. Run chmod calculations to verify.
DevToolKit — 42+ Free Online Developer Tools