chmod / chown system
permission denied. the two words that ruin your afternoon.
The chmod and chown man pages are about 500 lines combined. You need three concepts and you’ll never Google “permission denied linux” again.
You tried to run a script. “Permission denied.” You tried to edit a config file. “Permission denied.” You tried to delete a log file. “Permission denied.” So you did what everyone does — you typed sudo in front of the command and moved on with your life. You didn’t understand the problem. You just escalated privileges until it went away. That’s not fixing permissions. That’s the digital equivalent of kicking a locked door open instead of using the key.
Worse, someone told you to chmod 777 the file. So you did. It worked. You moved on. You just gave every user on the system full read, write, and execute access to that file. If this is a web server, you just created a security vulnerability. If this is a shared system, you just let everyone modify your files. 777 is not a fix. It’s a surrender.
Let’s actually understand this.
Unless you’re running Windows then wtf none of this applies to you. But hey, come to the dark side, go install WSL2 and you can follow along. We’ll wait. Impatiently.
If you’re lazy like me (all sysadmins are!) then click here for the chmod / chown cheat sheet.
How permissions work
Every file and directory has three sets of permissions for three categories of users:
-rwxr-xr-- 1 owner group 4096 Mar 15 10:00 script.sh
^^^ ^^^ ^^^
│ │ └── others (everyone else)
│ └─────── group (users in the file's group)
└──────────── owner (the file's owner)
Each set has three permissions:
| Letter | Permission | On files | On directories |
|---|---|---|---|
r |
Read | View contents | List contents |
w |
Write | Modify contents | Create/delete files inside |
x |
Execute | Run as a program | Enter the directory (cd into it) |
A dash (-) means that permission is not granted.
So -rwxr-xr-- means:
- Owner: read, write, execute (full control)
- Group: read and execute (can run it, can’t modify it)
- Others: read only (can look, can’t touch)
chmod: change permissions
Numeric (octal) mode
Each permission has a number: r=4, w=2, x=1. Add them up for each category.
| Number | Permissions | Meaning |
|---|---|---|
7 |
rwx | Read, write, execute |
6 |
rw- | Read, write |
5 |
r-x | Read, execute |
4 |
r– | Read only |
0 |
— | No permissions |
chmod 755 script.sh
- Owner: 7 (rwx) — full control
- Group: 5 (r-x) — read and execute
- Others: 5 (r-x) — read and execute
This is the standard permission for scripts and executables. The owner can modify them, everyone else can run them.
chmod 644 config.yml
- Owner: 6 (rw-) — read and write
- Group: 4 (r–) — read only
- Others: 4 (r–) — read only
Standard for regular files. Owner can edit, everyone can read.
Common permission sets
| Octal | Meaning | Use case |
|---|---|---|
755 |
rwxr-xr-x | Scripts, executables, directories |
644 |
rw-r–r– | Regular files, configs |
700 |
rwx—— | Private scripts (owner only) |
600 |
rw——- | Private files (SSH keys, secrets) |
444 |
r–r–r– | Read-only for everyone |
777 |
rwxrwxrwx | Don’t. Just don’t. |
Symbolic mode
Instead of numbers, use letters:
chmod u+x script.sh
Add execute permission for the user (owner). u = user/owner, g = group, o = others, a = all.
chmod g+rw file.txt # Add read+write for group
chmod o-w file.txt # Remove write for others
chmod a+r file.txt # Add read for everyone
chmod u+x,g-w script.sh # Multiple changes at once
+ adds permission. - removes it. = sets it exactly.
Make a script executable
chmod +x script.sh
The single most common chmod command. You wrote a script. You tried to run it. “Permission denied.” This fixes it. The +x adds execute permission for everyone (shorthand for a+x).
Recursive permissions
chmod -R 755 /var/www/html/
-R applies to the directory and everything inside it recursively. Use with caution — you probably don’t want every file to be executable.
Better: different permissions for files and directories
find /var/www -type d -exec chmod 755 {} +
find /var/www -type f -exec chmod 644 {} +
Directories get 755 (need execute to cd into them). Files get 644 (no need to execute). This is the correct way to fix web server permissions.
chown: change ownership
chown owner:group file.txt
Changes both the owner and group. Requires sudo unless you’re root.
sudo chown www-data:www-data /var/www/html/index.html
Makes the web server user own the file. Now nginx/Apache can read and write it.
Change just the owner
sudo chown owner file.txt
Change just the group
sudo chown :group file.txt
Or use chgrp:
sudo chgrp www-data file.txt
Recursive ownership change
sudo chown -R www-data:www-data /var/www/html/
The entire directory tree. Every file and subdirectory now belongs to www-data.
Check current permissions
ls -la file.txt
-rw-r--r-- 1 owner group 4096 Mar 15 10:00 file.txt
The first column is permissions. The third column is the owner. The fourth is the group. ls -la shows you everything.
stat file.txt
More detailed — shows numeric permissions, ownership, timestamps, and inode info.
Special permissions
SUID (Set User ID)
chmod u+s program
When executed, the program runs as the file owner, not the user who ran it. This is how passwd works — it runs as root so it can modify /etc/shadow, even when a normal user runs it.
SGID (Set Group ID)
chmod g+s directory/
Files created inside this directory inherit the directory’s group instead of the creator’s primary group. Useful for shared directories where a team needs group access to all files.
Sticky bit
chmod +t /tmp/
Only the file owner (or root) can delete files in this directory. This is why you can’t delete other people’s files in /tmp/ even though everyone can write there.
The flags that actually matter
chmod:
| Flag / Mode | What it does |
|---|---|
755, 644, etc. |
Set permissions with octal numbers. |
u+x, g-w, etc. |
Set permissions symbolically. |
-R |
Apply recursively. |
u+s |
Set SUID bit. |
g+s |
Set SGID bit. |
+t |
Set sticky bit. |
chown:
| Flag / Mode | What it does |
|---|---|
owner:group file |
Change owner and group. |
owner file |
Change owner only. |
:group file |
Change group only. |
-R |
Apply recursively. |
“But I just use sudo—”
Stop.
“I just sudo everything.” You’re running commands as root because you don’t understand why they failed as your user. That’s not a solution — it’s a bypass. One wrong sudo rm and you’re reinstalling. Fix the permissions, don’t escalate the privileges.
“I chmod 777 and it works.” Yes, because you gave everyone on earth permission to do everything to that file. It’s like fixing a locked door by removing the door. On a web server, 777 means any exploited process can modify your files. On a shared system, it means your coworkers can delete your work. Learn the right permission numbers.
“Windows doesn’t have this problem.” Windows has ACLs — access control lists — which are arguably more complex than Unix permissions. The difference is Windows hides them behind a “Security” tab that most users never open. When Windows says “Access Denied,” the fix is just as confusing; it’s just hidden behind a GUI.
“I use a file manager to change permissions.” Your file manager’s permissions dialog shows checkboxes for read, write, and execute. It’s the same information as chmod, just slower to use and harder to apply recursively. Also, your file manager isn’t available when you’re SSH’d into a server.
chmod / chown cheat sheet
You made it. Or you skipped straight here. Either way, no judgment. Copy and paste these. Pin them. Tattoo them on your forearm. Whatever works.
| What you’re doing | Command |
|---|---|
| Make script executable | chmod +x script.sh |
| Standard file permissions | chmod 644 file.txt |
| Standard directory permissions | chmod 755 directory/ |
| Private file (owner only) | chmod 600 secret.key |
| Change owner and group | sudo chown user:group file |
| Recursive ownership | sudo chown -R www-data:www-data /var/www/ |
| Fix web permissions (dirs) | find /var/www -type d -exec chmod 755 {} + |
| Fix web permissions (files) | find /var/www -type f -exec chmod 644 {} + |
| Check permissions | ls -la file |
The decoder ring: r=4, w=2, x=1. Add them up. 7=rwx, 6=rw, 5=rx, 4=r. First digit is owner, second is group, third is others.
chmod 755= owner can do everything, everyone else can read and execute.