Copied a script to the server — it does not run. Uploaded a file via FTP — cannot read it. Created a directory — another user cannot write to it. Nine times out of ten the cause is the same: wrong file permissions. chmod fixes that.
How Permissions Work in Linux
Every file has three permission groups — for the owner (u), the group (g), and everyone else (o). Each group has three bits:
r— readw— writex— execute
Check current permissions:
ls -l filename
The first 9 characters after - are the permissions: first three for the owner (rwx), next three for the group (r-x), last three for others (r--).
Symbolic Format: Readable and Precise
To add or remove a specific permission — use symbolic format. + adds, - removes, = sets exactly.
Give the owner execute permission:
chmod u+x script.sh
Remove write permission from group and others:
chmod go-w file.txt
Give the group read and execute:
chmod g+rx file.txt
Set permissions for all three at once (ugo or the shorthand a):
chmod a+r file.txt
Set exact permissions for the group — read only, remove everything else:
chmod g=r file.txt
Change permissions for multiple groups in one command:
chmod u+x,go-x script.sh
Numeric Format: Fast and Universal
Each permission has a numeric value: r=4, w=2, x=1. Permissions are summed:
| Permissions | Number |
|---|---|
| --- | 0 |
| --x | 1 |
| -w- | 2 |
| -wx | 3 |
| r-- | 4 |
| r-x | 5 |
| rw- | 6 |
| rwx | 7 |
Three digits — for owner, group, others. Most common masks:
Owner full access (7), group and others read and execute (5). Standard for executables and web server directories:
chmod 755 script.sh
Owner read and write (6), others read only (4). Standard for configuration files:
chmod 644 config.conf
Owner only reads and writes. Required minimum for SSH keys — without this ssh refuses to use them:
chmod 600 private_key
Full access for everyone. Use only where genuinely needed:
chmod 777 file.txt
Recursive Change: the -R Flag
Change permissions for an entire directory and all its contents:
chmod -R 755 /var/www/mysite
The -v flag shows what changed:
chmod -Rv 755 /var/www/mysite
The -c flag — only files whose permissions actually changed (not those already at 755):
chmod -Rc 755 /var/www/mysite
A common server task — set 755 for directories and 644 for files separately. Via find:
find /var/www/mysite -type d -exec chmod 755 {} +
find /var/www/mysite -type f -exec chmod 644 {} +
Special Bits: SUID, SGID, Sticky
SUID (Set User ID) — the file runs with the owner's permissions rather than the permissions of the user who launched it. Used for system utilities like passwd — a regular user runs it under their own account, but it operates with root privileges.
Set SUID:
chmod u+s /usr/bin/program
In ls -l output, s appears instead of x for the owner: -rwsr-xr-x.
SGID (Set Group ID) — on a directory, new files inside inherit the directory's group rather than the creating user's group. Useful for shared team folders:
chmod g+s /shared/team
Sticky bit — on a directory, prevents users from deleting each other's files. Classic example — /tmp: anyone can create a file, but only the owner can delete it.
chmod +t /shared/uploads
In ls -l output, t appears at the end: drwxrwxrwt.
Numeric values for special bits — a fourth leading digit:
chmod 4755 /usr/bin/program # SUID
chmod 2775 /shared/team # SGID
chmod 1777 /tmp # Sticky bit
Quick Reference
| Task | Command |
|---|---|
| Give execute to owner | chmod u+x file |
| Remove write from group and others | chmod go-w file |
| Standard for scripts and directories | chmod 755 file |
| Standard for config files | chmod 644 file |
| Owner only (SSH keys) | chmod 600 file |
| Recursive on directory | chmod -R 755 /path/ |
| Directories only recursively | find /path -type d -exec chmod 755 {} + |
| Files only recursively | find /path -type f -exec chmod 644 {} + |
| Set SUID | chmod u+s file or chmod 4755 file |
| Set SGID | chmod g+s dir or chmod 2755 dir |
| Set Sticky bit | chmod +t dir or chmod 1777 dir |
| Check current permissions | ls -l file |