Ahosting Logo
Knowledge Base

Understanding File Permissions and Ownership

Two values cover essentially every normal website644 on files755 on directories777 on anythingOwnerread and writeread, write, entereverythingEveryone elsereadread and enterread, write, executeMeansthe server can serve itthe server can traverse itany process on the servercan rewrite it777 is not a fix for a permissions error. It is a way of making the error stop being reported.

Every file on the server carries permissions saying who may read it, write to it, or execute it. Getting them wrong produces two failures: a site that does not work, or a site anyone can modify.

The numbers look cryptic and the system underneath is small enough to learn in a few minutes.

Reading the numbers

Three digits, for three groups: owner, group, everyone else.

Each digit is a sum: read is 4, write is 2, execute is 1.

So 7 is read, write and execute (4+2+1). 6 is read and write. 5 is read and execute. 4 is read only.

Read 644 as: the owner can read and write, everyone else can only read. And 755 as: the owner can do everything, everyone else can read and traverse.

The two values you need

644 for files. The owner edits them, the web server reads them.

755 for directories. On a directory, execute means "can enter", so a directory without it cannot be opened even if its contents are readable.

That is the correct arrangement for essentially every normal website, and a fresh upload usually produces it.

Why 777 is never the answer

It appears constantly in old forum advice as a fix for upload problems and permission errors. It works, and it works by making the file writable by anyone on the server.

On shared hosting that means other accounts. A file at 777 can be modified by a script running under a different account, and that is how one compromised site infects its neighbours.

If something only works at 777, the real problem is ownership rather than permissions, see below. Setting 777 does not fix that; it hides it behind an exposure.

Ownership matters more than permissions

This is the part the numbers do not show, and it is behind most confusing permission errors.

Every file has an owner. Permissions are evaluated relative to that owner, so 644 means something different depending on who owns the file.

When a file uploaded by FTP is owned by your account and the web server runs as your account too, everything works. When a file was created by a different process (a restore, a script, a tool running as another user) the ownership can be wrong, and no amount of changing permissions helps.

The symptom is a permission error on a file whose permissions are plainly correct. That is an ownership problem, and on shared hosting it needs support to fix.

Configuration files

Files holding database credentials deserve tighter permissions than the rest.

wp-config.php and its equivalents work at 600 on most setups, owner only, nothing for anyone else. Some server configurations need 640 or 644 instead, depending on how PHP runs.

Try 600 first. If the site breaks, step up to 640, then 644. Do not go past 644, and never leave a configuration file group- or world-writable. Understanding wp-config.php goes into what is in the file that matters.

Setting them in cPanel

In File Manager, right-click a file and choose Change Permissions. You get checkboxes and the resulting number, which is a good way to build an intuition for the digits.

For a whole tree, use the recursive option carefully: applying 755 to everything makes files executable, and applying 644 to everything makes directories unenterable, which breaks the site immediately.

Files and directories need different values, so a single recursive change is almost always wrong. Do them separately.

From the command line

The correct way to fix a whole tree, in two commands:

find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;

Files first, directories second, each with its own value. This is the standard repair for a site whose permissions were mangled by a bad recursive change. For getting a shell, see cPanel terminal and SSH access.

When uploads fail

An application that cannot write uploads usually needs the directory writable, not the files.

On most cPanel hosting, 755 is sufficient because the web server runs as your account. The advice to use 777 for upload directories comes from setups where it does not.

Try 755 first. If it genuinely does not work, the cause is ownership, and that is a support question rather than a permissions one.

Files that should not be reachable at all

Permissions control who may read a file. They do not control whether the web server serves it.

A database export in public_html at 644 is readable by the web server, which means anyone who guesses the filename can download your entire database, permissions did exactly what they were told.

The fix is placement, not permissions: keep anything that is not part of the website above public_html, where the web server does not look. For the directory layout, see uploading website files.

A quick diagnostic

403 Forbidden on a whole directory: the directory is missing execute, so it cannot be entered. Set 755.

403 on one file: the file is not readable. Set 644.

500 error after uploading: on some configurations, a file or directory that is group- or world-writable is refused outright. 644 and 755 resolve it.

"Permission denied" with correct-looking permissions: ownership. Not something you can fix by changing numbers.

One directory needs more than correct permissions, because the files in it were chosen by strangers. How to Set Up a File Upload Directory Safely goes into it.

The execute bit means something different on a directory

The same bit does two unrelated jobs, and confusing them produces permission errors that look impossible.

On a file it means the file may be run. On a directory it means the directory may be entered, so a directory without it cannot be traversed even if everything inside is readable.

ls -ld ~/public_html ~/public_html/assets
namei -l ~/public_html/assets/style.css

The second command walks the whole path and prints the permissions at each level, which is how you find the one directory in the middle that blocks access to everything below it.

That is the usual cause of a file that is plainly readable and still returns a forbidden error. The file is fine and one parent directory is not.

Why new files come out with the wrong permissions

Files created by different routes get different owners and different modes, which is why a site works until somebody uploads by another method.

A file written by the web server belongs to the web server. One uploaded over FTP belongs to the account. One created by a shell session belongs to whoever was logged in. Each also gets a mode derived from the creating process rather than from the directory.

umask
ls -l ~/public_html/uploads | head
find ~/public_html -newermt '-1 day' ! -user "$(whoami)" 2>/dev/null | head

The last command finds recently created files that do not belong to the account, which is the fastest way to spot a mixed ownership problem before it produces failures.

Fixing the existing files matters less than fixing what creates them. Corrected by hand, the same problem returns with the next upload.

The bits that most people never set deliberately

Beyond the familiar three, two more exist and one of them is genuinely useful on a shared directory.

Setgid on a directory makes everything created inside it inherit the directory's group instead of the creator's. That is how a directory written to by more than one process stays consistently readable, rather than acquiring files nobody else can open.

chmod g+s /path/to/shared
ls -ld /path/to/shared
find ~ -perm -4000 -type f 2>/dev/null | head

The last command lists files that run as their owner rather than as the person running them. On a hosting account there should be none, and anything that appears there is worth understanding immediately, because that is exactly what an intruder leaves behind. Securing your hosting account goes into the rest.