Linux File Permissions Explained: chmod, chown and the Numbers

Read any ls -l line, understand 644 vs 755, fix "Permission denied" properly, and set the ownership a web server needs — without chmod 777.

3 min read

Half of all "my site is broken" tickets that reach us are permissions. A plugin cannot write to uploads, a deploy script created files as root, or someone ran chmod -R 777 and now the server flags everything as a risk. Ten minutes with this guide and you will never need to guess again.

Reading an ls -l line

bash
ls -l /var/www/vhosts/example.com/httpdocs/
# -rw-r--r-- 1 example psacln  418 Sep 12 10:02 index.php
# drwxr-xr-x 5 example psacln 4096 Sep 12 10:02 wp-content

Take the first field apart:

Part Meaning
- or d regular file, or directory
rw- what the owner (example) can do: read, write, not execute
r-- what the group (psacln) can do: read only
r-- what everyone else can do: read only

Then example psacln is the owner and group. Every permission question is one of those three columns.

What the numbers mean

Each column is a number: read = 4, write = 2, execute = 1. Add them up.

Number Permissions Typical use
7 rwx owner of a directory
6 rw- owner of a file
5 r-x everyone else, on a directory
4 r-- everyone else, on a file
0 --- nothing

So 644 is owner read/write, everyone else read — the right default for files. 755 adds execute — the right default for directories (on a directory, "execute" means "may enter it"). 600/700 mean "only the owner", which is what wp-config.php and .env should be.

chmod: set permissions

bash
chmod 644 index.php          # one file
chmod 755 wp-content         # one directory
chmod 600 wp-config.php      # secrets: owner only

To fix an entire site in one go without giving files execute:

bash
cd /var/www/vhosts/example.com/httpdocs
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
chmod 600 wp-config.php

The symbolic form is handy for one change at a time — u owner, g group, o others, a all:

bash
chmod u+x deploy.sh      # let the owner run the script
chmod go-w config/       # remove write from group and others

chown: set the owner

Permissions are only half of it. If the web server runs as a different user than the one who owns the files, 644 still means "no write". On Plesk, PHP runs as the subscription's system user and the group is psacln:

bash
chown -R example:psacln /var/www/vhosts/example.com/httpdocs

On a plain Ubuntu box with Nginx and PHP-FPM, the user is usually www-data:

bash
chown -R www-data:www-data /var/www/example.com

Find out which user PHP actually runs as before you change anything:

bash
ps aux | grep -E 'php-fpm|httpd|apache2' | head

Why chmod 777 is never the fix

777 lets every account on the machine write to the file. On shared hosting, that is every other customer. On a VPS, it is any process that gets compromised — a vulnerable plugin can then rewrite your .htaccess, drop a web shell, and spread. Plesk and most malware scanners flag 777 for a reason. If something needs write access, give it to the right owner, not to the world.

Quick fixes for common errors

"Permission denied" when uploading in WordPress — the uploads directory is not owned by the PHP user:

bash
chown -R example:psacln wp-content/uploads
chmod 755 wp-content/uploads

"Failed to open stream: Permission denied" for a config file — the file is 600 and owned by someone else. Fix the owner, not the mode.

A script that "cannot be executed" — missing the x bit: chmod u+x script.sh.

Files created by root after a deploy — you ran git pull or composer install as root. Re-own the tree, and next time run deploys as the site user or with sudo -u example.

Directories deserve a second look

Two bits on directories confuse people:

  • Sticky bit (chmod +t /tmp) — anyone can create files, only the owner can delete their own. That is why /tmp shows as drwxrwxrwt.
  • setgid (chmod g+s dir) — new files inherit the directory's group. Useful on shared project folders so everything stays in psacln without re-running chown.

On VPSPioneer shared and reseller plans, ownership is set correctly at account creation and the File Manager shows the mode next to every file. On a managed VPS we set it up per site and put it right when a deploy breaks it — just open a ticket.

#linux#permissions#chmod#chown