Every file and directory on a Linux system has three properties that control who can access it: an owner, a group, and a set of permission flags. These determine whether a given user can read the file, write to it, or execute it. Get them wrong and your web server cannot read your site files, your PHP process cannot write uploads, or your private keys are exposed to other users on the system.
This guide covers how Linux permissions work, what the numeric values like 755 and 644 mean, how to change permissions with chmod, how to change ownership with chown, and the specific permission values that WordPress requires to function correctly.
How Linux permissions work#
Every file and directory has three attributes:
- Owner — the user who owns the file
- Group — a group of users who share access
- Permissions — what the owner, group, and everyone else can do with the file
You can see all three by running
ls -l
:
ls -l wp-config.php
Output:
-rw-r--r-- 1 www-data www-data 3065 Mar 19 14:00 wp-config.php
Breaking this down:
-rw-r--r-- 1 www-data www-data 3065 Mar 19 14:00 wp-config.php
│└──┬──┘│ │ │ │
│ │ │ │ owner group
│ │ │ │
│ │ │ number of hard links
│ │ │
│ │ └── others: r-- (read only)
│ └────── group: r-- (read only)
└────────── owner: rw- (read, write)
The first character indicates the type:
-
for a regular file,
d
for a directory,
l
for a symbolic link.
The three permission types
| Permission | Symbol | On files | On directories |
|---|---|---|---|
| Read |
r
| View file contents | List directory contents |
| Write |
w
| Modify file contents | Create, delete, rename files in the directory |
| Execute |
x
| Run as a program/script | Enter the directory (cd into it) |
Each permission type applies to three categories of users:
- Owner (u) — the user who owns the file
- Group (g) — users who belong to the file’s group
- Others (o) — everyone else on the system
Numeric (octal) permissions#
The numeric permission system represents each permission as a number:
| Permission | Value |
|---|---|
| Read (r) | 4 |
| Write (w) | 2 |
| Execute (x) | 1 |
| None (-) | 0 |
Add the values together to get the permission for each category. A three-digit number represents owner, group, and others (in that order).
Common permission values
| Value | Symbolic | Meaning |
|---|---|---|
| 755 | rwxr-xr-x | Owner: full control. Group and others: read and execute. Standard for directories. |
| 644 | rw-r–r– | Owner: read and write. Group and others: read only. Standard for files. |
| 600 | rw——- | Owner: read and write. Nobody else can access. Sensitive files like private keys and wp-config.php. |
| 640 | rw-r—– | Owner: read and write. Group: read only. Others: no access. Alternative for config files when the web server runs as a different user in the same group. |
| 700 | rwx—— | Owner: full control. Nobody else can access. Private directories like .ssh. |
| 744 | rwxr–r– | Owner: full control. Group and others: read only. Less common, sometimes used for scripts that only the owner should execute. |
| 666 | rw-rw-rw- | Everyone can read and write. Almost never correct. A security risk on production servers. |
| 777 | rwxrwxrwx | Everyone can do everything. Never use this on a production server. |
How to calculate the number
For owner read + write + execute: 4 + 2 + 1 = 7 For group read + execute: 4 + 0 + 1 = 5 For others read + execute: 4 + 0 + 1 = 5
Result: 755
For owner read + write: 4 + 2 + 0 = 6 For group read: 4 + 0 + 0 = 4 For others read: 4 + 0 + 0 = 4
Result: 644
chmod: changing permissions#
Basic syntax
chmod 644 file.txt
Sets
file.txt
to owner read/write, group read, others read.
Change permissions on a directory
chmod 755 /var/www/html
For directories, the execute bit (x) is required to enter the directory. A directory with 644 permissions is readable but you cannot
cd
into it or access any files inside it. This is why directories use 755 (not 644).
Change permissions recursively
chmod -R 755 /var/www/html
The
-R
flag applies the change to every file and directory inside the specified path. Be careful: this sets the same permission on both files and directories. For most web applications, files should be 644 and directories should be 755. Setting everything to 755 makes files executable, which is unnecessary and slightly less secure.
Set files and directories separately
To set directories to 755 and files to 644 in a single path:
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
The first command finds all directories (
-type d
) and sets them to 755. The second finds all files (
-type f
) and sets them to 644. This is the standard approach for fixing WordPress permissions.
Symbolic mode
Instead of numbers, you can use letters to add or remove specific permissions:
# Add execute permission for the owner
chmod u+x script.sh
# Remove write permission for group and others
chmod go-w file.txt
# Add read permission for everyone
chmod a+r file.txt
# Set exact permissions: owner rwx, group rx, others rx
chmod u=rwx,g=rx,o=rx directory
The letters:
-
u= owner (user) -
g= group -
o= others -
a= all (owner + group + others)
The operators:
-
+= add permission -
-= remove permission -
== set exact permission
Symbolic mode is useful when you want to change one specific permission without affecting the others. Numeric mode is better when you want to set all permissions at once.
Make a script executable
chmod +x script.sh
Without a user specifier,
+x
adds execute permission for owner, group, and others. This is the most common use of symbolic mode: making a script runnable.
chown: changing ownership#
Basic syntax
chown www-data file.txt
Changes the owner of
file.txt
to
www-data
. Requires root or sudo because changing file ownership is a privileged operation.
sudo chown www-data file.txt
Change owner and group
sudo chown www-data:www-data file.txt
The format is
owner:group
. This sets both the owner and group in one command.
Change group only
sudo chown :www-data file.txt
A colon with no owner before it changes only the group.
Or use
chgrp
:
sudo chgrp www-data file.txt
Change ownership recursively
sudo chown -R www-data:www-data /var/www/html
The
-R
flag changes ownership of the directory and everything inside it: all subdirectories and all files. This is the command you run after extracting a WordPress backup or moving files between servers, because the extracted files are typically owned by root or whatever user performed the extraction.
Why chown requires sudo
Changing file ownership is restricted to root. Without this restriction, any user could claim ownership of another user’s files. This is a fundamental security boundary in Linux. If you get “Operation not permitted,” add
sudo
:
# This fails for non-root users
chown www-data file.txt
# This works
sudo chown www-data:www-data file.txt
Find the current owner
ls -la /var/www/html/wp-config.php
The third and fourth columns are the owner and group. On a properly configured WordPress server, these should match the user PHP-FPM runs as (usually
www-data
on Ubuntu/Debian,
nginx
or
apache
on CentOS/RHEL).
Find your user ID
Some tools (like SFTP’s chown command) require the numeric user ID instead of the username. See SFTP commands: a complete reference guide for how SFTP handles permissions. To find the ID:
id www-data
Output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
The
uid
is the numeric user ID (33 for www-data on Ubuntu).
WordPress file permissions#
WordPress has specific permission requirements. The PHP process needs to read all WordPress files and write to certain directories. Getting this wrong either breaks functionality or creates security holes.
Recommended WordPress permissions
| Path | Permission | Owner | Why |
|---|---|---|---|
| All directories | 755 | www-data | PHP needs to enter and list directories |
| All files | 644 | www-data | PHP needs to read files |
| wp-config.php | 600 or 640 | www-data | Contains database password. No one except the owner (and optionally group) should read it. |
| wp-content/uploads/ | 755 | www-data | PHP needs to write uploaded files here |
| wp-content/cache/ | 755 | www-data | Caching plugins write here |
Setting WordPress permissions correctly
# Set ownership to the web server user
sudo chown -R www-data:www-data /var/www/html
# Set directory permissions
find /var/www/html -type d -exec chmod 755 {} \;
# Set file permissions
find /var/www/html -type f -exec chmod 644 {} \;
# Lock down wp-config.php
chmod 600 /var/www/html/wp-config.php
Why 777 is never the answer
When WordPress shows an error like “The uploaded file could not be moved to wp-content/uploads”, the temptation is to set permissions to 777 to “fix” it. This works because 777 means everyone can do everything, but it also means:
- Other users on a shared server can read your wp-config.php (which contains your database password)
- Other processes can modify your WordPress files (injection point for malware)
- Upload directories become executable (attackers can upload and run PHP scripts)
The correct fix is to ensure the file owner matches the PHP-FPM user, not to open permissions to everyone. If WordPress cannot write to the uploads directory, the problem is almost always ownership (chown), not permissions (chmod).
SSH key file permissions
SSH is strict about key file permissions. If your private key file is readable by anyone other than the owner, SSH refuses to use it:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Required permissions:
| File | Permission |
|---|---|
~/.ssh/
| 700 |
~/.ssh/id_ed25519
(private key) | 600 |
~/.ssh/id_ed25519.pub
(public key) | 644 |
~/.ssh/authorized_keys
| 600 |
~/.ssh/config
| 600 |
Set them:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/authorized_keys
See the SSH Keys knowledge base page for generating and configuring SSH keys.
Common scenarios#
Fix permissions after extracting a backup
After extracting a tar archive or copying files between servers, the files are often owned by root or by the user who performed the extraction:
sudo chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
chmod 600 /var/www/html/wp-config.php
Fix permissions after a plugin install fails
If a WordPress plugin or theme installation fails with a permissions error, the uploads directory may have wrong ownership:
sudo chown -R www-data:www-data /var/www/html/wp-content
Check who PHP-FPM runs as
The PHP-FPM pool configuration defines the user:
grep "^user" /etc/php/8.3/fpm/pool.d/www.conf
Output:
user = www-data
All WordPress files should be owned by this user.
Find files with wrong permissions
Find all files that are not 644:
find /var/www/html -type f ! -perm 644
Find all directories that are not 755:
find /var/www/html -type d ! -perm 755
Find files owned by root (which is usually wrong for web content):
find /var/www/html -user root
Check permissions on a specific path
namei -l /var/www/html/wp-content/uploads
namei
shows the permissions of every directory in the path. This is useful when something deep in a directory tree is inaccessible — the problem might be a parent directory, not the file itself. If any directory in the path lacks the execute bit for the relevant user, everything below it is inaccessible.
File permissions on Hostney#
On Hostney, each account runs in an isolated container where your files are owned by your account user. PHP-FPM runs as the same user, so ownership conflicts between the web server and your files do not occur.
File permissions are set correctly during WordPress installation. If you need to adjust them (for example, after uploading files via SFTP or extracting an archive), you can do so via SSH from the Terminal Access section in the control panel, or through the file manager.
The standard permissions (755 for directories, 644 for files) apply on Hostney the same as on any Linux server. The container isolation means that even if a file has group or world-readable permissions, other accounts on the platform cannot access it.