Ubuntu does not ship PHP 8.2 in its own archive. Ubuntu 24.04 comes with PHP 8.3 and Ubuntu 22.04 with PHP 8.1, so an application pinned to PHP 8.2 needs OndΕej SurΓ½’s PPA, which builds every supported PHP branch. The branch added readonly classes and stand-alone null, false and true types (full list on PHP.Watch). Upstream security support for PHP 8.2 ends on 31 December 2026, so plan your move to a newer branch now.
We add the PPA, install PHP 8.2 with its common modules, prove the build carries the PHP2Shell fix and hook it up to Nginx or Apache. Ubuntu 20.04 and 18.04 are no longer covered. In October 2026 we ran the install, both web server setups and the upgrade check on fresh Ubuntu 24.04 and 22.04 systems, and the output blocks come from those runs.
[ebook product=”2″ theme=”blue”]
Debian installation article: How To Install PHP 8.2 on Debian
Update Ubuntu System
Bring the server up to date before adding any repository, because the PPA builds link against current Ubuntu libraries and a stale system is where dependency errors come from. We also clear old packages and reboot if the upgrade pulled in a new kernel, so you start from a clean, known state.
sudo apt update && sudo apt -y upgrade
Remove packages nothing depends on any more, which keeps old kernels from filling /boot.
sudo apt autoremove
If the upgrade touched the kernel or core libraries, Ubuntu drops a flag file, so this line reboots only when that file exists.
[ -f /var/run/reboot-required ] && sudo reboot
Confirm which Ubuntu release you are on, because the PPA only builds for some of them.
cat /etc/os-release
Look at VERSION_CODENAME. It must read noble (24.04) or jammy (22.04) for the rest of this guide to work.
PRETTY_NAME="Ubuntu 24.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.5 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
A 22.04 server shows jammy in the same field. Anything else, such as focal or resolute, means the PPA below will not give you PHP 8.2, so read the next section before you add it and decide whether the server needs a release upgrade first.
Add SurΓ½ PHP APT repository
To get PHP 8.2 packages installed on Ubuntu we’ll use OndΕej SurΓ½’s PHP PPA, which provides the supported PHP branches for current Ubuntu LTS releases. Today that means Ubuntu 24.04 and 22.04 only, and the older releases are a dead end:
- Ubuntu 20.04: the PPA’s focal index is empty, 0 packages
- Ubuntu 18.04: the bionic index is empty as well
- Ubuntu 26.04: no resolute build in the PPA at all
On 20.04 and 18.04 the only PHP left is Ubuntu’s own old branch, and its PHP2Shell fix ships through Ubuntu Pro, not the free archive, so a box on those releases without Pro has no free patched PHP. Upgrade the server to 24.04 instead of hunting for packages. On Ubuntu 26.04, use the native packages from the PHP 8.5 guide for Ubuntu 26.04, or SurΓ½’s packages.sury.org repository if an application really needs 8.2 there. Its setup steps are in the repository README.
Make sure add-apt-repository and the CA bundle are present before adding the repo.
sudo apt update
sudo apt install -y ca-certificates software-properties-common
Add the PPA. The -y flag skips the “Press ENTER” prompt, and add-apt-repository refreshes the package index on its own:
sudo add-apt-repository -y ppa:ondrej/php
On 22.04 it writes the source list and the signing key. The new description also says the PPA is being merged into packages.sury.org, with jammy and noble still served from here.
PPA publishes dbgsym, you may need to include 'main/debug' component
Repository: 'deb https://ppa.launchpadcontent.net/ondrej/php/ubuntu/ jammy main'
Description:
This repository is in process of being merged into https://packages.sury.org/php/;
For Ubuntu Resolute, https://packages.sury.org/php/ is the canonical way of getting PHP packages, for previous releases, I will provide a simple way how to migrate to the new repositories in upcoming weeks, you can still use this repository for Ubuntu Jammy and Ubuntu Noble.
More info: https://launchpad.net/~ondrej/+archive/ubuntu/php
Adding repository.
Adding deb entry to /etc/apt/sources.list.d/ondrej-ubuntu-php-jammy.list
Adding disabled deb-src entry to /etc/apt/sources.list.d/ondrej-ubuntu-php-jammy.list
Adding key to /etc/apt/trusted.gpg.d/ondrej-ubuntu-php.gpg with fingerprint B8DC7E53946656EFBCE4C1DD71DAEAAB4AD4CAB6
Confirm APT now sees PHP 8.2 and that the candidate comes from the PPA.
apt-cache policy php8.2
The candidate should be 8.2.35 or newer, served from ppa.launchpadcontent.net. “Unable to locate package” or an empty candidate means the PPA is not active for your release.
php8.2:
Installed: (none)
Candidate: 8.2.35-1+ubuntu24.04.1+deb.sury.org+1
Version table:
8.2.35-1+ubuntu24.04.1+deb.sury.org+1 500
500 https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble/main amd64 Packages
On 22.04 you get the same release with ubuntu22.04.1 in the version string. The deb.sury.org suffix is how you tell a PPA build from an Ubuntu archive package later, which matters when you check for security fixes, because Ubuntu’s own PHP packages follow a different version scheme. On 22.04 the PPA also carries its own builds of libpcre2-8-0, libpcre3 and libxml2, so your next apt upgrade replaces those Ubuntu libraries with the PPA versions.
Install PHP 8.2 on Ubuntu
Once the PPA is added, use the apt command to install PHP 8.2. The php8.2 package pulls in Apache and libapache2-mod-php8.2 as well, which is fine for an Apache server. If you plan to run Nginx, run sudo apt install php8.2-cli in place of this line so Apache never lands on the server, then carry on with the version check and the modules. The Nginx section adds FPM later.
sudo apt install php8.2
Accept the package list when prompted. The exact count depends on what the server already has, so treat this 24.04 list as a guide:
The following additional packages will be installed:
apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php8.2
libapr1t64 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaprutil1t64 libbsd0
libcurl4t64 libedit2 libgdbm-compat4t64 libgdbm6t64 libjansson4 liblua5.4-0
libperl5.38t64 libsodium23 perl perl-modules-5.38 php-common php8.2-cli
php8.2-common php8.2-opcache php8.2-readline psmisc ssl-cert
Suggested packages:
apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser ufw
php-pear gdbm-l10n perl-doc libterm-readline-gnu-perl
| libterm-readline-perl-perl make libtap-harness-archive-perl
The following NEW packages will be installed:
apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php8.2
libapr1t64 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaprutil1t64 libbsd0
libcurl4t64 libedit2 libgdbm-compat4t64 libgdbm6t64 libjansson4 liblua5.4-0
libperl5.38t64 libsodium23 perl perl-modules-5.38 php-common php8.2
php8.2-cli php8.2-common php8.2-opcache php8.2-readline psmisc ssl-cert
0 upgraded, 28 newly installed, 0 to remove and 0 not upgraded.
Need to get 16.1 MB of archives.
Check which PHP version the command line now uses.
php -v
The first line names the PHP release and the build date.
PHP 8.2.35 (cli) (built: Oct 21 2026 14:30:30) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.35, Copyright (c) Zend Technologies
with Zend OPcache v8.2.35, Copyright (c), by Zend Technologies
Anything older than 8.2.35 here means the server still runs a build from before the October 2026 security release. The version line is a quick hint, but it does not prove what is fixed, so you should read the package changelog next.
Confirm the PHP2Shell fix (CVE-2026-109618 and CVE-2026-109619)
PHP2Shell is a pair of critical remote code execution bugs in PHP itself, CVE-2026-109618 and CVE-2026-109619, both scored CVSS v4.0 9.2 and fixed upstream on 21 October 2026 in PHP 8.2.35 (and 8.5.12, 8.4.27, 8.3.36). The OndΕej SurΓ½ PPA already ships 8.2.35 for both Ubuntu 24.04 and 22.04, so a fresh install from this guide is patched. Details are in the PHP security advisory.
The package changelog is the reliable check, because it names the CVEs the build fixes. Run it on any server that already had PHP 8.2 from this PPA:
zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.2-common/changelog.Debian.gz
A patched build prints the changelog line below, on 24.04 and 22.04 alike. No output means the installed package is older than the fixed 8.2.35 build.
+ (CVE-2026-109618, CVE-2026-109619): Avoid state corruption via
A fresh install from this guide can stop here and move on to the modules. On an existing server where the check prints nothing, upgrade every PHP 8.2 package. The Apache module and the embed library start with lib, so the glob misses them and they are named explicitly:
sudo apt update
sudo apt install --only-upgrade 'php8.2*' libapache2-mod-php8.2 libphp8.2-embed
APT skips anything in that list that is not installed, so the same line suits FPM and mod_php servers. On 22.04, needrestart can pop up a dialog offering to restart services. Whatever you pick there, restart the PHP handler yourself so no worker keeps running the old code. An Nginx server restarts FPM:
sudo systemctl restart php8.2-fpm
A mod_php server restarts Apache instead:
sudo systemctl restart apache2
If you installed the module set from this guide, php8.2-fpm is on the Apache server as well, so restart both:
sudo systemctl restart php8.2-fpm apache2
Long-running PHP CLI processes, such as queue workers kept alive by supervisor or a systemd unit, also hold the old code in memory. Restart each of them the same way:
sudo systemctl restart <worker>.service
Now prove the running service is newer than the package on disk. This prints the time of the last PHP 8.2 upgrade, including entries in rotated logs:
zgrep -h ' upgrade php8.2' /var/log/dpkg.log* | sort | tail -1
Compare it with the moment the service you restarted came up. Swap apache2 for php8.2-fpm on an FPM server:
systemctl show -p ActiveEnterTimestamp apache2
The timestamp has to be later than the dpkg line. Our Apache test server printed this right after the restart:
ActiveEnterTimestamp=Thu 2026-10-22 15:38:56 UTC
Rerun the zgrep afterwards and expect the CVE line. Then request a PHP page through the web server again, such as the test page from the Nginx or Apache section below. The PPA ships upstream 8.2.35, so the version the page reports comes from the restarted worker itself:
curl -s http://127.0.0.1/info.php
Our Apache test server answered with the patched release after the restart. An FPM site reports fpm-fcgi in the second field instead:
8.2.35 apache2handler
A server still on Ubuntu 20.04 or 18.04 cannot get there from this PPA, which is one more reason to move it to 24.04.
Install PHP 8.2 modules
PHP modules are libraries that add functionality to PHP, usually written in C and loaded as shared objects. Each one is its own package named php8.2- plus the module name, so the intl module installs like this:
sudo apt install -y php8.2-intl
Most web applications (WordPress, Laravel, Nextcloud) need a similar set, so install the commonly used modules in one go:
sudo apt install php8.2-{bcmath,fpm,xml,mysql,zip,intl,ldap,gd,cli,bz2,curl,mbstring,pgsql,opcache,soap,cgi}
List the modules PHP loads to confirm they all registered.
php -m
Every module you installed shows up, along with the ones compiled into PHP.
[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
ldap
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_pgsql
pgsql
Phar
posix
random
readline
Reflection
session
shmop
SimpleXML
soap
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zip
zlib
[Zend Modules]
Zend OPcache
If a module you installed is missing, the CLI is probably reading a different PHP version. Run php -v again, and if it shows another branch, point the default back with sudo update-alternatives --config php. Web requests are not affected by that switch, because FPM and mod_php load their own php.ini under /etc/php/8.2/.
Using PHP with Nginx or Apache
Pick one web server per host. Both paths below serve the same small test page, so you can see which PHP handler answered the request.
Hosting PHP application with Nginx web server
With Nginx, PHP code is executed by a separate process, PHP-FPM (FastCGI Process Manager). PHP-FPM is a daemon that listens for incoming PHP requests on a Unix socket and runs them in its own worker pool, while Nginx only forwards the request.
If you installed the php8.2 package earlier, Apache is already running on port 80, and the Nginx package will not start while Apache holds the port. Stop and disable Apache before installing Nginx. Skip this line if Apache was never installed:
sudo systemctl disable --now apache2
Install Nginx and the FPM package.
sudo apt install nginx php8.2-fpm
Create the document root for the site.
sudo mkdir -p /var/www/mysite
Then create a server block for the site in its own file, so the default site and future sites stay separate.
sudo vim /etc/nginx/sites-available/mysite
Paste the block below and change server_name to your domain. The fastcgi_pass line points at the PHP 8.2 FPM socket:
server {
listen 80;
server_name mysite.example.com;
root /var/www/mysite;
index index.php index.html;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
Enable the site and validate the configuration.
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo nginx -t
Both lines must report success before you reload, otherwise the reload keeps the old configuration and the error sits in the output above.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Reload Nginx so it picks up the new site:
sudo systemctl reload nginx
Check that both services are up before testing a page:
systemctl is-active nginx php8.2-fpm
Both of our test servers printed two lines of active, which means Nginx and FPM are serving. Anything else, such as failed, points to journalctl -u nginx or journalctl -u php8.2-fpm for the reason:
active
active
Now add a test page that prints the PHP version and the handler that ran it:
sudo vim /var/www/mysite/index.php
Add these two lines.
<?php
echo PHP_VERSION, " ", PHP_SAPI, "\n";
Request it through Nginx. The Host header lets you test before DNS points at the server.
curl -s -H "Host: mysite.example.com" http://127.0.0.1/
A working setup answers with the version and fpm-fcgi. A 502 Bad Gateway means Nginx cannot reach the socket, so check that php8.2-fpm is running and that the socket path matches the config:
8.2.35 fpm-fcgi
Delete the test page once you have seen the result, since it tells anyone who asks which PHP release the server runs.
Hosting PHP application with Apache web server
Apache can run PHP inside its own worker processes through mod_php, so there is no separate daemon to manage. The PHP with Apache guide for Ubuntu and Debian goes further into virtual hosts and PHP-FPM under Apache.
Install the Apache web server and the Apache PHP module.
sudo apt install apache2 libapache2-mod-php8.2
Enable the mod_php module.
sudo a2enmod php8.2
The package already enabled it and switched Apache to the prefork MPM, which mod_php requires, so the command only confirms it:
Considering dependency mpm_prefork for php8.2:
Considering conflict mpm_event for mpm_prefork:
Considering conflict mpm_worker for mpm_prefork:
Module mpm_prefork already enabled
Considering conflict php5 for php8.2:
Module php8.2 already enabled
Restart Apache web server after the configuration.
sudo systemctl restart apache2
Create the same two-line test page in Apache’s default document root:
sudo vim /var/www/html/info.php
Paste the <?php and echo lines from the Nginx test, save, then request the page. This time Apache’s handler answers instead of FPM:
curl -s http://127.0.0.1/info.php
The response confirms mod_php is serving PHP 8.2.
8.2.35 apache2handler
If you get the raw PHP source back instead, mod_php is not loaded, so rerun sudo a2enmod php8.2 and restart Apache. Remove info.php when you are done with it, for the same reason as the Nginx test page.
Wrapping up
PHP 8.2 on Ubuntu 24.04 and 22.04 comes down to the OndΕej SurΓ½ PPA, the php8.2-* packages and one handler, FPM for Nginx or mod_php for Apache. Treat it as a bridge rather than a destination: security support for the branch ends on 31 December 2026, and the PPA is already moving to packages.sury.org. If your code runs on a newer branch, the PHP 8.5 install on Ubuntu 24.04 follows the same pattern, and so does PHP 8.3 on Ubuntu. Back up the site before any PHP upgrade, and rerun the changelog check after every security release.
Recommended Web Development books to read:
Thank you for this helpful tutorial. I am a beginner in linux/ubuntu. All works fine except one thing in GD.
The code (see (1)) creates the file but I get an error on line 8 – though the image is created, but not shown – this message is shown as an image (see (2)) – on another provider-server it is executed as intended and shows the image. All modules are indicated as enabled in GD – jpg too . I cannot find the error π . Could you give me a hint?
(1)
<?php
$dest = imagecreatefromjpeg('Bilder/Background-Travel.jpg'); //Room01
$src = imagecreatefromjpeg('BilderUpload/SunriseSunsetSonnenaufgang-Februar-2019.jpg');
$src = imagecreatefromjpeg('BilderUpload/TravelNZRS9157_neu2.jpg');
$src = imagecreatefromjpeg('BilderUpload/TravelPD_11_File_001.jpg');
$srcScaled = imagescale( $src, 200, 150 );
imagecopymerge($dest, $srcScaled, 135, 50, 0, 0, 200, 150, 100);
header('Content-Type: image/jpg');
imagejpeg($dest,'AAATest.jpg',100);
echo "”;
imagedestroy($dest);
imagedestroy($src);
?>
(2)
Hi,
it had been a … header_remove php.ini on apache server … which made the difference in the error behaviour … π
Best
Axel
Nice Tutorial!
https://imperiodostes.com.br
Thank you very much for good information.
Much welcome.
Hi. I’ve been using these instructions to install PHP8.2 on Ubuntu 18.04 (Bionic Beaver). When I attempt to install PHP it can’t find 8.2 in the repository for Bionic. Have this PHP vesrion been removed for Bionic? Thanks
I am having the exact same problem. 8.2.6 installs but the additional packages won’t install
This tutorial no longer works for Ubuntu 18.04. Because PPA ondrej PHP has removed the support for Ubuntu 18.04. so you can’t install php 8 with that.
That’s true… And how to do it now?
Build from source
Thanks for this tutorial. Works great
Welcome anytime!
Thanks for this information
Welcome!