Unix File Permissions Explained: A Developer's Cheat Sheet

If you've ever deployed code to a Linux server, you've almost certainly run into file permissions. Maybe you've typed chmod 755 without fully understanding what those numbers mean, or been hit with a "Permission denied" error that stopped a deployment cold.

This guide breaks down Unix file permissions from first principles — so you'll understand exactly what's happening and never have to guess again.

The Three Permission Groups

Every file and directory in Unix has three permission groups:

You can see these when you run ls -l:

-rwxr-xr-- 1 paul staff 4096 Mar 4 10:30 deploy.sh

The first 10 characters tell the whole story. The first character is the file type (- for file, d for directory). The remaining 9 characters are three groups of three:

  rwx     r-x     r--
 owner   group   other

Read, Write, Execute

Each group has three possible permissions:

SymbolPermissionFor FilesFor Directories
rReadView contentsList files inside
wWriteModify contentsCreate/delete files inside
xExecuteRun as a programEnter the directory (cd)

Tip: Directories need the execute (x) permission for users to cd into them. A directory with r-- lets you list files but not access them.

Octal Notation

Instead of writing out rwxr-xr--, Unix lets you represent each group as a single digit. Each permission has a numeric value:

PermissionValue
Read (r)4
Write (w)2
Execute (x)1

Add them up for each group. For example, rwx = 4 + 2 + 1 = 7, and r-x = 4 + 0 + 1 = 5.

So rwxr-xr-- becomes 754:

rwx = 4+2+1 = 7  (owner: read, write, execute)
r-x = 4+0+1 = 5  (group: read, execute)
r-- = 4+0+0 = 4  (other: read only)

Symbolic Notation

The chmod command also accepts symbolic notation, which is more readable for targeted changes:

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

# Remove write for group and other
chmod go-w config.yml

# Set exact permissions for all
chmod a=rx public_page.html

# Combine multiple changes
chmod u+rwx,go+rx deploy.sh

The syntax is: who (u/g/o/a) + operator (+/-/=) + permission (r/w/x).

Common Permission Presets

These are the permissions you'll use 90% of the time:

OctalSymbolicUse Case
755rwxr-xr-xExecutable scripts, directories, web roots
644rw-r--r--Regular files, HTML, CSS, images
700rwx------Private scripts, home directories
600rw-------SSH keys, secrets, .env files
444r--r--r--Read-only config, immutable files
775rwxrwxr-xShared group directories
664rw-rw-r--Shared group files

Warning: Never use 777 in production. It gives everyone full access to read, write, and execute — a major security risk. If you find yourself reaching for 777, you probably need to fix ownership (chown) or group membership instead.

Quick Recipes

# Deploy a web app
chmod 755 /var/www/myapp
chmod 644 /var/www/myapp/*.html
chmod 755 /var/www/myapp/cgi-bin/*.sh

# Lock down SSH keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

# Shared project directory
chmod 775 /opt/project
chmod 664 /opt/project/*.config

Recursive Permissions

Use -R to apply permissions recursively. But be careful — files and directories often need different permissions:

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

Tip: Avoid chmod -R 755 on a directory tree. It makes every file executable, which is rarely what you want. Use the find pattern above instead.

Checking Permissions

Use ls -la to see permissions, ownership, and hidden files:

$ ls -la
drwxr-xr-x  5 paul staff  160 Mar 4 10:30 .
-rw-r--r--  1 paul staff  512 Mar 4 10:28 index.html
-rwx------  1 paul staff  128 Mar 4 10:25 deploy.sh
-rw-------  1 paul staff 1675 Mar 4 10:20 .env

Use stat for a more detailed view including the octal value:

$ stat -f '%A %N' *
644 index.html
700 deploy.sh
600 .env

Skip the Mental Maths

BoltKit's ChmodCalc tool lets you toggle permissions with a visual checkbox grid and instantly see the octal, symbolic, and command output. Free to use, right on your iPhone or iPad.

Get BoltKit Free