Installing PHP on Ubuntu is straightforward through the default package manager — running multiple versions side by side, needed when different projects on the same server require different PHP versions, needs a specific third-party repository instead.
Installing PHP from Ubuntu's default repositories
sudo apt update
sudo apt install php php-cli php-fpm php-mysql
php -v
Ubuntu's default repositories ship one specific PHP version tied to that particular Ubuntu release — this is fine for a server running a single project, but it means apt install php alone can't provide a choice of PHP versions or run more than one at once.
Adding the Ondřej Surý PPA, for access to every PHP version
sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
This community-maintained PPA (Personal Package Archive) is the de facto standard source for installing a specific, current PHP version on Ubuntu — it's what makes installing PHP 8.1, 8.2, 8.3, or several at once actually possible, beyond whatever single version ships with Ubuntu's own repositories.
Installing a specific PHP version
sudo apt install php8.3 php8.3-cli php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-xml
Installing multiple PHP versions side by side
sudo apt install php8.1 php8.1-fpm php8.1-cli
sudo apt install php8.3 php8.3-fpm php8.3-cli
Installing versions via the PPA doesn't uninstall or conflict with each other — each version installs to its own separate path (like /usr/bin/php8.1 and /usr/bin/php8.3), which is exactly why explicitly calling /usr/bin/php8.4 (rather than the bare php command) is the reliable way to target a specific version in a multi-version setup.
Switching the default CLI version with update-alternatives
sudo update-alternatives --set php /usr/bin/php8.3
sudo update-alternatives --config php
update-alternatives is what controls which installed version the bare php command actually points to — without explicitly setting this, the bare php command's version can be ambiguous or unexpectedly tied to whichever version was installed or configured last.
Configuring which version Nginx or Apache actually serves
# Nginx: point fastcgi_pass at the specific version's socket
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
The web server's own configuration (not update-alternatives, which only affects the CLI) is what determines which PHP-FPM version actually serves a given site — each PHP-FPM version runs its own separate socket file, and a site's config must point at the correct one for the version actually intended.
Verifying which version is running
php8.3 -v
sudo systemctl status php8.3-fpm
Installing common extensions
sudo apt install php8.3-curl php8.3-gd php8.3-zip php8.3-bcmath php8.3-intl
A fresh PHP install includes only a minimal set of extensions — a real Laravel application typically needs several of these added explicitly, and the specific set needed varies by project, worth checking against composer.json's require section for extension requirements listed there.