the IT Hustle
ToolsPricingBlogAbout
SysadminAI-Assisted2026-03-18•10 min read

Unix File Permissions Explained for Humans

By The IT Hustle Team

✨ AI-Assisted Content

This article was generated with AI assistance and reviewed by our team for accuracy and quality. All technical information and examples have been verified.

You set up a web server. Everything looks good. You navigate to your site and get a 403 Forbidden error. Or you write a script, try to run it, and get "Permission denied." Or you deploy an application and it can't read its own configuration file. Every time, the answer is the same: file permissions.

Unix file permissions are one of those concepts that seem simple on the surface but trip up even experienced developers. The good news is that once you genuinely understand the system — not just memorize chmod 755 — you'll never be confused by a permission error again.

Let's break this down from the ground up, assuming you're starting from zero.

The Three Categories: User, Group, Others

Every file and directory on a Unix system has an owner and a group. When the system checks whether you can access a file, it asks three questions in order:

  • User (u): Are you the file's owner? If yes, user permissions apply.
  • Group (g): Are you a member of the file's group? If yes (and you're not the owner), group permissions apply.
  • Others (o): If you're neither the owner nor in the group, "others" permissions apply.

This is the fundamental model. Every permission decision on a Unix system flows from this three-tier classification. The system doesn't combine them — it uses the first match. If you're the owner, only the user permissions matter, even if the group or others permissions are more permissive.

You can see the owner and group of any file with ls -l:

$ ls -l index.html
-rw-r--r-- 1 sarah webteam 4096 Mar 15 10:30 index.html
              ↑      ↑
            owner   group

The Three Permissions: Read, Write, Execute

Each of the three categories (user, group, others) can have three permissions:

  • Read (r): For files, you can view the contents. For directories, you can list the filenames inside.
  • Write (w): For files, you can modify the contents. For directories, you can create, delete, or rename files inside.
  • Execute (x): For files, you can run it as a program. For directories, you can cd into it and access files inside.

Why it matters:

The execute permission on directories is the one that surprises people most. A directory with read but no execute permission lets you see the filenames inside (via ls) but you can't access any of the files or their metadata. Conversely, execute without read lets you access files if you know their names, but you can't list the directory contents. This distinction is actually used for security in some configurations.

Reading Permission Strings

When you run ls -l, you see a 10-character permission string. Here's how to read it:

-rwxr-xr-- 1 sarah webteam 4096 Mar 15 10:30 deploy.sh

Position 1:   - = regular file (d = directory, l = symlink)
Positions 2-4: rwx = owner can read, write, and execute
Positions 5-7: r-x = group can read and execute (no write)
Positions 8-10: r-- = others can only read

Each dash represents an absent permission. So r-x means read and execute but not write. --- means no permissions at all.

Octal Notation: The Number System

Instead of typing rwxr-xr--, Unix uses a three-digit octal number to represent permissions. Each digit represents one category (user, group, others), and each permission has a numeric value:

  • Read = 4
  • Write = 2
  • Execute = 1

You add the values together to get the digit for each category. So:

rwx = 4 + 2 + 1 = 7
r-x = 4 + 0 + 1 = 5
r-- = 4 + 0 + 0 = 4
rw- = 4 + 2 + 0 = 6
--- = 0 + 0 + 0 = 0

So rwxr-xr-- = 754
And rwxr-xr-x = 755
And rw-r--r-- = 644

Once you internalize this mapping, you'll read permission numbers instantly. The key insight is that each digit is independent — the first digit is always the owner, the second is always the group, and the third is always others.

If math isn't your thing, use our Chmod Calculator to convert between symbolic and octal notation with a visual interface. Toggle permissions on and off and see the corresponding chmod command in real time.

Common Permission Patterns

You'll encounter these permission patterns constantly. Memorize what they mean and when to use them:

644 — Standard Files

rw-r--r-- (644)
Owner: read + write
Group: read only
Others: read only

This is the default for most regular files — HTML, CSS, images, configuration files. The owner can edit them, everyone else can read them. This is what your web server files should typically be.

755 — Executable Files and Directories

rwxr-xr-x (755)
Owner: read + write + execute
Group: read + execute
Others: read + execute

This is the standard for directories and executable scripts. The owner has full control, everyone else can read and execute (for files) or enter and list (for directories). Most web server directories should be 755.

700 — Private Files and Directories

rwx------ (700)
Owner: read + write + execute
Group: none
Others: none

Only the owner can access these. Use this for sensitive directories like ~/.ssh, private key storage, and personal scripts. If anyone else needs access, they shouldn't have it — use a different mechanism.

600 — Private Data Files

rw------- (600)
Owner: read + write
Group: none
Others: none

Like 700 but without execute. This is what SSH expects for private key files (~/.ssh/id_rsa). In fact, SSH will refuse to use a private key with more permissive settings — it's one of the few programs that actively checks permissions.

Other Common Patterns

666 (rw-rw-rw-) — Everyone can read/write (rarely appropriate)
777 (rwxrwxrwx) — Everyone can do everything (NEVER use this in production)
750 (rwxr-x---) — Owner full access, group can read/execute, others blocked
640 (rw-r-----) — Owner read/write, group read only, others blocked
444 (r--r--r--) — Read-only for everyone, including the owner

The chmod Command

chmod (change mode) is the command that sets file permissions. It accepts either octal notation or symbolic notation:

# Octal notation (set exact permissions)
chmod 755 script.sh
chmod 644 index.html
chmod 600 ~/.ssh/id_rsa

# Symbolic notation (add/remove specific permissions)
chmod u+x script.sh      # add execute for user (owner)
chmod g-w config.yml      # remove write for group
chmod o-rwx secret.key    # remove all permissions for others
chmod a+r readme.txt      # add read for all (user + group + others)
chmod u=rwx,g=rx,o=r file # set exact permissions symbolically

# Recursive (apply to directory and everything inside)
chmod -R 755 /var/www/html/

Symbolic notation is useful when you want to change one specific permission without knowing or affecting the others. Octal notation is useful when you want to set all permissions at once to a known state.

Why it matters:

Be extremely careful with chmod -R (recursive). Applying 755 recursively to a directory makes all files executable, which is usually wrong — regular files should typically be 644. A better approach is to set directories and files separately:

# Set directories to 755 and files to 644 (web server standard)
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

chown and chgrp: Changing Ownership

Sometimes the issue isn't the permission bits — it's who owns the file. chown changes the owner, and chgrp changes the group:

# Change owner
chown sarah file.txt

# Change owner and group
chown sarah:webteam file.txt

# Change group only
chgrp webteam file.txt

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

A classic mistake: deploying web files as root but running the web server as www-data. The files have correct permissions (644), but the web server user isn't the owner and isn't in the right group, so it falls into the "others" category. Fix it by changing ownership to the web server user, or add the web server user to the file's group.

Special Permissions: setuid, setgid, and Sticky Bit

Beyond the basic rwx permissions, Unix has three special permission bits that you'll encounter in specific scenarios:

setuid (Set User ID) — 4xxx

When set on an executable file, it runs with the permissions of the file's owner instead of the user who executed it. The classic example is /usr/bin/passwd — it needs to modify /etc/shadow (which only root can write), so it has the setuid bit set and is owned by root. Any user can run passwd, and it executes with root privileges.

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Mar 15 10:30 /usr/bin/passwd
   ↑ the 's' instead of 'x' indicates setuid

chmod 4755 myprogram # set the setuid bit

Security warning: setuid on a script or program you don't trust is an enormous security risk. It effectively gives anyone who runs that program the owner's privileges. Only system programs should have setuid, and you should audit any setuid binaries on your system regularly.

setgid (Set Group ID) — 2xxx

On files, setgid works like setuid but for the group — the program runs with the file's group permissions. More commonly, setgid is used on directories: when set on a directory, new files created inside automatically inherit the directory's group instead of the creating user's primary group.

# Create a shared project directory
mkdir /opt/project
chgrp developers /opt/project
chmod 2775 /opt/project

# Now any file created inside will belong to the 'developers' group
# regardless of who creates it

This is incredibly useful for shared directories where multiple users need to collaborate. Without setgid, files would be created with each user's primary group, and other team members might not have access.

Sticky Bit — 1xxx

The sticky bit on a directory prevents users from deleting or renaming files they don't own, even if they have write permission on the directory. The classic example is /tmp:

$ ls -ld /tmp
drwxrwxrwt 22 root root 4096 Mar 15 10:30 /tmp
         ↑ the 't' instead of 'x' indicates sticky bit

chmod 1777 /tmp # set sticky bit

Without the sticky bit, anyone with write permission on /tmp could delete anyone else's temporary files. The sticky bit ensures you can only delete your own files, even in a world-writable directory.

Real-World Scenarios

Web Server Files

The most common permission-related question: "What permissions should my web files have?"

# Web root directory
chown -R www-data:www-data /var/www/html

# Directories: 755 (owner rwx, group and others rx)
find /var/www/html -type d -exec chmod 755 {} \;

# Files: 644 (owner rw, group and others r)
find /var/www/html -type f -exec chmod 644 {} \;

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

SSH Keys

SSH is famously strict about permissions. If your key files are too permissive, SSH refuses to use them:

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: owner rw, others read
chmod 600 ~/.ssh/authorized_keys  # authorized keys: owner only
chmod 644 ~/.ssh/config      # SSH config: owner rw, others read

If you get the dreaded "Permissions 0644 for 'id_rsa' are too open" error, now you know why. SSH protects you from accidentally exposing your private key.

Shell Scripts

A script needs execute permission to be run directly. Without it, you get "Permission denied":

# Make a script executable
chmod +x deploy.sh

# Or with explicit permissions
chmod 755 deploy.sh    # everyone can run it
chmod 700 deploy.sh    # only owner can run it

Note: you can always bypass the execute permission by calling the interpreter directly: bash deploy.sh works even without execute permission, because bash itself has execute permission and it's just reading the script as a text file. The execute bit only matters when you run ./deploy.sh directly.

Common Permission Mistakes

These are the mistakes I see repeatedly, especially from developers who are more comfortable with application code than system administration:

  • chmod 777 everything: This is the "I don't understand permissions so I'll just open everything up" approach. It's a massive security hole. Anyone on the system can read, modify, and execute your files. Never do this in production.
  • Running everything as root: If you sudo everything, permissions never cause problems — but you also have no protection against mistakes or malicious code. Root can delete your entire system with a typo.
  • Forgetting directory execute: Setting a directory to 644 (rw-r--r--) means nobody can cd into it or access files inside, even though they can see the filenames with ls. Directories almost always need execute permission.
  • Recursive chmod on /: Running chmod -R 755 / will make your system unusable. It changes permissions on critical system files, including /etc/shadow (which needs to be 640 or 600) and setuid binaries (which lose their setuid bit).
  • Ignoring umask: The umask determines the default permissions for newly created files. If your umask is 022, new files get 644 and new directories get 755. If it's 077, new files get 600 and new directories get 700. Know your umask.
  • Wrong ownership after sudo: Creating files with sudo makes them owned by root. If your application runs as a different user, it can't read or write those files even with correct permission bits.

Understanding umask

The umask is a value that determines what permissions are removed from newly created files and directories. It's a mask, not a setting — it subtracts permissions from the maximum.

# Check your current umask
umask

# Common values:
# umask 022 → files: 644, directories: 755 (default on most systems)
# umask 027 → files: 640, directories: 750 (more restrictive)
# umask 077 → files: 600, directories: 700 (private)

# How it works:
# Maximum file permissions:      666 (no execute by default)
# Maximum directory permissions: 777
# Subtract umask:                -022
# Result for files:               644
# Result for directories:         755

Note that new files never get execute permission by default, regardless of umask. This is a security measure — you have to explicitly make files executable with chmod +x.

Security Implications

File permissions are a fundamental security boundary on Unix systems. Getting them wrong can expose sensitive data, allow unauthorized modifications, or enable privilege escalation:

  • Configuration files with database passwords should be 600 or 640, never world-readable
  • Log files should be 640 — readable by the application and its group, not by everyone
  • Upload directories should never have execute permission on uploaded files
  • Cron scripts should be owned by root and not writable by other users (otherwise anyone can escalate privileges)
  • Audit setuid and setgid binaries regularly: find / -perm -4000 -type f
  • World-writable directories without the sticky bit are a security risk

The principle of least privilege applies directly to file permissions: every file should have the minimum permissions needed for the system to function. Start restrictive and open up as needed, not the other way around.

Debugging Permission Issues

When you hit a permission error, here's a systematic debugging approach:

# 1. Check who you are
whoami
id      # shows your user ID, group ID, and all groups

# 2. Check the file's permissions and ownership
ls -la /path/to/file

# 3. Check every directory in the path (all need execute permission)
namei -l /path/to/file

# 4. Check if SELinux or AppArmor is blocking access
getenforce         # SELinux status
ls -Z /path/to/file  # SELinux context

# 5. Check ACLs (access control lists) if basic permissions look correct
getfacl /path/to/file

Step 3 is the one people forget most often. Even if the target file has correct permissions, you need execute permission on every directory in the path to reach it. A common scenario: /home/sarah/public_html/index.html is 644, but /home/sarah is 700, so the web server (running as www-data) can't traverse into the home directory.

Beyond Basic Permissions: ACLs

The traditional user/group/others model has a limitation: there's only one group. What if you need multiple groups with different levels of access? That's where Access Control Lists (ACLs) come in. ACLs let you set permissions for specific users and groups beyond the basic three categories:

# Grant a specific user read access
setfacl -m u:bob:r /opt/reports/quarterly.pdf

# Grant a specific group read/write access
setfacl -m g:editors:rw /opt/content/draft.txt

# View ACLs
getfacl /opt/reports/quarterly.pdf

ACLs are more flexible but also more complex. For most scenarios, getting the basic user/group/others permissions right is sufficient. Use ACLs when you genuinely need more granularity.

File permissions are not glamorous. They won't make it into your portfolio or your LinkedIn headline. But they are the difference between a secure system and an exposed one, between an application that works and one that fails with cryptic errors. Master them, and a whole category of frustrating bugs becomes trivial to diagnose and fix.

Need to calculate permissions quickly? The Chmod Calculator lets you toggle permission bits visually and see the corresponding octal value and chmod command. No more mental arithmetic.

Every 403 Forbidden error, every "Permission denied," every SSH key rejection — they all come back to these same fundamentals. Learn them once, solve permission problems forever. Calculate your permissions with the Chmod Calculator.

IT
The IT Hustle Team

We build free developer tools and write about AI, automation, and developer productivity. 30 tools, 33 articles, and an AI Prompt Engine — all built to help workers navigate the AI era. Published by Salty Rantz LLC.

Our ToolsAll ArticlesAbout Us

The IT Hustle Weekly

What changed in AI this week and what it means for your job. Free tools, honest reviews, zero spam.

Generate Your Own Anti-Hallucination Prompts

Our AI Prompt Engine uses patent-pending technology to generate prompts with built-in verification and contradiction testing.

Try 3 Free Generations →

Company

  • About
  • Blog
  • Contact

Product

  • Tools
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
  • Disclaimer

© 2026 Salty Rantz LLC. All rights reserved.

Made for workers navigating tech upheaval.