How to Install Apache, PHP 7, and PHP-FPM on CentOS 7
Posted onThis tutorial is also available for Ubuntu 18.x and 19.04.
PHP-FPM, or PHP FastCGI Process Manager, is an alternative implementation of PHP FastCGI that can handle a high volume of queries. Combined with PHP 7, PHP-FPM achieves a higher performance level than any previous version of PHP.
In this tutorial, we’ll see how to install and configure Apache, PHP 7.2, and PHP-FPM on a CentOS server.
Step # 1: Preparations
At first, disable SELinux:
setenforce 0
Edit the SELinux configuration file:
vi /etc/selinux/config
Change the value of the “SELINUX” parameter to “disabled”:
# This file controls the state of SELinux on the system.
# SELINUX = can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX = disabled
# SELINUXTYPE = can take one of three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE = Targeted
Before you begin the installation, update the operating system and installed packages:
yum update -y
Import the GPG key that is needed to validate the software packages:
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY*
Add the EPEL repository. It contains most of the packages we will install later:
yum install -y epel-release
Finally, install the “Development Tools” group and the “yum-utils” package:
yum -y groupinstall 'Development Tools' yum -y install yum-utils
Step # 2: Installing Apache, PHP 7.2, and PHP-FPM
On CentOS 7, PHP version 5.6 is installed by default. You must add and activate the REMI repository to install PHP 7.
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum-config-manager --enable remi-php72
Then install Apache, PHP, and PHP-FPM, as well as some needed packages:
yum -y install httpd mod_ssl php php-zip php-fpm php-devel php-gd php-imap php-ldap php-mysql php-odbc php-pear php-xml php-xmlrpc php-pecl-apc php-mbstring php-mcrypt php-soap php-tidy curl curl-devel perl-libwww-perl ImageMagick libxml2 libxml2-devel mod_fcgid php-cli httpd-devel php-fpm php-intl php-imagick php-pspell wget
Step # 3: Apache Service Configuration
Add the following HTTP header rule to the Apache configuration. This security rule prevents attacks that exploit HTTPOXY vulnerability:
echo "RequestHeader unset Proxy early" >> /etc/httpd/conf/httpd.conf
Enable and start the httpd
service:
systemctl enable httpd systemctl restart httpd
Verify that the web server responds as it should:
Step # 4: Configure PHP-FPM for the Main Website
On a new CentOS installation, the main website files are located in “/var/www/html”. The Apache service accesses this folder as the “apache” user, which is the user account of the service.
By default, PHP is configured as an Apache module. To verify this, create a file named “info.php” in /var/www/html
:
vi /var/www/html/info.php
Copy the following content to the file:
<?php phpinfo(); ?>
Access this file through your web browser:
The Apache 2.0 Handler module currently manages PHP processes. We will now change that for PHP-FPM.
PHP-FPM configuration
For PHP requests to be handled by PHP-FPM, create two directories to hold the configuration files:
mkdir /etc/php-fpm.d/sites-enabled mkdir /etc/php-fpm.d/sites-available
Then modify the PHP-FPM configuration file:
vi /etc/php-fpm.conf
Change the following line:
include=/etc/php-fpm.d/*.conf
For:
include=/etc/php-fpm.d/sites-enabled/*.conf
Then move the file “www.conf” into the subdirectory “sites-available”:
mv /etc/php-fpm.d/www.conf /etc/php-fpm.d/sites-available
Next, create a symbolic link to “www.conf” in “sites-enabled”:
ln -s /etc/php-fpm.d/sites-available/www.conf /etc/php-fpm.d/sites-enabled/www.conf
Create a directory to host PHP-FPM sockets files:
mkdir /var/run/php-fpm
Then modify the configuration file “www.conf”:
vi /etc/php-fpm.d/sites-available/www.conf
For performance reasons, we will use a UNIX socket rather than a TCP socket for communications between Apache and PHP-FPM services. Find the “listen” setting:
listen = 127.0.0.1:9000
And change it as follows:
listen = /var/run/php-fpm/default.sock
You must now specify which user will listen on the “socket.” Find the following lines:
;listen.owner = nobody ;listen.group = nobody ;listen.mode = 0660
Remove the semicolon in front of each parameter and change them as follows:
listen.owner = apache listen.group = apache listen.mode = 0660
While you’re there, scroll to the bottom of the file “www.conf” and enable the OPCache module :
php_value[opcache.file_cache] = /var/lib/php/opcache
Save the file and exit the editor. Activate the “php-fpm” service and start it:
systemctl enable php-fpm systemctl start php-fpm
Apache configuration
To use PHP-FPM on the main Web site, you must configure a default virtual host on port 80. Create a file named “default.conf”:
vi /etc/httpd/conf.d/default.conf
Copy the following directives to the file:
<VirtualHost _default_:80> DocumentRoot "/var/www/html" <Directory "/var/www/html"> # allow from all Order deny,allow Options FollowSymLinks SymLinksIfOwnerMatch Require all granted AllowOverride All php_admin_value open_basedir /var/www/html </Directory> ErrorLog logs/default-error_log LogLevel warn TransferLog logs/default-access_log CustomLog logs/default-request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" SuexecUserGroup apache apache <Proxy "unix:/var/run/php-fpm/default.sock|fcgi://php-fpm"> ProxySet disablereuse=off </Proxy> <FilesMatch \.php$> SetHandler proxy:fcgi://php-fpm </FilesMatch> </VirtualHost>
Save the file and exit the editor.
When installing the package mod_ssl, a file named “ssl.conf” is created to enable the SSL module for Apache. This file contains directives for the default virtual host running on port 443 (HTTPS). Edit this file:
vi /etc/httpd/conf.d/ssl.conf
At the end of the file, insert the instructions for PHP-FPM, before closing the “VirtualHost” section:
# [...] # Per-Server Logging: # The home of a custom SSL log file. Use this when you want a # compact non-error SSL logfile on a virtual host basis. CustomLog logs/ssl_request_log \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" SuexecUserGroup apache apache <Proxy "unix:/var/run/php-fpm/default.sock|fcgi://php-fpm"> ProxySet disablereuse=off </Proxy> <FilesMatch \.php$> SetHandler proxy:fcgi://php-fpm </FilesMatch> </VirtualHost>
Then restart the “http” service:
systemctl restart httpd
Refresh the “info.php” page to check that PHP-FPM is working:
Step # 5: Configuring PHP-FPM for a Virtual Host
It is common for a web server to host multiple sites, and often each of these sites belongs to a different user. ToIn order to prevent PHP from accessing everyone’s files, different instances of PHP-FPM (called “pool”) must be run under different user accounts.
For this tutorial, we’ll be creating a virtual host for the “webhostinghero.home.lan” domain.
PHP-FPM configuration
First, create a user account and a directory for the new website:
adduser webhostinghero sudo -u webhostinghero mkdir /home/webhostinghero/public_html chmod -R +s /home/webhostinghero chmod -R 0755 /home/webhostinghero
It is also better to create a folder to isolate the PHP session files:
sudo -u webhostinghero mkdir -p /home/webhostinghero/var/lib/php/session
Copy the default configuration file for PHP-FPM and edit the new file:
cp /etc/php-fpm.d/sites-available/www.conf /etc/php-fpm.d/sites-available/webhostinghero.conf vi /etc/php-fpm.d/sites-available/webhostinghero.conf
Change the name of the instance:
; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[webhostinghero]
Enter the user name and the group that PHP-FPM will use to execute the PHP scripts:
; Unix user/group of processes ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. ; RPM: apache user chosen to provide access to the same directories as httpd user = webhostinghero ; RPM: Keep a group allowed to write in log dir. group = webhostinghero
Change the name of the socket file:
listen = /var/run/php-fpm/webhostinghero.sock
The value of the parameters “listen.owner” and “listen.group” must remain the same:
listen.owner = apache listen.group = apache listen.mode = 0660
At the very end of the file, change the “session.save_path” setting:
php_value[session.save_path] = /home/webhostinghero/var/lib/php/session
Save the file. Quit the editor and create a symbolic link to the file in “sites-enabled”:
ln -s /etc/php-fpm.d/sites-available/webhostinghero.conf /etc/php-fpm.d/sites-enabled/webhostinghero.conf
Restart the PHP-FPM service:
systemctl restart php-fpm
Then check that the new pool is active:
ps ax | grep php-fpm
13746 ? Ss 0:00 php-fpm: master process (/etc/php-fpm.conf)
13747 ? S 0:00 php-fpm: pool webhostinghero
13748 ? S 0:00 php-fpm: pool webhostinghero
13749 ? S 0:00 php-fpm: pool webhostinghero
13750 ? S 0:00 php-fpm: pool webhostinghero
13751 ? S 0:00 php-fpm: pool webhostinghero
13752 ? S 0:00 php-fpm: pool www
13753 ? S 0:00 php-fpm: pool www
13754 ? S 0:00 php-fpm: pool www
13755 ? S 0:00 php-fpm: pool www
13756 ? S 0:00 php-fpm: pool www
13760 pts/0 S+ 0:00 grep --color=auto php-fpm
Virtual Host Configuration File
With the new PHP-FPM pool ready, create a configuration file for the virtual host:
vi /etc/httpd/conf.d/webhostinghero.org.conf
Insert the following configuration:
<VirtualHost *:80> DocumentRoot "/home/webhostinghero/public_html" ServerName webhostinghero.home.lan ServerAlias www.webhostinghero.home.lan <Directory "/home/webhostinghero/public_html"> # allow from all Order deny,allow Options FollowSymLinks SymLinksIfOwnerMatch Require all granted AllowOverride All php_admin_value open_basedir /home/webhostinghero </Directory> ErrorLog logs/webhostinghero.home.lan-error_log LogLevel warn TransferLog logs/webhostinghero.home.lan-access_log CustomLog logs/webhostinghero.home.lan-request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" SuexecUserGroup webhostinghero webhostinghero <Proxy "unix:/var/run/php-fpm/webhostinghero.sock|fcgi://php-fpm"> ProxySet disablereuse=off </Proxy> <FilesMatch \.php$> SetHandler proxy:fcgi://php-fpm </FilesMatch> </VirtualHost> <VirtualHost *:443> DocumentRoot "/home/webhostinghero/public_html" ServerName webhostinghero.home.lan ServerAlias www.webhostinghero.home.lan <Directory "/home/webhostinghero/public_html"> # allow from all Order deny,allow Options FollowSymLinks SymLinksIfOwnerMatch Require all granted AllowOverride All php_admin_value open_basedir /home/webhostinghero </Directory> ErrorLog logs/webhostinghero.home.lan-ssl_error_log LogLevel warn TransferLog logs/webhostinghero.home.lan-ssl_access_log CustomLog logs/webhostinghero.home.lan-ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" SuexecUserGroup webhostinghero webhostinghero <Proxy "unix:/var/run/php-fpm/webhostinghero.sock|fcgi://php-fpm"> ProxySet disablereuse=off </Proxy> <FilesMatch \.php$> SetHandler proxy:fcgi://php-fpm </FilesMatch> # SSLEngine on # SSLCertificateFile /etc/pki/tls/webhostinghero.org/webhostinghero.org.pem # SSLCertificateKeyFile /etc/pki/tls/webhostinghero.org/webhostinghero.org.key # SSLCertificateChainFile /etc/pki/tls/webhostinghero.org/chain.pem </VirtualHost>
Save the file and exit the editor.
Note that this virtual host configuration will generate an SSL certificate error since a valid certificate is not configured.
Restart the Apache service:
systemctl restart httpd
Copy the “info.php” file created in step # 4 into the virtual host’s public directory:
cp /var/www/html/info.php /home/webhostinghero/public_html chown -R webhostinghero:webhostinghero /home/webhostinghero
Now access “info.php” from your web browser. Make sure that FPM / FastCGI is now in charge of PHP processes:
Scroll down to the “Environment” section and check “User” and “Home” variables for the user created for this virtual host:
Thus, it will be impossible for PHP scripts to access anything outside of “/home/webhostinghero” and files created by PHP will belong to the user “webhostinghero.”
Thank you so much for this, I once had to convert a Nextcloud instance from regular PHP to PHP-FPM but it was relatively recent for apache I guess bc most help was for NGINX. I did it but I felt like it was still to slow so I scratch it and I sort of regretted it when I realized I had to start over then I setup the basic CentOS server and added my root to it and DuckDuck-went to “install httpd with php-fpm” and this was literally the first result!
Everything went textbook. Now I hope I don’t screw it up when it’s time to get a certificate–if it is I’ll just cheat with HAProxy. :) Thanks!