Understanding Unix File Permissions: A Practical Guide

DevToolkit Team · · 15 min read

File permissions are one of the first things that trip up developers on Linux and macOS. You get a "Permission denied" error, frantically Google "chmod 777", fix it, and move on — without really understanding what happened.

This guide gives you a practical understanding of Unix permissions that will save you from both "Permission denied" errors and accidental security holes. Whether you are deploying web applications, managing SSH keys, or scripting server automation, having chmod permissions explained clearly will make you a more effective developer.

The Owner / Group / Other Permission Model

Every file and directory on a Unix system has three sets of permissions for three classes of users:

Each class can have three permissions:

This three-by-three model creates a total of nine permission bits. Understanding how these bits interact is the key to managing file security on any Unix-like operating system.

How Ownership Is Determined

When you create a file, the operating system automatically sets you as the owner. The file's group is typically set to your primary group (which you can check with the id command). You can change ownership with chown and group with chgrp:

chown alice file.txt          # Change owner to alice
chgrp developers file.txt     # Change group to developers
chown alice:developers file.txt  # Change both at once

Only the root user (or a user with sudo) can change file ownership. Regular users can only change the group to another group they belong to.

Reading Permission Output

When you run ls -la, you see permissions like -rwxr-xr-x. Here's how to read it:

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

Each position is either the permission letter or a dash. Dashes mean "not granted." The file type character at the beginning is not a permission — it tells you what kind of filesystem entry you are looking at:

Octal vs Symbolic Notation: A Complete Comparison

There are two ways to express Unix file permissions: octal (numeric) and symbolic. Both are used with the chmod command, and each has advantages depending on the situation.

Octal (Numeric) Notation

The octal system represents each permission set as a single digit from 0 to 7. Each permission has a numeric value:

So -rwxr-xr-x = 755. Three digits: owner, group, others. Here is the full reference table for a single digit:

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

Symbolic Notation

Symbolic notation uses letters and operators to modify permissions. It is more flexible when you want to change specific bits without affecting others:

chmod u+x script.sh          # Add execute for owner
chmod go-w config.json       # Remove write from group and others
chmod a+r README.md          # Add read for all users
chmod u=rwx,g=rx,o=r file   # Set exact permissions

The operators are:

The user classes are:

When to Use Which?

Use octal notation when you want to set all permissions at once and know exactly what the result should be. It is concise and unambiguous — chmod 644 file always produces the same result regardless of the file's current permissions.

Use symbolic notation when you want to modify one specific permission without touching the rest. For example, chmod +x script.sh adds execute without changing any read or write bits.

Use our Chmod Calculator to convert between octal, symbolic, and see the chmod command ready to copy. If you are working with number conversions in other contexts, our Number Base Converter can help with octal-to-binary and other base conversions.

Common Permission Patterns

Here is a comprehensive reference table of the most common chmod permission patterns, what they mean, and when to use them:

OctalSymbolicUse CaseExample
777rwxrwxrwxFull access for everyone (avoid in production)Temporary debug only
755rwxr-xr-xExecutables, directories, public scriptsWeb root, shell scripts
750rwxr-x---Group-accessible executables and directoriesShared project directories
700rwx------Private directories~/.ssh, ~/private
666rw-rw-rw-Read/write for everyone (rare, usually a mistake)Shared temp files
664rw-rw-r--Owner+group can edit, others read-onlyShared project files
644rw-r--r--Regular files (default)HTML, CSS, config files
640rw-r-----Owner edits, group reads, no public accessApplication config files
600rw-------Private files (owner only).env, credentials, database config
400r--------Read-only private filesSSH private keys, TLS certificates
444r--r--r--Read-only for everyonePublished reference files

755 — Standard for Executables and Directories

chmod 755 script.sh
chmod 755 /var/www/html

Owner can read, write, and execute. Everyone else can read and execute but not modify. This is the default for directories and executable scripts.

644 — Standard for Regular Files

chmod 644 index.html
chmod 644 config.json

Owner can read and write. Everyone else can only read. This is the default for most files.

600 — Private Files

chmod 600 .env
chmod 600 credentials.json

Only the owner can read and write. No access for anyone else. Use this for sensitive files like environment variables, database credentials, and private keys. If you are generating credentials, our Password Generator can create strong, random passwords.

400 — Read-Only Private Files

chmod 400 ~/.ssh/id_rsa

Owner can only read. SSH actually requires this — it refuses to use private keys with more permissive settings. If you get "Permissions 0644 for '~/.ssh/id_rsa' are too open", this is the fix.

700 — Private Directories

chmod 700 ~/.ssh
chmod 700 ~/private

Only the owner can access the directory at all. Others can't even list its contents.

750 — Group-Shared Directories

chmod 750 /var/www/project
chgrp developers /var/www/project

Owner has full access, group members can read and enter the directory, and others have no access at all. This is ideal for team projects on shared servers.

The chmod Command in Depth

Octal Mode

chmod 755 file.sh      # Set exact permissions
chmod -R 644 ./docs    # Recursive (all files in docs/)

Symbolic Mode

Symbolic mode lets you add or remove specific permissions without changing others:

chmod +x script.sh       # Add execute for everyone
chmod u+w file.txt       # Add write for owner
chmod go-w file.txt      # Remove write for group and others
chmod a+r file.txt       # Add read for all (a = all)
chmod u=rwx,go=rx dir    # Set exact: owner=rwx, group+others=rx

Useful chmod Flags

chmod --reference=known-good.conf new.conf   # Match permissions from another file
chmod -Rv 755 /var/www/html/                 # Recursive with verbose output

Directory vs File Permissions

The same permission bits mean different things for files and directories:

A common gotcha: a directory needs execute permission for users to access files inside it, even if those files have read permission. Without x on the directory, users can't reach the files. This is why directories almost always have execute permission (755 or 700) while regular files do not (644 or 600).

Another subtlety: having write permission on a directory means you can delete any file in that directory, even files you do not own and cannot read. This is why the sticky bit (covered below) exists.

Special Permissions: Setuid, Setgid, and Sticky Bit

Beyond the basic nine rwx bits, Unix has three special permission bits that control advanced behavior. These are represented by an optional fourth digit prepended to the octal notation.

Setuid (4000) — Run as File Owner

When the setuid bit is set on an executable file, the program runs with the permissions of the file's owner, not the user executing it. This is how the passwd command works — it is owned by root and has setuid set, which allows regular users to modify the /etc/shadow file that only root can write to.

chmod 4755 /usr/bin/passwd
# ls -la shows: -rwsr-xr-x

Notice the s in the owner's execute position. A lowercase s means both setuid and execute are set. An uppercase S means setuid is set but execute is not (which is usually a misconfiguration).

Security warning: Setuid programs are a common attack vector. Never set setuid on scripts, and audit any setuid binaries on your system regularly.

Setgid (2000) — Run as File Group or Inherit Group

On executable files, setgid works like setuid but for the group — the program runs with the file's group permissions. On directories, setgid has a different and very useful behavior: new files and subdirectories created inside inherit the directory's group instead of the creating user's primary group.

# Set setgid on a shared directory
chmod 2775 /var/www/shared
chgrp webdevs /var/www/shared

# Now any file created inside /var/www/shared
# automatically belongs to the "webdevs" group

This is invaluable for team collaboration. Without setgid, files created by different users would belong to each user's primary group, making shared access unpredictable.

# ls -la shows: drwxrwsr-x
# Note the 's' in the group execute position

Sticky Bit (1000) — Restrict Deletion

The sticky bit on a directory prevents users from deleting files they do not own. Without it, anyone with write permission on the directory can delete any file inside it. The classic example is /tmp:

chmod 1777 /tmp
# ls -la shows: drwxrwxrwt
# Note the 't' in the others execute position

The t at the end indicates the sticky bit. With this set, anyone can create files in /tmp, but only the file's owner (or root) can delete them. This prevents users from deleting each other's temporary files.

Combining Special Permissions

Special permissions are added as a leading digit in octal notation:

chmod 4755 file    # setuid + rwxr-xr-x
chmod 2755 dir     # setgid + rwxr-xr-x
chmod 1777 dir     # sticky + rwxrwxrwx
chmod 6755 file    # setuid + setgid + rwxr-xr-x

Use our Chmod Calculator to experiment with these special permission bits visually.

Step-by-Step Tutorial: Using the DevToolkit Chmod Calculator

If calculating octal values in your head feels error-prone, the DevToolkit Chmod Calculator makes it visual and instant. Here is how to use it:

  1. Open the tool — Navigate to DevToolkit Chmod Calculator in your browser.
  2. Toggle permission checkboxes — Click the read, write, and execute checkboxes for Owner, Group, and Others. Each click immediately updates the octal value and the symbolic representation.
  3. Or type an octal number — If you already have a permission number like 644, type it in the octal input field. The checkboxes and symbolic notation update automatically.
  4. Review the generated command — The tool generates the full chmod command (e.g., chmod 755 filename) ready to copy.
  5. Copy to clipboard — Click the copy button and paste the command directly into your terminal.

This is especially useful when you are configuring server deployments, writing CI/CD scripts, or setting up cron jobs that need specific file permissions. If you are building deployment scripts, you might also find our Regex Tester helpful for parsing log files and our JSON Formatter useful for reading configuration files.

Security Best Practices: The Principle of Least Privilege

The golden rule of file permissions is the principle of least privilege: grant only the minimum permissions needed for a file or directory to function correctly. Here are concrete guidelines:

For Web Applications

For SSH

For Application Secrets

To generate secure credentials for these files, use our Password Generator. For encoding sensitive data in configuration, our Base64 Encoder and Hash Generator can be useful. If you are working with JWT tokens, the JWT Decoder helps verify token contents without exposing secrets.

Common Mistakes and Troubleshooting

Mistake 1: chmod 777 Everything

chmod 777 gives everyone full access. This is a security risk and usually means you don't understand what permission is actually needed. Instead:

Mistake 2: Recursive chmod on Mixed Content

Running chmod -R 755 . gives everything execute permission — including text files, images, and configs that should never be executable. Instead, set files and directories separately:

# Directories: 755 (need execute for cd)
find . -type d -exec chmod 755 {} \;

# Files: 644 (don't need execute)
find . -type f -exec chmod 644 {} \;

Mistake 3: Forgetting Group Permissions

On shared servers, group permissions matter. If multiple users need to edit files in a shared directory, set the group appropriately:

chgrp -R developers /var/www/project
chmod -R 775 /var/www/project

Mistake 4: Ignoring umask

The umask controls the default permissions for newly created files. A umask of 022 means new files get 644 and new directories get 755. A umask of 077 means new files get 600 and directories get 700. If your files always seem to have the wrong permissions, check your umask:

umask          # Show current umask
umask 022      # Set standard umask (files: 644, dirs: 755)
umask 077      # Set restrictive umask (files: 600, dirs: 700)

The umask is subtracted from the maximum permissions (666 for files, 777 for directories). So with a umask of 027, new files get 640 and new directories get 750.

Mistake 5: Not Using Groups Effectively

Instead of loosening permissions with chmod 777, add users to appropriate groups and use group permissions:

# Create a group for the project
sudo groupadd webdevs

# Add users to the group
sudo usermod -aG webdevs alice
sudo usermod -aG webdevs bob

# Set the directory group and permissions
chgrp -R webdevs /var/www/project
chmod -R 2775 /var/www/project  # setgid ensures new files inherit group

Troubleshooting "Permission Denied" Errors

When you encounter "Permission denied", follow this diagnostic checklist:

  1. Check the file permissions: ls -la /path/to/file
  2. Check who you are: whoami and id
  3. Check directory permissions: You need execute on every directory in the path. Run namei -l /path/to/file to see permissions on each component.
  4. Check for ACLs: getfacl /path/to/file — Access Control Lists can override basic permissions.
  5. Check SELinux/AppArmor: On systems with mandatory access control, regular permissions might not be enough. Check ls -Z for SELinux contexts.

umask: Controlling Default Permissions

While chmod changes existing permissions, umask controls what permissions new files and directories receive. Understanding umask prevents you from having to chmod every new file.

The umask value is a mask that is subtracted from the maximum permissions. Files have a maximum of 666 (no execute by default) and directories have a maximum of 777:

umaskNew FileNew DirectoryUse Case
022644755Standard (most systems)
027640750Group-friendly, no public
077600700Private (security-sensitive)
002664775Collaborative (group writable)

Set your umask in ~/.bashrc or ~/.profile for persistent configuration. For servers handling sensitive data, a umask of 077 is a good baseline.

Frequently Asked Questions

What does chmod 755 mean?

chmod 755 sets the file to be readable, writable, and executable by the owner, and readable and executable (but not writable) by the group and others. In symbolic notation, this is rwxr-xr-x. It is the standard permission for executable scripts and directories.

What is the difference between chmod 644 and 755?

The difference is the execute bit. 644 (rw-r--r--) does not grant execute permission to anyone — use this for regular files like HTML, CSS, images, and config files. 755 (rwxr-xr-x) grants execute permission — use this for scripts, binaries, and directories (which need execute for users to enter them).

Why is chmod 777 dangerous?

chmod 777 grants read, write, and execute permissions to every user on the system. This means any user or process can modify or delete the file. On a web server, this could allow an attacker to inject malicious code. Always use the minimum permissions required.

How do I make a file executable in Linux?

Use chmod +x filename to add execute permission for all users, or chmod u+x filename to add it only for the owner. For scripts, you also need a shebang line (e.g., #!/bin/bash) at the top of the file.

What permissions should .env files have?

Environment files containing secrets (API keys, database passwords, etc.) should have 600 permissions — only the owner can read and write. Never commit .env files to version control either; add them to your .gitignore.

How do I check current file permissions?

Use ls -la filename to see permissions in symbolic format, or stat filename for more detailed information including the octal representation. You can also use our Chmod Calculator to decode octal values into human-readable format.

What is the difference between chmod and chown?

chmod changes what actions (read, write, execute) are allowed. chown changes who owns the file. Often you need both — for example, setting the correct owner and the correct permissions for a web server to access files properly.

Can I undo a chmod command?

There is no built-in undo for chmod. If you accidentally change permissions and do not remember the original values, check your backup or use chmod --reference=similar_file broken_file to copy permissions from a known-good file. This is why it is always a good idea to check permissions with ls -la before changing them.

Related Tools and Resources

Working with Unix systems involves more than just file permissions. Here are other DevToolkit tools that complement your workflow:

Conclusion

File permissions are simple once you understand the model: three user classes, three permission types, three digits. With the addition of special permissions (setuid, setgid, sticky bit), umask defaults, and group management, you have a complete toolkit for securing files on any Unix-like system.

Remember the essentials: use 644 for regular files, 755 for directories and scripts, 600 for sensitive files, and never use 777 unless you genuinely want every user on the system to have full access. When in doubt, follow the principle of least privilege — start restrictive and loosen only as needed.

Need to calculate permissions quickly? Our Chmod Calculator lets you toggle permissions visually and copies the chmod command to your clipboard — no mental math required.

Enjoyed this article?

Get the free Developer Cheatsheet Pack + weekly tips on tools, workflows, and productivity.

Subscribe Free

Try These Tools

Related free tools mentioned in this article

Back to Blog