Amazon Linux 2 still ships PHP 5.4 in its core repository, so any PHP 8 you install on it comes from an extras topic. On 22 October 2026 the php8.2 topic was the only PHP 8 topic in the extras list, and its 8.2.35 build carries the fix for PHP2Shell (CVE-2026-109618 and CVE-2026-109619). PHP 8.1 has no fixed build on this OS: the hidden php8.1 topic stopped at 8.1.34, and the Remi EL7 repository this guide used before is frozen at 8.1.29 from June 2024.
AWS ended support for Amazon Linux 2 on 30 June 2026, so if you are building a new server, install PHP 8.4 on Amazon Linux 2023 instead and use this page to keep an existing box patched while you plan the move. Every command below was run in October 2026 on fresh Amazon Linux 2 test systems (not EC2), with PHP 8.2.35 from the extras topic served through Apache and PHP-FPM. Security groups, reboots, mod_php and Nginx were not part of that test.
PHP 8.1 features that 8.2 keeps
PHP 8.2 is a superset of 8.1, so code written for the 8.1 features below runs on the 8.2 build this guide installs:
- Enums: native enumerations
- AVIF image format support: GD can read and write AVIF when PHP is built with libavif (the Amazon Linux 2 8.2 build reports
AVIF Supportas false) - Readonly properties: class properties that can only be written once
- Never return type: a return type hint for functions that never return
- Support for DNS-over-HTTPS (DoH)
- array_is_list as a built-in function
- Fibers: the low level mechanism for cooperative concurrency
- File uploads with CURLStringFile: the curl extension uploads files from a string
- Pure intersection types
- Final class constants
- Explicit octal numeral notation
- New fdatasync() and fsync() functions
Pick a PHP source on Amazon Linux 2
Four PHP sources still answer on Amazon Linux 2, and only one of them ships the PHP2Shell fix. We checked each one on 22 October 2026, and the newest build each source serves decides which one you can run on a server that takes web traffic:
| Source | Newest build | PHP2Shell fix |
|---|---|---|
| amzn2-core (default repo) | php 5.4.16-46.amzn2.0.7 | No, and long out of support |
| Extras topic php8.2 | php-common 8.2.35-1.amzn2.0.1 | Yes |
| Extras topic php8.1 (end of support 2025-12-31) | php-common 8.1.34-1.amzn2 | No |
| Remi EL7 (remi-php81, SCL php81) | php81-php-common 8.1.29-1.el7.remi | No, frozen since June 2024 |
Use the php8.2 topic. The older install path on this page also broke on its own: the EPEL 7 URL it used (dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm) no longer downloads, and remi-release-7.rpm then refuses to install with Requires: epel-release = 7. Pulling EPEL from amazon-linux-extras install epel gets Remi installed again, but only to hand you the June 2024 build in the last row.
Enable the php8.2 extras topic
Extras topics are switched on per server with amazon-linux-extras, which is already installed on Amazon Linux 2. List the PHP topics first:
amazon-linux-extras list | grep php
On a fresh system only one PHP topic shows up. The php8.1 topic is hidden from the list, which is how AWS retires topics:
68 php8.2 available [ =stable ]
Enable it, then clear the yum metadata cache so yum reads the new repository on its next run.
sudo amazon-linux-extras enable php8.2
sudo yum clean metadata
Before installing, confirm the repository offers the patched build. Anything older than 8.2.35-1.amzn2.0.1 here means your mirror has not caught up yet:
yum list available php-cli php-fpm php-common
All three packages came from amzn2extra-php8.2 at the fixed version on our system:
Available Packages
php-cli.x86_64 8.2.35-1.amzn2.0.1 amzn2extra-php8.2
php-common.x86_64 8.2.35-1.amzn2.0.1 amzn2extra-php8.2
php-fpm.x86_64 8.2.35-1.amzn2.0.1 amzn2extra-php8.2
If you see an older release in the second column, your region’s mirror has not caught up yet. Wait, run sudo yum clean metadata again and repeat the check before you install, because installing now would give you a build without the fix.
Install PHP 8.2 and extensions on Amazon Linux 2
Install the CLI, PHP-FPM and the extensions most PHP applications ask for. The curl and json extensions are built into php-common on this build, so they have no separate packages:
sudo yum -y install php-{cli,fpm,mysqlnd,gd,mbstring,xml,opcache,bcmath,intl,ldap,pdo,devel,pear}
Yum resolves the extensions plus their libraries in one transaction, and you only confirm once.
Transaction Summary
================================================================================
Install 13 Packages (+45 Dependent packages)
Total download size: 35 M
Once yum finishes, check which PHP version you got.
php --version
The build date of 21 October 2026 matches the upstream security release:
PHP 8.2.35 (cli) (built: Oct 21 2026 16:01:03) (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
Unlike the Remi SCL build, which lived under /etc/opt/remi/php81/ and ran as php81, the extras packages use the standard paths: /etc/php.ini for the main settings, one file per extension in /etc/php.d/, and the FPM pool in /etc/php-fpm.d/www.conf. The command is plain php. List the loaded modules:
php -m
Every extension from the install line shows up, along with the ones compiled into php-common. If one you need is missing, install it before you point an application at this server.
[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dom
exif
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
ldap
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
random
readline
Reflection
session
shmop
SimpleXML
sockets
SPL
sqlite3
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zip
zlib
[Zend Modules]
Zend OPcache
To add another extension later, install php-<name> from the same topic and restart PHP-FPM so the workers load it.
Start PHP-FPM and serve a test page
The CLI working says nothing about the PHP that answers web requests, and that is the PHP an attacker reaches. Enable PHP-FPM so it starts at boot:
sudo systemctl enable --now php-fpm
systemctl status php-fpm
The master process should be active with five workers in the www pool:
● php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2026-10-22 20:12:44 UTC; 321ms ago
Main PID: 374 (php-fpm)
Status: "Ready to handle connections"
CGroup: /system.slice/php-fpm.service
├─374 php-fpm: master process (/etc/php-fpm.conf)
├─375 php-fpm: pool www
├─376 php-fpm: pool www
├─377 php-fpm: pool www
├─378 php-fpm: pool www
└─379 php-fpm: pool www
The pool listens on the socket /run/php-fpm/www.sock and runs as the apache user, and the php-fpm package drops /etc/httpd/conf.d/php.conf, which hands every .php file to that socket. So Apache needs no PHP configuration of its own. Install it and start it:
sudo yum -y install httpd
sudo systemctl enable --now httpd
Create a small probe page. It prints the version and SAPI of the PHP that served the request, plus the settings the PHP2Shell mitigation below changes:
echo '<?php echo PHP_VERSION, " ", PHP_SAPI, " upload_progress=", ini_get("session.upload_progress.enabled"), " memory_limit=", ini_get("memory_limit"), " post_max_size=", ini_get("post_max_size"), " upload_max_filesize=", ini_get("upload_max_filesize"), "\n";' | sudo tee /var/www/html/phpver.php
Now request it through Apache, the same path your visitors take.
curl -s http://localhost/phpver.php
fpm-fcgi confirms Apache passed the request to PHP-FPM and that the patched build answered it, with the stock limits in place:
8.2.35 fpm-fcgi upload_progress=1 memory_limit=128M post_max_size=8M upload_max_filesize=2M
If you are opening the page from a browser, allow TCP port 80 in the instance’s security group (we did not test that part). Keep the probe for the checks below and delete it when you are done, because it tells anyone who finds it which PHP build you run.
Check for the PHP2Shell fix (CVE-2026-109618, CVE-2026-109619)
PHP2Shell is a pair of critical remote code execution bugs in PHP itself, which php.net’s 20 October pre-announcement rated CVSS v4.0 9.2. PHP fixed them on 21 October 2026 in 8.5.12, 8.4.27, 8.3.36 and 8.2.35. The PHP security advisory lists every PHP SAPI that serves web requests as at risk, mod_php most of all. A fresh install from the steps above already has the fix, so you can stop at the check below. Query the installed package:
rpm -qa 'php*-common'
The pattern also catches Remi’s php81-php-common, so a server that still carries the old install shows both. A patched server prints this one line:
php-common-8.2.35-1.amzn2.0.1.x86_64
Amazon published the fix as ALAS2PHP8.2-2026-015 on 22 October 2026, rated Important, naming both CVEs and the fixed build php-8.2.35-1.amzn2.0.1. So the extras topic still gets security fixes even though Amazon Linux 2 itself is past its end of support. The package changelog only says “Package updated to 8.2.35”, so the version is the proof on the box: 8.2.35-1.amzn2.0.1 or later is patched, and anything older, any 8.1.x from the extras topic and any php81-php-common-8.1.29 from Remi is vulnerable. The probe page tells you the same thing about the PHP that serves requests, which matters if a pool was never restarted after an update.
If this was a fresh install and you are done, delete the probe page now:
sudo rm -f /var/www/html/phpver.php
A request for it then returns 404. The sections below are for servers that were running PHP before 21 October.
Upgrade and restart on an existing server
A server that installed the php8.2 topic before 21 October has an older build. If you skipped the install steps above, create the probe page from the test page step first, so you can see which PHP your site actually serves. If your site has its own virtual host and DocumentRoot, write the file into that DocumentRoot and request it by your site’s hostname instead of localhost. We put a server back to 8.2.34 and ran the upgrade the way you would. Ask yum which packages Amazon’s advisory covers:
yum -q updateinfo list ALAS2PHP8.2-2026-015
Each installed PHP package shows up with the fixed build. If this prints nothing on an old build, run sudo yum clean metadata and retry, because the mirror may still serve old metadata:
ALAS2PHP8.2-2026-015 important/Sec. php-bcmath-8.2.35-1.amzn2.0.1.x86_64
ALAS2PHP8.2-2026-015 important/Sec. php-cli-8.2.35-1.amzn2.0.1.x86_64
ALAS2PHP8.2-2026-015 important/Sec. php-common-8.2.35-1.amzn2.0.1.x86_64
ALAS2PHP8.2-2026-015 important/Sec. php-devel-8.2.35-1.amzn2.0.1.x86_64
ALAS2PHP8.2-2026-015 important/Sec. php-fpm-8.2.35-1.amzn2.0.1.x86_64
Apply the advisory, then restart PHP-FPM so every worker loads the new code. On our server the update upgraded all 14 PHP packages; sudo yum -y update 'php*' did the same job in an earlier run. The package restarted PHP-FPM on its own in our test, but restart it anyway and confirm, since a worker still running the old build stays vulnerable:
sudo yum clean metadata && sudo yum -y update --advisory ALAS2PHP8.2-2026-015
sudo systemctl restart php-fpm
Compare when PHP-FPM last started with when the packages landed. On Amazon Linux 2 rpm -q --last prints the install time of each package, and yum history lists the transaction if you want the whole picture:
systemctl show -p ActiveEnterTimestamp php-fpm
rpm -q --last php-common php-fpm
The service started at 20:29:42, one second after php-fpm was upgraded, so the running workers are the patched ones:
ActiveEnterTimestamp=Thu 2026-10-22 20:29:42 UTC
php-fpm-8.2.35-1.amzn2.0.1.x86_64 Thu Oct 22 20:29:41 2026
php-common-8.2.35-1.amzn2.0.1.x86_64 Thu Oct 22 20:29:39 2026
The probe page then returned 8.2.35 fpm-fcgi. If you installed the php package and Apache runs PHP as a module (httpd -M lists php_module), restart httpd too, because PHP-FPM restarts do not touch it; we did not test mod_php on Amazon Linux 2. Long-running PHP CLI processes such as queue workers under supervisor keep the old code in memory until you restart them as well.
PHP 8.1 on Amazon Linux 2 has no fix
No free PHP 8.1 build for Amazon Linux 2 carries the PHP2Shell fix. The PHP project no longer releases 8.1, the php8.1 extras topic is past its own end of support, and Remi has published nothing newer for EL7 than its June 2024 build. You can see the topic’s status yourself:
amazon-linux-extras info php8.1 | head -1
The topic reports a date that has already passed, so you will not get another build from it.
php8.1 has end-of-support date of 2025-12-31
Its newest package, php-common-8.1.34-1.amzn2, arrived with ALAS2PHP8.1-2026-008 on 22 January 2026, which fixed three 2025 CVEs. Amazon has published no PHP 8.1 advisory for PHP2Shell, and the package changelog has no entry for either CVE. The fix is to move the site to the php8.2 topic, which we did on servers running both 8.1 sources (steps in the last section). If you cannot move today, the interim settings below cut down the confirmed attack paths. They are not a fix, and PHP’s advisory says so plainly.
Reduce exposure until you can upgrade
The PHP advisory recommends memory_limit = -1 and a low post_max_size against CVE-2026-109618, and session.upload_progress.enabled = 0 against CVE-2026-109619, all set where applications cannot override them. In an FPM pool that means php_admin_value and php_admin_flag. Use post_max_size = 8M when the site takes no file uploads and 32M when it does, and keep upload_max_filesize below it. For the php8.1 extras topic, append the lines to /etc/php-fpm.d/www.conf:
printf '%s\n' 'php_admin_value[memory_limit] = -1' 'php_admin_flag[session.upload_progress.enabled] = off' 'php_admin_value[post_max_size] = 8M' | sudo tee -a /etc/php-fpm.d/www.conf
sudo systemctl restart php-fpm
Remi’s SCL build keeps its pool under /etc/opt/remi/php81/ and runs its own service, so the same lines go there with a different restart:
printf '%s\n' 'php_admin_value[memory_limit] = -1' 'php_admin_flag[session.upload_progress.enabled] = off' 'php_admin_value[post_max_size] = 8M' | sudo tee -a /etc/opt/remi/php81/php-fpm.d/www.conf
sudo systemctl restart php81-php-fpm
Check the result through the web server, not the CLI, because the pool settings only apply to FPM workers (php -r still reported upload progress as 1 in our test):
curl -s http://localhost/phpver.php
The php8.1 extras build answered with all three settings in force, and Remi’s 8.1.29 pool returned the same values. Both builds started from the same defaults we saw on 8.2.35, post_max_size=8M and upload_max_filesize=2M:
8.1.34 fpm-fcgi upload_progress=0 memory_limit=-1 post_max_size=8M upload_max_filesize=2M
An unlimited memory_limit lets one request take all of the instance’s RAM, so watch memory while it is in place. The advisory suggests a container or cgroup limit as the availability boundary; on Amazon Linux 2 that would be a systemd MemoryLimit= on the PHP-FPM service, which we did not test. Upload progress is off for the whole pool, so any upload progress bar that depends on it stops reporting.
If Apache runs PHP 8.1 as a module instead of through FPM, the same settings belong in an Apache config file. We did not test this form on Amazon Linux 2. Create the file:
sudo vim /etc/httpd/conf.d/php2shell.conf
Add the three settings, guarded so Apache still starts when the module is not loaded, then restart httpd and check the probe:
<IfModule mod_php.c>
php_admin_value memory_limit -1
php_admin_flag session.upload_progress.enabled off
php_admin_value post_max_size 8M
</IfModule>
The probe should report apache2handler with the three values changed.
Move a PHP 8.1 site to the php8.2 topic
Both 8.1 sources move to the patched 8.2 build without reinstalling the server. Test the application on a PHP 8.2 copy of the server first and read its error log for new warnings; a local Amazon Linux 2 KVM guest is enough for that. The steps depend on where 8.1 came from.
From the php8.1 extras topic. Take an EBS snapshot or an AMI of the instance first, because amazon-linux-extras prints Beware that disabling topics is not supported after they are installed. when you disable php8.1, and a snapshot is your way back. You have to disable it anyway: enabling php8.2 while php8.1 is enabled fails with Refusing because php8.2 could cause an invalid combination. Swap the topics and refresh the metadata:
sudo amazon-linux-extras disable php8.1
sudo amazon-linux-extras enable php8.2
sudo yum clean metadata
Before updating, make sure every PHP package you have installed has an 8.2 counterpart in the new topic, because an 8.1 package with no 8.2 match would block the update. This compares the installed names with the available ones and prints only the orphans:
comm -23 <(rpm -qa 'php*' --qf '%{NAME}\n' | sort) <(yum -q list available 'php-*' | awk 'NR>1 {sub(/\.(x86_64|noarch)$/, "", $1); print $1}' | sort)
It printed nothing on our server, so all nine installed packages had a match. If it lists a package, remove it or find its replacement before going on. Then update and restart PHP-FPM:
sudo yum -y update 'php*'
sudo systemctl restart php-fpm
The 8.2 packages carry the same names and simply upgrade the 8.1 ones. Yum keeps your edited www.conf during the upgrade, so the interim lines are still in force afterwards. The probe confirmed both, the new build and the leftover settings:
8.2.35 fpm-fcgi upload_progress=0 memory_limit=-1 post_max_size=8M upload_max_filesize=2M
Once the patched build answers, take the interim lines out and restart PHP-FPM, so memory goes back under a limit:
sudo sed -i '/^php_admin_value\[memory_limit\] = -1$/d; /^php_admin_flag\[session.upload_progress.enabled\] = off$/d; /^php_admin_value\[post_max_size\] = 8M$/d' /etc/php-fpm.d/www.conf
sudo systemctl restart php-fpm
The probe then returned 8.2.35 fpm-fcgi upload_progress=1 memory_limit=128M post_max_size=8M upload_max_filesize=2M.
From Remi’s php81 SCL build. Remi’s packages live under /opt/remi/php81 and its pool listens on 127.0.0.1:9000, so the extras build installs and runs next to it without a conflict. That lets you switch without downtime: start the new FPM, move the web server over, and stop the old FPM last. Install PHP 8.2 with the commands from the install section above (enable the php8.2 topic, clean the metadata, then the same yum -y install line), copy any custom settings from /etc/opt/remi/php81/ into /etc/php.ini and /etc/php.d/, then start the new FPM:
sudo systemctl enable --now php-fpm
The site still runs on 8.1.29 at this point, because Apache sends requests to port 9000. With Apache, the php.conf from the php-fpm package already points at the new /run/php-fpm/www.sock socket, so delete whatever handler you added for port 9000 (on our server a SetHandler "proxy:fcgi://127.0.0.1:9000" block in its own file under /etc/httpd/conf.d/), then restart Apache and check. With Nginx, change fastcgi_pass to unix:/run/php-fpm/www.sock and reload it instead; we did not test Nginx here.
sudo systemctl restart httpd
curl -s http://localhost/phpver.php
The same probe that reported 8.1.29 a moment earlier now comes from the patched build:
8.2.35 fpm-fcgi upload_progress=1 memory_limit=128M post_max_size=8M upload_max_filesize=2M
Only now stop the Remi FPM, and when the site works on 8.2, remove the Remi packages. PHP-FPM and Apache stayed active through both steps on our server:
sudo systemctl disable --now php81-php-fpm
sudo yum -y remove 'php81*'
Whichever path you followed, delete the probe page once the last check passes, so it stops advertising your PHP build:
sudo rm -f /var/www/html/phpver.php
That gets the server patched today, but it does not get it a long future. PHP 8.2 reaches end of life on 31 December 2026 according to php.net’s 8.2.35 release announcement, and Amazon Linux 2 is already past its own end of support, so treat the php8.2 topic as a bridge. The lasting fix is a new Amazon Linux 2023 instance, and the Amazon Linux 2023 KVM image lets you rehearse that move locally before you touch production.
Most PHP sites on these servers also carry a database, and MySQL 8.4 on Amazon Linux 2023 is the matching piece for the new instance, so the database moves in the same window as PHP.
If you are leaving Amazon’s distributions altogether, the same PHP2Shell checks for Rocky Linux and AlmaLinux are in the RHEL family PHP guide, and the Rocky Linux 10 and AlmaLinux 10 AppStream builds carry the fix.
Great! But I’d like to know how to configure it in nginx? Please!
Well explained and easy to follow, thanks!
Thanks and welcome