Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Install PHP on Ubuntu

By Kokil Thapa | Last reviewed: September 2026

You need to install PHP on Ubuntu before any Laravel app, WordPress site, or custom API can run. The default Ubuntu repositories ship older PHP builds. They rarely match what modern frameworks expect in 2026. On production servers I maintain, I always use the Ubuntu server setup for PHP applications pattern: add the trusted Ondřej Surý PPA, install a specific PHP minor version, enable PHP-FPM, and add only the extensions the project actually uses. This guide walks through that process on Ubuntu 22.04 and 24.04 with copy-paste commands you can run today.

What is the best way to install PHP on Ubuntu in 2026?

The best approach depends on your use case. For development laptops, the PPA method gives you current PHP versions with minimal fuss. For production VPS instances, the same PPA works well when paired with PHP-FPM and a reverse proxy. For containers, Docker images often replace native installs entirely.

Ubuntu's default universe repository typically lags behind upstream PHP. As of 2026, you want PHP 8.3 or higher for Laravel 13. Laravel 12 still runs on PHP 8.2. WordPress 7.1 recommends PHP 8.3 or newer. The Ondřej Surý PHP PPA is the standard choice among PHP developers on Ubuntu. It packages PHP 8.2 through 8.5 with matching extensions.

Install PHP on Ubuntu — Core FlowUpdate APTapt updateAdd PPAondrej/phpInstall PHPphp8.5-fpmVerifyphp -vProduction Add-onsExtensionsPHP-FPM poolWeb serverNginx or Apache forwards requests to unix socketSee LEMP stack and opcache guides for tuning
Install PHP on Ubuntu: from APT update through PPA install to PHP-FPM production wiring

Step 1: Prepare the system

Start with a fresh package index and the tools needed to add external repositories. Run these commands as a user with sudo privileges.

sudo apt update
sudo apt install -y software-properties-common ca-certificates lsb-release apt-transport-https

If you are building a public-facing server, harden the box before exposing port 80. Basic firewall rules and SSH key auth belong in your baseline. See the Ubuntu security hardening guide and UFW firewall configuration for details.

Step 2: Add the Ondřej Surý PHP PPA

This PPA provides maintained PHP packages for Ubuntu LTS releases. It is widely used on VPS hosts, including servers I manage for Linux system administration clients.

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

If add-apt-repository fails, import the signing key manually and add the source list. The Ubuntu repository management guide covers troubleshooting duplicate entries and GPG key errors.

Step 3: Install PHP and PHP-FPM

Replace 8.5 with your target version. PHP 8.5 is the current anchor release. PHP 8.4 and 8.3 remain common on shared hosting and managed platforms.

sudo apt install -y php8.5-fpm php8.5-cli php8.5-common

Confirm the install:

php -v

Expected output shows PHP 8.5.x with a build date and the CLI SAPI identifier. If the command is not found, check that /usr/bin/php symlinks to your chosen version.

Which PHP version should you install on Ubuntu for Laravel and WordPress?

Version choice should follow your application's requirements, not whatever is newest. Running an unsupported PHP on a live CMS or framework creates upgrade debt within months.

Laravel 13 requires PHP 8.3 or higher. Laravel 12 supports PHP 8.2 through 8.5. Symfony 8.1 needs PHP 8.4.1 minimum. Symfony 7.4 LTS accepts PHP 8.2+. WordPress 7.1 runs best on PHP 8.3 or 8.4. WooCommerce 11.1 follows the same baseline.

ApplicationMinimum PHPRecommended PHP (2026)Notes
Laravel 13.x8.38.5PHP 8.2 not supported
Laravel 12.x8.28.4 or 8.5Supported until Feb 2027
Symfony 8.18.4.18.5Requires recent minor
WordPress 7.17.2+8.3–8.5Older PHP blocked by plugins
Custom PHP API8.2+8.5Match team and CI version

On a legal-tech portal I built with Laravel, we pinned PHP 8.3 across local, CI, and production. That consistency prevented "works on my machine" Composer conflicts. For greenfield Laravel 13 projects in 2026, install PHP 8.5 unless your host restricts it.

If you maintain legacy code on PHP 7.x, plan an incremental upgrade rather than a big-bang rewrite. I've seen this approach work well on long-running client systems. Pair version bumps with automated refactoring tools covered in our PHP Rector guide.

Choose Your PHP VersionWhat are you running?Laravel 13Install PHP 8.5WordPress 7.1Install PHP 8.4Symfony 8.1Install PHP 8.5Legacy Laravel 12?PHP 8.2 minimum still OKPlan upgrade before EOLProduction ruleSame PHP minor in dev, CI, and prodNever mix 8.3 local with 8.5 server
PHP version decision tree when you install PHP on Ubuntu for common frameworks and CMS platforms

How do you install PHP extensions on Ubuntu?

Core PHP alone is not enough for real applications. You need database drivers, image libraries, XML parsers, and often Redis or Memcached clients. On Ubuntu, extensions ship as separate packages named php{version}-{extension}.

Essential extensions for Laravel and Symfony

Install these alongside PHP-FPM for a typical Laravel 13 stack backed by MySQL 9.7 or PostgreSQL 18:

sudo apt install -y \
  php8.5-mysql \
  php8.5-pgsql \
  php8.5-redis \
  php8.5-mbstring \
  php8.5-xml \
  php8.5-curl \
  php8.5-zip \
  php8.5-gd \
  php8.5-intl \
  php8.5-bcmath \
  php8.5-opcache \
  php8.5-readline

After adding extensions, restart PHP-FPM so loaded modules take effect:

sudo systemctl restart php8.5-fpm

List loaded modules from the CLI:

php -m

WordPress and WooCommerce extension set

WordPress sites need a similar bundle. Image handling and internationalisation extensions matter for themes with Nepali Unicode content. Our Devanagari Unicode handling in PHP article explains mbstring and database charset pitfalls.

sudo apt install -y \
  php8.5-mysql \
  php8.5-mbstring \
  php8.5-xml \
  php8.5-curl \
  php8.5-gd \
  php8.5-imagick \
  php8.5-zip \
  php8.5-intl \
  php8.5-opcache

For WordPress development projects, I also enable php8.5-soap when a payment or SMS plugin requires it. Check plugin docs before installing every optional module.

Verify extension configuration

Each extension has an INI file under /etc/php/8.5/mods-available/. Enabled modules symlink into cli/conf.d/ and fpm/conf.d/. Use phpini paths to debug missing classes at runtime:

php --ini

If an extension loads in CLI but not FPM, you likely restarted only one SAPI. Always restart php8.5-fpm after changes. CLI and FPM read separate config trees.

How do you configure PHP-FPM on Ubuntu for production?

PHP-FPM runs PHP as a separate service pool. Nginx or Apache forwards requests to it over a Unix socket or TCP port. This model scales better than mod_php on Apache. It is the default for modern LEMP stack deployments on Ubuntu.

PHP-FPM Production ArchitectureBrowserHTTPS requestNginxReverse proxyPHP-FPMUnix socketMySQL 9.7Application dataRedis 8.10Cache and queuesPool config: /etc/php/8.5/fpm/pool.d/www.confTune pm.max_children, upload limits, and slowlog for your VPS RAM
PHP-FPM sits between Nginx and MySQL when you install PHP on Ubuntu for production Laravel or API workloads

Enable and start PHP-FPM

sudo systemctl enable php8.5-fpm
sudo systemctl start php8.5-fpm
sudo systemctl status php8.5-fpm

The default pool config lives at /etc/php/8.5/fpm/pool.d/www.conf. Key settings for a 2 GB VPS running a Laravel app:

  • pm.max_children — cap concurrent workers; start around 10 and adjust after load testing.
  • php_admin_value[upload_max_filesize] — raise for document upload portals.
  • slowlog — enable to catch blocking queries during peak traffic.
  • listen.owner / listen.group — must match the web server user, usually www-data.

Wire Nginx to PHP-FPM

A minimal Nginx server block passes .php files to the FPM socket:

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

Test Nginx config and reload:

sudo nginx -t
sudo systemctl reload nginx

Pair this with a database layer. Follow our MySQL installation guide on Ubuntu if the stack is not ready yet. For Symfony deployments, the step-by-step Symfony on Ubuntu VPS guide covers env vars and cache warmup.

Production PHP.ini tuning

Edit /etc/php/8.5/fpm/php.ini for production values. Keep display_errors = Off and log to file instead. Set a sane memory limit:

memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 60

Enable and tune OPcache for bytecode caching. Misconfigured OPcache is a common reason deployed code appears stale after releases. Read the dedicated PHP OPcache configuration for production article before go-live.

On sites I deploy with Deployer 7, PHP-FPM reload after symlink swap clears opcache for new releases. Without that reload, visitors can hit old cached bytecode for minutes.

How do you run multiple PHP versions side by side on Ubuntu?

Agencies and hosts often need PHP 8.2 for a legacy app and PHP 8.5 for a new Laravel build on one server. Ubuntu supports this cleanly when each version has its own FPM service and socket.

Multi-Version PHP on One Ubuntu HostNginx vhostsPHP 8.3-FPMLegacy WordPress sitePHP 8.5-FPMNew Laravel 13 appupdate-alternativesSets default php CLI binaryComposer uses this versionPer-site Nginx passphp8.3-fpm.sock vs 8.5Isolate pools by project
Run PHP 8.3 and 8.5 FPM pools in parallel after you install PHP on Ubuntu for mixed legacy and modern apps

Install a second PHP version

sudo apt install -y php8.3-fpm php8.3-cli php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl
sudo systemctl enable php8.3-fpm
sudo systemctl start php8.3-fpm

Each version exposes its own socket at /run/php/php8.3-fpm.sock and /run/php/php8.5-fpm.sock. Point each Nginx vhost to the correct socket.

Switch the default CLI binary

Composer and Artisan commands use the CLI binary. Manage it with update-alternatives:

sudo update-alternatives --set php /usr/bin/php8.5
php -v

When running Composer for a PHP 8.3 project, invoke the matching binary explicitly:

php8.3 /usr/local/bin/composer install

This avoids platform requirement mismatches during dependency resolution.

How do you verify and troubleshoot a PHP install on Ubuntu?

A successful install PHP on Ubuntu checklist covers version, extensions, FPM status, and a live HTTP test. Skipping any step leads to late-night production surprises.

  1. Run php -v and confirm the expected minor version.
  2. Run php -m and verify critical extensions appear.
  3. Check systemctl status php8.5-fpm shows active (running).
  4. Create /var/www/html/info.php with <?php phpinfo(); only on a dev box — delete it before production.
  5. Hit the URL over HTTP and confirm the PHP version page loads.
  6. Review /var/log/php8.5-fpm.log for startup errors.

Common errors and fixes

502 Bad Gateway from Nginx usually means PHP-FPM is down or the socket path in Nginx does not match the pool config. Compare fastcgi_pass with the listen directive in www.conf.

Missing extension fatal errors after deploy mean the extension package was never installed on the server. Add the module, restart FPM, and redeploy. I hit this regularly when moving from a bloated local Docker image to a minimal VPS.

Permission denied on socket happens when Nginx runs as a user not in the FPM group. Align listen.owner, listen.group, and listen.mode with your web server user.

Wrong PHP version in cron is a silent bug. Cron uses a minimal PATH. Specify the full binary path in crontab entries, as shown in the Ubuntu cron jobs guide.

For JSON API debugging during setup, paste responses into the JSON formatter tool to validate structure before wiring frontend clients.

Composer and project bootstrap

Install Composer 2.10 globally after PHP is ready:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
composer --version

Official guidance for Debian-based systems also appears in the PHP manual Debian install notes. Cross-check extension names there if a package search fails.

On a new Laravel project, run composer install, copy .env, generate the key, and migrate. Payment integrations such as eSewa for PHP apps need curl and openssl extensions enabled from day one.

Security basics after install

Do not expose phpinfo() on public servers. Disable dangerous functions in php.ini if your app does not need them:

disable_functions = exec,passthru,shell_exec,system,proc_open,popen

Keep PHP patched through routine apt upgrade cycles. The Ubuntu security updates guide explains unattended upgrades for LTS boxes. For ongoing patch management on client infrastructure, see support and maintenance services.

File ownership matters for upload directories and Laravel's storage/ tree. The Ubuntu file permissions guide prevents the classic "failed to write cache" deploy error.

Key Takeaways

  • Add the ppa:ondrej/php repository to install PHP on Ubuntu with current 8.3–8.5 builds, not outdated distro defaults.
  • Match PHP version to your framework: Laravel 13 needs 8.3+, Symfony 8.1 needs 8.4.1+, WordPress 7.1 runs best on 8.3–8.5.
  • Install extensions as separate packages and restart PHP-FPM after every change.
  • Use PHP-FPM behind Nginx or Apache, tune pool settings, and reload FPM after each deploy to clear OPcache.
  • Run multiple PHP versions with separate FPM sockets and explicit CLI binaries per project.
  • Verify with php -v, php -m, FPM status, and a test vhost before pointing production DNS.

People Also Ask

Does Ubuntu 24.04 come with PHP preinstalled?

No. Ubuntu 24.04 desktop and server images do not ship with PHP by default. You must install it through APT. The default universe packages are often too old for Laravel 13 or Symfony 8.1. Use the Ondřej Surý PPA for supported recent versions.

Should I use PHP-FPM or mod_php on Ubuntu?

Use PHP-FPM for new projects in 2026. It isolates PHP workers from the web server process and pairs naturally with Nginx. mod_php remains available on Apache but consumes more memory per connection and complicates multi-version hosting.

How much RAM does PHP-FPM need on a small VPS?

Budget roughly 50–80 MB per active worker for a typical Laravel app. On a 2 GB VPS with MySQL and Redis, start with pm.max_children = 8 to 12. Monitor swap usage and adjust. Over-provisioning workers causes OOM kills under traffic spikes.

Can I install PHP 8.5 on Ubuntu 22.04?

Yes. The Ondřej Surý PPA supports both Ubuntu 22.04 LTS and 24.04 LTS. Run the same add-apt-repository and apt install php8.5-fpm commands on either release. Always run apt update after adding the PPA.

Build your next PHP stack on solid ground

When you install PHP on Ubuntu correctly the first time, every later step gets easier. Composer installs succeed, extensions match production, and deploys stop failing on missing modules. I've used this exact workflow on booking platforms, legal-tech portals like Court Marriage In Nepal, and Laravel CRM builds such as Adventure Third Pole Trek. Start with the right PHP minor, enable PHP-FPM, add only the extensions you need, and tune OPcache before traffic arrives.

If you want a production-ready server without trial-and-error, explore web development services or browse the full project portfolio. Need help migrating an old PHP 7 site to 8.5? Contact us and we'll map a safe upgrade path for your stack.

Frequently Asked Questions

Add the ppa:ondrej/php repository, run apt install php8.5-fpm plus required extensions, then verify with php -v. Use PHP-FPM behind Nginx or Apache for production web apps.

No. Ubuntu 24.04 desktop and server images do not ship with PHP by default. Install it through APT, and use the Ondřej Surý PPA because default universe packages are often too old for Laravel 13 or Symfony 8.1.

Yes. The Ondřej Surý PPA supports both Ubuntu 22.04 LTS and 24.04 LTS. Run the same add-apt-repository and apt install php8.5-fpm commands on either release, then apt update after adding the PPA.

For development laptops and production VPS instances, add the trusted Ondřej Surý PPA, install a specific PHP minor version, enable PHP-FPM, and add only the extensions your project needs. Ubuntu's default universe repository typically lags behind upstream PHP. For containers, Docker images often replace native installs entirely. This PPA pattern is what I use on production servers for Laravel, WordPress, and custom API workloads.

Match the version to your application, not whatever is newest. Laravel 13 requires PHP 8.3 or higher; Laravel 12 supports PHP 8.2 through 8.5. Symfony 8.1 needs PHP 8.4.1 minimum. WordPress 7.1 and WooCommerce 11.1 run best on PHP 8.3 through 8.5. For greenfield Laravel 13 projects in 2026, install PHP 8.5 unless your host restricts it. Pin the same version across local, CI, and production to avoid Composer conflicts.

Extensions ship as separate packages named php{version}-{extension}. For a typical Laravel 13 stack, install php8.5-mysql, php8.5-pgsql, php8.5-redis, php8.5-mbstring, php8.5-xml, php8.5-curl, php8.5-zip, php8.5-gd, php8.5-intl, php8.5-bcmath, php8.5-opcache, and php8.5-readline alongside PHP-FPM. WordPress sites need a similar bundle plus php8.5-imagick; enable php8.5-soap only when a plugin requires it. Restart php8.5-fpm after every change, then confirm with php -m.

Use PHP-FPM for new projects in 2026. It isolates PHP workers from the web server process and pairs naturally with Nginx, which is the default for modern LEMP stack deployments on Ubuntu. mod_php remains available on Apache but consumes more memory per connection and complicates multi-version hosting. PHP-FPM also scales better than mod_php when you run multiple application pools on one VPS.

Enable and start the service with systemctl, then tune the default pool at /etc/php/8.5/fpm/pool.d/www.conf. On a 2 GB VPS running Laravel, start pm.max_children around 10, set listen.owner and listen.group to match www-data, and enable slowlog for blocking queries. Wire Nginx with fastcgi_pass pointing to unix:/run/php/php8.5-fpm.sock. Edit /etc/php/8.5/fpm/php.ini for production: display_errors Off, memory_limit 256M, and tuned OPcache. Reload PHP-FPM after each deploy to clear stale bytecode.

Budget roughly 50 to 80 MB per active worker for a typical Laravel app. On a 2 GB VPS also running MySQL and Redis, start with pm.max_children set to 8 through 12 in www.conf. Monitor swap usage under real traffic and adjust. Over-provisioning workers causes out-of-memory kills during traffic spikes, so load-test before pointing production DNS at the server.

Install each version with its own FPM service and extension packages, for example php8.3-fpm alongside php8.5-fpm. Each version exposes a separate socket at /run/php/php8.3-fpm.sock and /run/php/php8.5-fpm.sock. Point each Nginx vhost fastcgi_pass to the correct socket. For CLI and Composer, manage the default binary with update-alternatives, or invoke the matching binary explicitly, such as php8.3 /usr/local/bin/composer install, to avoid platform requirement mismatches.

Run php -v and confirm the expected minor version. Run php -m and verify critical extensions appear. Check systemctl status php8.5-fpm shows active running. On a dev box only, create a test phpinfo page over HTTP, then delete it before production. Review /var/log/php8.5-fpm.log for startup errors. After wiring Nginx, run nginx -t and reload. Skipping any step leads to late-night production surprises when DNS switches over.

A 502 from Nginx usually means PHP-FPM is down or the socket path in your server block does not match the pool config. Compare fastcgi_pass in Nginx with the listen directive in www.conf. Also check that PHP-FPM is running with systemctl status php8.5-fpm. Permission denied on the socket happens when Nginx runs as a user not aligned with listen.owner, listen.group, and listen.mode in the FPM pool. Fix ownership, restart FPM, and reload Nginx.

CLI and FPM read separate configuration trees under /etc/php/8.5/. Enabled modules symlink into cli/conf.d and fpm/conf.d separately. If an extension loads with php -m but your web app throws a missing class error, you likely restarted only one SAPI or installed the package without restarting php8.5-fpm. Run php --ini to trace config paths. Always restart php8.5-fpm after installing or enabling extensions, then retest over HTTP.

First confirm software-properties-common, ca-certificates, lsb-release, and apt-transport-https are installed, then retry sudo add-apt-repository ppa:ondrej/php -y followed by sudo apt update. If add-apt-repository still fails, import the signing key manually and add the source list yourself. Duplicate repository entries and GPG key errors are the usual culprits. Resolve those before running apt install php8.5-fpm, or APT will refuse to install current PHP builds.

Harden the server before exposing port 80: basic UFW firewall rules and SSH key authentication belong in your baseline. Never leave phpinfo() on a public server. In php.ini, set display_errors Off and consider disable_functions for exec, passthru, shell_exec, system, proc_open, and popen if your app does not need them. Keep PHP patched through routine apt upgrade cycles. Set correct file ownership on upload directories and Laravel storage to prevent cache write failures after deploy.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: