🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

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.

DevOpsBoys5 min read
Share:Tweet

"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:

bash
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

BitFile meaningDirectory meaning
r (read)Open and read fileList contents (ls)
w (write)Modify or delete fileCreate/delete files inside
x (execute)Run as programEnter 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:

NumberBitsPermissions
7rwxRead + Write + Execute
6rw-Read + Write
5r-xRead + Execute
4r--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

bash
chmod 600 ~/.ssh/id_rsa

Permission: -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

bash
chmod 644 ~/.ssh/id_rsa.pub
chmod 644 /etc/nginx/nginx.conf

Permission: -rw-r--r-- — Owner can edit, everyone can read.

Shell scripts / binaries — 755

bash
chmod 755 deploy.sh

Permission: -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

bash
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

bash
chmod 600 .env
chmod 640 /etc/app/config.yml  # readable by group too

chmod Symbolic Mode

Instead of numbers, you can use letters:

bash
# 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.sh

u = user (owner), g = group, o = others, a = all three.

chown: Changing Ownership

bash
# 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

bash
chgrp developers project-config.yml

Equivalent 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:

bash
umask  # Show current umask
# Output: 0022
  • Default file permissions: 0666 minus umask 0022 = 0644 (rw-r--r--)
  • Default directory permissions: 0777 minus umask 0022 = 0755 (rwxr-xr-x)

For stricter defaults (files readable only by owner):

bash
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.

bash
ls -la /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 /usr/bin/passwd
#    ^ 's' here = SUID set

passwd 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.

bash
chmod 2775 /shared/project/
# drwxrwsr-x — new files created here belong to the directory's group

Sticky Bit — bit 1000

On a directory: users can only delete their own files, even if they have write access to the directory.

bash
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.

bash
chmod +t /shared/uploads/

Why chmod 777 Is Dangerous

bash
chmod 777 /var/www/html/  # NEVER DO THIS IN PRODUCTION

777 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:

bash
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 all

Quick Troubleshooting

Permission denied when running a script:

bash
chmod +x myscript.sh
./myscript.sh

SSH "WARNING: UNPROTECTED PRIVATE KEY FILE":

bash
chmod 600 ~/.ssh/id_rsa

Nginx can't read your files:

bash
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:

bash
sudo chown $USER:$USER filename

Linux 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

Browse fixes
Newsletter

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

Comments