How to Install Apache, PHP 7, and PHP-FPM on Ubuntu
Posted onThis tutorial is also available for CentOS 7.
PHP is everywhere and is, without a doubt, the most used programming language on the Web. However, PHP is not recognized for its performance, but rather for its flexibility and ease of integration with Apache and Nginx.
That said, there are several things you can do to improve the performance of PHP. The first thing to do is to install PHP-FPM, which stands for PHP FastCGI Process Manager. PHP-FPM is used to manage PHP requests received from the Web server.
PHP-FPM shines, especially when it comes time to handle a high volume of competing queries. Therefore, for a website with little traffic, the use of PHP-FPM may not present a significant gain.
In this tutorial, we will see how to install and configure Apache and PHP-FPM on an Ubuntu 19.04 server.
Step # 1: Installing Apache, PHP 7.2, and PHP-FPM
At first, disable AppArmor:
service apparmor stop update-rc.d -f apparmor remove apt-get remove apparmor apparmor-utils
Update the operating system and installed packages:
apt update -y && sudo apt upgrade -y && sudo apt autoremove -y
Then install Apache, PHP 7.2, and PHP-FPM:
apt-get -y install apache2 apache2-doc apache2-utils libapache2-mod-php php7.2 php7.2-common php7.2-gd php7.2-mysql php7.2-imap php7.2-cli php7.2-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear mcrypt imagemagick libruby libapache2-mod-python php7.2-curl php7.2-intl php7.2-pspell php7.2-recode php7.2-sqlite3 php7.2-tidy php7.2-xmlrpc php7.2-xsl memcached php-memcache php-imagick php-gettext php7.2-zip php7.2-mbstring php-soap php7.2-soap php7.2-fpm php7.2-opcache php-apcu
Step # 2: Apache Web Server Configuration
To prevent HTTPOXY attacks, create the “httpoxy.conf” file:
nano /etc/apache2/conf-available/httpoxy.conf
Then insert this configuration:
<IfModule mod_headers.c> RequestHeader unset Proxy early </IfModule>
Save the file and exit the editor. Enable the HTTPOXY configuration file:
a2enconf httpoxy
Then activate the necessary Apache modules:
a2enmod suexec rewrite ssl actions include cgi dav_fs dav auth_digest headers proxy_fcgi alias
If the firewall is active, add a rule allowing access to ports 80 and 443:
ufw allow 'Apache Full' ufw delete allow 'Apache'
Then enable and restart the apache2
service:
systemctl enable apache2 systemctl restart apache2
Check that the web server is responding:
While you are there, take the opportunity to check that PHP is functional. Create a file named “info.php” in “/var/www/html”:
nano /var/wwww/html/info.php
Copy the following content to the file:
<?php phpinfo(); ?>
Save the file and access it from your web browser:
As you can see, PHP is active; however, it is not handled by PHP-FPM but rather by the Apache module.
Step # 3: Enabling PHP-FPM
To make PHP-FPM the default PHP handler, type this command:
a2enconf php7.2-fpm
Enable and start the PHP-FPM daemon:
systemctl enable php7.2-fpm systemctl start php7.2-fpm
Reload the Apache configuration:
systemctl reload apache2
Step # 4: Configure PHP-FPM for the default website
When you install Apache, the default Web site files are in “/var/www/html.” The Apache server uses the “www-data” user account to access these files.
Make sure the permissions on the folder are correct:
chown -R www-data.www-data /var/www/html
Then edit the default virtual host configuration file:
nano /etc/apache2/sites-enabled/000-default.conf
Insert these lines before the closing tag “</ VirtualHost>”:
[...]
<Directory /var/www/html>
AllowOverride All
</Directory>
<IfModule proxy_fcgi_module>
# Enable http authorization headers
<IfModule setenvif_module>
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
</IfModule>
<FilesMatch ".+\.ph(ar|p|tml)$">
SetHandler "proxy:unix:/run/php/php7.2-fpm.sock|fcgi://localhost"
</FilesMatch>
<FilesMatch ".+\.phps$">
# Deny access to raw php sources by default
# To re-enable it's recommended to enable access to the files
# only in specific virtual host or directory
Require all denied
</FilesMatch>
# Deny access to files without filename (e.g. '.php')
<FilesMatch "^\.ph(ar|p|ps|tml)$">
Require all denied
</FilesMatch>
</IfModule>
</VirtualHost>
</IfModule>
Reload the Apache configuration:
systemctl reload apache2
Refresh the “info.php” page and check that PHP-FPM is active:
Step # 5: Configuring PHP-FPM for a Virtual Host
In many cases, a single web server can host multiple sites that must be isolated from each other at the PHP layer. To prevent PHP scripts from one site accessing files from another site, you must use distinct PHP-FPM pools.
For this tutorial, we will create a virtual host for the “webhostinghero.home.lan” domain. Start by creating the user account:
adduser webhostinghero
Then create the directory that will contain the files of the website:
sudo -u webhostinghero mkdir /home/webhostinghero/public_html chmod -R 0755 /home/webhostinghero/public_html chmod +x /home/webhostinghero
Then copy the PHP-FPM configuration file from the default site and edit it:
cp /etc/php/7.2/fpm/pool.d/www.conf /etc/php/7.2/fpm/pool.d/webhostinghero.home.lan.conf nano /etc/php/7.2/fpm/pool.d/webhostinghero.home.lan.conf
Make the changes identified in red:
; Start a new pool named 'webhostinghero'. ; the variable $pool can be used in any directive and will be replaced by the ; pool name ('www' here) [webhostinghero] ; Per pool prefix ; It only applies on the following directives: ; - 'access.log' ; - 'slowlog' ; - 'listen' (unixsocket) ; - 'chroot' ; - 'chdir' ; - 'php_values' ; - 'php_admin_values' ; When not set, the global prefix (or /usr) applies instead. ; Note: This directive can also be relative to the global prefix. ; Default Value: none ;prefix = /path/to/pools/$pool ; Unix user/group of processes ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. user = webhostinghero group = webhostinghero ; The address on which to accept FastCGI requests. ; Valid syntaxes are: ; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on ; a specific port; ; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on ; a specific port; ; 'port' - to listen on a TCP socket to all addresses ; (IPv6 and IPv4-mapped) on a specific port; ; '/path/to/unix/socket' - to listen on a unix socket. ; Note: This value is mandatory. listen = /run/php/php7.2-fpm-webhostinghero.sock php_admin_value[open_basedir] = /home/webhostinghero ; Set listen(2) backlog. ; Default Value: 511 (-1 on FreeBSD and OpenBSD) ;listen.backlog = 511
Save the configuration and restart the PHP-FPM service:
systemctl restart php7.2-fpm
You can then verify that the new PHP-FPM pool is active:
root@ubuntu-server:/etc/php/7.2/fpm# ps ax | grep fpm
30000 ? Ss 0:00 php-fpm: master process (/etc/php/7.2/fpm/php-fpm.conf)
30020 ? S 0:00 php-fpm: pool webhostinghero
30021 ? S 0:00 php-fpm: pool webhostinghero
30022 ? S 0:00 php-fpm: pool www
30023 ? S 0:00 php-fpm: pool www
30028 pts/0 S+ 0:00 grep --color=auto fpm
Now copy the default virtual host configuration file and edit it:
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/webhostinghero.home.lan.conf nano /etc/apache2/sites-available/webhostinghero.home.lan.conf
Edit the file as follows:
<VirtualHost *:80> # The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName # specifies what hostname must appear in the request's Host: header to # match this virtual host. For the default virtual host (this file) this # value is not decisive as it is used as a last resort host regardless. # However, you must set it for any further virtual host explicitly. ServerName webhostinghero.home.lan ServerAdmin webmaster@localhost DocumentRoot /home/webhostinghero/public_html # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, # error, crit, alert, emerg. # It is also possible to configure the loglevel for particular # modules, e.g. #LogLevel info ssl:warn ErrorLog ${APACHE_LOG_DIR}/webhostinghero.home.lan-error.log CustomLog ${APACHE_LOG_DIR}/webhostinghero.home.lan-access.log combined <Directory /home/webhostinghero/public_html> AllowOverride All Require all granted </Directory> <IfModule proxy_fcgi_module> # Enable http authorization headers <IfModule setenvif_module> SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1 </IfModule> <FilesMatch ".+\.ph(ar|p|tml)$"> SetHandler "proxy:unix:/run/php/php7.2-fpm-webhostinghero.sock|fcgi://localhost" </FilesMatch> <FilesMatch ".+\.phps$"> # Deny access to raw php sources by default # To re-enable it's recommended to enable access to the files # only in specific virtual host or directory Require all denied </FilesMatch> # Deny access to files without filename (e.g. '.php') <FilesMatch "^\.ph(ar|p|ps|tml)$"> Require all denied </FilesMatch> </IfModule> # For most configuration files from conf-available/, which are # enabled or disabled at a global level, it is possible to # include a line for only one particular virtual host. For example the # following line enables the CGI configuration for this host only # after it has been globally disabled with "a2disconf". #Include conf-available/serve-cgi-bin.conf </VirtualHost>
Save the configuration and exit the editor. Then activate the new virtual host:
ln -s /etc/apache2/sites-available/webhostinghero.home.lan.conf /etc/apache2/sites-enabled/webhostinghero.home.lan.conf
Restart the apache2
service:
systemctl reload apache2
Copy the info.php
file created previously:
cp /var/www/html/info.php /home/webhostinghero/public_html/ chown webhostinghero.webhostinghero /home/webhostinghero/public_html/info.php
Go now to “info.php” with your web browser. Check that PHP-FPM is active:
Scroll to the “Environment” section and verify that PHP-FPM uses the account specified in the configuration:
Also, check the value of the “open_basedir” parameter to make sure PHP scripts are restricted to the user’s home directory:
If you need to change the PHP configuration for a virtual host, know the PHP settings applied in the Apache configuration files do not affect. You must always modify the PHP-FPM pool configuration file.
So far, one of the best general PHP-FPM how-to’s I’ve come across in a long while.
Thank you