Linux File Permissions and chmod Explained Simply
Learn Linux file permissions from scratch — how to read ls -la output, use chmod and chown, understand octal vs symbolic mode, SUID/SGID/sticky bit, umask, and why chmod 777 is dangerous.
"Permission denied." Two words that stop every Linux beginner cold. File permissions control who can read, write, and execute every file and directory on a Linux system. Once you understand the pattern, you'll never be confused by ls -la output again.
Reading ls -la Output
Run ls -la on any directory:
ls -la /var/www/html/drwxr-xr-x 2 www-data www-data 4096 Jun 25 10:00 .
drwxr-xr-x 14 root root 4096 Jun 20 08:00 ..
-rw-r--r-- 1 www-data www-data 1234 Jun 25 10:00 index.html
-rwxr-xr-x 1 www-data www-data 5678 Jun 25 10:00 deploy.sh
-rw------- 1 root root 256 Jun 25 10:00 .env
The first column (like -rw-r--r--) is the permission string. Break it down:
- rw- r-- r--
│ │ │ └── Others (everyone else): read-only
│ │ └────── Group: read-only
│ └────────── Owner: read + write
└──────────── File type: - = regular file, d = directory, l = symlink
The Three Permission Bits: r, w, x
| Bit | File meaning | Directory meaning |
|---|---|---|
r (read) | Open and read file | List contents (ls) |
w (write) | Modify or delete file | Create/delete files inside |
x (execute) | Run as program | Enter directory (cd) |
A - means the permission is not granted.
Numeric (Octal) Mode
Each permission group (owner/group/others) is represented as a number 0-7:
| Number | Bits | Permissions |
|---|---|---|
| 7 | rwx | Read + Write + Execute |
| 6 | rw- | Read + Write |
| 5 | r-x | Read + Execute |
| 4 | r-- | Read only |
| 0 | --- | No permissions |
So chmod 644 index.html means:
- Owner: 6 = rw- (read + write)
- Group: 4 = r-- (read only)
- Others: 4 = r-- (read only)
Common Permission Patterns
SSH private key — 600
chmod 600 ~/.ssh/id_rsaPermission: -rw------- — Only you can read/write. SSH client refuses to connect if your private key is world-readable. This is one of the most common SSH errors beginners hit.
Public key / config files — 644
chmod 644 ~/.ssh/id_rsa.pub
chmod 644 /etc/nginx/nginx.confPermission: -rw-r--r-- — Owner can edit, everyone can read.
Shell scripts / binaries — 755
chmod 755 deploy.shPermission: -rwxr-xr-x — Owner can run and edit, group and others can read and run.
Web server document root — 755 for dirs, 644 for files
chmod -R 755 /var/www/html/
find /var/www/html -type f -exec chmod 644 {} \;
find /var/www/html -type d -exec chmod 755 {} \;Private config with secrets — 600 or 640
chmod 600 .env
chmod 640 /etc/app/config.yml # readable by group toochmod Symbolic Mode
Instead of numbers, you can use letters:
# Add execute for owner
chmod u+x script.sh
# Remove write from group and others
chmod go-w sensitive.txt
# Set exact permissions symbolically
chmod u=rw,g=r,o=r config.txt
# Add execute for everyone
chmod a+x deploy.shu = user (owner), g = group, o = others, a = all three.
chown: Changing Ownership
# Change owner
chown www-data index.html
# Change owner and group
chown www-data:www-data /var/www/html/
# Recursively change ownership
chown -R www-data:www-data /var/www/html/Check current ownership with ls -la. The second and third columns are owner and group.
chgrp: Changing Group
chgrp developers project-config.ymlEquivalent to chown :developers project-config.yml.
umask: Default Permissions for New Files
When you create a new file, Linux applies a umask (permission mask) to strip some default permissions. Common umask values:
umask # Show current umask
# Output: 0022- Default file permissions:
0666minus umask0022=0644(rw-r--r--) - Default directory permissions:
0777minus umask0022=0755(rwxr-xr-x)
For stricter defaults (files readable only by owner):
umask 0077
# New files: 0666 - 0077 = 0600 (rw-------)Set umask in ~/.bashrc or /etc/profile to persist.
Special Bits: SUID, SGID, Sticky Bit
These are the 4th digit in octal notation and appear in the ls -la output in specific positions.
SUID (Set User ID) — bit 4000
When set on an executable, it runs as the file owner, not the user who launched it.
ls -la /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 /usr/bin/passwd
# ^ 's' here = SUID setpasswd needs to write to /etc/shadow (owned by root). SUID lets regular users change their own password without being root.
Set SUID: chmod 4755 program or chmod u+s program
SGID (Set Group ID) — bit 2000
On a file: runs with the group of the file owner, not the user's group. On a directory: new files created inside inherit the directory's group — very useful for shared project directories.
chmod 2775 /shared/project/
# drwxrwsr-x — new files created here belong to the directory's groupSticky Bit — bit 1000
On a directory: users can only delete their own files, even if they have write access to the directory.
ls -la /tmp
# drwxrwxrwt 20 root root 4096 /tmp
# ^ 't' = sticky bit/tmp is world-writable but you can't delete other users' temp files. Useful for shared directories.
chmod +t /shared/uploads/Why chmod 777 Is Dangerous
chmod 777 /var/www/html/ # NEVER DO THIS IN PRODUCTION777 means every user on the system — including any compromised process, web vulnerability, or malicious script — can read, write, and execute everything in that directory.
If your web app has an upload feature and the upload directory is 777, an attacker can upload and execute a PHP shell. This is how most shared hosting compromises happen.
The correct approach for a web server:
chown -R www-data:www-data /var/www/html/
chmod -R 755 /var/www/html/
chmod 750 /var/www/html/private/ # not readable by others at allQuick Troubleshooting
Permission denied when running a script:
chmod +x myscript.sh
./myscript.shSSH "WARNING: UNPROTECTED PRIVATE KEY FILE":
chmod 600 ~/.ssh/id_rsaNginx can't read your files:
chown -R www-data:www-data /var/www/
find /var/www -type d -exec chmod 755 {} \;
find /var/www -type f -exec chmod 644 {} \;File created as root, regular user can't edit:
sudo chown $USER:$USER filenameLinux file permissions look cryptic at first but follow a simple 9-character pattern. Once you can read rwxr-xr-x at a glance, diagnosing permission issues takes seconds instead of minutes.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
What Is SSH? Explained Simply (2026)
SSH (Secure Shell) is how engineers connect to remote servers. Here's what SSH actually is, how it works, and how to use it — explained without jargon.
Build a Kubernetes Cluster with kubeadm from Scratch (2026)
Step-by-step guide to building a real multi-node Kubernetes cluster using kubeadm — no managed services, no shortcuts.
How to Set Up Ansible from Scratch (Complete Beginner Guide 2026)
Learn Ansible from zero — install it, configure SSH, write your first playbook, use variables and loops, and automate real server tasks step by step.