Which wordpress should be obligatory writeable?

There is no definitive answer to this, but I’d like to share my 2 cents anyways.

In practice, many plugins write to custom folders in ./wp-content/. Just checking one client site I see 6 custom folders in there (e.g. from security, backup, caching plugins, etc.).

Some themes and plugins may even expect that they are able to write inside their own folder (inside ./wp-content/themes/foo/ or ./wp-content/plugins/bar/), so restricting file access within ./wp-content/ will usually lead to problems.

Depending on the project, I usually do a mix of the following:

  1. Have wp-config.php one level below the webroot. WordPress supports this out of the box and I consider it good practice to avoid accidental leakage of secure credentials.
/var/www/
        |- wp-config.php
/var/www/html/
             |- index.php
             |- wp-activate.php
             ...
  1. Make wp-config.php read-only. This way you avoid hacks that read the file, remove restrictive elements, and overwrite it.

  2. Set DISALLOW_FILE_EDIT (disallows editing via the editor in wp-admin) and DISALLOW_FILE_MODS (disallows any plugin/theme/core updates).

  3. Regularly scan your complete installation and compare against original files. (Most security plugins have features of this, beware that this might be resource-intensive, so you might want to do it automated at night.)

  4. Force secure passwords and if possible even 2FA for all backend users. (Forcing it for admins is a start, but there are “privilege escalation” scenarios, so forcing it for all users that have backend-access is usually best.)

  5. Use advanced setups like Roots’ Bedrock. If you manage your dependencies (core, plugin, theme) via composer, it is much easier to setup a new site. Bedrock also separates core from custom files better, so you can use more restrictive file-access.

  6. Make related services internal. E.g. your DB and Redis do not need to be public, but only be accessible by WP itself.