Linux file permissions on a VPS: chmod, chown and Permission denied

A “Permission denied”, or a 403 on a website, is almost always one of two things: the file’s owner is not who the service runs as, or a permission is missing on the file or on one of the folders in its path. See with ls -l who owns it and what is allowed, and with namei -l /full/path the first folder in the path that blocks. You fix it with chown (change the owner) and chmod (change the permissions). On an unmanaged VPS this is yours to do.

Reading what ls -l says

A line like -rw-r--r-- 1 deploy www-data 1200 Oct 10 site.php has three parts. The first ten characters are the type and permissions (- file, d folder; then three groups of three: owner, group, others, each with r read, w write, x execute). Then come the owner (deploy) and the group (www-data).

Number Meaning When to use it
644 Owner reads and writes; group and others only read A site’s files
755 Owner reads, writes, executes; others read and execute Folders, and programs
600 Only the owner reads and writes Secrets: keys, files with passwords
700 Only the owner gets in Private folders, like ~/.ssh
777 Everybody does everything Never. It cures the symptom and opens the door to whoever gets in through any other site.

Step by step for a site giving 403 or “Permission denied”

1 Find out who the service is. ps aux | grep -E "nginx|apache|httpd|php-fpm" | head. On Debian and Ubuntu it is usually www-data; on AlmaLinux and Rocky, nginx or apache.
2 Look at the whole path. namei -l /var/www/yourdomain.tld/public/index.php shows the permissions of each folder down to the file. The server must be able to traverse (x permission) every folder in the path, not just read the file. A closed home folder (/home/user at 700) blocks everything inside it.
3 Set the owner right. If the site is managed by a user of yours and served by another, give the right group: sudo chown -R deploy:www-data /var/www/yourdomain.tld. Or let the service own only the folders it must write to (uploads, caches).
4 Set the permissions to sensible values: sudo find /var/www/yourdomain.tld -type d -exec chmod 755 {} \; and sudo find /var/www/yourdomain.tld -type f -exec chmod 644 {} \;.
5 Give write access only where needed. An uploads folder needs write for the service (for example chmod 775 with the service’s group); the rest of the site does not.
6 Test again and read the error log. If it is still denied once everything is right, it may be SELinux or AppArmor: when they block a service.
Mind the -R in the wrong place. chown -R or chmod -R on a folder higher up than you meant (the root /, /etc, /home) can break the whole system: SSH stops accepting keys with loose permissions, and system programs need their owners. Read the path twice before pressing Enter.
Do not make root the owner of the site. If a root task writes into the folder, the files end up root’s and the site cannot change them. Run that task as the right user: cron that does not run.
Secrets want 600: a .env file with passwords is read only by its owner (environment variables and secrets). And a systemd service runs as whichever user you give it: running your own program as a service.

Locked yourself out by touching system permissions? The panel console gets you in without the network: tell us what you did.

Open a support ticket

SEE ALSO

SELinux or AppArmor blocking a service

Running your own program as a systemd service

Environment variables and secrets

Keeping your VPS secure

RECOMMENDED PRODUCT

VPS server with root access

Resources of your own, the OS you choose, reinstall whenever you like. from $8.40/mo (3-year plan, with coupon)

See plans
  • 0 Users Found This Useful
Was this answer helpful?