Every file and directory on a Linux system has a set of permissions that controls who can read, write, or execute it. If you have ever seen -rwxr-xr-x in an ls -l output and wondered what it means, or blindly typed chmod 755 because a tutorial told you to, this guide will make it all click.
Understanding permissions is not just about passing a certification exam. It is a daily skill — misconfigured permissions are behind everything from "permission denied" errors to serious security vulnerabilities. Once you understand the system, you will never have to guess again.
The Permission Model
Linux uses a simple three-tier permission model. Every file has three sets of permissions:
| Who | Description |
|---|---|
| Owner (u) | The user who created the file |
| Group (g) | Users who belong to the file's group |
| Others (o) | Everyone else on the system |
Each tier can have three types of access:
| Permission | Symbol | On Files | On Directories |
|---|---|---|---|
| Read | r | View file contents | List directory contents |
| Write | w | Modify file contents | Create/delete files in directory |
| Execute | x | Run as a program | Enter the directory (cd into it) |
Reading Permission Strings
When you run ls -l, you see something like:
-rwxr-xr-x 1 sam staff 4096 Mar 10 09:30 deploy.sh
drwxr-x--- 2 sam staff 4096 Mar 10 09:30 secrets/
The first column breaks down as:
- rwx r-x r-x
│ │ │ │
│ │ │ └── Others: read + execute
│ │ └────── Group: read + execute
│ └────────── Owner: read + write + execute
└──────────── Type: - = file, d = directory, l = symlink
So -rwxr-xr-x means:
- It is a regular file
- Owner can read, write, and execute
- Group can read and execute (no write)
- Others can read and execute (no write)
Octal (Numeric) Notation
Each permission has a numeric value:
| Permission | Value |
|---|---|
| Read (r) | 4 |
| Write (w) | 2 |
| Execute (x) | 1 |
| None (-) | 0 |
Add them up for each tier:
| Octal | Permissions | Meaning |
|---|---|---|
| 7 | rwx | Read + Write + Execute |
| 6 | rw- | Read + Write |
| 5 | r-x | Read + Execute |
| 4 | r-- | Read only |
| 3 | -wx | Write + Execute |
| 2 | -w- | Write only |
| 1 | --x | Execute only |
| 0 | --- | No permissions |
So chmod 755 means:
- Owner: 7 (rwx) — full access
- Group: 5 (r-x) — read and execute
- Others: 5 (r-x) — read and execute
And chmod 644 means:
- Owner: 6 (rw-) — read and write
- Group: 4 (r--) — read only
- Others: 4 (r--) — read only
Common Permission Patterns
Here are the permissions you will use 90% of the time:
Files
| Octal | Symbolic | Use Case |
|---|---|---|
| 644 | rw-r--r-- | Regular files (configs, HTML, text). Default for most files. |
| 755 | rwxr-xr-x | Scripts and executables that everyone can run. |
| 600 | rw------- | Private files (SSH keys, secrets, .env). Only the owner can access. |
| 400 | r-------- | Read-only private files (SSH private keys). |
| 666 | rw-rw-rw- | World-writable files. Rarely appropriate — security risk. |
Directories
| Octal | Symbolic | Use Case |
|---|---|---|
| 755 | rwxr-xr-x | Standard directories. Owner has full control, others can browse. |
| 700 | rwx------ | Private directories. Only the owner can enter or list. |
| 750 | rwxr-x--- | Group-accessible directories. Owner and group members can access. |
| 777 | rwxrwxrwx | World-writable directory. Almost never appropriate. |
Using chmod
Octal mode (most common)
chmod 755 deploy.sh # Owner: rwx, Group: r-x, Others: r-x
chmod 644 config.yaml # Owner: rw-, Group: r--, Others: r--
chmod 600 .env # Owner: rw-, no access for others
chmod 400 ~/.ssh/id_rsa # Owner: r--, SSH private key
Symbolic mode
chmod u+x script.sh # Add execute for owner
chmod g-w file.txt # Remove write from group
chmod o-rwx secret.txt # Remove all permissions from others
chmod a+r readme.md # Add read for all (a = all)
chmod u=rwx,g=rx,o=rx file # Set exact permissions (same as 755)
Recursive
chmod -R 755 /var/www/html/ # Apply to directory and everything inside
Warning:
chmod -R 777is almost never the right answer. If a tutorial tells you to do this, find a better tutorial.
Using chown
chown changes who owns a file:
chown sam file.txt # Change owner to sam
chown sam:staff file.txt # Change owner to sam, group to staff
chown :staff file.txt # Change only the group
chown -R www-data:www-data /var/www/ # Recursive
Real-World Scenarios
Web Server Files
For a typical Nginx or Apache web server:
# Web root owned by www-data
chown -R www-data:www-data /var/www/html/
# Directories: 755 (server can browse)
find /var/www/html -type d -exec chmod 755 {} \;
# Files: 644 (server can read)
find /var/www/html -type f -exec chmod 644 {} \;
# Upload directories: 775 (group can write)
chmod 775 /var/www/html/uploads/
SSH Keys
SSH is strict about key permissions. If they are wrong, SSH refuses to use them:
chmod 700 ~/.ssh/ # Directory
chmod 600 ~/.ssh/id_rsa # Private key (some prefer 400)
chmod 644 ~/.ssh/id_rsa.pub # Public key
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/config
Application Secrets
chmod 600 .env # Environment variables
chmod 600 credentials.json # API keys
chmod 600 /etc/ssl/private/* # TLS private keys
Special Permissions
Beyond the basic rwx, Linux has three special permission bits:
Setuid (4xxx)
When set on an executable, it runs as the file's owner instead of the user who launched it.
chmod 4755 /usr/bin/passwd
# -rwsr-xr-x (note the 's' instead of 'x' for owner)
The passwd command needs root access to modify /etc/shadow, so it has setuid set. Any user can run it, but it executes with root privileges.
Setgid (2xxx)
On a directory, new files inherit the directory's group instead of the creator's primary group. Useful for shared folders.
chmod 2775 /shared/projects/
# drwxrwsr-x (note the 's' instead of 'x' for group)
Sticky Bit (1xxx)
On a directory, only the file's owner (or root) can delete files — even if others have write access. Used on /tmp:
chmod 1777 /tmp
# drwxrwxrwt (note the 't' instead of 'x' for others)
Troubleshooting Permission Issues
When you hit "Permission denied":
- Check the file permissions:
ls -la filename - Check who you are:
whoamiandgroups - Check the entire path: Every directory in the path needs at least execute permission for you to traverse it
- Check the owner:
stat filenameshows owner, group, and permissions in detail
# Quick debug command
namei -l /full/path/to/file
# Shows permissions for every component of the path
Try It Yourself
Use our free Chmod Calculator to visually toggle permissions and instantly see the octal number, symbolic notation, and the chmod command. Perfect for when you need to set permissions and want to double-check before running the command.