Domain insights

Linux File Permissions Without the Mystery: chmod, chown, 644, 755, and Why 777 Is Usually Wrong

Read Linux permissions, understand 644 and 755, use chmod and chown, and diagnose website access errors before changing ownership or modes.

Linux and VPS
Linux File Permissions Without the Mystery: chmod, chown, 644, 755, and Why 777 Is Usually Wrong

Your website returns 403 Forbidden.

You search the web and find a forum answer:

chmod -R 777 /var/www/example.com

You run it. The website works.

Problem solved?

Not necessarily.

You may have replaced a permission problem with a security problem.

Linux permissions look cryptic at first:

-rw-r--r--
drwxr-xr-x

Then tutorials introduce 644, 755, chmod, chown, owners, groups, and "others."

Fortunately, the system is much smaller than it appears. Once you understand three permissions and three categories of users, strings such as rwxr-xr-x become readable.

This guide explains the system using website files on a VPS, because that is where many hosting customers encounter permissions for the first time.

Start with ls -l

Connect to the VPS and run:

ls -l

You may see:

-rw-r--r-- 1 marco www-data 1842 Oct 2 10:15 index.php
drwxr-xr-x 4 marco www-data 4096 Oct 2 10:16 public

There is a lot of information here.

For now, focus on:

-rw-r--r--

and:

marco www-data

The first part describes file type and permissions. The names identify owner and group.

Read the permission string in three pieces

For:

-rw-r--r--

the first character - means a regular file.

A directory normally begins with:

d

The remaining nine characters can be split into three groups:

rw- r-- r--

They correspond to:

owner group others

The three permission letters are:

r = read
w = write
x = execute

So rw-r--r-- means the owner can read and write, while group and others can read.

That is the central idea behind normal Linux permissions.

Owner, group, and everyone else

Every normal file has an owner and a group.

For this example:

-rw-r--r-- 1 marco www-data 1842 Oct 2 10:15 index.php

owner:

marco

group:

www-data

The three permission sets therefore mean:

owner:  marco
group:  www-data
others: everyone else

On Ubuntu and Debian systems, www-data is commonly associated with web services, although your hosting stack may use another account or group.

Do not assume every server uses the same process user.

Directories use the same letters differently

For directories, the letters have related but slightly different meanings.

Read permission lets a process read the directory listing.

Write permission lets it create or remove directory entries, subject to other rules.

Execute permission lets it traverse the directory and access entries inside when other permissions allow it.

That surprises beginners.

A directory often needs x even though nobody is "executing" the directory like a script.

For:

drwxr-xr-x

owner:

rwx

group:

r-x

others:

r-x

This is the familiar numeric mode 755.

Where 644 comes from

Linux permissions are often represented with numbers.

The values are:

read    4
write   2
execute 1

Add the permissions you want.

Read plus write:

4 + 2 = 6

Read plus execute:

4 + 1 = 5

Read only:

4

So:

644

means:

owner:  6 = read + write
group:  4 = read
others: 4 = read

In letters:

rw-r--r--

That is why many ordinary website files are commonly seen with mode 644.

It is not a magical website number. It is arithmetic.

Where 755 comes from

Now:

755

Owner:

7 = read + write + execute

Group:

5 = read + execute

Others:

5 = read + execute

In letters:

rwxr-xr-x

This is common for directories that need to be traversable and for executable scripts or programs.

Again, it is not automatically correct for every directory.

What 777 actually means

Now the famous one:

777

Each 7 means read, write, and execute.

So:

rwxrwxrwx

Owner can read, write, execute.

Group can read, write, execute.

Everyone else can read, write, execute.

That is extremely permissive.

If an application only needs one upload directory to be writable by a web-service identity, giving every user write permission across the whole website is not a sensible fix.

777 can make a permission error disappear because it removes many restrictions.

That does not make it correct.

It is the permissions equivalent of solving a lost-key problem by removing the front door.

Use chmod to change permissions

Use chmod to change permission bits.

Numeric form:

chmod 644 index.php

For a directory:

chmod 755 public

You can also use symbolic notation.

Add execute permission for the owner:

chmod u+x script.sh

Remove write permission from others:

chmod o-w file.txt

Add read permission for the group:

chmod g+r file.txt

The letters mean:

u = user/owner
g = group
o = others
a = all

Symbolic notation is often easier to understand because it says exactly what you are changing.

Use chown to change ownership

Permissions may be reasonable while ownership is wrong.

Suppose:

ls -l index.php

returns:

-rw-r--r-- 1 root root 1842 Oct 2 10:15 index.php

but your deployment process expects marco to own the file.

Change the owner:

sudo chown marco index.php

Change owner and group:

sudo chown marco:www-data index.php

For an entire tree:

sudo chown -R marco:www-data /var/www/example.com

The -R means recursive.

Use recursive ownership changes carefully. Verify the path before pressing Enter.

A typo can alter thousands of files you never intended to touch.

Why a website can return 403

A 403 does not automatically mean "run chmod 777."

Possible causes include:

  • a parent directory cannot be traversed;
  • the web-server user cannot read the file;
  • ownership is wrong;
  • Nginx or Apache access rules deny the request;
  • no valid index file exists;
  • an application rule denies access;
  • another security layer is involved.

Start by checking the path:

ls -ld /var
ls -ld /var/www
ls -ld /var/www/example.com
ls -l /var/www/example.com

Then read the web-server error log.

For Nginx:

sudo tail -n 50 /var/log/nginx/error.log

For Apache on Ubuntu:

sudo tail -n 50 /var/log/apache2/error.log

The log may identify the exact file or directory that produced Permission denied.

Fix that cause instead of opening everything.

A sensible website permission model

There is no universal permission recipe for every web application.

A useful starting concept is:

  • normal HTML, CSS, images, and PHP source usually do not need Unix execute permission;
  • directories need traversal permission;
  • only directories that an application must modify should be writable by the required identity;
  • sensitive configuration may need stricter access;
  • ownership should match the deployment and web-server model.

Simple sites often show files as 644 and directories as 755.

But WordPress uploads, cache directories, application storage, PHP-FPM pools, control panels, and shared groups can require something different.

Ask one question:

Who actually needs to write here?

Then grant that identity the access it needs.

Inspect before changing

Find normal files:

find /var/www/example.com -type f -ls | head

Find directories:

find /var/www/example.com -type d -ls | head

Find world-writable files:

find /var/www/example.com -type f -perm -0002 -print

Find world-writable directories:

find /var/www/example.com -type d -perm -0002 -print

These commands print results without changing them.

Investigation should usually come before repair.

Why chmod -R 755 can also be wrong

A less dangerous but still flawed internet recipe is:

chmod -R 755 /var/www/example.com

This gives execute permission to ordinary files too.

Your JPEG does not need to be executable.

Your CSS file does not need to be executable.

Your PHP source normally does not need Unix execute permission simply because PHP processes it through a web stack.

If you intentionally need to normalize a simple tree, files and directories can be handled separately after you confirm the application requirements:

find /var/www/example.com -type d -exec chmod 755 {} \;
find /var/www/example.com -type f -exec chmod 644 {} \;

Do not run these commands blindly on an application that requires special writable or executable paths.

Scripts may really need execute permission

Suppose you create:

backup.sh

Check it:

ls -l backup.sh

If it shows:

-rw-r--r--

then:

./backup.sh

may fail.

Add owner execute permission:

chmod u+x backup.sh

That is a legitimate use of the execute bit.

It is different from making every file in a website executable.

Protect sensitive configuration files

Configuration files may contain:

  • database passwords;
  • API credentials;
  • secret keys;
  • SMTP passwords;
  • application tokens.

Do not make these world-writable.

A mode such as:

chmod 600 secret.conf

means:

rw-------

Only the owner can read and write the file.

But 600 is not automatically correct for every application. The process that needs the file must still be able to read it.

The goal is the minimum access that lets the application operate.

Shared hosting and cPanel

On shared hosting, you may manage permissions through File Manager instead of SSH.

The concepts remain the same:

  • owner;
  • group;
  • read;
  • write;
  • execute.

Control panels hide some operating-system details, but they do not eliminate Linux permissions.

If ownership appears wrong in a managed hosting environment, contact support before changing it. The platform may intentionally manage ownership.

If a plugin tells you to make the entire hosting account 777, stop and investigate why.

Writable upload and cache directories

Applications often need write access for:

  • uploaded images;
  • cache;
  • sessions;
  • generated files;
  • temporary exports.

The right approach is not "make the whole website writable."

It is "make the required location writable by the correct identity."

For example, an uploads directory may need different access from the directory that contains application configuration.

Separating code from writable data reduces the amount of the website that can be modified if an account or process is compromised.

The root-upload mistake

A common VPS mistake looks like this:

  1. You log in as root.
  2. You copy website files into /var/www/example.com.
  3. Every file becomes owned by root.
  4. Your deployment user cannot modify them.
  5. You use chmod 777 so editing works.

The underlying problem is ownership.

Check:

ls -la /var/www/example.com

Then fix ownership according to the actual deployment model.

Permissions and ownership are related, but they are not interchangeable.

Do not use overly broad permissions to compensate for incorrect ownership.

Recursive commands deserve caution

Before a large recursive change, capture the current state or take a proper backup or snapshot.

Recursive chmod and chown can modify thousands of objects in seconds.

That speed is useful when the command is right and impressive when it is wrong.

Always verify the target path.

A practical troubleshooting sequence

When an application cannot read or write a file:

  1. Identify the exact path.
  2. Run ls -l on the file.
  3. Run ls -ld on parent directories.
  4. Identify the user the application process runs as.
  5. Check owner and group.
  6. Decide whether the process needs read, write, or directory traversal.
  7. Read application and web-server logs.
  8. Change only what is necessary.
  9. Test again.
  10. Document the final ownership and mode.

Start with evidence, not 777.

If ordinary ownership and permission bits look correct, check any access-control lists and security policies such as SELinux or AppArmor used by your system. They can restrict access independently of the basic mode shown by ls -l.

Quick permission decoder

7 = rwx
6 = rw-
5 = r-x
4 = r--
3 = -wx
2 = -w-
1 = --x
0 = ---

Common examples:

600 = rw-------
640 = rw-r-----
644 = rw-r--r--
700 = rwx------
750 = rwxr-x---
755 = rwxr-xr-x
777 = rwxrwxrwx

These are descriptions, not universal recommendations.

The right mode depends on who needs access.

More practical answers

Why do directories need execute permission?

Execute permission on a directory allows traversal and access to entries inside it, subject to other permissions.

Should all website files be 644 and directories 755?

Those are common modes in simple setups, but they are not universal rules. Applications may require writable storage, special groups, or different process ownership.

How do I check permissions?

Use:

ls -l

For a directory itself:

ls -ld directory

What should I do when I see Permission denied?

Identify the exact file or directory, check owner and permissions, determine which user the process runs as, and read relevant logs before changing access.

Frequently asked questions

What does chmod 644 mean?

The owner can read and write. The group and others can read. In symbolic form: rw-r--r--.

What does chmod 755 mean?

The owner has read, write, and execute. Group and others have read and execute. In symbolic form: rwxr-xr-x.

Why is 777 usually wrong?

It grants read, write, and execute permission to owner, group, and others. That is far more access than most website files need.

What is the difference between chmod and chown?

chmod changes permission bits. chown changes ownership.