Linux File Permissions Explained: chmod, 755, 644 and More

Every file and directory on a Linux system carries three sets of permissions — for the owner, for the group, and for everyone else — each controlling read, write and execute. Those permissions are what stop one user reading another’s files, and what decide whether your web server can serve your site.

Most of the confusion around them comes from one thing: the execute bit means something completely different on a file than on a directory. Once that clicks, the standard values stop looking arbitrary.

Quick answer
See permissionsls -l
Change themchmod 644 file.txt
Web files644 — owner writes, everyone reads
Directories755 — the execute bit is what lets anyone enter
Files with secrets600 — owner only, nobody else reads

How to list file permissions in Linux

The command is ls -l, and its output is dense but entirely readable once you know where to look:

$ ls -l
-rw-r--r-- 1 john developers 4096 Jun 12 09:31 index.html
drwxr-xr-x 3 john developers 4096 Jun 12 09:28 uploads
-rwx------ 1 john developers 812 Jun 10 17:02 deploy.sh

The first column is the permission string, and it’s ten characters split into four parts:

   -   rw-   r--   r--
   │    │     │     │
   │    │     │     └── others
   │    │     └──────── group
   │    └────────────── owner
   └─────────────────── type

The first character is the type: - for a regular file, d for a directory, l for a symbolic link.

The next nine are three groups of three, always in the order read, write, execute — and always in the order owner, group, others. A letter means the permission is granted; a dash means it isn’t.

So -rw-r--r-- reads as: a regular file, owner can read and write, group can read, others can read. That’s 644.

Two other useful commands:

# Show permissions in numeric form
stat -c "%a %n" index.html

# List everything, including hidden files
ls -la

The three permissions, and what they actually allow

Each of the three actions has a number attached, and those numbers are how chmod works:

  • Read (r) = 4
  • Write (w) = 2
  • Execute (x) = 1

Add them together for each group, and you get the familiar three-digit number. 7 is 4+2+1 — everything. 5 is 4+1 — read and execute. 6 is 4+2 — read and write.

There’s no ambiguity in this system: each number from 0 to 7 can only be formed one way. These same permissions govern more than local access. A permission denied error in SCP or SFTP is this exact system refusing a transfer, on one end or the other.

Linux permissions shown as nine switches in three groups — read, write and execute for owner, group and others — combining into the number 755

Linux directory permissions: the same bits, different meanings

This is the section worth reading twice, because it explains almost every permission decision you’ll make.

On a file:

  • r — read the contents
  • w — modify the contents
  • x — run it as a program

On a directory:

  • r — list what’s inside
  • w — create, rename and delete files within it
  • xenter the directory

That last one is the key. Without the execute bit on a directory, nobody can access anything inside it — not even files they have full permission to read. The directory becomes a locked door regardless of what’s behind it.

And this is why the standard is 755 for directories and 644 for files. Directories need the execute bit so they can be traversed; regular files don’t, because a PHP or HTML file isn’t executed by the system — the web server reads it and hands it to an interpreter.

A corridor of folders showing that a directory without the execute bit blocks access to everything inside it, even to files that are perfectly readable
⚠️ The recursive chmod that breaks websites

Running chmod -R 644 /var/www/html looks like it should set every file to a safe value. What it actually does is strip the execute bit from every directory too — and the whole site becomes inaccessible, because the web server can no longer enter any folder.

The correct approach separates the two. The same pair of commands appears in our guide to the Nginx 500 internal server error, where wrong permissions are one of the most frequent causes.

# Directories to 755
find /var/www/html -type d -exec chmod 755 {} \;

# Files to 644
find /var/www/html -type f -exec chmod 644 {} \;

The permissions you’ll actually use

OctalSymbolicWhat it allowsUse it for
755rwxr-xr-xOwner does everything. Group and others read and enterDirectories and executable scripts
644rw-r--r--Owner reads and writes. Everyone else reads onlyWeb files: HTML, PHP, CSS, images
600rw-------Owner only. Nobody else can even read itFiles with credentials: wp-config.php, .env, SSH keys
700rwx------Owner does everything. Nobody else gets inPrivate directories, personal scripts
775rwxrwxr-xOwner and group do everything. Others read and enterDirectories shared by a team
664rw-rw-r--Owner and group write. Others readFiles edited by more than one user
777rwxrwxrwxEveryone does everything⚠️ Never on a web server. See below

Why 777 is never the answer

It appears in forum threads as the fix for every permission error, and it does make the error go away — by removing the protection entirely.

On a shared server, 777 means every other account on that machine can read, modify and delete your files. On any server, it means a compromised script running as any user can overwrite yours.

The irony is that the problem 777 is meant to solve usually shows up as a 403 Forbidden error — and that one is almost always fixed by setting 644 and 755 correctly, not by opening everything.

When an upload or write fails at 755, the problem is almost never the permission — it’s the ownership. If the web server process runs as a different user than the one that owns the files, no permission value will fix that cleanly. The correct fix is chown:

# Give ownership to the web server user
chown -R www-data:www-data /var/www/html

# Check who owns what
ls -l /var/www/html

This is the single most useful thing to know about Linux permissions in a hosting context: ownership and permissions are two different systems, and reaching for 777 is usually an ownership problem being treated as a permission one.

Changing permissions: numeric and symbolic

chmod accepts two notations, and both are worth knowing.

Numeric sets everything at once:

chmod 644 index.html
chmod 755 /var/www/html
chmod 600 .env

Symbolic changes only what you name, leaving the rest alone:

chmod u+x deploy.sh # add execute for the owner
chmod g-w report.txt # remove write from the group
chmod o=r public.html # set others to read only
chmod a+r manual.pdf # add read for everyone

The letters are u (user/owner), g (group), o (others) and a (all), combined with + to add, – to remove and = to set exactly.

Symbolic notation is safer for targeted changes: chmod u+x adds one bit without touching anything else, while the numeric equivalent requires knowing and restating every other permission.

Where new files get their permissions: umask

Create a file and it arrives at 644 without you doing anything. That default comes from umask, a mask that subtracts from the system’s base values.

$ umask
0022

Linux starts at 666 for files and 777 for directories, then subtracts the umask. With the common default of 022, that gives 644 for files and 755 for directories — the values you see everywhere.

Setting umask 077 makes every new file 600 and every new directory 700, which is a reasonable default on a machine handling sensitive data.

The special permission bits

Beyond the nine standard bits, three special ones show up occasionally — and they change what the permission string looks like.

SUID (4000) — a program runs with the permissions of its owner rather than whoever launched it. passwd uses this: it needs root access to write to the password file, but any user must be able to run it. Shows as an s in the owner’s execute position.

SGID (2000) — on a program, it runs with the group’s permissions. On a directory, more usefully, every file created inside inherits the directory’s group. That’s how shared team folders stay consistent.

Sticky bit (1000) — on a shared directory, only the owner of a file can delete it, even if others have write access to the directory. /tmp uses this, which is why it shows as drwxrwxrwt — the t at the end.

You’ll rarely set these by hand, but recognising them in ls -l output prevents confusion when a permission string has letters where you expected x.

Permissions set correctly from the start

On Copahost hosting, your account owns its own files and the standard 755/644 values are applied on setup — so uploads work without anyone ever needing to reach for 777. Full SSH and File Manager access when you do need to change something, on LiteSpeed servers with NVMe storage. Free migration from your current host.

See hosting plans

Frequently asked questions

How do I check file permissions in Linux?

Run ls -l in the directory. The first column shows a ten-character string like -rw-r--r--: the first character is the file type, and the remaining nine are three groups of three covering read, write and execute for owner, group and others. For the numeric form instead, use stat -c "%a %n" filename.

What does 755 mean in Linux?

The owner can read, write and execute (7 = 4+2+1); the group and others can read and execute (5 = 4+1). On a directory — which is where it’s most used — the execute bit means the ability to enter, so 755 lets anyone traverse the folder while only the owner can change what’s in it.

What’s the difference between 755 and 644?

The execute bit. 755 includes it, 644 doesn’t. That’s why 755 is used on directories, which need it to be entered, and 644 on regular files, which don’t need to be executed. A PHP or HTML file works perfectly at 644 — the web server reads it rather than running it.

Why do directories need the execute permission?

Because on a directory, the execute bit doesn’t mean “run” — it means “enter”. Without it, nothing inside is accessible, no matter what permissions the individual files carry. A directory at 644 becomes a locked door.

Is chmod 777 ever safe?

Not on a server exposed to the internet. It grants read, write and execute to every user on the machine, which on shared hosting means every other account. When an upload fails at 755, the underlying issue is almost always ownership rather than permissions — and the fix is chown, not opening the file to everyone.

How do I change permissions for all files in a folder?

Not with a single chmod -R, because that applies the same value to files and directories alike and strips the execute bit that directories need. Use find to separate them: find /path -type d -exec chmod 755 {} \; for directories and find /path -type f -exec chmod 644 {} \; for files.

What’s the difference between chmod and chown?

chmod changes what the owner, group and others are allowed to do. chown changes who the owner and group are. They solve different problems: if the web server can’t write to a folder, the question is usually whether it owns the folder, not what the permission number is.

What is umask?

A mask that determines the permissions new files receive. Linux starts at 666 for files and 777 for directories, then subtracts the umask value. With the common default of 022, new files arrive at 644 and new directories at 755. Run umask alone to see the current value.

What do the letters s and t mean in a permission string?

They’re the special bits. An s in the owner’s execute position is SUID — the program runs with the owner’s permissions. An s in the group position is SGID. A t at the end is the sticky bit, which on a shared directory means only a file’s owner can delete it. /tmp is the classic example, shown as drwxrwxrwt.

Do file permissions apply to root?

Not in the usual sense. The root user bypasses permission checks entirely and can read, write and delete anything on the system. That’s why a file set to 000 — no permissions for anyone — is still fully accessible to root.

Conclusion

Linux permissions look cryptic until you notice they’re just three questions asked three times: can this person read it, write to it, run it — and is this person the owner, in the group, or neither?

Three things carry most of the practical weight. The execute bit means “enter” on a directory, which is the whole reason 755 and 644 are the standard pair. A recursive chmod applied to both files and directories will break a website, and separating them with find is the fix. And 777 is almost always an ownership problem in disguise — when a write fails at 755, chown is the answer, not opening the file to the entire server.

Get those three right and the rest is reference material, which is what the table above is for.

Share the Post:
Picture of Gustavo Gallas

Gustavo Gallas

Graduated in Computing at PUC-Rio, Brazil. Specialized in IT, networking, systems administration and human and organizational development​. Also have brewing skills.