Linux File Permissions: The Complete Guide
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 → filenameRead, 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
| Permission | Symbol | Octal | Effect on Files |
|---|---|---|---|
| Read | r | 4 | View file contents (cat, less, head) |
| Write | w | 2 | Modify file contents (edit, truncate, append) |
| Execute | x | 1 | Run as a program or script |
Permissions on Directories
| Permission | Symbol | Octal | Effect on Directories |
|---|---|---|---|
| Read | r | 4 | List directory contents (ls) |
| Write | w | 2 | Create, rename, or delete files inside |
| Execute | x | 1 | Enter 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.
| Octal | Binary | Symbolic | Meaning |
|---|---|---|---|
| 0 | 000 | --- | No permissions |
| 1 | 001 | --x | Execute only |
| 2 | 010 | -w- | Write only |
| 3 | 011 | -wx | Write + execute |
| 4 | 100 | r-- | Read only |
| 5 | 101 | r-x | Read + execute |
| 6 | 110 | rw- | Read + write |
| 7 | 111 | rwx | Read + 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: 754Skip 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/*.cssSymbolic 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.shSymbolic 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 Permission | Octal | On Files | On Directories |
|---|---|---|---|
| Setuid | 4000 | Runs as file owner | No effect |
| Setgid | 2000 | Runs as file group | New files inherit group |
| Sticky bit | 1000 | No modern effect | Only 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" >> ~/.bashrcAccess 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 existCommon 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/*.phpSSH 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 onlyApplication 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 configsSecurity Rules to Follow
- Never use 777 -- If you think you need 777, you have a different problem. Fix ownership or group membership instead.
- Never use 666 on executables -- World-writable executables can be replaced with malicious code by any user.
- Principle of least privilege -- Grant the minimum permissions needed. Start restrictive and add permissions as needed.
- Check for world-writable files regularly -- Run
find / -perm -o+w -type fto find world-writable files. - Audit setuid binaries -- Run
find / -perm -4000 -type fto find all setuid programs. Each one is a potential privilege escalation vector. - 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 CalculatorRelated Articles
Cron Jobs Tutorial
Schedule automated tasks in Linux with crontab syntax explained.
Regex Cheat Sheet
Regular expressions for file matching, log parsing, and text processing.
HTTP Status Codes Guide
Understand 403 Forbidden errors caused by incorrect file permissions.
Base64 Encoding Explained
How binary encoding works for SSH keys and certificate files.