In this post, I’ll detail a step by step process to set up WordPress on a fresh install of CentOS 7. SELinux will be enabled and in a virtual host.

After changing providers, I had to migrate my site and couldn’t find a guide that I was happy with. Some were not complete, some directly disabled SELinux, … so I chose to write my own. Also, disabling SELinux is a big NO-NO in my book.

The steps to follow are:

  1. Add users
  2. Install Apache
  3. Check and configure the firewall
  4. Install MySQL and PHP
  5. Create virtual hosts
  6. Configure SELinux
  7. Install WordPress


First things first, we’ll add a user and add him to the sudoers. This way, we won’t need to be root.

As root user:

# adduser dummyuser
# passwd dummyuser

Add dummyuser to sudoers:


Find the following part:

## Allow root to run any commands anywhere
root ALL=(ALL) ALL

Add the following line after that:

dummyuser ALL=(ALL) ALL

Log off and log in again as dummyuser, and go on.


sudo yum install httpd

After the installation is complete, start Apache and check if it’s working or not.

sudo systemctl start httpd.service

Launch a browser and visit the root page of the server. You should see a welcome page.


Whether it worked or not, it’s time to check firewall status:

firewall-cmd --state

If the result is running and you can see apache’s test site, you can skip the following steps up to the next section. Otherwise, we’ll have to configure and enable it.

A little safeguard in case we do something wrong and end up locked out of our server (can be safely skipped when working locally)

sudo shutdown -r 30

This will reboot the server in 30 minutes, losing every change that wasn’t permanent. In case you mess up and get locked out, go grab a coffe and carry on later. To cancel the reboot:

sudo shutdown -c

This safeguard is not strictly necessary, but I prefer to be safe when working remotely, and a reboot is allowed. You should be careful with timing. When it runs out, the server will reboot losing not saved changes. Adjust the timing to your needs or refresh the timing by cancelling the reboot and programming a new one.
I’ve taken up this practice when working with remote equipment (not your typical server room) Being looked out means someone commutes for 2 hours to work revert changes. Better safe than sorry.

If the firewall service was not running, we’ll check again with it running:

sudo systemctl start firewalld.service
firewall-cmd --state

Now we should have it in a running state.

firewall-cmd --get-default-zone

Returns public which is fine, as it’s the least trustworthy zone that actually allows some connections from the outside.

firewall-cmd --list-all

Returns the services allowed, that on a fresh install shoudl be few.

Now we’ll add http service:

sudo firewall-cmd --zone=public --add-service=http

This command should return success

Just to recheck, if we repeat firewall-cmd --list-all, it should have added http service.

As a bonus, firewall-cmd --get-services lists currently predefined services

Once tested that the configuration is correct, make all changes permanent so they’ll remain after a reboot:

sudo firewall-cmd --permanent --zone=public --add-service=http

This command should return success

Finally, enable the firewall so it starts on boot:

sudo systemctl enable firewalld


Now that apache is finaly working and accesible from the outside, enable it so it starts on boot:

sudo systemctl enable httpd.service


Now we’ll install the database and PHP.

sudo yum install mariadb-server mariadb
sudo systemctl start mariadb

This last step takes care of securing some defaults.
As it’s freshly installled, mysql will probably not have a password for it’s user root.

Let’s enable mysql on system start:

sudo systemctl enable mariadb.service

Now we’ll install PHP;

sudo yum install php php-cli php-common php-gd php-intl php-mbstring php-mysql php-pear php-pdo php-pecl-memcache php-xml

And restart apache:

systemctl restart httpd.service


Time to check if PHP is working correctly. Create a simple page with your editor of choice:

vi /var/www/html/info.php

And the actual content:


Browse test page, and check whether mod_rewrite is enabled or not (it will come handy later)

After checking everythings working, remove the test file:

rm /var/www/html/info.php


Create directory structure for Virtual Hosts:

sudo mkdir -p /var/www/vhosts/
sudo mkdir -p /var/www/vhosts/
sudo mkdir -p /var/www/vhosts/

Set up permissions:

sudo chown -R $USER:$USER /var/www/vhosts/
sudo chown -R $USER:$USER /var/www/vhosts/
sudo chown -R $USER:$USER /var/www/vhosts/

$USER will take the currently logged user value (no need to change it)

sudo chmod -R 755 /var/www


Time to test Virtual Hosts:
Create a demo page for each virtual host

vi /var/www/vhosts/

A simple demo page:

    <title>Virtual Host for!</title>
    <h1>The virtual host is working!</h1>

Create a different file for each virtualhost you want to create, replace the name accordingly.

sudo mkdir /etc/httpd/sites-available
sudo mkdir /etc/httpd/sites-enabled
sudo vi /etc/httpd/sites-available/

As a simple example, this .conf could look like:

<VirtualHost *:80>
DocumentRoot /var/www/vhosts/
ErrorLog /var/www/vhosts/
CustomLog /var/www/vhosts/ combined

For each virtual host, add the corresponding .conf file.


To enable virtual hosts:

sudo vi /etc/httpd/conf/httpd.conf

Add at the end:

# Include virtual hosts
IncludeOptional sites-enabled/*.conf

To make a site go live, make a link from sites-available to sites-enabled:

sudo ln -s /etc/httpd/sites-available/ /etc/httpd/sites-enabled/

And restart Apache:

sudo systemctl restart httpd.service

For disabling a site, just remove the link and restart Apache.


SELinux won’t allow httpd to write in our custom log location. Now we’ll configure it properly:

sudo yum install setools setroubleshoot

sudo semanage fcontext -a -t httpd_sys_content_t "*)?"
sudo semanage fcontext -a -t httpd_log_t "*)?"
sudo restorecon -Rv

sudo semanage fcontext -a -t httpd_sys_content_t "*)?"
sudo semanage fcontext -a -t httpd_log_t "*)?"
sudo restorecon -Rv

sudo semanage fcontext -a -t httpd_sys_content_t "example2(/.*)?"
sudo semanage fcontext -a -t httpd_log_t "example2/logs(/.*)?"
sudo restorecon -Rv


If there’s any problem with SELinux policies

sealert -a /var/log/audit/audit.log

will parse the log and provide hints at problems and possible solutions.

If you are note sure whether the problem is SELinux related or not, the policy can be set to permissive, so the system will not enforce the SE policies but will log them.

sudo setenforce permissive

To check those logs:

sealert -a /var/log/audit/audit.log

will parse SELinux related problems and propose solutions.
Finally, remember to ALWAYS set to enforcing mode.

sudo setenforce enforcing


Finally, it’s time to install WordPress. The first step will be to create the database:

mysql -u root -p
CREATE USER wordpressuser@localhost IDENTIFIED BY 'wpuserpassword';
GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost IDENTIFIED BY 'wpuserpassword';

This will ask for root password that was set up while securing the database. wordpress wordpressuser wpuserpassword can should be changed to your needs.

Now, we’ll download the latest WordPress version:

tar -zxvf latest.tar.gz

Next, create the final directory, copy WordPress and create Uploads directory:

sudo mkdir /var/www/vhosts/
sudo chown dummyuser:apache

sudo rsync -avP /home/dummyuser/wordpress/ /var/www/vhosts/

mkdir /var/www/html/wp-content/uploads


cd /var/www/vhosts/
cp wp-config-sample.php wp-config.php
vi wp-config.php

Change DB_NAME DB_USER DB_PASSWORD to your version of wordpress wordpressuser wpuserpassword
Change the authentication keys and salts to the values you get in: WordPress API Salt

Optionally, $table_prefix can be modified. It will usually not be neccesary, but if you intend on sharing the same database with multiple wordpress installations, this identifier must be unique and different for all of them.

Apache should be allowed to write on wp-content so SELinux context should be modified:

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/vhosts/*)?"
sudo restorecon -Rv ./

During the installation, Apache should be able to modify wp-config.php

sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/vhosts/"
sudo restorecon -Rv ./

Now, WordPress should be up and running, ready to configure from the web interface with your preferred theme, plugins, users, … Hint: If an error appears asking for FTP user / password credentials when installing new plugins or themes, modify wp-config.php and add the following:

/** Error installing plugins and themes. System asks for FTP user / password
define('FS_METHOD', 'direct');

Optionally (but I would recommend it), after your changes have taken place, you should return wp-config.php to it’s previous context, so no writing will happen without your knowledge.

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/vhosts/"
sudo restorecon -Rv ./

Happy Blogging

Did you find the post useful? Would you invite me to a nice coffe or offer some help running the site ad-free?