Linux File Permissions Explained: chmod, chown & Beyond

Every "Permission denied" error has a reason. Linux file permissions are the gatekeepers of your system — they control who can read, write, and execute every file and directory. This guide takes you from zero to confident with permissions.

Reading permission strings

When you run ls -la, you see something like this:

-rwxr-xr-x 1 root root 4096 Feb 18 10:00 deploy.sh drwxr-x--- 2 www www 4096 Feb 18 09:30 uploads/ -rw-r--r-- 1 root root 1234 Feb 18 08:15 config.json

The first column is the permission string. Let's break down -rwxr-xr-x:

- rwx r-x r-x │ │ │ │ │ │ │ └── Other: read + execute │ │ └── Group: read + execute │ └── Owner: read + write + execute └── File type (- = file, d = directory, l = symlink)

Each group of three characters represents read (r), write (w), and execute (x). A dash - means that permission is not granted.

Numeric (octal) notation

Each permission has a numeric value:

PermissionValueDescription
r4Read — view file contents or list directory
w2Write — modify file or add/remove files in directory
x1Execute — run file as program or enter directory

Add the values together for each role. For example, rwxr-xr-x becomes:

Owner: r(4) + w(2) + x(1) = 7 Group: r(4) + -(0) + x(1) = 5 Other: r(4) + -(0) + x(1) = 5 Result: 755

That's why you see commands like chmod 755 — it's a compact way to represent rwxr-xr-x.

Calculate permissions visually

Click checkboxes to set permissions and see the numeric value update in real time.

Open Chmod Calculator →

Using chmod

Numeric mode (most common)

# Set to 755 (rwxr-xr-x) chmod 755 deploy.sh # Set to 644 (rw-r--r--) chmod 644 config.json # Set to 600 (rw-------) chmod 600 secrets.env

Symbolic mode

Symbolic mode uses letters to add (+), remove (-), or set (=) permissions:

# Add execute for owner chmod u+x deploy.sh # Remove write for group and other chmod go-w config.json # Set exact permissions for owner, group read chmod u=rwx,g=rx,o=rx deploy.sh # Add execute for everyone chmod a+x script.sh # Remove all permissions for other chmod o= secrets.env

The letters mean: u = user/owner, g = group, o = other, a = all.

Recursive permissions

# Set permissions recursively on all files and subdirectories chmod -R 755 /var/www/html/ # Better approach: different permissions for files vs directories find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \;
Warning: Be very careful with recursive chmod. Running chmod -R 777 / on a production server will create serious security vulnerabilities and can break system services.

Using chown and chgrp

Permissions define what can be done. Ownership defines who the permissions apply to.

# Change owner chown www-data index.html # Change owner and group chown www-data:www-data index.html # Change only group chgrp www-data index.html # Recursive ownership change chown -R www-data:www-data /var/www/html/

How directories differ

Permission meanings change for directories:

PermissionOn filesOn directories
r (read)View file contentsList directory contents (ls)
w (write)Modify file contentsCreate, delete, rename files inside
x (execute)Run as a programEnter directory (cd into it)

Key insight: to cd into a directory, you need execute permission. To list its contents, you need read. To create files in it, you need write.

This is why directories almost always have execute permission — without it, nobody can enter them.

Common permission patterns

PermissionUse case
755Directories and scripts — owner has full access, everyone can read and execute. Standard for web directories and executable scripts.
644Regular files — owner can read/write, everyone else can read. Default for HTML, CSS, config files.
600Sensitive files — only owner can read/write. Use for SSH keys, .env files, database credentials.
700Private directories — only owner has any access. Good for home directories and private scripts.
750Group-shared directories — owner has full access, group members can read and enter.
640Group-readable files — owner reads/writes, group can read. Good for log files a monitoring group needs to access.
444Read-only for everyone — nobody can modify. Useful for critical system files you want to protect.
400SSH private keys — SSH requires this permission on private key files. chmod 400 ~/.ssh/id_rsa

Special permissions

Beyond the basic read/write/execute, Linux has three special permission bits:

Setuid (4xxx)

When set on an executable, it runs with the file owner's permissions, not the executing user's. The classic example is passwd — it needs to modify /etc/shadow which only root can write to.

# Set setuid chmod 4755 program chmod u+s program # You'll see an 's' in the owner execute position: -rwsr-xr-x

Setgid (2xxx)

On executables, it runs with the file group's permissions. On directories, new files created inside inherit the directory's group instead of the creator's primary group. This is incredibly useful for shared project directories.

# Set setgid on a shared directory chmod 2775 /shared/project/ # New files created here inherit the group # Instead of each user's personal group

Sticky bit (1xxx)

On directories, only the file owner (or root) can delete or rename files, even if others have write permission on the directory. The classic example is /tmp:

# /tmp has the sticky bit set: drwxrwxrwt — notice the 't' at the end # Set sticky bit chmod 1777 /tmp chmod +t /tmp

Without the sticky bit, anyone who can write to /tmp could delete other users' files. The sticky bit prevents that.

Troubleshooting "Permission denied"

When you hit "Permission denied", work through this checklist:

1. Check the file permissions

ls -la /path/to/file

Look at which role you fall into (owner, group, or other) and whether you have the needed permission.

2. Check the directory chain

You need execute permission on every directory in the path. Even if you have read permission on a file, you can't access it if you don't have execute permission on its parent directory.

# Check the full path namei -l /var/www/html/index.html

3. Check who owns it

ls -la /path/to/file # Check: am I the owner? Am I in the group? id groups

4. Check for ACLs

Access Control Lists can override standard permissions:

getfacl /path/to/file

5. Common web server fix

The most common "Permission denied" in web development is the web server (nginx/Apache) running as www-data not being able to read your files:

# Fix ownership chown -R www-data:www-data /var/www/html/ # Fix permissions find /var/www/html -type d -exec chmod 755 {} \; find /var/www/html -type f -exec chmod 644 {} \;

Never miscalculate permissions again

Visual checkboxes, instant numeric conversion, and the chmod command ready to copy.

Open Chmod Calculator →