I’ve been frustrated lately with the number of tutorials for installing WordPress on CentOS 7 that say to simply turn SELinux off. This is an unacceptable workaround. It’s simply lazy administration. SELinux is not designed to make your job harder (although it can do that pretty well), it’s there to make your system safer.
I have scoured the internet and pieced together bits of information from several sources – mainly here, here, and here to put together a tutorial that walks you through how to install WordPress in CentOS7 while keeping SELinux turned on.
It took a lot of reading to understand SELinux, but once you understand it, it makes a whole lot more sense. Go figure.
Apache
Install required packages:
sudo yum -y install httpd sudo systemctl enable httpd
Modify apache config to allow mod_rewrite:
sudo sed -i /etc/httpd/conf/httpd.conf -e 's/AllowOverride None/AllowOverride All/g'
Open necessary firewall ports:
sudo firewall-cmd --add-service=http --permanent sudo systemctl restart firewalld
Start apache:
sudo systemctl start httpd
Navigate to your new site to make sure the testing page comes up.
Update 11/4/2016: If you are behind a reverse proxy such as varnish or a web application firewall, you will want to modify your apache configuration to log x-forwarded-for IPs to make the logs more meaningful:
sudo sed -i /etc/httpd/conf/httpd.conf -e 's/%h/%{X-Forwarded-For}i/g'
MariaDB
Install:
sudo yum -y install mariadb-server mariadb sudo systemctl enable mariadb
Run initial mysql configuration to set database root password
sudo systemctl start mariadb sudo mysql_secure_installation
Create a wordpress database and user:
mysql -u root -p
#enter your mysql root password here
create user wordpress;
create database wordpress;
GRANT ALL PRIVILEGES ON wordpress.* To 'wordpress'@'localhost' IDENTIFIED BY 'password';
quit;
WordPress
Install PHP and restart apache
sudo yum -y install php php-mysql php-gd php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-snmp php-soap curl sudo systemctl restart httpd
Configure base wordpress directory
Download, extract, and set permissions for your wordpress installation:
wget https://wordpress.org/latest.zip sudo unzip latest.zip -d /var/www/html sudo chown apache:apache -R /var/www/html/wordpress
Optional: Change Apache document root so you don’t need to tack /wordpress at the end of the url:
sudo sed -i /etc/httpd/conf/httpd.conf -e 's/DocumentRoot \"\/var\/www\/html/&\/wordpress/g' sudo systemctl restart httpd
Configure upload directory
If you want users to upload content, then you will want to assign the http_sys_rw_content_t selinux security context
for the wp-uploads directory (create it if it doesn’t exist)
sudo mkdir /var/www/html/wordpress/wp-content/uploads sudo chown apache:apache /var/www/html/wordpress/wp-content/uploads sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/wordpress/wp-content/uploads(/.*)?" sudo restorecon -Rv /var/www/html/wordpress/wp-content/uploads
Run the wizard
In order for the wizard to run properly we need to temporarily give the wordpress directory httpd_sys_rw_content_t selinux context
sudo chcon -t httpd_sys_rw_content_t /var/www/html/wordpress/
Now navigate to your new website in a browser and follow the wizard, which will create a wp-config.php file inside the wordpress directory. Once your site is properly set up, restore the original security context for the wordpress directory:
sudo restorecon -v /var/www/html/wordpress/
Success! Everything is working within the proper SELinux contexts.
Troubleshooting
Permission denied when accessing /wordpress
The obvious thing to check is to make sure the directory /var/www/html/wordpress has the ownership set to apache. That didn’t fix my issue, though. Thanks to serverfault I narrowed this down to a selinux permissions issue. Changing the selinux context to httpd_sys_content_t for the wordpress folder fixed the issue.
sudo semanage fcontext -a -t httpd_sys_content_t /var/www/html/wordpress/ sudo restorecon -v /var/www/html/wordpress/
Sorry, but I can’t write the wp-config.php
file.
“You can create the wp-config.php
manually and paste the following text into it.”
I had a suspicion that writing files was also a selinux issue. This was confirmed when I decided to tail /var/log/audit/audit.log and found this when the wordpress installer tried to write wp-config.php:
type=AVC msg=audit(1475596102.558:16868): avc: denied { write } for pid=5751 comm="httpd" name="wordpress" dev="dm-0" ino=68494934 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=dir type=SYSCALL msg=audit(1475596102.558:16868): arch=c000003e syscall=21 success=no exit=-13 a0=7f9f4b931478 a1=2 a2=0 a3=1 items=0 ppid=5740 pid=5751 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)
This led me to find this great explanation from Francis Pereira on how to get wordpress and selinux to peacefully coexist. Also thanks to the excellent Redhat Manual for more information on what to do, combined with this very helpful guide from serverlab.
First, we need to temporarily grant httpd_sys_rw_content_t
to the wordpress directory. This is to allow the initial wizard to create the wp-config.php file.
sudo chcon -t httpd_sys_rw_content_t /var/www/html/wordpress/
Now you can run the wizard and it will work properly.
Once your site is set up, restore the context to http_sys_content_t
sudo restorecon -v /var/www/html/wordpress/