You try to edit a file, access a directory, or run a script, and Linux responds with "Permission denied." This is one of the most common errors new and experienced users encounter, but understanding Linux permissions makes it straightforward to resolve.

Understanding Linux Permissions

Linux uses a three-tier permission model: user (owner), group, and others. Each tier can have read (r), write (w), and execute (x) permissions.

Typical Error Messages

bash
bash: ./script.sh: Permission denied
mkdir: cannot create directory 'project': Permission denied
rm: cannot remove 'file.txt': Permission denied
cat: file.txt: Permission denied
sudo: /etc/sudoers is mode 0777, should be 0440

Diagnosing Permission Issues

Check Current Permissions

```bash # View permissions in long format ls -la /path/to/file

# View permissions recursively ls -laR /path/to/directory

# View numeric permissions stat /path/to/file

# View permissions with user/group names ls -ld /path/to/directory ```

Understanding ls -l output: `` -rwxr-xr-- 1 john developers 4096 Jan 15 10:30 script.sh │└┬┘└┬┘└┬┘ │ │ │ │ │ └─ filename │ │ │ │ │ │ │ │ └─ modification time │ │ │ │ │ │ │ └─ size │ │ │ │ │ │ └─ group │ │ │ │ │ └─ owner │ │ │ │ └─ number of hard links │ │ │ └─ others permissions (r--) │ │ └─ group permissions (r-x) │ └─ owner permissions (rwx) └─ file type (- = file, d = directory, l = symlink)

Check User Context

```bash # Current user whoami

# User's groups groups

# User's numeric ID id

# Check if user can access a file test -r /path/to/file && echo "Can read" || echo "Cannot read" test -w /path/to/file && echo "Can write" || echo "Cannot write" test -x /path/to/file && echo "Can execute" || echo "Cannot execute"

# Use namei to trace permission path namei -l /path/to/deeply/nested/file ```

Solutions

Fix File Permissions with chmod

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

# Add read/write for group chmod g+rw file.txt

# Remove write for others chmod o-w file.txt

# Set exact permissions (owner=rwx, group=rx, others=r) chmod 754 file.txt

# Common permission values: # 755 = rwxr-xr-x (executable, directories) # 644 = rw-r--r-- (regular files) # 600 = rw------- (sensitive files) # 700 = rwx------ (private directories) # 777 = rwxrwxrwx (avoid unless necessary)

# Recursive permission change chmod -R 755 /var/www/html

# Set permissions for directories only find /var/www -type d -exec chmod 755 {} \;

# Set permissions for files only find /var/www -type f -exec chmod 644 {} \; ```

Change File Ownership with chown

```bash # Change owner chown john file.txt

# Change owner and group chown john:developers file.txt

# Change group only chown :developers file.txt

# Recursive ownership change chown -R www-data:www-data /var/www/html

# Change ownership following symlinks chown -hR john:developers /var/www/html ```

Change Group with chgrp

```bash # Change group chgrp developers project/

# Recursive chgrp -R developers project/ ```

Fix Script Execution Permission

```bash # Make script executable chmod +x script.sh

# Run without execute permission (using interpreter) bash script.sh python script.py

# Check script interpreter head -1 script.sh ```

Handle Special Permissions

```bash # SUID - Run with owner's permissions (shows as 's' in owner execute position) chmod u+s /usr/bin/passwd

# SGID - Run with group's permissions, new files inherit group chmod g+s /var/www/html

# Sticky bit - Only owner can delete files (shows as 't' in others execute) chmod +t /tmp

# Numeric equivalents: # 4755 = SUID + 755 # 2755 = SGID + 755 # 1777 = Sticky bit + 777 (like /tmp) ```

Fix sudo Permission Issues

```bash # If sudoers file has wrong permissions, boot to recovery mode or: pkexec chmod 0440 /etc/sudoers

# Edit sudoers properly visudo

# Add user to sudo group usermod -aG sudo username # Debian/Ubuntu usermod -aG wheel username # RHEL/CentOS/Fedora

# Check sudoers configuration visudo -c ```

Fix Home Directory Permission Issues

```bash # Reset home directory to proper permissions chown -R username:username /home/username chmod 755 /home/username chmod 700 /home/username/.ssh chmod 600 /home/username/.ssh/authorized_keys

# Fix .ssh directory for SSH access chmod 700 ~/.ssh chmod 600 ~/.ssh/id_rsa chmod 644 ~/.ssh/id_rsa.pub chmod 600 ~/.ssh/authorized_keys chmod 644 ~/.ssh/known_hosts ```

Fix Web Server Permission Issues

```bash # For Apache/Nginx with PHP # Directories: 755, Files: 644, Owner: web user

# Set ownership chown -R www-data:www-data /var/www/html

# Set directory permissions find /var/www/html -type d -exec chmod 755 {} \;

# Set file permissions find /var/www/html -type f -exec chmod 644 {} \;

# Writable directories (uploads, cache) chmod 775 /var/www/html/wp-content/uploads chown -R www-data:www-data /var/www/html/wp-content/uploads

# For Laravel applications chown -R www-data:www-data /var/www/laravel/storage chown -R www-data:www-data /var/www/laravel/bootstrap/cache chmod -R 775 /var/www/laravel/storage chmod -R 775 /var/www/laravel/bootstrap/cache ```

Fix Shared Directory Permissions

```bash # Create shared group groupadd project-team

# Add users to group usermod -aG project-team alice usermod -aG project-team bob

# Set up shared directory mkdir /opt/project chown :project-team /opt/project chmod 775 /opt/project chmod g+s /opt/project # New files inherit group

# Set default ACL for finer control setfacl -R -m g:project-team:rwx /opt/project setfacl -R -d -m g:project-team:rwx /opt/project

# View ACLs getfacl /opt/project ```

Using ACLs for Fine-Grained Control

When standard permissions aren't enough:

```bash # Install ACL tools sudo apt-get install acl # Debian/Ubuntu sudo yum install acl # RHEL/CentOS

# Grant user specific access setfacl -m u:john:rw file.txt

# Remove user access setfacl -x u:john file.txt

# Set default ACL for new files setfacl -d -m u:john:rw directory/

# Copy ACLs getfacl file1.txt | setfacl --set-file=- file2.txt

# View ACLs getfacl file.txt ```

Verification

After making changes, verify permissions:

```bash # Verify file permissions ls -la /path/to/file

# Test access sudo -u username cat /path/to/file sudo -u username ls /path/to/directory

# Verify script is executable ./script.sh

# Verify SSH permissions ssh -v user@host

# Check for permission issues across path namei -l /var/www/html/index.html ```

Common Permission Scenarios

File/DirectoryOwnerGroupPermissionsNotes
/etc/passwdrootroot644Readable by all
/etc/shadowrootshadow640Password hashes, restricted
/tmprootroot1777Sticky bit prevents deletion by others
~/.sshuseruser700Private SSH directory
~/.ssh/authorized_keysuseruser600SSH public keys
Web document rootwww-datawww-data755/644Directories 755, files 644
Web uploadswww-datawww-data775Writable by web server

Quick Reference

```bash # Permission errors checklist ls -la filename # Check permissions ls -ld directory # Check directory permissions stat filename # Detailed permission info namei -l /full/path # Check full path permissions groups username # Check user groups id username # Check user/group IDs

# Fix common issues chmod 644 filename # Standard file chmod 755 directory # Standard directory chmod 600 filename # Private file chmod 700 directory # Private directory chmod +x script.sh # Make executable chown user:group file # Change ownership ```