The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.
The Apache web server uses virtual hosts to manage multiple domains on a single instance. Similarly, PHP-FPM uses a daemon to manage multiple PHP versions on a single instance. Together, you can use Apache and PHP-FPM to host multiple PHP web-applications, each using a different version of PHP, all on the same server, and all at the same time. This is useful because different applications may require different versions of PHP, but some server stacks, like a regularly configured LAMP stack, can only manage one. Combining Apache with PHP-FPM is also a more cost-efficient solution than hosting each application on its own instance.
PHP-FPM also offers configuration options for stderr
and stdout
logging, emergency restarts, and adaptive process spawning, which is useful for heavy-loaded sites. In fact, using Apache with PHP-FPM is one of the best stacks for hosting PHP applications, especially when it comes to performance.
In this tutorial, you will set up two PHP sites on a single instance. Each site will use its own domain, and each domain will deploy its own version of PHP. The first, site1.your_domain
, will deploy PHP 7.0. The second, site2.your_domain
, will deploy PHP 7.2.
A
record in our DNS settings: site1.your_domain
and site2.your_domain
.With the prerequisites completed, you will now install PHP versions 7.0 and 7.2. The SCL (Software Collections) repository maintains numerous versions of the PHP stack for the CentOS 7 system. If you require the absolute newest version of PHP and it is not available on SCL, check the remi
PPA (personal package archive) instead.
Begin by installing the SCL repository to your system:
- sudo yum install centos-release-scl -y
First let’s discover what versions of PHP 7 are available on SCL:
- sudo yum list rh-php7[0-9].x86_64
You’ll see an output like this:
OutputAvailable Packages
rh-php70.x86_64 2.3-1.el7 centos-sclo-rh
rh-php71.x86_64 1-1.el7 centos-sclo-rh
rh-php72.x86_64 1-2.el7 centos-sclo-rh
rh-php73.x86_64 1-1.el7 centos-sclo-rh
You will note that the newest version, PHP 7.3, is also available. For our examples, however, we will install versions 7.0 and 7.2.
Lets begin with the older version. Install rh-php70
and rh-php70-php-fpm
:
- sudo yum install rh-php70 rh-php70-php-fpm -y
rh-php70
is a metapackage that runs PHP applications.rh-php70-php-fpm
provides the Fast Process Manager interpreter that runs as a daemon and receives Fast/CGI requests.Now repeat the process for PHP version 7.2. Install rh-php72
and rh-php72-php-fpm
.
- sudo yum install rh-php72 rh-php72-php-fpm -y
Next, run the following commands to start using both software collections:
- sudo scl enable rh-php70 bash
- sudo scl enable rh-php72 bash
By default, both PHP versions are listening on port 9000
. But in this tutorial, we want to run two versions simultaneously. Therefore, let’s designate two new ports:
To accomplish this, you can open /etc/opt/rh/rh-php70/php-fpm.d/www.conf
in your favorite text editor and change every appearance of 9000
to 9002
. Then save and close the file and repeat the process for /etc/opt/rh/rh-php72/php-fpm.d/www.conf
, only now substitute 9000
with 9003
. Alternately, you can use these two sed
commands to make the replacements:
- sudo sed -i 's/:9000/:9002/' /etc/opt/rh/rh-php70/php-fpm.d/www.conf
- sudo sed -i 's/:9000/:9003/' /etc/opt/rh/rh-php72/php-fpm.d/www.conf
You have now designated a dedicated port for each of your PHP services. Before these modifications will work, however, you must add the ports to your SELinux configuration.
SELinux is short for Security Enhanced Linux, and it is enabled by default on CentOS 7. You must add your new ports of 9002
and 9003
to your SELinux database and assign them to your httpd services, or your applications will not run. Use the semanage
command to perform this task:
- sudo semanage port -a -t http_port_t -p tcp 9002
- sudo semanage port -a -t http_port_t -p tcp 9003
The -a
flag specifies that you are adding an object to the database. The -t
flag specifies the type of object, which in this case is http_port_t
. And the -p
flag designates the tcp
protocol. You can learn more about SELinux and the semanage
command in this tutorial, or by visiting the official SELinux documentation.
Now you are ready to start and enable your PHP services. Begin with your rh-php70-php-fpm
service and enable it to start at boot:
- sudo systemctl start rh-php70-php-fpm
- sudo systemctl enable rh-php70-php-fpm
Next, verify the status of your rh-php70-php-fpm
service:
- sudo systemctl status rh-php70-php-fpm
You’ll see an output like this:
Output● rh-php70-php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/rh-php70-php-fpm.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2020-04-18 04:49:59 UTC; 1min 6s ago
Main PID: 1852 (php-fpm)
Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec"
CGroup: /system.slice/rh-php70-php-fpm.service
├─1852 php-fpm: master process (/etc/opt/rh/rh-php70/php-fpm.conf)
├─1853 php-fpm: pool www
├─1854 php-fpm: pool www
├─1855 php-fpm: pool www
├─1856 php-fpm: pool www
└─1857 php-fpm: pool www
Apr 18 04:49:59 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Starting The PHP FastCGI Process Manager...
Apr 18 04:49:59 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Started The PHP FastCGI Process Manager.
Repeating this process, start the rh-php72-php-fpm
service and enable it to start at boot:
- sudo systemctl start rh-php72-php-fpm
- sudo systemctl enable rh-php72-php-fpm
Next, verify the status of your rh-php72-php-fpm
service:
- sudo systemctl status rh-php72-php-fpm
You’ll see another output like this:
Output● rh-php72-php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/rh-php72-php-fpm.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2020-04-18 04:50:04 UTC; 1min 59s ago
Main PID: 1876 (php-fpm)
Status: "Processes active: 0, idle: 5, Requests: 0, slow: 0, Traffic: 0req/sec"
CGroup: /system.slice/rh-php72-php-fpm.service
├─1876 php-fpm: master process (/etc/opt/rh/rh-php72/php-fpm.conf)
├─1877 php-fpm: pool www
├─1878 php-fpm: pool www
├─1879 php-fpm: pool www
├─1880 php-fpm: pool www
└─1881 php-fpm: pool www
Apr 18 04:50:04 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Starting The PHP FastCGI Process Manager...
Apr 18 04:50:04 centos-s-1vcpu-1gb-blr1-01 systemd[1]: Started The PHP FastCGI Process Manager.
At this point you have installed two PHP versions on your server. Next, you will create a directory structure for each website you want to deploy.
In this section, you will create a document root directory and an index page for each of your two websites.
First, create document root directories for both site1.your_domain
and site2.your_domain
:
- sudo mkdir /var/www/site1.your_domain
- sudo mkdir /var/www/site2.your_domain
By default, the Apache webserver runs as an apache
user and an apache
group. So /var/www/
and all of its files and subdirectories should also be owned by them. Run the following commands to verify the correct ownership and permissions of your website root directories:
- sudo chown -R apache:apache /var/www/site1.your_domain
- sudo chown -R apache:apache /var/www/site2.your_domain
- sudo chmod -R 755 /var/www/site1.your_domain
- sudo chmod -R 755 /var/www/site2.your_domain
The chown
command changes the ownership of your two website directories to the apache
user and the apache
group. The chmod
command changes the permissions associated with that user and group, as well as others.
Next you will create an info.php
file inside each website root directory. This will display each website’s PHP version information. Begin with site1
:
- sudo vi /var/www/site1.your_domain/info.php
Add the following line:
<?php phpinfo(); ?>
Save and close the file. Now copy the info.php
file you created to site2
:
- sudo cp /var/www/site1.your_domain/info.php /var/www/site2.your_domain/info.php
Your web server now has the document root directories that each site requires to serve data to visitors. Next, you will configure your Apache web server to work with two different PHP versions.
In this section, you will create two virtual host configuration files. This will enable your two websites to work simultaneously with two different PHP versions.
In order for Apache to serve this content, it is necessary to create a virtual host file with the correct directives. You’ll create two new virtual host configuration files inside the directory /etc/httpd/conf.d/
.
First create a new virtual host configuration file for the website site1.your_domain
. Here you will direct Apache to render content using PHP 7.0:
- sudo vi /etc/httpd/conf.d/site1.your_domain.conf
Add the following content. Make sure the website directory path, server name, port, and PHP version match your setup:
<VirtualHost *:80>
ServerAdmin admin@site1.your_domain
ServerName site1.your_domain
DocumentRoot /var/www/site1.your_domain
DirectoryIndex info.php
SetHandler "proxy:fcgi://127.0.0.1:9002
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
AddHandler php70-fcgi .php
Action php70-fcgi /cgi-bin/php70.fcgi
ErrorLog /var/log/httpd/site1.your_domain_error.log
CustomLog /var/log/httpd/site1.your_domain_access.log combined
</VirtualHost>
For DocumentRoot
you are specifying the path of your website root directory. For ServerAdmin
you are adding an email that the your_domain
site administrator can access. For ServerName
you are adding the url for your first subdomain. For SetHandler
you are specifying port 9002
. The remaining directives also configure your service to deploy PHP 7.0.
Save and close the file.
Next, create a new virtual host configuration file for the website site2.your_domain
. You will specify this subdomain to deploy PHP 7.2:
- sudo vi /etc/httpd/conf.d/site2.your_domain.conf
Add the following content. Again, make sure the website directory path, server name, port, and PHP version match your unique information:
<VirtualHost *:80>
ServerAdmin admin@site2.your_domain
ServerName site2.your_domain
DocumentRoot /var/www/site2.your_domain
DirectoryIndex info.php
SetHandler "proxy:fcgi://127.0.0.1:9003
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
AddHandler php72-fcgi .php
Action php72-fcgi /cgi-bin/php72.fcgi
ErrorLog /var/log/httpd/site2.your_domain_error.log
CustomLog /var/log/httpd/site2.your_domain_access.log combined
</VirtualHost>
Save and close the file when you are finished. Then check the Apache configuration file for any syntax errors:
- sudo apachectl configtest
You’ll see an output printing Syntax OK
:
- OutputSyntax OK
Finally, restart the Apache service to implement your changes:
- sudo systemctl restart httpd
Now that you have configured Apache to serve each site, you will test them to make sure the proper PHP versions are running.
At this point, you have configured two websites to run two different versions of PHP. Now test the results.
Open your web browser and visit both sites http://site1.your_domain
and http://site2.your_domain
. You will see two pages that look like this:
Note the titles. The first page indicates that site1.your_domain
deployed PHP version 7.0. The second indicates that site2.your_domain
deployed PHP version 7.2.
Now that you’ve tested your sites, remove the info.php
files. Because they contain sensitive information about your server and are accessible to unauthorized users, they pose a security vulnerability. Remove the files:
- sudo rm -rf /var/www/site1.your_domain/info.php
- sudo rm -rf /var/www/site2.your_domain/info.php
You now have a single CentOS 7 server handling two websites with two different PHP versions. PHP-FPM, however, is not limited to this one application.
You have now combined virtual hosts and PHP-FPM to serve multiple websites and multiple versions of PHP on a single server. The only practical limit on the number of PHP sites and PHP versions that your Apache service can handle is the processing power of your instance.
From here you might consider exploring PHP-FPM’s more advanced features, like its adaptive spawning process or how it can log sdtout
and stderr
Alternatively, you could now secure your websites. To accomplish this, you can follow our tutorial on how to secure your sites with free TLS/SSL certificates from Let’s Encrypt.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
There are multiple issues with this guide. Following it step by step does not work.
You shouldn’t use both SetHandler and AddHandler directives. The AddHandler directive reference a script that is never created as part of this guide (php72.fcgi") and is not needed anyways.
You should only keep the SetHandler inside a File directive, as explained in section “3. Running multiple versions of PHP” of this guide: https://developers.redhat.com/blog/2017/10/25/php-configuration-tips/