Which PHP version apt install php pulls in has nothing to do with what your application needs and everything to do with which Debian you run. Debian 12 ships 8.2, Debian 13 ships 8.4. There is nothing in between, and nothing to choose from.

Which version each Debian ships

Every Debian release freezes exactly one PHP version and maintains it with security fixes for the whole lifetime of that release.

DebianCodenamePHP
11bullseye7.4
12bookworm8.2
13trixie8.4

To find out what you are on:

cat /etc/debian_version; lsb_release -sc

The upstream version number in the packages stays put even as fixes land. Debian raises its own revision instead, turning 8.2.20-1~deb12u1 into 8.2.20-1~deb12u2. So an upstream number that looks older than the current PHP release does not mean vulnerabilities are open.

If the bundled version is not enough, Ondřej Surý's repository is the established route. It carries PHP 5.6 through 8.6 for current Debian releases; setup is covered in installing PHP via Sury.

Which packages you actually need

The php metapackage drags in a long list of dependencies, Apache and libapache2-mod-php among them. On a server running nginx, or one that only needs PHP on the command line, that is unwanted. Install deliberately instead.

For cron jobs or Composer, the command line is enough:

sudo apt install php-cli

Behind a web server, PHP-FPM is the usual choice. It runs as its own service, and both Apache and nginx talk to it:

sudo apt install php-fpm

Then the extensions your application asks for. This selection covers most web applications:

sudo apt install php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl php-bcmath
PackageWhat it is for
php-mysqlMySQL and MariaDB, provides PDO and mysqli
php-curloutbound HTTP requests from the application
php-gdimage processing, thumbnails, captchas
php-mbstringstrings with accents and multi-byte characters
php-xmlXML, SimpleXML, DOM
php-zipreading and writing archives
php-intllocale-aware sorting, date and number formats
php-bcmatharbitrary precision arithmetic

php-json appears in plenty of older guides and no longer exists. JSON support has been part of the core since PHP 8.0, so the install attempt ends with an error about an unknown package.

Wiring up Apache

Two routes lead there, and they are mutually exclusive.

Through PHP-FPM

The recommended route, because it works with the faster mpm_event.

sudo apt install php-fpm libapache2-mod-fcgid
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.2-fpm
sudo systemctl reload apache2

Adjust the number in php8.2-fpm to your version. ls /etc/apache2/conf-available/ | grep fpm shows which configurations are available.

Through mod_php

sudo apt install libapache2-mod-php

Works, but forces Apache onto mpm_prefork, because mod_php is not thread-safe. On a server with many concurrent connections that costs noticeable performance. If you later move from mod_php to FPM, disable the module first:

sudo a2dismod php8.2 mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif
sudo a2enconf php8.2-fpm
sudo systemctl restart apache2

Wiring up nginx

nginx has no mod_php; FPM is the only way. In the server block:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

Confirm the actual socket path with ls /run/php/. After changes, test and reload:

sudo nginx -t && sudo systemctl reload nginx

The two php.ini files

Debian keeps separate configurations for the command line and for FPM:

/etc/php/8.2/cli/php.ini      ← php on the command line
/etc/php/8.2/fpm/php.ini      ← PHP behind the web server

Change upload_max_filesize and wonder why the web interface still refuses the file, and you edited the wrong one. To see which file a given invocation actually reads:

php -i | grep "Loaded Configuration File"

The same applies to the web side through a script calling phpinfo(). After any change to the FPM configuration the service needs a restart — reloading the web server is not enough:

sudo systemctl restart php8.2-fpm
Caution
Do not leave a phpinfo() script reachable. It exposes paths, loaded extensions, version numbers and parts of your configuration — a ready-made map for anyone who finds the page. Delete it once you have looked.

Checking that it works

php -v
php -m
systemctl status php8.2-fpm

php -v reports the command-line version, php -m lists loaded extensions. If one you installed is missing, the service was not restarted afterwards.

Troubleshooting

ProblemCause and fix
The browser offers the PHP file as a downloadPHP is not wired to the web server. Enable the FPM configuration or check fastcgi_pass.
php -v shows a different version than the websiteCommand line and FPM can run different versions. See running multiple PHP versions.
A php.ini change has no effectThe wrong one of the two files was edited, or php-fpm was not restarted.
An extension is missing despite installing itThe service was not restarted, or the package belongs to a different PHP version.
php-json cannot be installedBuilt into the core since PHP 8.0; there is no separate package.
Apache will not start after moving to FPMmpm_prefork and mpm_event are both enabled. Disable one.
No socket under /run/php/FPM is not running. systemctl status php8.2-fpm gives the reason.

Frequently asked questions about PHP on Debian

Which PHP version does my Debian have?

Debian 11 ships PHP 7.4, Debian 12 ships 8.2 and Debian 13 ships 8.4. No other version is available from Debian's own repositories; that needs an additional one.

Do I need php-fpm or libapache2-mod-php?

PHP-FPM for new installations. It works with both Apache and nginx and allows the faster mpm_event. mod_php forces Apache onto mpm_prefork and is the weaker choice today.

Where is php.ini?

At /etc/php/<version>/cli/php.ini for the command line and /etc/php/<version>/fpm/php.ini for the web server. They are separate. php -i | grep "Loaded Configuration File" shows which one applies.

How do I get a newer PHP version than Debian offers?

Through the Sury repository, which provides PHP 5.6 to 8.6 for current Debian releases. Setup is covered in installing PHP via Sury.

Do I have to restart after a configuration change?

With FPM, yes: systemctl restart php8.2-fpm. Reloading the web server is not enough, because PHP runs in its own service.