Skip to content

PHP

Using custom respositories provided by deb.sury.org

The versions provided by Debian or Ubuntu are usally not the latest versions. To make sure that you get the latest version of PHP, it is recommended to use the repositories provided by https://deb.sury.org.

Adding the repository for Debian

sudo apt -y install apt-transport-https lsb-release ca-certificates curl
sudo curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
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'
sudo apt update

Adding the repository for Ubuntu

sudo apt -y install software-properties-common ca-certificates lsb-release apt-transport-https
sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
sudo apt update

Installation

Please always check https://www.php.net/supported-versions.php to make sure, the PHP version you want to use, is still supported!

PHP 8.3

sudo apt -y install php8.3 php8.3-apcu php8.3-bcmath php8.3-bz2 php8.3-cli php8.3-common php8.3-curl php8.3-fpm php8.3-gd php8.3-imap php8.3-intl php8.3-ldap php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-redis php8.3-sqlite3 php8.3-xml php8.3-xsl php8.3-yaml php8.3-zip

PHP 8.2

sudo apt -y install php8.2 php8.2-apcu php8.2-bcmath php8.2-bz2 php8.2-cli php8.2-common php8.2-curl php8.2-fpm php8.2-gd php8.2-imap php8.2-intl php8.2-ldap php8.2-mbstring php8.2-mysql php8.2-opcache php8.2-redis php8.2-sqlite3 php8.2-xml php8.2-xsl php8.2-yaml php8.2-zip

PHP 8.1

Note: this version will be end of life by November 2023 and should not be used any longer!

sudo apt -y install php8.1 php8.1-apcu php8.1-bcmath php8.1-bz2 php8.1-cli php8.1-common php8.1-curl php8.1-fpm php8.1-gd php8.1-imap php8.1-intl php8.1-ldap php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-redis php8.1-sqlite3 php8.1-xml php8.1-xsl php8.1-yaml php8.1-zip

PHP 8.0

Note: this version is end of life since November 2023 and should not be used any longer!

sudo apt -y install php8.0 php8.0-apcu php8.0-bcmath php8.0-bz2 php8.0-cli php8.0-common php8.0-curl php8.0-fpm php8.0-gd php8.0-imap php8.0-intl php8.0-ldap php8.0-mbstring php8.0-mysql php8.0-opcache php8.0-redis php8.0-sqlite3 php8.0-xml php8.0-xsl php8.0-yaml php8.0-zip

PHP 7.4

Note: this version is end of life since November 2022 and should not be used any longer!

sudo apt -y install php7.4 php7.4-apcu  php7.4-bcmath php7.4-bz2 php7.4-cli php7.4-common php7.4-curl php7.4-fpm php7.4-gd php7.4-imap php7.4-intl php7.4-json php7.4-ldap php7.4-mbstring php7.4-mysql php7.4-opcache php7.4-redis php7.4-sqlite3 php7.4-xml php7.4-xsl php7.4-yaml php7.4-zip

Enabling PHP-FPM for Apache

Overview

Apache will forward every request to PHP scripts to the PHP-FPM process which will then use one of the running workers to handle the request and return the output to Apache.

uml diagram

Configuration file

Usually PHP already provides a configuration file at /etc/apache2/conf-available/php7.4-fpm.conf or /etc/apache2/conf-available/php8.1-fpm.conf and so on.

The following documentation is only required if you ever need to create a configuration manually.

The configuration to use PHP-FPM in Apache looks as following. The important thing here is the handler which matches a certain file pattern and will use the local socket of the PHP-FPM service.

Example: /etc/apache2/conf-available/php8.1-fpm.conf

# Redirect to local php-fpm if mod_php is not available
<IfModule !mod_php8.c>
<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/php8.1-fpm.sock|fcgi://localhost"
    </FilesMatch>
# The default configuration works for most of the installation, however it could
# be improved in various ways. One simple improvement is to not pass files that
# doesn't exist to the handler as shown below, for more configuration examples
# see https://wiki.apache.org/httpd/PHP-FPM
#    <FilesMatch ".+\.ph(ar|p|tml)$">
#        <If "-f %{REQUEST_FILENAME}">
#            SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
#        </If>
#    </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>
</IfModule>

You can also create a custom configuration file like this which uses a custom socket instead of /run/php/php8.1-fpm.sock. This requires to have a custom FPM pool configuration which may also use a different user/group for PHP. See below at "Pool configuration".

Enable FCGI in Apache

Make sure, that PHP is not used as module and that the correct MPM module is used and enable FCGI:

sudo a2dismod php8.1
sudo a2dismod mpm_prefork
sudo a2dismod mpm_event
sudo a2enmod mpm_worker
sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo systemctl restart apache2

Note: Instead of php8.1 use the version which is installed actually.

Enable PHP-FPM globally

To enable PHP-FPM 8.1 globally for all sites in Apache use the following command:

sudo a2enconf php8.1-fpm

Note: this also means all PHP scripts will be executed with the same PHP user and with the same FPM pool!

Enable PHP-FPM for individual websites only

If you want to have PHP-FPM only enabled in specific websites or different PHP version for each website, you can also include the respective configuration in the <VirtualHost> section of the website:

<VirtualHost *:80>
    ServerName mysite.example
    DocumentRoot /var/www/mysite.example

    <Directory /var/www/mysite.example>
        AllowOverride all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/mysite.example-error.log
    CustomLog ${APACHE_LOG_DIR}/mysite.example-access.log combined

    # Enable PHP FPM 8.1 for this website
    Include /etc/apache2/conf-available/php8.1-fpm.conf
</VirtualHost>

Define the PHP version to be used for the command line

You can install multiple PHP versions parallel. However when using the command php a specific version is used.

Check the current version:

php -v

Change the version interactive:

sudo update-alternatives --config php

This will present a list of all installed version to choose from:

There are 2 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.1   81        manual mode

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

"auto mode" means, this is the version selected automatically when installing a newer version. But you may also manually select an another version to be sure, that the command php will use that version.

Using a specific PHP version in the command line If needed, you can also use a specific version by adding the version number to the command name:

  • PHP 7.4: php7.4
  • PHP 8.0: php7.4
  • PHP 8.1: php8.1

Adjusting the PHP configuration

Note: After changing any of the following configurations you need to restart PHP-FPM (depending on the version):

sudo systemctl restart php8.1-fpm

Pool configuration of PHP-FPM

You may want to optimize the performance by definig a static pool instead of dynamic in /etc/php/<VERSION>/fpm/pool/www.conf:

[www]

pm = static
pm.max_children = 10

The line pm.max_children = 10 defines the number of workers started by PHP-FPM. For very high volume sites this may need to be more. The number limits how many requests can be handled parallel at the same time.

You can also create additional pools beside /etc/php/<VERSION>/fpm/pool/www.conf for other users/groups (which of course must exist in your system) to separate access rights for individual PHP processes and refer to them using the respective socket. Just make sure, that the additional pool uses a different path for the runtime socket. For example as /etc/php/<VERSION>/fpm/pool/mypool.conf:

[myuser]

user = myuser
group = mygroup
pm = static
pm.max_children = 10

listen = /run/php/php8.1-fpm-myuser.sock

To use that pool in Apache, you just need to make sure, that the socket /run/php/php8.1-fpm-myuser.sock is used in the PHP configuration file as explained above.

Memory limits for PHP-FPM

Increase the memory limits for processes, post data and uploads in /etc/php/<VERSION>/fpm/php.ini:

memory_limit = 2048M
upload_max_filesize = 100M
post_max_size = 1024M

Configure XDebug

Before you can use XDebug you have to install the extension, for example for PHP 8.2:

sudo apt -y install php8.2-xdebug

To enable xdebug to be used with the XDebug-Helper in Browsers, use the following settings in /etc/php/<VERSION>/fpm/conf.d/20-xdebug.ini:

zend_extension=xdebug.so
xdebug.mode=debug
xdebug.client_host=<IP address or FQDN of your development system>
xdebug.client_port=9000
xdebug.start_with_request=trigger

Note: using a fixed client host makes the configuration more secure since then not everybody can connect to a debug sssion on the server. However XDebug also supports auto detection of the host IP address asking for a debug session.