Back to Home

Ubuntu 24.04 – Multiple PHP Versions + Apache Development Setup

The complete, battle-tested guide (December 2025)

Everything you need to develop PHP projects in ~/Sites with instant switching between PHP 7.0 → 8.4, exactly like the famous macOS sphp script — but working perfectly on Ubuntu 24.04.

⚠️ For the Brave Souls Only!

This guide is for developers who aren't afraid to get their hands dirty with the Linux terminal. You'll be:

  • Running commands with sudo (root access)
  • Editing system configuration files
  • Installing and configuring server software
  • Potentially breaking things (so have a backup plan!)

If you're comfortable with the terminal or willing to learn, dive in! If not, maybe stick to Docker or a VM for now.

Final Result You Will Have

  • Apache 2.4 + PHP-FPM (not mod_php)
  • PHP 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 installed side-by-side
  • One command to switch versions: sudo sphp 8.3, sudo sphp 7.4, etc.
  • All projects live safely in ~/Sites
  • http://localhost/info.php instantly reflects the active version
  • No permission errors, no socket errors, no AppArmor headaches

1 Clean Start (if you already messed with PHP)

sudo apt purge php* libapache2-mod-php* -y
sudo apt autoremove -y
sudo rm -rf /etc/php/*/fpm/pool.d/www.conf.bak* 2>/dev/null || true

What this does:

  • apt purge – Completely removes packages and their config files (like npm uninstall + deleting node_modules)
  • apt autoremove – Cleans up leftover dependencies that are no longer needed
  • rm -rf – Force delete files/folders (the -rf means recursive + force)

2 System Update & Tools

sudo apt update && sudo apt upgrade -y
sudo apt install -y software-properties-common curl unzip wget

What this does:

  • apt update – Refreshes the list of available packages (like checking for new npm package versions)
  • apt upgrade – Installs newer versions of installed packages
  • apt install – Installs new packages (similar to npm install)
  • && – Runs the second command only if the first succeeds (like chaining promises)

3 Add Ondřej Surý's PHP PPA (all versions)

sudo add-apt-repository ppa:ondrej/php -y
sudo apt update

What this does:

  • add-apt-repository – Adds a new package source (like adding a custom npm registry)
  • ppa:ondrej/php – A third-party repository that provides all PHP versions

4 Install Apache

sudo apt install -y apache2
sudo a2enmod rewrite actions alias proxy_fcgi setenvif
sudo systemctl enable apache2

What this does:

  • a2enmod – "Apache 2 Enable Module" - activates Apache modules (like enabling plugins)
  • systemctl enable – Makes Apache start automatically when your computer boots
  • proxy_fcgi – The module that lets Apache talk to PHP-FPM

5 Install All PHP Versions + Common Extensions

sudo apt install -y php7.0 php7.0-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php7.1 php7.1-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php7.2 php7.2-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php7.3 php7.3-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php7.4 php7.4-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php8.0 php8.0-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php8.1 php8.1-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php8.2 php8.2-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php8.3 php8.3-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}
sudo apt install -y php8.4 php8.4-{cli,fpm,curl,gd,mbstring,mysql,xml,zip,opcache}

What this does:

  • {cli,fpm,curl,...} – Bash brace expansion, installs multiple packages at once (like installing multiple npm packages in one command)
  • cli – Command line version of PHP (for running scripts)
  • fpm – FastCGI Process Manager (the server version that Apache will use)

6 Fix PHP-FPM Socket Permissions (Critical on Ubuntu 24.04!)

This step is critical for Ubuntu 24.04!

sudo sed -i 's/;listen.mode = 0660/listen.mode = 0666/' /etc/php/*/fpm/pool.d/www.conf
sudo systemctl restart php*-fpm

What this does:

  • sed -i – "Stream editor in-place" - edits files by find/replace (like Find & Replace in your code editor)
  • s/find/replace/ – The find/replace pattern (s = substitute)
  • 0666 – File permissions (read+write for everyone, needed for Apache to access the socket)
  • systemctl restart – Restarts a service (like restarting a Node.js server)

7 Create Apache Config Files for Every Version

for v in 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4; do
    sudo tee /etc/apache2/conf-available/php${v}-fpm.conf > /dev/null <<EOF
<FilesMatch \.php$>
    SetHandler "proxy:unix:/run/php/php${v}-fpm.sock|fcgi://localhost/"
</FilesMatch>
EOF
done

What this does:

  • for v in ... – A loop that iterates over each version (like for...of in JavaScript)
  • tee – Writes text to a file (like fs.writeFileSync)
  • <<EOF...EOF – A "heredoc" (like template literals in JS, creates multi-line strings)
  • ${v} – Variable substitution (like ${v} in JS template literals)

8 Enable PHP 8.3 by Default (or any version you want first)

sudo a2enconf php8.3-fpm
sudo systemctl restart apache2

What this does:

  • a2enconf – "Apache 2 Enable Configuration" - activates a config file
  • This tells Apache to start using PHP 8.3 by default

9 Allow Apache to Read Your Home Directory

chmod +x ~/
mkdir -p ~/Sites
chmod 755 ~/Sites

What this does:

  • chmod – "Change mode" - changes file/folder permissions
  • +x – Makes a folder executable (allows entering it)
  • 755 – Permission code: owner can read/write/execute, others can read/execute
  • mkdir -p – Creates a directory (the -p means "don't error if it already exists")
  • ~ – Shortcut for your home folder (like /home/username)

10 Set Up DirectoryIndex (show index.php first)

Edit /etc/apache2/mods-enabled/dir.conf and make it look like this:

<IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
</IfModule>

What this does:

  • DirectoryIndex – Tells Apache which files to look for when visiting a folder
  • By putting index.php first, it prioritizes PHP files (like how Express.js looks for index.js)

11 Create the Real Ubuntu sphp Switcher Script

Create the script at /usr/local/bin/sphp with the following content:

#!/usr/bin/env bash
# sphp — Ubuntu PHP version switcher (FPM + Apache)
# Usage: sudo sphp 8.3   sudo sphp 7.4   etc.

VERSION="${1#php@}"
case "$VERSION" in
    7.0|7.1|7.2|7.3|7.4|8.0|8.1|8.2|8.3|8.4) ;;
    *) echo "Supported: 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4"; exit 1 ;;
esac

echo "Switching to PHP $VERSION..."
sudo systemctl stop 'php*-fpm' 2>/dev/null || true
sudo systemctl start php${VERSION}-fpm
sudo update-alternatives --set php /usr/bin/php${VERSION} >/dev/null 2>&1 || true
sudo a2disconf php*-fpm.conf 2>/dev/null || true
sudo a2enconf php${VERSION}-fpm.conf
sudo systemctl restart apache2

echo "Active PHP version:"
php -v | head -1
echo "Test at http://localhost/info.php"

After creating the file, make it executable:

sudo chmod +x /usr/local/bin/sphp

What the script does:

  • #!/usr/bin/env bash – Shebang line (tells the system this is a bash script)
  • case "$VERSION" in – Switch statement (like switch in JavaScript)
  • systemctl stop/start – Stops/starts services (manages background processes)
  • update-alternatives – Changes which version of PHP the php command uses in terminal
  • a2disconf/a2enconf – Disables old config, enables new config for the chosen PHP version

12 Test Everything

echo "<?php phpinfo(); ?>" > ~/Sites/info.php

# Try different versions
sudo sphp 8.3
sudo sphp 8.2
sudo sphp 7.4
sudo sphp 8.1

What this does:

  • echo "text" > file – Writes text to a file (redirects output, like fs.writeFileSync)
  • # – Comment line (like // in JavaScript)
  • sudo sphp 8.3 – Runs your custom script to switch PHP versions

Open http://localhost/info.php after each command — version changes instantly.

Optional: Test with Grav CMS

cd ~/Sites
curl -OL https://getgrav.org/download/core/grav-admin/latest
unzip -q grav-admin*.zip && rm grav-admin*.zip

What this does:

  • cd – "Change directory" - navigates to a folder (like cd in your terminal)
  • curl -OL – Downloads a file (-O saves with original name, -L follows redirects)
  • unzip -q – Extracts a zip file (-q = quiet mode, no verbose output)
  • * – Wildcard that matches any characters (like *.js in glob patterns)

Visit http://localhost/grav-admin → works on any PHP version you switch to.

Updating PHP Versions

sudo apt update && sudo apt upgrade
# Then switch to each version once so its binaries get updated
for v in 8.3 8.2 8.1 7.4; do sudo sphp $v; done

What this does:

  • apt upgrade – Updates all installed packages to their latest versions
  • for v in ...; do ...; done – Loop through versions and activate each one
  • $v – References the loop variable (like ${v} in JS)

You're done with Part 1! 🎉

You now have the perfect, rock-solid multiple-PHP development environment on Ubuntu 24.04 — exactly like the famous macOS setup, but actually working.

Ready to take it further?

🚀 Continue to Part 2

Complete your professional PHP development setup with:

  • MySQL/MariaDB with phpMyAdmin or Adminer
  • Wildcard *.test virtual hosts
  • Xdebug debugging with easy toggle
  • APCu cache for 5X faster performance
  • Native YAML support
Continue to Part 2: MySQL, Virtual Hosts & Xdebug

📚 Credits & Inspiration

This guide was inspired by and adapted from the excellent macOS Sequoia Apache Multiple PHP Versions guide from the Grav CMS team.

I've translated and adapted their approach to work perfectly on Ubuntu 24.04, adding beginner-friendly explanations for those new to Linux.