Wrong file permissions cause two kinds of WordPress problems: too strict, and you get “Could not create directory” errors or FTP prompts during updates; too loose (the infamous 777), and any compromised plugin or other site can modify your files. Here’s how to set them correctly on a Linux VPS.

Background: Linux file permissions explained.

The standard setup

On a typical Nginx or Apache server, PHP-FPM runs as www-data (Debian/Ubuntu) or nginx/apache (RHEL family).

Path Owner:group Permission
Directories www-data:www-data (or youruser:www-data) 755 (or 750)
Files same 644 (or 640)
wp-config.php same 640 or 600
.htaccess (Apache) same 644

Apply it:

cd /var/www/example.com
sudo chown -R www-data:www-data .
sudo find . -type d -exec chmod 755 {} \;
sudo find . -type f -exec chmod 644 {} \;
sudo chmod 640 wp-config.php

See chown and chmod.

With this setup, WordPress can update itself, install plugins and upload media directly, without asking for FTP details.

Never use 777

777 means any user and any process on the server can write the files. On a VPS with several sites or users, one compromised site can then infect the others. If a guide or plugin tells you to use 777, fix the ownership instead: the web server user needs to own the files (or be in a group with write access). 777 is never needed.

“Could not create directory” or FTP credential prompts

WordPress checks whether it can write files as the PHP user. If not, it asks for FTP details or fails to update. Fix it:

ps aux | grep php-fpm | grep -v root | head -2      # which user runs PHP?
sudo chown -R www-data:www-data /var/www/example.com

If you deliberately keep files owned by another user, you can add to wp-config.php:

define( 'FS_METHOD', 'direct' );

This only works if PHP can actually write the files.

A hardened alternative: separate owner and PHP user

For stricter security, the files are owned by a deploy user, and PHP gets write access only where it needs it:

sudo chown -R deploy:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 750 {} \;
sudo find /var/www/example.com -type f -exec chmod 640 {} \;
# writable only for uploads (and cache dirs if your plugins need them)
sudo chown -R www-data:www-data /var/www/example.com/wp-content/uploads

Then PHP (and malware running through it) can’t modify core, theme or plugin files. The trade-off: dashboard updates and plugin installs no longer work. You update with WP-CLI as the deploy user, or through Git deployments:

sudo -u deploy wp core update && sudo -u deploy wp plugin update --all

See WordPress Git deployment and WP-CLI guide.

One site, one PHP-FPM pool

If you host several sites, give each its own Linux user and PHP-FPM pool, so a hack on one site can’t touch the others:

; /etc/php/8.3/fpm/pool.d/example.conf
[example]
user = example
group = example
listen = /run/php/php8.3-fpm-example.sock
listen.owner = www-data
listen.group = www-data

Point that site’s Nginx fastcgi_pass at its own socket. See PHP-FPM tuning.

Protect sensitive files in the web server

Permissions control who on the server can read files. The web server config controls what visitors can fetch. Block access to wp-config.php, hidden files and PHP in uploads. See the ideal Nginx config for WordPress.

Check your permissions

find /var/www/example.com -perm -o+w -ls      # anything world-writable? should be empty
stat -c '%a %U:%G %n' /var/www/example.com/wp-config.php

Quick reference

Item Setting
Directories 755 (or 750)
Files 644 (or 640)
wp-config.php 640 / 600
Owner PHP user (e.g. www-data), or a deploy user + writable uploads
Never 777

Related: WordPress hardening and WordPress malware removal.

  • WordPress
  • Security
  • Linux