BytePane

Linux File Permissions: The Complete Guide

Linux15 min read

Understanding the Linux Permission Model

Every file and directory in Linux has a set of permissions that controls who can read, write, and execute it. This permission model is the foundation of Linux security. Understanding it is essential for every developer, system administrator, and DevOps engineer who works with Linux servers, containers, or deployments.

Linux permissions operate on three levels: the file owner (user), the group assigned to the file, and everyone else (other). Each level can independently be granted read, write, and execute permissions. This creates a simple but powerful access control system that protects sensitive files while allowing collaboration.

To quickly calculate permission values without memorizing the octal system, use our Chmod Calculator. It converts between symbolic and octal notation and shows exactly what each permission means.

# View file permissions with ls -l
$ ls -l myfile.txt
-rw-r--r-- 1 alice developers 4096 Mar 06 10:30 myfile.txt

# Breaking down the output:
# -rw-r--r--  →  file type + permissions
# 1           →  number of hard links
# alice       →  owner (user)
# developers  →  group
# 4096        →  file size in bytes
# Mar 06 10:30 → last modified
# myfile.txt  →  filename

Read, Write, and Execute Explained

The three basic permissions -- read (r), write (w), and execute (x) -- have different meanings depending on whether they are applied to files or directories. Understanding this distinction prevents common permission mistakes.

Permissions on Files

PermissionSymbolOctalEffect on Files
Readr4View file contents (cat, less, head)
Writew2Modify file contents (edit, truncate, append)
Executex1Run as a program or script

Permissions on Directories

PermissionSymbolOctalEffect on Directories
Readr4List directory contents (ls)
Writew2Create, rename, or delete files inside
Executex1Enter directory (cd) and access files within

A common mistake is giving a directory read permission without execute. A user with only r on a directory can list file names but cannot access the files themselves or see their metadata. You need x to actually enter the directory and interact with its contents.

# The permission string has 10 characters:
# -rwxrw-r--
# │└┬┘└┬┘└┬┘
# │ │  │  └── Other permissions (r--)  = read only
# │ │  └───── Group permissions (rw-)  = read + write
# │ └──────── Owner permissions (rwx)  = read + write + execute
# └────────── File type (- = file, d = directory, l = symlink)

# Examples:
# drwxr-xr-x  → directory, owner=rwx, group=r-x, other=r-x
# -rwx------  → file, only owner can read/write/execute
# -rw-rw-r--  → file, owner and group can read/write, others read only
# lrwxrwxrwx  → symbolic link (permissions on link itself are meaningless)

Octal (Numeric) Notation

Octal notation represents permissions as a three or four digit number. Each digit is the sum of its component permissions: read (4) + write (2) + execute (1). This is the most common way to set permissions with the chmod command.

OctalBinarySymbolicMeaning
0000---No permissions
1001--xExecute only
2010-w-Write only
3011-wxWrite + execute
4100r--Read only
5101r-xRead + execute
6110rw-Read + write
7111rwxRead + write + execute
# Common octal permission values:
# 755 = rwxr-xr-x  → Standard for directories and executables
# 644 = rw-r--r--  → Standard for regular files
# 600 = rw-------  → Private files (SSH keys, configs with secrets)
# 700 = rwx------  → Private directories or scripts
# 775 = rwxrwxr-x  → Shared directories (group can write)
# 664 = rw-rw-r--  → Shared files (group can write)
# 777 = rwxrwxrwx  → NEVER use this — everyone has full access
# 000 = ---------  → No access for anyone (except root)

# How to calculate: add up the values for each position
# Owner: r(4) + w(2) + x(1) = 7
# Group: r(4) + -(0) + x(1) = 5
# Other: r(4) + -(0) + -(0) = 4
# Result: 754

Skip the mental math -- use our Chmod Calculator to convert between octal and symbolic notation instantly. Toggle checkboxes for each permission and get the exact chmod command.

The chmod Command: Changing Permissions

The chmod (change mode) command modifies file and directory permissions. You can use either octal notation or symbolic notation to specify the desired permissions.

Octal Mode

# Set exact permissions using octal
chmod 755 script.sh       # rwxr-xr-x (executable script)
chmod 644 config.json     # rw-r--r-- (readable config)
chmod 600 id_rsa          # rw------- (private SSH key)
chmod 700 ~/.ssh          # rwx------ (private directory)

# Apply recursively to directory and all contents
chmod -R 755 /var/www/html/
chmod -R 644 /var/www/html/*.css

Symbolic Mode

Symbolic mode uses letters and operators to add, remove, or set specific permissions without affecting others. This is more flexible than octal mode when you need to change just one permission.

# Symbolic mode syntax: chmod [who][operator][permission] file
# Who:      u = owner, g = group, o = other, a = all
# Operator: + = add, - = remove, = = set exactly
# Permission: r = read, w = write, x = execute

# Add execute permission for the owner
chmod u+x script.sh

# Remove write permission from group and other
chmod go-w sensitive.conf

# Set group permissions to read-only
chmod g=r document.txt

# Add execute to all (owner, group, other)
chmod a+x deploy.sh

# Multiple operations in one command
chmod u+rwx,g+rx,o-rwx private-script.sh

# Make a file executable (common shortcut)
chmod +x run.sh

Symbolic vs Octal: When to Use Each

Use octal when you want to set all permissions at once (e.g., chmod 644 file). Use symbolic when you want to modify a specific permission without changing the others (e.g., chmod g+w file). In scripts and documentation, octal is more common because it is unambiguous.

chown and chgrp: Changing Ownership

Permissions only matter when combined with ownership. The chown command changes the owner and/or group of a file, while chgrp changes only the group. Only root (or sudo) can change file ownership.

# Change owner
sudo chown alice myfile.txt          # Owner → alice
sudo chown alice:developers myfile.txt  # Owner → alice, Group → developers

# Change group only
sudo chgrp developers myfile.txt     # Group → developers
sudo chown :developers myfile.txt    # Same as above (shorthand)

# Change ownership recursively
sudo chown -R www-data:www-data /var/www/html/

# Common use cases:
# Web server files
sudo chown -R www-data:www-data /var/www/
sudo chmod -R 755 /var/www/

# Application deployment
sudo chown -R deploy:deploy /opt/myapp/

# Fix home directory after user creation
sudo chown -R newuser:newuser /home/newuser/

Special Permissions: Setuid, Setgid, and Sticky Bit

Beyond the standard read, write, and execute permissions, Linux has three special permission bits that modify how files and directories behave when accessed. These are represented by a fourth octal digit prepended to the standard three.

Setuid (Set User ID) -- 4000

When setuid is set on an executable, it runs with the permissions of the file owner (not the user who launched it). This is how commands like passwd can modify /etc/shadow even when run by a normal user -- the passwd binary is owned by root with setuid set.

# View setuid files (shown as 's' in owner execute position)
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Mar 06 /usr/bin/passwd
#   ^-- 's' instead of 'x' means setuid is set

# Set setuid
chmod 4755 myprogram    # setuid + rwxr-xr-x
chmod u+s myprogram     # Symbolic notation

# SECURITY WARNING: setuid is dangerous!
# A setuid root program with a vulnerability gives attackers root access.
# Only use setuid when absolutely necessary and audit the code carefully.

Setgid (Set Group ID) -- 2000

On files, setgid works like setuid but for the group -- the program runs with the group permissions of the file. On directories, setgid is much more useful: all new files created inside the directory inherit the directory's group instead of the creator's primary group. This is essential for shared project directories.

# Set setgid on a shared directory
chmod 2775 /shared/project/
chmod g+s /shared/project/

# Now all files created in /shared/project/ inherit the group
$ ls -ld /shared/project/
drwxrwsr-x 2 root developers 4096 Mar 06 /shared/project/
#      ^-- 's' in group execute position means setgid

# Without setgid: new files get creator's primary group
# With setgid:    new files get directory's group (developers)

Sticky Bit -- 1000

The sticky bit on a directory prevents users from deleting or renaming files they do not own, even if they have write permission on the directory. The most well-known example is /tmp, where everyone can create files but only the owner (or root) can delete them.

# View the sticky bit on /tmp
$ ls -ld /tmp
drwxrwxrwt 15 root root 4096 Mar 06 /tmp
#         ^-- 't' in other execute position means sticky bit

# Set sticky bit
chmod 1777 /shared/uploads/
chmod +t /shared/uploads/

# Without sticky bit: any user with write permission can delete any file
# With sticky bit:    users can only delete their own files
Special PermissionOctalOn FilesOn Directories
Setuid4000Runs as file ownerNo effect
Setgid2000Runs as file groupNew files inherit group
Sticky bit1000No modern effectOnly owner can delete

The umask: Default Permission Control

The umask (user file-creation mode mask) determines the default permissions for newly created files and directories. It works by subtracting permissions from the system defaults: 666 for files and 777 for directories.

# View current umask
$ umask
0022

# How umask works:
# Default file permissions:   666 (rw-rw-rw-)
# umask:                     -022
# Result:                     644 (rw-r--r--)

# Default directory permissions: 777 (rwxrwxrwx)
# umask:                        -022
# Result:                        755 (rwxr-xr-x)

# Common umask values:
# 022 → files=644, dirs=755 (standard, group/other can read)
# 027 → files=640, dirs=750 (group can read, others blocked)
# 077 → files=600, dirs=700 (private, only owner has access)
# 002 → files=664, dirs=775 (shared, group can write)

# Set umask (for current session)
umask 027

# Set umask permanently (add to ~/.bashrc or ~/.profile)
echo "umask 027" >> ~/.bashrc

Access Control Lists (ACLs)

Standard Linux permissions only support one owner and one group per file. Access Control Lists (ACLs) extend this model by allowing you to grant specific permissions to any number of individual users or groups. ACLs are essential when the simple owner/group/other model is too restrictive.

# Check if ACLs are supported (look for acl in mount options)
$ mount | grep acl

# View ACLs on a file
$ getfacl myfile.txt
# file: myfile.txt
# owner: alice
# group: developers
user::rw-
user:bob:r--          # Bob has read access (ACL entry)
group::r--
group:designers:rw-   # designers group has read/write (ACL entry)
mask::rw-
other::---

# Set ACL: give user bob read+write access
setfacl -m u:bob:rw myfile.txt

# Set ACL: give group designers read access
setfacl -m g:designers:r myfile.txt

# Set ACL: remove bob's ACL entry
setfacl -x u:bob myfile.txt

# Set default ACLs on a directory (inherited by new files)
setfacl -d -m g:developers:rwx /shared/project/

# Remove all ACLs
setfacl -b myfile.txt

# A '+' in ls -l indicates ACLs are present
$ ls -l myfile.txt
-rw-rw----+ 1 alice developers 4096 Mar 06 myfile.txt
#          ^-- '+' means ACLs exist

Common Permission Schemes and Security Tips

Here are the most common permission configurations used in production Linux systems, along with security best practices that prevent common vulnerabilities.

Web Server Files

# Nginx/Apache document root
sudo chown -R www-data:www-data /var/www/html/
sudo find /var/www/html/ -type d -exec chmod 755 {} \;  # Directories
sudo find /var/www/html/ -type f -exec chmod 644 {} \;  # Files

# Upload directories (web server needs write access)
sudo chmod 775 /var/www/html/uploads/

# PHP/CGI scripts
sudo chmod 750 /var/www/html/cgi-bin/*.php

SSH Keys

# SSH is strict about permissions — wrong permissions = connection refused
chmod 700 ~/.ssh/              # Directory: owner only
chmod 600 ~/.ssh/id_rsa        # Private key: owner read/write only
chmod 644 ~/.ssh/id_rsa.pub    # Public key: anyone can read
chmod 600 ~/.ssh/authorized_keys  # Authorized keys: owner only
chmod 600 ~/.ssh/config        # SSH config: owner only

Application Deployment

# Application directory
sudo chown -R deploy:deploy /opt/myapp/
sudo chmod 750 /opt/myapp/
sudo chmod 640 /opt/myapp/.env           # Environment secrets
sudo chmod 750 /opt/myapp/bin/*          # Executables

# Log directory (app needs write, monitoring needs read)
sudo chown deploy:monitoring /var/log/myapp/
sudo chmod 2750 /var/log/myapp/          # setgid for group inheritance

# Cron jobs
chmod 600 /etc/cron.d/myapp-cron         # Only root should read cron configs

Security Rules to Follow

  1. Never use 777 -- If you think you need 777, you have a different problem. Fix ownership or group membership instead.
  2. Never use 666 on executables -- World-writable executables can be replaced with malicious code by any user.
  3. Principle of least privilege -- Grant the minimum permissions needed. Start restrictive and add permissions as needed.
  4. Check for world-writable files regularly -- Run find / -perm -o+w -type f to find world-writable files.
  5. Audit setuid binaries -- Run find / -perm -4000 -type f to find all setuid programs. Each one is a potential privilege escalation vector.
  6. Protect sensitive config files -- Database passwords, API keys, and .env files should be 600 or 640 at most.

Automate your scheduled permission audits and maintenance tasks with our Crontab Generator. Create cron jobs for regular security scans with the correct syntax on the first try.

Frequently Asked Questions

Why can root access files with 000 permissions?

Root (UID 0) bypasses all standard permission checks. The root user can read, write, and execute any file regardless of its permissions. This is by design -- root is the system administrator and needs unrestricted access for maintenance. The only exception is that root cannot execute a file without at least one execute bit set (the kernel enforces this).

What is the difference between chmod 755 and chmod 775?

With 755 (rwxr-xr-x), the group can read and execute but cannot write. With 775 (rwxrwxr-x), the group can also write. Use 755 for files that only the owner should modify. Use 775 for shared directories where multiple users in the same group need to create and edit files.

Why does SSH refuse to connect when my key permissions are wrong?

SSH intentionally refuses to use private keys that are readable by other users. If your ~/.ssh/id_rsa has permissions other than 600, SSH will display "WARNING: UNPROTECTED PRIVATE KEY FILE!" and ignore the key. Fix it with chmod 600 ~/.ssh/id_rsa. The same applies to the ~/.ssh directory (must be 700) and authorized_keys (must be 600).

How do I recursively set different permissions for files and directories?

Use the find command with -type to target files and directories separately. For example: find /path -type d -exec chmod 755 {} \; for directories and find /path -type f -exec chmod 644 {} \; for files. Never use chmod -R 755 on everything, because files do not need execute permission.

Can I make a file immutable so even root cannot modify it?

Yes, using file attributes with chattr. Running sudo chattr +i myfile sets the immutable attribute, preventing any modification, deletion, or renaming -- even by root. To undo it, run sudo chattr -i myfile. This is useful for protecting critical configuration files from accidental changes. View attributes with lsattr myfile.

Calculate File Permissions Instantly

Stop memorizing octal numbers. Our chmod calculator lets you toggle permissions visually and gives you the exact command to run. Supports standard permissions, setuid, setgid, sticky bit, and symbolic notation. Everything runs in your browser.

Open Chmod Calculator

Related Articles