Strict file ownership for your WordPress installation

WordPress requires write access to one directory, and that one directory only: the directory returned by wp_upload_dir(). By default, this is /wp-content/uploads, but it can be configured to anything that is beneath your document root, like /media, if you want to.

But since you want WordPress itself, plugins etc, to be updatable you can’t just make everything but the uploads directory to be non-writable.

A better solution is to use separate users for the separate matters.

Setup PHP-FPM (or HHVM) to run scripts as an arbitrary user. The users “www-data” and “www-user” are common ones. It’s best to avoid using the same user as your web server runs as, which probably is “nginx” (look in nginx.conf). I’m using “www-user” here, but note that this should be a separate user per site/pool, so the sites does not have write access to each others’ files.

Edit the user and group directives in your “pool” file (/etc/php5/fpm/pool.d/www.conf is the default on Ubuntu):

Then you make the upload folder owned by that user (replace path according to your WordPress setup):

All other files and folders should be owned by a regular user on your system – the user you are using to deploy updates to WordPress and plugins.

All folders should have the permissions 0755 and files should have 0644 as usual:

Updates with strict file ownership

Now, it is not possible to write to any of the files outside of the uploads directory via the webserver. But you still need to be able to manage and update plugins, themes and WordPress itself.

Either you use:

  • Some kind of deployment system, like Capistrano or Deploybot
  • Pull manually with a version control system, like Git
  • Use WP-CLI, either manually or in a cronjob

You should go for the solution that suits your strategy. Here are two generalisations to help you define a strategy:

  1. You trust nobody. All code, even security fixes, should be examined before put in production.If this is the case, you certainly don’t want to run automatic updates, but use some kind of deployment system.
  2. The “better to risk untested code than leave production unpatched” strategy. You trust the authors of WordPress and the plugins you use.If this is the case, you can well use WP-CLI with a cronjob that runs every ten minutes that updates everything:

    (You probably also want to use a pre-upgrade backup, a post-upgrade health check, and a rollback if needed if you go this route.)

    Please note that some premium plugins does not support being upgraded via WP-CLI. E.g. I know BackupBuddy and Gravity Forms works fine, but the plugins from Yoast does not.

BTW, strategy 2 is basically the same as the automatic updates feature in WordPress.

A helpful WordPress config directive

To not confuse users in the WordPress dashboard to think they actually can do updates or install plugins directly, is is possible to add a constant to wp-config.php to disable plugin and theme update and installation.

This will remove links and buttons in the WordPress dashboard to actions that requires file modification permissions.

There are 2 comments

I love comments that bring new insights, shares ideas and experiences, and most of all: corrects my mistakes. For support questions, there are other fora, like Stack Overflow, Server Fault and the WordPress support forum.

Your email address will not be published. Required fields are marked *