PHP Basic Setup on Ubuntu
PHP version and repositories
By default Ubuntu 22.04 supports PHP 8.x. We can check that by the following command.
apt-cache policy php
In order to install any supported (active) PHP versions on Ubuntu independent of the version of the OS we could use the third party repository Ondrej PPA.
sudo add-apt-repository ppa:ondrej/php
sudo apt update
List and install PHP packages
Here is a script that will create a list of the PHP and related packages installed on the system.
PHP_VER="8.1"
OS_VER="$(lsb_release -ir | grep -oP ':\s+\K.*' | awk '{print tolower($0)}' | sed -z 's/\n/./')"
for pkg in $(sudo apt-cache policy *php${PHP_VER}* | grep -P "^(lib.*|php)${PHP_VER}.*:$" | sed 's/:$//');
do echo "$pkg";
done | tee /tmp/list-of-php${PHP_VER}-pkgs-${OS_VER}.txt
The lists of the PHP packages that should be installed on the server to run CMS as WordPress and MediaWiki, and other services like as NextCloud, Plex and more, are the follow:
Some of the packages, provided in the lists above, are dependencies of other and will be automatically installed. We ca use the following commands to install the core packages list.
PHP_VER="8.1"
sudo apt install -y php${PHP_VER} php${PHP_VER}-cli php${PHP_VER}-fpm
sudo apt install -y php${PHP_VER}-mbstring php${PHP_VER}-gd php${PHP_VER}-zip
sudo apt install -y php${PHP_VER}-iconv php${PHP_VER}-simplexml
sudo apt install -y php${PHP_VER}-xmlreader php${PHP_VER}-mysql
sudo apt install -y php${PHP_VER}-curl php${PHP_VER}-xml php${PHP_VER}-xmlrpc
sudo apt install -y php${PHP_VER}-imagick php${PHP_VER}-bcmath php${PHP_VER}-dom
sudo apt install -y php${PHP_VER}-exif php${PHP_VER}-fileinfo php${PHP_VER}-json
sudo apt install -y php${PHP_VER}-apcu php${PHP_VER}-mcrypt php${PHP_VER}-intl
sudo php${PHP_VER} -m | grep 'apcu\|mcrypt' # Test does specific expensions are installed
apcu
mcrypt
Migrate to a newer PHP version
Approach 1
Generate a list and install the new packages on the fly.
OLD_PHP_VER="7.4"; NEW_PHP_VER="8.1"
for pkg in $(sudo apt-cache policy *php${OLD_PHP_VER}* | grep -P "^(lib.*|php)${OLD_PHP_VER}.*:$" | sed -e 's/:$//' -e "s/${OLD_PHP_VER}/${NEW_PHP_VER}/");
do sudo apt install "$pkg" -y;
done 2>/tmp/php${NEW_PHP_VER}.install.error.log
Approach 2
Use previously generated list to install the new packages.
OLD_PHP_VER="7.4"; NEW_PHP_VER="8.1"
while IFS= read -r pkg;
do sudo apt install "${pkg/$OLD_PHP_VER/$NEW_PHP_VER}" -y;
done </tmp/list-of-php7.4-pkgs-ubuntu.22.04.txt 2>/tmp/php${NEW_PHP_VER}.install.error.log
Remove the old version
REMOVE_PHP_VER="7.4"
# remove 'echo' to apply the actual changes
for pkg in $(sudo apt-cache policy *php${REMOVE_PHP_VER}* | grep -P "^(lib.*|php)${REMOVE_PHP_VER}.*:$" | sed 's/:$//');
do echo sudo apt remove -y "$pkg";
done 2>/tmp/php${REMOVE_PHP_VER}.remove.error.log
PHP configuration
CLI version
sudo nano /etc/php/8.1/cli/php.ini
# Thin Server 1G # Normal Server 16G # Default
opcache.enable = 1 # 1 # 1
opcache.enable_cli = 1 # 0 # 0
sudo nano /etc/php/8.1/mods-available/apcu.ini
extension=apcu.so
apc.enable_cli=1
Some services as NextCloud/cron.php
are using Memcache\APCu
in the command line. In case it is not enabled by the configuration, as it is shown above, the CLI command can enable this parameter for a while.
sudo -u www-data php --define apc.enable_cli=1 /var/www/nextcloud/occ maintenance:repair
Apache2 module
The configuration file for the module libapache2-mod-php
is /etc/php/8.1/apache2/php.ini
. My preferable configuration is the same as the PHP-FPM's configuration – fpm/php.ini
, for this reason it is not explicitly listed here. This file wont be used when PHP-FPM is in use, but it's good to be configured in case you switch to libapache2-mod-php
for some reason.
PHP-FPM service
My preferable configuration is shown below.
sudo nano /etc/php/8.1/{fpm,apache2}/php.ini
# Thin Server 1G # Normal Server 16G # Default
zlib.output_compression = On # On # Off
max_execution_time = 600 # 600 # 30
max_input_time = 120 # 120 # 60
max_input_vars = 3000 # 3000 # 1000
memory_limit = 256M # 2048M # 128M
post_max_size = 128M # 1024M # 8M
upload_max_filesize = 128M # 512M # 2M
max_file_uploads = 40 # 80 # 20
allow_url_fopen = On # On # On
default_socket_timeout = 360 # 360 # 60
pcre.backtrack_limit = 400000 # 400000 # 100000
session.cookie_secure = True # True # True
session.gc_maxlifetime = 14400 # 14400 # 1440 (seconds)
session.cache_expire = 540 # 540 # 180 (minutes)
mbstring.encoding_translation = On # On # Off
opcache.enable = 1 # 1 # 1
opcache.enable_cli = 1 # 0 # 0
opcache.memory_consumption = 256 # 2048 # 128
opcache.interned_strings_buffer = 64 # 256 # 8
opcache.max_accelerated_files = 1000000 # 1000000 # 10000
- According to the value of
opcache.memory_consumption
– for a single small site about 50 MB should be enough. For example, a server that run about 10 instances of MediaWiki/WordPress consumes about 500 MB. Ref: ZendOPcache.
PHP-FPM service specific configuration.
sudo nano /etc/php/8.1/fpm/pool.d/www.conf
# Thin Server 1G # Normal Server 16G # Default
pm.max_children = 50 # 100 # 5
pm.start_servers = 4 # 8 # 2
pm.min_spare_servers = 2 # 2 # 1
pm.max_spare_servers = 6 # 9 # 3
pm.max_requests = 1000 # 2000 # 500
;php_admin_value[memory_limit] = 512M # 2048M # 32M
php_admin_value[memory_limit]
– according to the documentation of NextCloud the value should be at least 512M. The value-1
, removes the limit. Not set;
means, the relevant value fromphp.ini
is in used.
PHP set CLI version
sudo update-alternatives --set php /usr/bin/php8.1 && php -v
PHP and Apache2 – PHP-FPM, HTTP2
It is preferable to use PHP-FPM instead the Apache's PHP module. PHP-FPM is the modern way to handle PHP files – it is faster, it supports HTTP2 and so on.
In order to disable the Apache2 PHP module – libapache2-mod-php
, and prepare for PHP-FPM execute the following commands.
sudo a2dismod php8.1 mpm_prefork mpm_worker
sudo a2enmod headers rewrite ssl setenvif http2 dav_fs expires ext_filter proxy_fcgi mpm_event
I also prefer to do not enable phpX.X‑fpm
configuration by default.
sudo a2disconf php8.1-fpm
Thus we can enable different PHP versions for the different virtual hosts when it is needed. So at the virtual host level we can use the following directives.
# Redirect to local php-fpm if mod_php is not available
# The variable PHP_IS_ENABLED is set in apache2.conf
<IfDefine !PHP_IS_ENABLED>
Include /etc/apache2/conf-available/php8.1-fpm.conf
</IfDefine>
# Define a variable flag if mod_php is enabled
# Then use it in the VH configuration to trigger 'php_flag' enable/disable...
# https://stackoverflow.com/questions/39450760/how-to-check-in-htaccess-if-php-is-enabled
<IfModule mod_php.c>
Define PHP_IS_ENABLED
</IfModule>
<IfModule mod_php5.c>
Define PHP_IS_ENABLED
</IfModule>
<IfModule mod_php7.c>
Define PHP_IS_ENABLED
</IfModule>
<IfModule mod_php8.c>
Define PHP_IS_ENABLED
</IfModule>
Enable and start PHP-FPM service
To enable and start the PHP-FPM service use the following commands. Note in this example two PHP versions are in use.
sudo systemctl enable --now php7.4-fpm.service
sudo systemctl enable --now php8.1-fpm.service
When the module libapache2-mod-php
is in use, to apply some changes of the PHP configuration the Apache service must be restarted. When php-fpm
is in use we can restart just its service to accomplish the same task. However during the initial setup I would restart them both few times…
sudo systemctl restart apache2.service
sudo systemctl restart php7.4-fpm.service
sudo systemctl restart php8.1-fpm.service
References
- Ask Ubuntu: Upgrade to the latest PHP version in Ubuntu
- PHP: Supported Versions
- Launchpad: Ondrej PPA/PHP
- Cwiki.Apache.org: PHP
- PHP supported version for WordPress:
- PHP supported version for MediaWiki:
- PHP supported version for NextCloud:
- NextCoud Docs: System requirements
- Website for Students: How to Install Memcached on Ubuntu Linux
- WVIP: How to Prepare Your WordPress Site for PHP 8
Errors solving:
- NextCloud GitHub: 21.0.3 OC\HintException: Memcache \OC\Memcache\APCu not available
- NextCloud Forum: OCC won’t run with memcache/apcu