Configuring WSGI on Ubuntu/Centos

Reading Time: 3 minutes

This article outlines the process of configuring a server for Python 3 web applications with Apache 2.4 using mod_wsgi. 

What is mod_wsgi?

Mod_wsgi is an Apache module that allows Python web applications to function on a server. This module provides a web framework for Flask, Django, and other Python based frameworks to operate within a production environment on a server.


  • A CentOS or Ubuntu server
  • Apache 2.4, apache-dev/httpd-devel and python3-dev installed
  • Python 3, pip3, and virtualenv installed
  • Access to a terminal

If you do not have the above prerequisites installed, this build will not work as expected. The following commands can be used to install the prerequisites

apt install apache2 apache2-dev python3 python3-dev python3-pip

pip3 install virtualenv

Step 1

Begin by downloading the source files for mod_wsgi.i

root@host [~]# wget

Next, unpack the archive

root@host [~]# tar -xzvf 4.6.5.tar.gz

Enter the source files directory

root@host [~]# cd mod_wsgi-4.6.5

Next, determine the path to the Python interpreter.

root@host [~]# which python3
root@host [~]# 

Configure the installation and define the Python interpreter for mod_wsgi.

root@host [~]# ./configure --with-python=/usr/bin/python3
checking for apxs2... no
checking for apxs... no
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/usr/src/mod_wsgi-4.6.5':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

Now, run the following commands to compile the package.

root@host [~]# make && make install

The path to where the module was installed will be at the end of the output from the last command.

root@host [~]# /usr/lib/apache2/modules/

Use the path noted above to load the module into Apache by adding the following snippet to the bottom of the apache.conf or httpd.conf

LoadModule wsgi_module /usr/lib/apache2/modules/

Now test the syntax and restart Apache.

Debian/Ubuntu based systems:

root@host [~]# apache2 -t
root@host [~]# service apache2 restart

RHEL/CentOS based systems:

root@host [~]# httpd -t
root@host [~]# service httpd restart

Step 2

Now that mod_wsgi has been installed, let’s take a look at the configuration. We will begin by creating a basic Python web application to detail the steps to configure mod_wsgi.

First, let’s create a virtual environment using the Python version that mod_wsgi was configured for. For this article, the example application will be placed in /var/www/. Next, we will run this command to create the directory wsgi_test, which will contain the virtual environment.

root@host [~]# virtualenv --python=python3 wsgi_test

Next, enter this directory and activate the virtualenv.

root@host [~]# cd wsgi_test
root@host [~]# source bin/activate
root@host [~]# pip install flask
root@host [~]# touch
root@host [~]# vim

Place the following configuration inside of the file

from flask import Flask
 app = Flask(__name__)
 def index():
     return "Hello, from WSGI"

Now, let’s create the wsgi file to load the application.

root@host [~]# touch
root@host [~]# vim

Next, add the following information to the file. This data will activate the virtual environment when a request is received and execute the application.

activate_this = '/var/www/wsgi_test/bin/'
 with open(activate_this) as file_:
         exec(, dict(__file__=activate_this))
 import sys
 sys.path.insert(0, '/var/www/wsgi_test/')
 from wsgi_test import app as application

Now that the example application has been created, let’s configure Apache.

We will begin by creating a virtual host for this application. This file will be placed inside of either
/etc/httpd/conf.d/ for RHEL based systems, or
/etc/apache2/sites-enabled/ for Debian based.


For RHEL based systems, write the file to the following path replacing with your domain.



For Debian based systems, write the file to the following path, replacing with your domain.


The contents of the file will be as follows, replacing with your domain.

<VirtualHost *:80>
     WSGIDaemonProcess wsgi_test user=www-data group=www-data threads=2
     WSGIScriptAlias / /var/www/wsgi_test/
     <Directory /var/www/wsgi_test>
         Require all granted

For RHEL based systems, replace the user and group with apache as follows:

WSGIDaemonProcess wsgi_test user=apache group=apache threads=2

Now test and restart Apache.

Debian based systems:

root@host [~]# apache2 -t
root@host [~]# service apache2 restart

RHEL based systems:

root@host [~]# httpd -t
root@host [~]#  Service httpd restart

You can also use the curl command via the CLI

root@host [~]# curl

or navigate directly to the domain in a browser to see your application. Any errors will be logged to Apache’s default error log file usually found in /var/log/apache2/error_log

Ready to get started?

Liquidweb offers multiple server options for setting up and configuring this type of environment to run your apps. Reach out to one of our Solutions Team members today and they can put together a hosting package that will definitely meet your specific needs.

You can also give us a call 24 hours a day 1.800.580.4985 or open a chat or ticket with us.

How to Configure Apache Virtual Hosts on CentOS 7

Reading Time: 4 minutesToday, we will be reviewing how to configure Apache virtual hosts on a CentOS 7 server. If you host websites, chances are you are hosting more than one website. If so, knowing how and why these virtual hosts work should allow you to better understand why they are needed.
By default, Apache can host only one document root for all requests, which likely isn’t what you want to happen.

We can use VirtualHost blocks to translate named domains into their appropriate document roots, with new settings per-block as needed. But, what goes into a valid VirtualHost? Where should it be stored?

Continue reading “How to Configure Apache Virtual Hosts on CentOS 7”

How To Sync Two Apache Web Servers

Reading Time: 8 minutesLoad balancing and replicating multiple servers has a great array of benefits, though orchestrating and keeping them in sync can be very tricky. Here, we will walk through some of the load balancing options available, as well as setting up a very basic one-way replication sync between two or more servers behind a load balancer.

What is server replication?

Load balancing is a way to increase the processing power and redundancy of your web application by spreading the traffic among multiple different servers. Traffic is orchestrated by a load balancer and the web nodes are orchestrated by another data replication mechanism. That is to say, the load balancer itself has nothing to do with data replication; it only routes traffic to the web nodes. Something else is necessary to keep the web nodes’ data and configuration in sync, which is server replication.

There are a variety of methods for syncing files between web servers. These fall into four overlapping categories, which are synchronous and asynchronous, as well as one-way and two-way. Most synchronous sync types are two way, while asynchronous sync types could be one-way or two-way.

Synchronous sync types instantly share files between servers, via a shared storage node (such as a SAN or object store), and/or by coordinating a shared local or remote file system (OCFS2). These methods are complicated to configure, since beyond mounting the file systems at the same time, all servers must also communicate about when they are ready to write files and write to all locations at the same time. Liquid Web offers Managed Replication in our Enterprise Hosting offerings, removing the planning and maintenance burden from your shoulders so you can focus on your application.

Asynchronous sync types are simpler to set up but do not share files instantaneously. After files are completely written to one location, they are pushed out to another location by a service running on that server (lsyncd) or by a regularly timed sync cron. These are generally set up in one direction, so that a master server replicates out to slave servers.

What are the advantages and drawbacks of server replication?

As I mentioned, load balancing multiple servers serving the same set of data will increase the processing power behind your website, as well as introduce some redundancy. If one of your replicated nodes fails, the other (or others) can continue to serve traffic while the failed node is repaired or replaced. Load balanced systems can also be scaled easily; nodes can be added when more traffic is expected, and taken down if they are no longer needed.
But, with more servers comes more configuration. Keeping all of the server nodes in sync with each other requires additional applications to be set up and running, as well as adding additional hardware for load balancing. It is also a good idea to dedicate the web nodes to Apache only, so database information should be offloaded to a separate server as well. Further, though the software may be freely available, multiple servers and appliances cost more money to run than a single server, so load balanced clusters are inherently more expensive.

What are the requirements for setting up replication?

To set up server replication, you need two servers and one load balancer at bare minimum. But it is recommended to have a separate database server or cluster as well, to further increase redundancy.

You should also plan for the type of replication you want to use. Some replication types require additional hardware or configuration beyond what is covered here. If you are interested in those types of replication, chat with our architects about our Managed Replication products.

For the purposes of this article, we will use Liquid Web’s Cloud Load Balancer, along with two core-managed VPS web servers, and one core-managed VPS database server, connected to each other via the Cloud Private Network with private IPs. We will call the web nodes web01 and web02, and the database node db01. The web01 node is set up with password-less SSH keys into web02. All servers have one public IP.

We will also assume that Apache is set up on each web server for name-based virtual hosting and is installed at /etc/httpd/. PHP is also installed on both machines, and their configuration files are static and matched. Finally, our database server has mariadb installed and running, and the firewall is open for external mysql connections.

Why aren’t we using cPanel? Account replication in cPanel requires rather a bit more replication work than we would be able to cover in this article, since cPanel account updates and creates also need to be synced. But, our Managed Replication services are built on cPanel servers, making your hosting management easier. We will use core-managed servers here for simplicity.

Step 1: Set Up Apache

In order to sync the Apache VirtualHost files, we will set up a single folder with single configuration files for each domain. In our main Apache config file at /etc/httpd/conf/httpd.conf, we will add the following line at the very end:

IncludeOptional vhosts/*.conf

This will allow Apache to load configuration files from the /etc/httpd/vhosts/ folder, if there are any, which we will make next. From the command line, run:

mkdir /etc/httpd/vhosts

Perform these steps on both web01 and web02.

In this folder, we can set up our individual domains’ configuration files. Make sure they end in .conf so that Apache will load them. In our example, we will make two files: and These both will be set up with valid VirtualHost blocks, which we won’t get into the details of here. For this exercise, the docroots of the domains are at /var/www/ and /var/www/ We only need to make these configuration files on web01 for now, since we will sync them later.

Step 2: Set Up Databases

If your application requires it, set up databases on your dedicated database server, and add grants so that all of the web nodes can connect. For instance, after configuring the database user with a good strong password, you might run the following grant statement if your web nodes had private IPs of and

mysql -e “grant all privileges on your_db.* to your_user@’’; grant all privileges on your_db.* to your_user@’’”

To introduce elasticity, and if you are sure that all of your private IPs will have the same prefix, you might consider running this instead:

mysql -e “grant all privileges on your_db.* to your_user@’192.168.0.%’”

This has allowed all IPs that start with 192.168.0 to access this database, if they have valid credentials. Now, if you add another web node, it will also be able to access the database without additional grants being made.

We can now connect the web node to the database using its configuration file. On WordPress, for instance, this file is wp-config.php. Enter the appropriate connection credentials, using the private IP of the database server as the DB_HOST. We use the private IP so that we don’t waste public bandwidth on MySQL communication. Setting up the host connection to a hostname or IP like this will help ensure that the wp-config.php file will work on all your web servers the same way.

Not using a database server? If you don’t have a separate node for databases, and are hosting them on web01, resist using ‘localhost’ in your configuration file! Once copied to your other web nodes, the connection won’t work. Use ‘web01’ or the exact private IP for web01 instead.

Step 3: Install and Configure LSyncD

For our asynchronous one-way replication, we will use Live Sync Daemon (lsyncd). This is a freely available daemon which can watch a folder for activity, and then replicate that activity with rsync in another local or remote location. We need to add the EPEL repository to install it via yum:

yum -y install epel-release
yum -y install lsyncd

Now that lsyncd is installed, we can configure it for each folder we want to sync to other nodes. In this case, we will be syncing the vhost directory we made earlier, as well as the docroots for each domain. In the /etc/lsyncd.conf file, delete the example sync command, and set up the following block of data:

sync {
source = "/var/www/",
host = "",
targetdir = "/var/www/",
rsync = {
binary = "/usr/bin/rsync",
archive = true,
hard_links = true,
update = true

Notice the required commas after all but the last configuration lines. This is because the sync command can also be set up on one line. Make sure you don’t add a comma after the final element of any curly brace array.

Based off of this block, we can set up similar blocks for /var/www/ and any other running sites. Just add them all one after the other in the /etc/lsyncd.conf file.

Lastly, enable and start lsyncd:

systemctl enable lsyncd
systemctl start lsyncd

This final command should return no output, unless there was a problem. If there was, run systemctl status lsyncd and double check your config file syntax.

You can test that it’s working by checking out the contents of the directory on web02. Everything should be there! Make an update to a file, and check the target to see how long it takes to arrive. It should take just 5-10 seconds for lsyncd to pick up the change and copy the file.

Step 4: Set Up Apache Configuration Replication

All of the above is sufficient for servers that do not regularly change the number of domains they host. But, if you configure new domains or update your Apache configuration frequently, you need to set up a script to help you sync this and restart Apache on the other servers. We can call this from lsyncd as the rsync execution binary and have it run post-sync tasks. Create a file called /root/ that looks like this:

/usr/bin/rsync "$@"
[ $? -eq 0 ] && ssh “systemctl reload httpd”

Exit your editor, then add execute permissions to the file:

chmod 700 /root/

This wrapper will perform the rsync task for you with the arguments passed by lsyncd, and if that is successful, connect to web02 by IP and reload the apache configuration. Now, head back into /etc/lsyncd.conf and add this sync block:

sync {
source = "/etc/httpd/vhosts",
host = "",
targetdir = "/etc/httpd/",
rsync = {
binary = "/root/"

Since we declare our script as the rsync binary, this script will execute instead of running rsync by itself. Reload lsyncd to add this sync to the running config:

systemctl restart lsyncd

Once it reloads, lsyncd should copy the folder over to web02 and reload Apache. And, since we already set up the folder to be included, web02 should now also be serving the two virtualhost blocks we made for and

Step 5: Route Traffic

That should just about do it! The final step is to test the configuration by connecting directly to web01 and web02 using hosts file modification, and make sure the content being served from both machines is the same. Also ensure that both servers can properly reach their database on db01.

Now, create the Cloud Load Balancer to route traffic to the IPs for web01 and web02. Use your hosts file again to connect to the load balancer’s VIP to ensure you can reach the nodes.
After testing, public DNS for the hosted domains can be changed to the VIP of the load balancer, allowing traffic to be routed into your cluster. Done!


As you may have noticed, this only sets up replication from web01 to web02, not vice versa. Therefore, if you upload content or make changes to your website, you should always do so from web01. It is possible in some Load Balancer solutions to route traffic for your website’s administrative panel, such as /wp-admin, to only one of your nodes, i.e. web01. This will allow content creators to properly upload data only to the master web node for correct replication. This is not an option on the Cloud Load Balancer, though it is available in our Shared and Dedicated Load Balancer offerings.

If you decide to add a new domain to the servers, you will need to do all the following:

    • Create the document root on web01
    • Create any databases on db01 and set up SQL grants
    • Add a new virtualhost file to the /etc/httpd/vhosts/ folder
    • Add a new sync statement to /etc/lsyncd.conf for the new docroot
    • Restart lsyncd and apache on web01

Additionally, when adding or removing a server, new blocks will need to be set up manually inside of /etc/lsyncd.conf to sync to this new host too, as well as a new vhostsync wrapper for restarting Apache on those new nodes after configuration sync.

None of this is an issue with our Managed Load Balancing solutions, which will be scaled as sites or servers are connected.

Finally, though this does provide some redundancy, your web01 server is still the master node, since it is running lsyncd. If web01 goes down, your website will still work, but you ought not add to or modify your sites until it can be repaired or replaced.

Do I Still Need Backups?


Server replication is not a stand-in for server backups. If a hard disk crashes or your RAM goes bad, the other web node will still be able to stand up traffic. However, if your website is compromised, or you accidentally delete files, these changes will be replicated over to the other web node, removing your “backups”. Make sure you have local and full-server backups for disaster recovery.

If you are interested in setting up your own load balanced server replication, or would like more information about our managed products to help you with synchronous or asynchronous replication, chat with a hosting advisor today!

Where is the Apache configuration in CentOS?

Reading Time: 2 minutes

Apache Main Configuration Files

On a CentOS server, the package manager used to install the Apache web server (such as rpm, yum, or dnf) will typically default to placing the main Apache configuration file in of one of the following locations on the server:


Continue reading “Where is the Apache configuration in CentOS?”

Why Choose CentOS 6 or 7

Reading Time: 6 minutes


The servers that run our applications, our businesses, all depend on the stability and underlying features offered by the operating system (or OS) installed. As administrators, we have to plan ahead and think to the future of how our users will use the machines we oversee while simultaneously ensuring that those machines remain stable and online. There are numerous operating systems to choose from; however one of the most popular, most stable, and highly supported OSes is CentOS. A combination of excellent features, rock-solid performance stability, and the backing of enterprise-focused institutions such as Red Hat and Fedora have led to CentOS becoming a mainstay OS that administrators can count on.

Continue reading “Why Choose CentOS 6 or 7”

How To Install the LAMP Stack on CentOS 7

Reading Time: 4 minutesWhether you’re new to hosting websites or a seasoned developer, you’ve more than likely heard of a LAMP stack. The LAMP stack is the base set of applications that most websites running on a Linux server are served from and is commonly referred to as “Lamp”. Rather than a single program that interacts with the website being served, LAMP is actually a number of independent programs that operate in tandem: Linux, Apache, MySQL/MariaDB, and PHP. Throughout this article, we’ll walk through installing the LAMP stack on your CentOS 7 server so you can run a website from any Dedicated Server or Virtual Private Server. Although we’re focusing on installing LAMP on a CentOS 7 server, the steps that we’ll cover are very similar across multiple Linux distributions.

Continue reading “How To Install the LAMP Stack on CentOS 7”

How to Convert .htaccess Rules to NGINX Directives

Reading Time: 6 minutesNGINX is a webserver that is becoming an increasingly popular option for webhosting, as sixteen percent of all sites on the internet are utilizing NGINX. This percentage is constantly increasing as clients are in need of a web server that can serve content faster. It can also be used for proxies, reverse proxies, load balancing, and more depending on what modules you load onto NGINX. One of the significant differences between Apache (a popular webserver) and NGINX is the way each system handles access rules. If you are familiar with using .htaccess rules in Apache, then the method that NGINX uses of including directives in the server’s vhost block will be substantial change.

Continue reading “How to Convert .htaccess Rules to NGINX Directives”

An Intro to React JS

Reading Time: 6 minutesIn our modern world of smartphones and apps, it is more important than ever to have a fast, responsive website that impresses your visitors. Created by the development team at Facebook, ReactJS is a JavaScript ‘framework’ or method of building web pages and apps that can ‘react’ to user interaction and external changes. ReactJS does this by way of components that can refresh themselves and their contents without a page reload. Better still, these components are modular. This concept means they can be coded quickly (called ‘hacking’ in the ReactJs community) and reused easily between projects.

While programming React JavaScript code is outside the scope of this tutorial, we are happy to help you and your development team hit the ground running by creating a development environment. Our focus is on getting the official ReactJS tutorial example running on a Liquid Web WHM/cPanel Virtual Private Server or VPS. Servers built on our VPS platform work well as development/testing servers and can be easily created. Feel free to spin one up to follow along with me today!

A dedicated server may provide more stability for your application over the long term once development has been completed. If your application is HIPAA related, you will need a dedicated server with HIPAA compliance. The differences between the VPS and Dedicated Server platforms can be found in our Knowledge Base article. Addtionally, ReactJS can also be installed on our Plesk, Windows, and Ubuntu platforms. Let’s get started!


Install NodeJS

First, we will need to install the latest version of NodeJS; This application allows our JavaScript files to import (or reference) each other, share global variables, access advanced command-line arguments, install additional modules and more.

At the time of writing, the latest version of NodeJS is 11.X Always use the most up-to-date software to ensure the stability and safety of your applications. Today we will be downloading and installing the latest version.

First, we log into our terminal and set up the NodeSource repository :

curl  -sL | bash -

Next, we install NodeJS and its dependencies :

yum  install  -y nodejs  gcc-c++ make

To verify the installation and check the version, we run :

node --version


Install Serve

ReactJS Apps can be served by Apache or by the lightweight “Serve” application. Serve can run alongside Apache/Nginx accomplished by running Serve on an alternate port.

To install Serve globally, we run the following command :

npm install -g serve

In this tutorial, we will be running this application on a newly created cPanel account. but it can also run on any existing account. Our cPanel username in this example is ‘react’, and our development folder meant to house our source code will be named ‘dev’. This dev folder will sit our cPanel account’s root folder (/home/react/dev). A folder can be created via File Manager or FTP, but in this example, we are doing this via the command line :

mkdir /home/react/dev/


Install ReactJS

Our next step is to use the application ‘create-react-app’ command to build the framework and install the necessary prerequisites. No need to worry about updating ‘create-react-app’, this application updates automatically when run.

This command requires a path to build properly. In our example we are running the following to build in our dev folder.

npx create-react-app /home/react/dev

The create-react-app process can take a few minutes, but it will keep you updated of progress like so :


When completed, you’ll see an overview of some important development commands and a warm welcome into the ReactJS Community.


The create-react-app script generated the above files for us with default content. With that, you and your developers can begin the development process.

Three main components of a ReactJS application are:

  • .html files; These provide the structure to your app.
  • .css files; These contain the styling for your app content.
  • .js or Javascript Files; These provide app functionality.

Run ReactJS Default Application

While Liquid Web Support is not able to assist with code-related issues, in this tutorial, we will be going a step further by launching the default application. Finally, we’ll be reviewing and launching the ReactJS ‘tic-tac-toe game’ tutorial application.

First, let’s confirm that ReactJS is running by building the default application. We want to be in the command line and our working folder.

cd /home/react/dev/Run the following code to have React build the default package contents.

npm  run build

There are a few options here, by default if we use ‘Serve’ it will use port 5000;  This is run by calling the following :

serve -s build

serve build

You may notice the error regarding ‘xsel’. That application is used to copy from command line to a Linux Desktop Environment or GUI (Gnome, KDE, Mate among others). In our case, our Linux server is not using a Desktop Environment, so we do not need nor could we use the xsel library so we’ll ignore the error.

Viewing ReactJS Default App

To have our app available to the outside world, we will need to ensure that port 5000 is open in the firewall; Though this port is not open by default we can adjust that easily;

We are looking for the section called ‘Opening and Closing Ports in the Firewall’. Once implemented, you’ll see the default ReactJS application running in the browser. We do not own the domain ‘’ so we will need to adjust our /etc/hosts file locally on our workstation. More information on editing your /etc/hosts files can be found here.

If you own your domain and your site’s DNS ‘A’ Record pointing to the Liquid Web server IP this should also be visible to you. The default ReactJS screen looks like this if everything is configured and running properly.



Run ReactJS

It is possible to run ReactJS applications over the typical Apache or Nginx ports; Please note, running ReactJS with Serve over port 80 means Apache or Nginx would need to be disabled. If the primary focus of your server is to handle this application, Apache can be disabled server-wide. Serve is a very lightweight application and works very well. If you do not have another service running on port 80; The following command will start ‘Serve’ on port 80.

PORT=80 serve -s build

serve build 2

The above can be adjusted to a different port as well. In this way, multiple ReactJS applications can be run on the same domain. In addition to this, Apache can serve your ReactJS application as static content. To do so, we would need to copy the contents of our application’s /build folder to the desired location within the directory configured for web delivery.

In our case, we will be copying /home/react/dev/build to /home/react/public_html. This can be done on the command line with :

cp -r  /home/react/dev/build  /home/react/public_html

Depending on how you built the application package, you may need to adjust the permissions of your files. In our case, the ownership of these files was set to ‘root’. In response to this, we are changing the ownership to ‘react’.

In this example, we are going to be adjusting all files in the public_html folder to be owned by the user ‘react’ with the following command :

chown  -R react.  /home/react/dev/public_html/*

To have Apache serve the above, we are going to be adjusting the .htaccess configuration in our project.

vim /home/react/public_html/.htaccess

With our text editor, we are going to be adding the following :

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

If everything is configured correctly, you should now see the contents of your application as delivered by the Apache service when visiting your site. You now know the basics of how to get the default ReactJS environment running on a Liquid Web Linux WHM/cPanel VPS Server!

Example ReactJS Application

We are going one step further here by going over a tutorial. This tutorial goes over every aspect of getting started with ReactJS with great detail into programming some components needed to get a running tic-tac-toe game. We advise going line by line through the code as well as the documentation. With this knowledge, you can build your own application. The best source for ReactJS syntax and concepts can be found in their documentation. Feel free to take your time going through these examples and documentation; There is a lot to go through, but you can start small and build your way up. Today we are going to copy the contents of the Final Code to see how they run on our Liquid Web Server.


There are multiple ways to adjust the contents of index.html, index.css, and index.jss files. While outside of the scope of this tutorial, you can use other command line text editing tools, FTP, cPanel ‘s File Manager tool, Git  and many more to edit files. In our case, we are using the cPanel File Manager’s Text Editor. A walkthrough of this interface and how to edit files can be found here.

First, we open the File Manager, navigate to the location of our file /home/react/dev/public/index.html, then we select the index.html file ( 1 ) and click“Edit” ( 2 )


We are going to be copy-pasting the code from CodePen into our server-side files.

Second, we do the same with /src/index.css.


Finally, we copy paste the contents of /src/index.js.

At the top of the index.js file, we add some needed code; This is necessary for referencing the React installation and our CSS files.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';


With all three files copied over, we are going to rebuild our project. To rebuild, we will go back to our development folder and rerun our build script. With that, we can test by serving our new build with our serve script. By visiting we see our tic-tac-toe game live on our Liquid Web server!


In conclusion, we went over what ReactJS offers developers, installed ReactJS along with customization. WIth the official documentation, you now have all you need to build out your dream application. We cannot wait to see what you have in mind!

Have other thoughts or questions about this topic? Our Sales and Support teams are available 24 hours a day and can be reached via phone or e-mail to assist. Open a support ticket with us today at, giving us a call at 1-800-580-4985 or, open a chat with us and we’ll be happy to answer any questions you may have!


The Best Settings for Configuring FastCGI (mod_fcgid)

Reading Time: 5 minutesIn our last tutorial, we showed you how to install Apache’s mod_fcgid and provided Linux scripts to assist in transitioning from mod_php. In this next section, we’ll be discussing how to configure a baseline setting for PHP optimization. Continue reading “The Best Settings for Configuring FastCGI (mod_fcgid)”

How to Install mod_fcgid on cPanel’s EasyApache 4 with CloudLinux

Reading Time: 6 minutesWhen it comes to PHP execution, mod_fcgid (also called FCGI) is one of the heavyweight contenders. There are a few rival handlers, like PHP-FPM or mod_lsapi, which come close to matching its execution speed, but they generally leave something to be desired when it comes to fine-tuning and resource consumption. FCGI is built for speed and includes a myriad of Apache directives that can be leveraged for resource regulation.

This article will cover installing mod_fcgid followed by basic configuration in a separate article. The article applies to any cPanel servers running the following operating systems:

The article will not cover EasyApache 3 (EA3). Due to the End-of-Fife (EOL) status of EA3, it is imperative that any systems running EA3 upgrade to EA4 as soon as possible. To avoid conflicts, upgrading to EA4 should be handled as an entirely separate procedure from installing mod_fcgid. If you need assistance with upgrading from EA3 to EA4, please feel free to contact our support team. If you’re running a Liquid Web Fully Managed cPanel server, our team will perform the entire upgrade procedure for you.

Expectations: Downtime & Performance

Downtime – Please plan ahead of time as this operation may cause downtime. While installing an Apache module and enabling a baseline configuration should only require an Apache restart, there may be unforeseen circumstances that require troubleshooting. This can lead to sites becoming unresponsive and/or slow.

Always plan for more downtime than expected and always have a reversion plan. Allot extra time for troubleshooting, testing, and reverting all changes if necessary.

Performance – While FCGI provides superior PHP execution time, it is not a blanket fix for performance. For server optimization there will be an adjustment period for configuration tweaking.This period can take hours to weeks as it must account for the unique caveats with the specific server hardware, software, traffic habits, and many other unpredictable variables.

Optimization is an ongoing, perceptual process. There is no one-size-fits-all optimized configuration. Traffic & resource usages continually change over time on all servers. Periodic evaluation and configuration adjustment are necessary to stay ahead of the curve.


Installation of mod_fcgid

The following steps should be followed as close to the examples as possible. Things will vary slightly depending on CentOS/CloudLinux versions, and a few other factors. The article will denote the differences where they are expected.

Step 1) [su_highlight background="#3ac6eb"]Liquid Web Servers Only[/su_highlight] Disable Mod_Zeus & Other EA3 Modules

Older Liquid Web cPanel servers with EasyApache 3 who upgraded to EA4 may find residual configs on the system that can cause conflicts in the Apache configuration. This step will help make sure these older configs are disabled. The following sed one-liner will take care of disabling the inclusion line for these modules. These modules are stored in the /usr/local/lp/configs/httpd/conf.d/ directory. This directory is typically mentioned in the /etc/apache2/conf.d/includes/post_virtualhost_global.conf config file. The sed code looks for and comments out the specific include statement for this file.

sed -i -e 's/[^#]+\(Include [/]usr[/]local[/]lp[/]configs[/]httpd[/]\)/#\1/g' /etc/apache2/conf.d/includes/post_virtualhost_global.conf

To confirm the change, print the contents of the post_virtualhost_global.conf file using cat:

cat /etc/apache2/conf.d/includes/post_virtualhost_global.conf

The output should be blank or have a commented out inclusion line like below:

#Include /usr/local/lp/configs/httpd/conf.d/*.conf

Step 2) Disable Litespeed

FCGI is not compatible with Litespeed, which uses its own mod_lsapi module to process PHP using lsphp. Disabling Litespeed in this way does not remove it from the server; it merely enables Apache as the default web server.

/usr/local/lsws/admin/misc/ apache

Step 3) Install mod_fcgid

The following yum command will install the necessary module:

yum install ea-apache24-mod_fcgid -y

Once completed, confirm Apache has the fcgid_module loaded:

httpd -M | grep expires\|version\|fcgid

Example output:

fcgid_module (shared)

Step 4) [su_highlight background="#3ac6eb"]CloudLinux Only[/su_highlight] Configure CageFS Map for FCGI

The following snippet will create the necessary directories needed by mod_fcgid to execute correctly. It will then add those directory entries into the /etc/cagefs/ file, allowing user-level access to said directories from within their caged environment. It finally forces cagefs to remount all user directories for access to the new directory on all sites.

mkdir -p /var/run/mod_fcgid /usr/share/cagefs-skeleton/var/run/mod_fcgid /run/mod_fcgid
cp -p /etc/cagefs/{,.lwbak.$(date +%F_%H%M%S)}
cat <<EOF>>/etc/cagefs/
cagefsctl -M

Step 5) [OPTIONAL] Remove Unnecessary Writable Permission

Due to security restrictions, any website files or directories with group-writable or other-writable permissions will be denied and a 500 Internal Server Error will be displayed. The following awk one-liner uses the find command to search all DocumentRoot directories configured on the server. It is advised to run this process in a screen session as it may take an hour or more depending on the size of the file system in question. The code takes care to use nice and ionice commands to run the process as a low priority so there will be minimal impact on server load or disk I/O. All changed files and their previous permissions are recorded in the /var/log/fixperms.log file.

Step 5a) Create & Attach to a Screen Session

screen -dmS fixperms; screen -x fixperms

Step 5b) Run the One-Liner

nice -n 15 ionice -c2 -n7 awk '/DocumentRoot/{DR[$NF]=$NF}END{for (e in DR) {x="find \""e"\" \\( -type f -or -type d \\) -and -perm /g+w,o+w -printf \"%M %y %m %p\\n\" -exec chmod g-w,o-w {} +"; while(x|getline) {print $0;print strftime("%F %T %Z"),$0 >> "/var/log/fixperms.log"} close(x)}}' /etc/apache2/conf/httpd.confExit screen by holding CTRL/CMD then pressing A, then D.


Step 6) [OPTIONAL] Disable mod_php Directives in .htaccess Files

Another common caveat when switching to FCGI is that any existing mod_php related directives inside any .htaccess file are not compatible with mod_fcgid and will cause the site to throw a 500 Internal Server Error. So these entries need to be located and disabled or removed.  The following awk one-liner checks all configured DocumentRoot directories for .htaccess files, and if they contain a php_value or php_admin_value entry, it will disable by commentting the line out. First, an in-place backup is created of the original file. The backup is named .htaccess.bak.YYYY-MM-DD_HHMMSS. All changed files and their previous permissions are logged in the /var/log/fixhtaccess.log file.

Step 6a) Create & Attach to a Screen Session

screen -dmS fixhtaccess; screen -x fixhtaccess

Step 6b) Run the One-Liner

nice -n 15 ionice -c2 -n7 awk '/DocumentRoot/{DR[$NF]=$NF}END{for (e in DR) { x="find "e" -name .htaccess -exec grep -iEl \"^([^#]*php_(admin_)?value)\" {} +"; s="sed -i.bak.$(date +%F_%H%M%S) \047s/^\\([^#]*php_\\(admin_\\)\\?value\\)/#\\1/gi\047 2>&1";
while(x|getline) {print $0; print s,$0; print strftime("%F %T %Z"),s,$0 >> "/var/log/fixhtaccess.log"; while(s" "$0|getline y) { print y; print strftime("%F %T %Z"),y >> "/var/log/fixhtaccess.log" } close(s" "$0)} close(x)}}' /etc/apache2/conf/httpd.conf

Step 7) Rebuild Apache Config (Troubleshoot Any Errors)

The following command checks the system httpd.conf file for syntax error and if none are found, runs the cPanel httpd.conf rebuild script. Fix any syntax errors, until a clean rebuild is completed without error.

httpd -t && /scripts/rebuildhttpdconf

Step 8) [su_highlight background="#3ac6eb"]CloudLinux ONLY[/su_highlight] Setup PHP Selector

The PHP Selector feature of CloudLinux is only compatible with the inherit PHP versions in the cPanel MultiPHP Manager interface. All sites should be using the inherited version of PHP or PHP Selector will not function for that site. This only applies to CloudLinux servers.

Step 8a) Force All Sites to Use Inherited Version of PHP in MultiPHP Selector

The following command uses cPanel’s whmapi1 system to force all sites onto the inherited version of PHP in MultiPHP Manager.

/usr/sbin/whmapi1 php_get_vhost_versions | awk  -F'[: ]+' '$2~/vhost/{x="/usr/sbin/whmapi1 php_set_vhost_versions version=inherit vhost-0="$3;print x;system(x);close(x)}'

Step 8b) Disable MultiPHP Manager & MultiPHP INI Editor

The following uses the cPanel whmapi1 system to add MultiPHP Manager/INI Editor to the disabled features list.

/usr/sbin/whmapi1 update_featurelist featurelist=disabled multiphp=1 multiphp_ini_editor=1 ; /usr/sbin/whmapi1 update_featurelist featurelist=disabled multiphp_ini_editor=1

Step 9) Switch All PHP Handlers over to FCGI

The following will convert all installed PHP Handlers to using FCGI. These handlers are viewalbe through the Handlers tab of WHM’s MultiPHP Manager interface or by running the cPanel rebuild_phpconf script.

/usr/local/cpanel/bin/rebuild_phpconf --current | awk 'NR>1{x="/usr/local/cpanel/bin/rebuild_phpconf --"$1"=fcgi"; print x; system(x);

To confirm the changes, run:

/usr/local/cpanel/bin/rebuild_phpconf --current

Example Output:

DEFAULT PHP: ea-php71
ea-php54 SAPI: fcgi
ea-php55 SAPI: fcgi
ea-php56 SAPI: fcgi
ea-php70 SAPI: fcgi
ea-php71 SAPI: fcgi
ea-php72 SAPI: fcgi

Step 10) Perform a Full Stop & Restart of Apache

The following script will stop Apache (gracefully if possible), and kill any unresponsive Apache & PHP processes before starting the Apache service again. It will also verify the Apache configuration syntax and will only perform the restart procedure if the syntax returns ok. This technique is handy as it is common for Apache processes to get stuck from time to time on busy servers.  This snippet deals with those scenarios after performing the humane stop request first.

httpd -t && (/scripts/restartsrv_apache stop; sleep 3; killall httpd php lsphp php-cgi; sleep 3; killall -9 httpd php lsphp php-cgi; /scripts/restartsrv_apache start) || echo Fix Apache Config and try again.

Toss this snippet into an alias called apache_rescue which you can add to your ~/.bashrc for easy access to this code. Below is a one-liner that will create this alias for you and load the modified profile in your current session. Once this alias is installed, it will always be available on that  server by typing apache_rescue.

cat <<'EOF'>>~/.bashrc && source ~/.bashrc
alias apache_rescue='httpd -t && (/scripts/restartsrv_apache stop; sleep 3; killall httpd php lsphp php-cgi; sleep 3; killall -9 httpd php lsphp php-cgi; /scripts/restartsrv_apache start) || echo Fix Apache Config and try again.'

This concludes our ten step process for installing mod_fcgid onto your cPanel system.  It’s recommended to adjust FCGI settings from their default settings. Tune into our next tutorial where we’ll be advising on how to optimize FCGI for various environments.