How to install PHP & PHP-FPM on Ubuntu 20.04 (LAMP)

PHP FPM (FastCGI Process Manager) is an alternative implementation of PHP FastCGI. It provides some additional features like Adaptive process spawning which is useful for sites. In this tutorial we will help you to install PHP-FPM/FastCGI on Ubuntu 20.04. If you have not installed Apache yet, follow this tutorial on Apache installation first, then come back.

For this tutorial, we will install PHP versions 7.4, 8.0 and 8.1, since you may be running an app on your site that requires an older version. However, we will focus on configuring everything for version 8.1, so after PHP itself is installed, if you want to configure for a different version, just replace 8.1 with the version you are installing. For example instead of entering sudo apt install php8.1-fpm. you may use sudo apt install php7.4-fpm.

$ sudo apt install software-properties-common
$ sudo apt install apache2 libapache2-mod-fcgid
$ sudo add-apt-repository ppa:ondrej/php

Now let's update:

$ sudo apt update && sudo apt upgrade

Now we will install PHP 7.4:

$ sudo apt install -y php7.4

then install PHP 8.0:

$ sudo apt install -y php8.0

then install PHP 8.1:

$ sudo apt install -y php8.1

Next we need to install the FPM for PHP 8.1

$ sudo apt install php8.1-fpm

Now let's see which version of PHP is active:

$ php -v

You should see output similar to this:

PHP 8.1.1 (cli) (built: Dec 31 2021 07:26:20) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies

Note that it shows PHP 8.1.1 is the active version.

Changing the Active Version of PHP Used by the Server

If you used a different version of PHP-FPM, you can set the default PHP version on your system like this:

$ sudo update-alternatives --config php

Based on having installed version 7.4, 8.0 and 9.1 above, we will see the following:

There are 3 choices for the alternative php (providing /usr/bin/php).

  Selection    Path             Priority   Status
------------------------------------------------------------
* 0            /usr/bin/php8.1   81        auto mode
  1            /usr/bin/php7.4   74        manual mode
  2            /usr/bin/php8.0   80        manual modev
  3            /usr/bin/php8.1   81        manual modev

  Press [enter] to keep the current choice[*], or type selection number:

In this case, if you want PHP 7.4 to be active, you would enter 1, then [ENTER]. If you want to fully follow along with this tutorial, we will be using version 8.1, so choose the number that corresponds with /usr/bin/php8.1 8. (in the example above it would be 0 or 3)

Now check the version again:

$ php -v

For PHP 8.1, it will still look like what we see below. For 7.4 or 8.0, the change should reflect in the output.

PHP 8.1.1 (cli) (built: Dec 31 2021 07:26:20) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies

The PHP FPM service should also be running now. Let's see how to check:

$ sudo systemctl status php8.1-fpm

We should see output similar to this:

● php8.1-fpm.service - The PHP 8.1 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.1-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-01-26 20:52:59 UTC; 5 days ago
       Docs: man:php-fpm8.1(8)
   Main PID: 780 (php-fpm8.1)
     Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 1114)
     Memory: 11.7M
     CGroup: /system.slice/php8.1-fpm.service
             ├─780 php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)
             ├─887 php-fpm: pool www
             └─890 php-fpm: pool www

Jan 26 20:52:58 temp systemd[1]: Starting The PHP 8.1 FastCGI Process Manager...
Jan 26 20:52:59 temp systemd[1]: Started The PHP 8.1 FastCGI Process Manager.

Enable FastCGI

Now we need to enable some of the Apache modules required for the FastCGI configuration. You can enable them by running:

$ sudo a2enmod actions fcgid alias proxy_fcgi

Install Common PHP Packages

Now let's install come of the more common packages used with PHP:

$ sudo apt install -y php8.1-cli php8.1-curl 
$ sudo apt install php8.1-xml php8.1-bcmath php8.1-imagick php8.1-bcmath 
$ sudo apt install php8.1-bz2 php8.1-intl php8.1-gd php8.1-mbstring 
$ sudo apt install php8.1-mysql php8.1-zip php8.1-common

Remember, if you are focusing on 7.4 or 8.0, replace each instance of 8.1 above with the version you are focusing on.

Enable PFP-FPM

Since we have chosen to focus on PHP 8.1, we need to enable the configuration of FPM in Apache by entering the following command:

$ sudo a2enconf php8.1-fpm

and make sure some of the Apache modules required for FastCGI are enabled:

$ sudo a2enmod actions fcgid alias proxy_fcgi

Now we will make some edits to the default website configuration. This assumes you have not added virtual hosts to your site (we will get to that in another tutorial), and are working on a fresh installation of Apache on Ubuntu 20.04.

$ sudo nano /etc/apache2/sites-available/000-default.conf

You should see the following in the nano editor:

<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 www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/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}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # 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>

Just below where you see DocumentRoot /var/www/html, paste the following:

    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks +MultiViews
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch \.php$>
        # 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost"
    </FilesMatch>

So now the file should look like this:

  GNU nano 4.8                                          /etc/apache2/sites-available/000-default.conf                                          Modified  
<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 www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        <Directory /var/www/html>
           Options -Indexes +FollowSymLinks +MultiViews
           AllowOverride All
           Require all granted
        </Directory>

        <FilesMatch \.php$>
           # 2.4.10+ can proxy to unix socket
           SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost"
        </FilesMatch>

        # 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}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # 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>

Note: There is a line that reads SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost". If you are focusing on 7.4 or 8.0, be sure to change this like to reflect the correct version.

Now save the file by hitting [CTRL-X] then Y, then [ENTER]

Finally, let's restart Apache and FPM:

$ sudo systemctl restart apache2.service && sudo systemctl restart php8.1-fpm

Assuming you did not make any typos, you should not see any errors. If you do see an error, go back and check for any possible mistakes you may have made. Don't worry, mistakes are common!

Testing Our Setup

We have now configured Apache with PHP-FPM. All the PHP files will be run with the FPM, which makes PHP run much faster!

First, let's verify our settings by creating a PHP script with the phpinfo() function in our server document root. Use this command to create the file:

$ sudo bash -c 'echo "<?php phpinfo(); ?>" > /var/www/html/info.php'

Then open your web browser and open:

http://SERVER-IP/info.php

You should now see a page that looks like this: phpinfo

Notice in #1, we have Server API set to FPM/FastCGI. It is working!

In #2, we see Configuration File (php.ini) Path is set to /etc/php/8.1/fpm. Now we know we are using php8.1-fpm. Of course, if you installed a different version, it should be reflected here.

In #3, we can see the path of out php.ini file, which we will be editing soon. In our case it is /etc/php/8.1/fpm/php.ini. So if what you see here is different than what is outlined below, edit the one you see listed here!

Editing PHP Configuration

Take special note where the loaded configuration file is, because we are going to do some editing here before we continue to make sure we get started with common settings in PHP.

    /etc/php/8.1/fpm/php.ini

Remember, if you chose to use PHP 7.4, the ini file is in /etc/php/7.4/fpm/php.ini, and for 8.0 it is in /etc/php/8.0/fpm/php.ini. We will continue to use version 8.1 for this tutorial. Open the configuration file:

$ sudo nano /etc/php/8.1/fpm/php.ini

There are many settings in the PHP.INI file, and if you are hosting multiple websites on this server, you can set them individually for each site in various other ways. Here are some common changes you will likely need to make if you are going to use PHP applications like Wordpress, or just about anything modern:

upload_max_filesize

This is a server setting which defines how large a file can be uploaded to the server via the browser. This is designed to restrict users uploading huge files which clog the system. The default is to disallow any uploads greater than 2 megabytes. But if you have a site that will allow uploading of files, or you use a CMS that allows you to upload plugins, this will almost never be enough. Here is how you can increase this limit to 20 megabytes, but the setting you choose is entirely up to you based on the software you will use.

Find the following text in the php.ini file:

upload_max_filesize = 2M

and change it to:

upload_max_filesize = 20M
post_max_size

This is the largest POST that can be made to the server. Usually, uploads will be done by the POST method. Generally this should be a little larger than the value set for upload_max_filesize.

Find the following text in the php.ini file:

post_max_size = 2M

and change it to:

post_max_size = 21M
memory_limit

This is the maximum amount of memory thata script can allocate. The default of 128 megabytes is generally ok, but many applicastions will require it to be higher. Consider two things before changing this:

  1. memory_limit must be a little higher than what is set in upload_max_filesize and post_max_size.
  2. Be sure you set this to a value your server can handle. If you have low RAM on your server, it is best to not set this too high.

Find the following text in the php.ini file:

memory_limit = 128M

and change it to:

memory_limit = 256M
max_execution_time

This is a setting which defines maximum amount of time the server is allowed to wait for a web page to load before killing the process. This is intended to help stop infinite loops and to keep web-servers responsive for multiple users, even if some pages are doing heavy loading. The problem with that is that many scripts necessarily take a long time. Uploading large files can take time, doing imports of large CSV files, sending large batches of emails, migrating large databases, etc. The default value of 30 seconds is often too low for many applications, so we will change it to 300 (10 minutes).

Find the following text in the php.ini file:

max_execution_time = 30

and change it to:

max_execution_time = 300

Now save the file by hitting [CTRL-X] then Y, then [ENTER]

Finally, let's restart the services again so everything takes effect:

$ sudo systemctl restart apache2.service && sudo systemctl restart php8.1-fpm

We're Done!

We now have PHP with FastCGI fully working on our server. If you have been following these tutorials in order, you also. have installed MySQL, so you have a complete and pretty secured LAMP stack up and running.

What we have not gotten into yet is how to work with databases and users in a graphical environment, so that is next. You can read the tutorial on How to Remotely Access MySQL on Ubuntu 20.04, which will help you set up MySQL to connect remotely using an app on your device, or How to Install phpMyAdmin on Ubuntu 20.04, which will provide you a web-based administration for MySQL.




Blog Comments powered by Disqus.