On the way to install Nextcloud we’ve already completed the initial setup of our VPS, the installation of Nginx and the installation of PostgreSQL.

I will now cover the installation of PHP 8.1.

Why PHP 8.1? Because, PHP 7.4 has no longer active support and will have its security support ending in November 2022.1 And, PHP 8.1 is the recommended version to run Nextcloud 25.2

I’m currently using Debian 11, but these instructions may be equally valid for other versions of Debian and Ubuntu.

Install PHP

PHP (recursive acronym for PHP: Hypertext Preprocessor) is an open source server side scripting language, widely used to create dynamic interactive web pages.

The PHP version on Debian 11 repositories is the 7.4. So, to install PHP 8.1, we first need to add the repository deb.sury.org, maintained by Ondřej Surý.

To do so, first run the following command to be sure the required dependencies are installed:

# sudo apt update
# sudo apt install apt-transport-https lsb-release ca-certificates curl

Then, import deb.sury.org’s GPG key:

# sudo curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg

And finally, add the repository to APT’s source list:

# sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'

Let’s than install PHP 8.1 along with some of it most common extensions with the following commands:

# sudo apt update
# sudo apt install php8.1 php8.1-common php8.1-fpm php8.1-pgsql

And that’s it. At any moment you can check the PHP 8.1 service status running:

# systemctl status php8.1-fpm

Test PHP Processing

To test PHP Processing we first need to configure Nginx to use it for dynamic content.

This is done at the server block level. For this example edit the server block we’ve created earlier. To do so, run:

# sudo nano /etc/nginx/sites-available/emanuelpina.ml

And edit the server block to add the following code, just bellow the server_name. Like this:

server {
    ###

    server_name emanuelpina.ml www.emanuelpina.ml;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    }
    
    ###
}

Test to make sure that there are no syntax errors in our Nginx files:

# sudo nginx -t

If there aren’t any issues, restart Nginx to enable the changes:

# sudo systemctl reload nginx

Now let’s create a test PHP file in the website root folder:

# sudo nano /var/www/html/info.php

Add the following content to the file, which is a valid PHP code that generates a page containing information about the server:

<?php
phpinfo();

Now visiting the page https://emanuelpina.ml/info.php on a browser we should see a page generated by PHP containing structured information about our server.

If you see this page then Nginx is successfully communicating with PHP!

At the end of this test, don’t forget to remove the PHP file we created:

# sudo rm /var/www/html/info.php

This is imporant because it exposes important information about our server and can make it vulnerable.

Tune PHP

Similar to what we did with PostgreSQL, we can tune some PHP settings depending on the hardware at our disposale.3

To proceed with this we need to know three things: how many CPU cores our server have; how much memory (RAM) we can dedicate to PHP; and how much memory the average PHP process consume.

To find out how many CPU cores your server has, run the following command:

# echo Cores = $(( $(lscpu | awk '/^Socket/{ print $2 }') * $(lscpu | awk '/^Core/{ print $4 }') ))

When determining how much memory you can dedicate to PHP, keep in mind that the server is also running Nginx and PostgreSQL. How much memory are these other processes consuming? For example, if you have 4GB of RAM and the other processes are consuming 1GB, that leaves you with 3GB – or 2GB if you want to play safe.

Finally, to get a general idea on how much memory each PHP process is consuming, run:

# ps --no-headers -o "rss,cmd" -C php-fpm8.1 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"M") }'

The settigns you need to change are all in the www.conf file. To edit it, run:

# sudo nano /etc/php/8.1/fpm/pool.d/www.conf

Search for each one of the following settings and change it accordingly.

To get a good value for pm.max_children, take the memory that you want to allocate to PHP and divide it by the average memory that is consumed by each PHP process. For example, if you want to allocate 2GB (2000MB) and each process consumes about 50MB. Dividing 2000 by 50 we get around 40.
So, set pm.max_children to 40.

For pm.start_servers, multiply the number of cores that you have by 4.
If you have 2 cores: 2 x 4 = 8
So, set pm.start_servers to 8.

For pm.min_spare_servers, multiply the number of cores that you have by 2.
If you have 2 cores: 2 x 2 = 4
So, set pm.min_spare_servers to 4.

For pm.max_spare_servers, multiply the number of cores on your server by 4.
If you have 2 cores: 2 x 4 = 8
So, set pm.max_spare_servers to 8. The same used before for pm.start_servers.

To finish, just restart the PHP-FPM service:

# sudo systemctl restart php8.1-fpm

And that’s all 😀

What’s next?

With Nginx, PostgreSQL and PHP up and running we’re now ready to install Nextcloud!

Do you want contribute and add something to this tutorial? Have you found a typo, grammar or formatting error? Please, feel free to contact me or edit this post and open a pull resquest.