
Debian 12 ships PHP 8.2. Ubuntu 24.04, 8.3. Debian 13, 8.4. Ubuntu 26.04, 8.5. A real host needs all three at once: the old WordPress, the new Laravel, the cron CLI. The distro repository does not allow it. The one from Ondřej Surý does. Nginx comes from nginx.org — stable, pinned, without mixing in distro modules.
The landscape in September 2026
PHP in the official lifecycle:
- 8.5 — active until Dec/2027, security until Dec/2029 (released 20 Nov 2025)
- 8.4 — active until Dec/2026, security until Dec/2028
- 8.3 — security only, until Dec/2027
- 8.2 — security until 31 Dec 2026
- 8.1 died on 31 Dec 2025 — do not install it on a new machine
Sury co-installs php8.3-fpm, php8.4-fpm and php8.5-fpm on the same box. Each has its own socket in /run/php/. Nginx chooses the socket in the vhost.
Sury's nginx repository closed in April 2026. PHP remains at packages.sury.org/php. Nginx: distro or nginx.org. Do not mix the two binaries.
Nginx from nginx.org
Debian 12 (bookworm), 13 (trixie); Ubuntu 24.04 (noble), 26.04 (resolute). amd64 and arm64. Key fingerprint: 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 (expires 24 May 2027).
Debian:
sudo apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show
/usr/share/keyrings/nginx-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg]
https://nginx.org/packages/debian $(lsb_release -cs) nginx"
| sudo tee /etc/apt/sources.list.d/nginx.list
Ubuntu — only the keyring and URL change:
sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg]
https://nginx.org/packages/ubuntu $(lsb_release -cs) nginx"
| sudo tee /etc/apt/sources.list.d/nginx.list
Pin it so apt does not revert to the distro's nginx, and install stable (even number: 1.30.x in 2026). Mainline is .../mainline/debian or .../mainline/ubuntu.
printf '%sn' 'Package: *' 'Pin: origin nginx.org' 'Pin: release o=nginx' 'Pin-Priority: 900'
| sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
nginx -v
The nginx.org package uses the user nginx and /etc/nginx/conf.d/ — it does not have sites-available. The distro package uses www-data and the Debian layout. Choose one and stick with it. systemd handles the service in both cases.
Want the distro's nginx, with sites-enabled and nginx-extras? Skip this section and run sudo apt install nginx. The rest of PHP is the same; only the socket owner changes.
PHP: Sury's DPA
Official recipe from packages.sury.org/php/README.txt — valid for Debian 12/13 and Ubuntu 24.04/26.04:
sudo apt-get update
sudo apt-get -y install lsb-release ca-certificates curl
curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb
echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main"
| sudo tee /etc/apt/sources.list.d/php.list
sudo apt-get update
Ubuntu-only shortcut (Launchpad PPA from the same Ondřej):
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt update
Do not enable both at once. One PHP source is enough.
Three FPMs side by side + typical WordPress/Laravel extensions:
sudo apt install -y
php8.3-fpm php8.3-cli php8.3-mysql php8.3-xml php8.3-curl php8.3-mbstring php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath
php8.4-fpm php8.4-cli php8.4-mysql php8.4-xml php8.4-curl php8.4-mbstring php8.4-zip php8.4-gd php8.4-intl php8.4-bcmath
php8.5-fpm php8.5-cli php8.5-mysql php8.5-xml php8.5-curl php8.5-mbstring php8.5-zip php8.5-gd php8.5-intl php8.5-bcmath
sudo systemctl enable --now php8.3-fpm php8.4-fpm php8.5-fpm
ls /run/php/
# php8.3-fpm.sock php8.4-fpm.sock php8.5-fpm.sock
Default CLI (what php without a number calls):
sudo update-alternatives --config php
php -v
php8.5 -v
Align the socket with nginx

With nginx.org, the worker runs as the user nginx. The default FPM pool is www-data. Without alignment, you get 502. In each pool:
sudo sed -i 's/^listen.owner.*/listen.owner = nginx/' /etc/php/8.4/fpm/pool.d/www.conf
sudo sed -i 's/^listen.group.*/listen.group = nginx/' /etc/php/8.4/fpm/pool.d/www.conf
# repita 8.3 e 8.5
sudo systemctl restart php8.3-fpm php8.4-fpm php8.5-fpm
If nginx is from the distro, leave www-data and skip the sed.
Example vhost — three sites, three PHP versions. With nginx.org, the file goes in /etc/nginx/conf.d/:
server {
listen 80;
server_name wp.exemplo.com.br;
root /var/www/wp.exemplo.com.br;
index index.php index.html;
location / { try_files $uri $uri/ /index.php?$args; }
location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}
server {
listen 80;
server_name app.exemplo.com.br;
root /var/www/app.exemplo.com.br/public;
index index.php;
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.5-fpm.sock;
}
}
sudo mkdir -p /var/www/wp.exemplo.com.br /var/www/app.exemplo.com.br/public
echo '<?php phpinfo();' | sudo tee /var/www/wp.exemplo.com.br/index.php
sudo nginx -t && sudo systemctl reload nginx
Check in phpinfo() the PHP Version and the path to php.ini (/etc/php/8.3/fpm/php.ini, etc.). Each major version has its own ini — changing 8.4 does not affect 8.5.
Firewall and what not to do
sudo ufw allow 22,80,443/tcp
sudo ufw enable
Do not install libapache2-mod-php* on this box. Do not point two identical server_name to different sockets and expect a miracle. Do not deploy PHP 8.1 “because the plugin requires it”: Sury still packages it, but upstream support has ended. 8.2 only lasts until the end of 2026.
A panel with nginx+PHP already set up: ISPConfig. This post covers the bare machine, without a panel.
Wrap-up
One pin for nginx.org, one Sury DPA, three FPMs, three sockets, three server. Apt updates the point release; the vhost selects the major version. When 8.2 loses security support, remove the package — 8.5 in the other vhost will not even notice.
Nginx: nginx.org/en/linux_packages.html · Sury PHP: packages.sury.org/php · PHP lifecycle: php.net/supported-versions.