Troubleshooting WordPress permissions errors on Linux hosts

WordPress permission errors usually manifest as a request for FTP credentials with the error message, “Connection Information: To perform the requested action, WordPress needs to access your web server. Please enter your FTP credentials to proceed. If you do not remember your credentials, you should contact your web host.” You generally do not need to enter these credentials. If you’re hosting WordPress on your own Linux server, read on to see what might be causing the problem, and how to fix it.

Connection Information Dialog
Connection Information Dialog

Directory Ownership/Permissions

Typical ownership permissions on a CentOS/RedHat/Fedora host should look like this:

# ls -la /var/www/html/
drwxr-xr-x.  5 apache apache  4096 Jan 14 16:16 .
drwxr-xr-x.  5 root   root     174 Jan 12 16:50 ..
-rw-r--r-x.  1 apache apache   151 Aug 26 20:57 .htaccess
-rw-r--r-x.  1 apache apache   418 Aug 26 16:38 index.php

The web server user name may be different on an Ubuntu or Debian host. Note that Apache owns the files, and has write access to the files. This is necessary if you want WordPress to update its own files, install plugins, etc. I would strongly recommend more restrictive permissions on the web directory for web applications or static web sites, when you specifically want to forbid a potentially compromised web server from altering files. I also recommend setting up separate web servers, in an environment completely isolated from other critical applications, when hosting vulnerable applications like WordPress.

SELinux Denials

SELinux denials are the second main reason WordPress asks for FTP credentials. On RedHat/CentOS/Fedora:

  1. In a terminal, using sudo or as root, run:
    ausearch -m avc --start recent

    If you see denials of the form

    type=AVC msg=audit(1547482570.350:117353): avc:  denied  { create } for  pid=20141 comm="httpd" name="blocks" scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=dir permissive=1

    then SELinux is blocking WordPress from accessing the directory it’s installed in.

  2. In the case of SELinux denials, run this command to temporarily set SELinux to Permissive only for web server files:
    semanage permissive -a httpd_t
  3. In WordPress, perform the desired operation
  4. Immediately run
    semanage permissive -d httpd_t

    to restore SELinux protections on files served by Apache.

I think this approach is more secure than making permanent context changes to Apache’s files. Only a few operations, such as optimizing the Wordfence firewall or installing a major WordPress upgrade, actually require this level of access. It’s best to restrict Apache most of the time.