Skip to main content
{/}codefunc
WorkflowJuly 8, 2026 · 5 min read

Unix File Permissions Explained: chmod, Octal, and the rwx Model

Understand Unix file permissions end to end — the user/group/other model, octal math, symbolic notation, common permission sets, and the security mistakes that cause 403s and leaked keys.

By codefunc

unixlinuxchmodpermissionssecurity

Permission denied. SSH key too open. A web server returning 403 on a file that clearly exists. Every one of these traces back to Unix file permissions — a model that looks cryptic (chmod 755, -rw-r--r--) but is completely mechanical once you see the structure. This guide breaks down the model, the octal math, and the permission sets you actually use.

Bottom line: Permissions are three groups (owner, group, others) of three bits (read, write, execute). Octal encodes each group as one digit where read = 4, write = 2, execute = 1. Learn to translate 644/755 on sight and you have covered 90% of daily use.

The permission model

Every file and directory has an owner (a user), an associated group, and everyone else ("others"). Each of those three classes gets three permissions:

Symbol On a file On a directory
r (read) read contents list entries
w (write) modify contents create/delete entries
x (execute) run as a program enter (cd) the directory

The key gotcha: on a directory, x means "can traverse into it". A directory with r but not x lets you see names but not access what is inside.

Reading ls -l

-rwxr-xr-x  1 deploy staff  2048 Jul  8 10:00 deploy.sh
│└┬┘└┬┘└┬┘
│ │  │  └── others: r-x
│ │  └───── group:  r-x
│ └──────── owner:  rwx
└────────── file type (- file, d directory, l symlink)

The first character is the file type, not a permission. The remaining nine characters are three rwx triplets for owner, group, and others.

Octal math

Each triplet is a 3-bit number. Assign values and add:

Permission Value
read (r) 4
write (w) 2
execute (x) 1

So one digit describes a whole triplet:

Octal Binary Symbolic Meaning
7 111 rwx read, write, execute
6 110 rw- read, write
5 101 r-x read, execute
4 100 r-- read only
0 000 --- none

Three digits describe the whole file. 755 = rwx (owner) r-x (group) r-x (others). 644 = rw- r-- r--. Converting between octal and symbolic is exactly base conversion — the same idea behind any number base converter.

The permission sets you actually use

Octal Symbolic Typical use
644 rw-r--r-- Regular files (web assets, configs read by others)
755 rwxr-xr-x Directories and executables/scripts
600 rw------- Private files — SSH keys, credentials
700 rwx------ Private directories (~/.ssh)
664 rw-rw-r-- Group-writable files (shared team dir)
775 rwxrwxr-x Group-writable directories
777 rwxrwxrwx Everything for everyone — almost always wrong

Memorize 644 for files and 755 for directories/scripts and most day-to-day work is covered.

Symbolic chmod: relative changes

Octal sets absolute permissions. Symbolic mode changes them relative to what exists, which is safer for targeted tweaks:

chmod u+x deploy.sh      # add execute for the owner
chmod go-w report.txt    # remove write for group and others
chmod a=r notes.md       # everyone gets read only (a = all)
chmod -R u+rwX assets/   # recurse; capital X adds x only to dirs/already-exec files

The capital X is underrated: it grants execute to directories and files that are already executable, without making every plain file runnable — ideal for recursive fixes.

Special bits (setuid, setgid, sticky)

A fourth, leading octal digit controls special bits:

Bit Octal Effect
setuid 4 Run a file as its owner (e.g. passwd)
setgid 2 Run as the file's group; on a dir, new files inherit the group
sticky 1 On a dir, only the owner can delete their files (e.g. /tmp)

Example: chmod 2775 shared/ sets setgid so new files in shared/ inherit the group. Special bits matter for shared servers but are rarely needed in app code — most permission work stays in the standard three-digit range.

umask: why new files are not 777

New files do not start fully open. The shell's umask subtracts permissions from a default (666 for files, 777 for directories). A typical umask 022 yields 644 files and 755 directories — which is exactly why those two sets are everywhere.

Real scenarios

  • SSH refuses your key (UNPROTECTED PRIVATE KEY FILE): chmod 600 ~/.ssh/id_ed25519 and chmod 700 ~/.ssh.
  • Web server 403: the web user needs x on every parent directory and r on the file — 755 dirs, 644 files.
  • Script "command not found" / won't run: chmod +x script.sh.
  • Deploy artifact too open: never ship secrets as 644; keep them 600 and owned by the service user.

Security: 777 is a smell

chmod 777 makes a file world-writable — any user or compromised process can modify it. It "fixes" permission errors by removing the protection entirely. If 777 solves your problem, the real fix is correct ownership (chown) plus a tighter mode like 755 or 775. World-writable files in a web root are a classic path to remote code execution.

Use these codefunc tools alongside this guide:

Practical takeaway

Read permissions as three rwx triplets; convert with the 4/2/1 rule. Default to 644 for files and 755 for directories, 600/700 for anything private. Use symbolic mode (u+x, go-w, capital X) for surgical changes, reach for special bits only on shared servers, and never paper over a permissions bug with 777. When in doubt, translate the number with a chmod calculator before running it.

Sources

Try it on codefunc

Related articles

3

Search tools

Find a developer tool