Install PHP on Ubuntu

Khimananda Oli 9 min read Virtualization
Install PHP on Ubuntu

By Khimananda Oli | Last reviewed: August 2026

To install PHP on Ubuntu 24.04 LTS for production workloads, you must move beyond the default repository packages and configure PHP-FPM as a dedicated process manager behind Nginx. Most tutorials stop at apt install php, leaving you with an insecure, unoptimized CLI binary that cannot serve web traffic efficiently. This guide covers the complete workflow: adding the Ondřej Surý PPA for current releases, installing PHP-FPM with necessary extensions, integrating it with Nginx via Unix sockets, and applying the security hardening required for compliance-ready infrastructure.

How Do You Install PHP on Ubuntu Using the Ondřej Surý PPA?

The default Ubuntu repositories often lag behind the latest stable PHP releases by months or even years. In August 2026, relying on the base repo might give you PHP 8.3 when 8.4 is the current standard with critical performance improvements and security patches. The Ondřej Surý PPA is the de facto industry standard for Debian/Ubuntu systems, providing timely updates and co-installable versions.

Before adding any third-party repository, ensure your base system is updated and you have the prerequisite tools. This is also the right moment to review your initial Ubuntu server setup to confirm SSH hardening and firewall rules are in place before exposing new services.

# Update base system and install prerequisites
sudo apt update && sudo apt upgrade -y
sudo apt install -y software-properties-common apt-transport-https ca-certificates curl gnupg

# Add the Ondřej Surý PPA
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update

Once the PPA is active, you can query available versions. Never assume a version exists; always verify against the package index. This prevents deployment failures in automated pipelines where silent fallbacks can mask configuration drift.

# List available PHP versions
apt-cache policy php8.4-fpm php8.4-cli php8.4-common

# Install the core FPM package (includes CLI and common dependencies)
sudo apt install -y php8.4-fpm php8.4-cli php8.4-common
Ondřej PPAphp8.4-fpmAPT InstallSystem PackagesPHP-FPM Service/run/php/*.sockNginx
PHP-FPM installation architecture: PPA provides packages, APT installs binaries, systemd manages the FPM service, and Nginx proxies requests via Unix socket.

Which PHP Extensions Are Required for Production Applications?

A bare PHP-FPM installation lacks the extensions most modern frameworks require. Installing everything "just in case" increases your attack surface and memory footprint. Instead, select extensions based on your actual application dependencies. For Laravel, WordPress, or Symfony applications in 2026, the following set covers 95% of production needs without bloat.

  • php8.4-mysql / pgsql: Database drivers. Choose only what you use; never install both unless running multi-database workloads.
  • php8.4-xml & php8.4-mbstring: Non-negotiable for string handling, DOM manipulation, and virtually every Composer package.
  • php8.4-curl: Required for HTTP clients, payment gateways, and external API integrations.
  • php8.4-gd / imagick: Image processing. GD is lighter; Imagick supports more formats but requires additional system libraries.
  • php8.4-opcache: Mandatory for performance. Caches compiled bytecode in shared memory, reducing CPU overhead by 50–70%.
  • php8.4-redis: Session storage, queue backends, and caching. Far superior to file-based sessions in multi-server environments.
  • php8.4-zip & php8.4-intl: Archive handling and internationalization. Often overlooked during initial setup, causing runtime errors later.
# Install recommended production extensions in one command
sudo apt install -y php8.4-mysql php8.4-xml php8.4-mbstring \
  php8.4-curl php8.4-gd php8.4-opcache php8.4-redis \
  php8.4-zip php8.4-intl php8.4-bcmath

# Verify installed modules
php -m | grep -E 'opcache|redis|mbstring'

After installation, restart FPM to load new extensions. Unlike Apache with mod_php, PHP-FPM does not hot-reload modules; a service restart is mandatory. In CI/CD pipelines, always include this restart step after extension installation to avoid deploying broken configurations.

How Do You Configure Nginx to Work with PHP-FPM?

Nginx does not execute PHP natively. It acts as a reverse proxy, passing requests to PHP-FPM via either a TCP port or a Unix domain socket. For single-server deployments, Unix sockets are faster and more secure: they avoid TCP overhead and cannot be accidentally exposed to the network. Reserve TCP connections only for distributed architectures where FPM runs on separate hosts.

Create or edit your Nginx server block. The critical directive is fastcgi_pass, which must match the socket path defined in /etc/php/8.4/fpm/pool.d/www.conf. On Ubuntu 24.04, the default socket location is /run/php/php8.4-fpm.sock.

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com/public;
    index index.php index.html;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        
        # Performance tuning
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
        fastcgi_read_timeout 300;
    }

    # Deny access to hidden files
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

Test the configuration before reloading. A syntax error here takes down your entire site. This validation step should be automated in your deployment pipeline, as discussed in guides on deploying Laravel on Ubuntu VPS with Nginx.

# Validate Nginx config
sudo nginx -t

# Reload if valid
sudo systemctl reload nginx

# Verify FPM is listening
sudo ss -lx | grep php
Client BrowserHTTP RequestNginxStatic Files*.php → FastCGIUnix SocketPHP-FPM MasterWorker 1Worker 2Worker 3Worker NApp Code/var/www
Nginx receives HTTP requests, serves static assets directly, and proxies PHP execution to FPM worker processes through a Unix domain socket for optimal performance.

What Security Hardening Steps Are Essential After Installation?

Default PHP configurations prioritize compatibility over security. Before serving traffic, you must restrict dangerous functions, limit resource consumption, and hide version information. These changes are non-negotiable for SOC 2 or ISO 27001 compliance, and they prevent entire classes of exploits that target misconfigured interpreters.

Edit the production FPM ini file. Never modify cli/php.ini for web security; FPM uses its own configuration at /etc/php/8.4/fpm/php.ini.

# Critical security directives for /etc/php/8.4/fpm/php.ini
expose_php = Off                    ; Hide PHP version in headers
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
max_execution_time = 30             ; Prevent runaway scripts
memory_limit = 256M                 ; Set realistic ceiling
upload_max_filesize = 10M           ; Restrict uploads
post_max_size = 12M                 ; Must exceed upload_max
open_basedir = /var/www:/tmp        ; Jail filesystem access
session.cookie_httponly = 1         ; Prevent JS session theft
session.cookie_secure = 1           ; HTTPS-only cookies
session.use_strict_mode = 1         ; Reject uninitialized sessions

Additionally, tune the FPM pool configuration at /etc/php/8.4/fpm/pool.d/www.conf. The default pm = dynamic settings are rarely optimal. Calculate workers based on available RAM: each PHP worker consumes 30–60MB depending on your application. On a 4GB VPS, reserve 1GB for OS/Nginx/DB, leaving ~50 workers maximum. Over-provisioning causes OOM kills under load.

DirectiveDefault ValueProduction RecommendationRationale
pm.max_children5RAM_MB / 50Prevents memory exhaustion while maximizing concurrency
pm.start_servers2max_children / 4Balances cold-start latency vs idle resource waste
pm.min_spare_servers1max_children / 8Maintains buffer for traffic spikes without over-provisioning
pm.max_requests0 (unlimited)500–1000Recycles workers to prevent memory leaks from accumulating
request_terminate_timeout0 (disabled)60sKills hung requests before they exhaust the worker pool

After making changes, validate the FPM configuration syntax and restart the service. Invalid pool configs silently fail to start workers, leaving your site returning 502 errors.

# Test FPM configuration
sudo php-fpm8.4 -t

# Restart and verify status
sudo systemctl restart php8.4-fpm
sudo systemctl status php8.4-fpm --no-pager

How Do You Manage Multiple PHP Versions on the Same Server?

Running multiple PHP versions simultaneously is common when hosting legacy applications alongside modern ones, or during migration windows. The Ondřej Surý PPA supports co-installation: php8.2-fpm, php8.3-fpm, and php8.4-fpm can all run concurrently, each with independent pools, sockets, and configurations.

Each version gets its own socket path (/run/php/php8.2-fpm.sock, etc.) and configuration directory. Switch between CLI versions using update-alternatives, but remember this does not affect FPM — each web application's Nginx config explicitly references its required socket.

# Install additional versions side-by-side
sudo apt install -y php8.2-fpm php8.3-fpm

# Set default CLI version
sudo update-alternatives --config php

# Verify all running FPM instances
sudo systemctl list-units --type=service | grep php.*fpm

This approach eliminates downtime during upgrades. Deploy the new version, update Nginx configs incrementally, test thoroughly, then decommission the old version. For teams managing multiple environments, consider automating this process as outlined in guides on PHP-FPM tuning for high-traffic websites.

Single Version (Default)PHP 8.4 FPMAll Apps⚠ Upgrade breaks legacy appsMulti-Version (Recommended)PHP 8.2PHP 8.3PHP 8.4Legacy AppStagingProduction✓ Safe upgrades, isolated environments
Single-version setups risk breaking all applications during upgrades. Multi-version FPM allows safe, incremental migrations with zero cross-version interference.

Install PHP on Ubuntu: Final Checklist and Next Steps

Successfully configuring PHP-FPM requires attention to detail that generic tutorials skip. You have now added the correct PPA, installed targeted extensions, configured Nginx with Unix sockets, applied security hardening, and planned for multi-version management. Before declaring production readiness, run through this verification checklist:

  1. Confirm FPM is active: systemctl is-active php8.4-fpm returns "active".
  2. Validate socket permissions: ls -la /run/php/php8.4-fpm.sock shows www-data ownership.
  3. Test PHP execution: Create a temporary info.php with <?php phpinfo(); ?>, verify output, then delete immediately.
  4. Check OPcache status: Confirm opcache.enable=1 in phpinfo output.
  5. Review error logs: journalctl -u php8.4-fpm --since "1 hour ago" for warnings.
  6. Run a security scan: Tools like Lynis or custom scripts to verify disable_functions and open_basedir.

If you are building this as part of a larger infrastructure automation effort, consider codifying these steps in Ansible or Terraform rather than manual execution. Reproducible infrastructure prevents configuration drift and makes disaster recovery predictable. For teams exploring AI-assisted operations, our guide on automating DevOps tasks with AI assistants demonstrates how to generate validated PHP-FPM configurations using LLMs with proper guardrails.

Need help auditing your PHP deployment or designing a compliant infrastructure? Reach out to discuss your specific requirements.

Frequently Asked Questions

Ubuntu 24.04 LTS ships with PHP 8.3 in the official repositories. Run apt show php to verify the exact candidate version before installation on your server.

Add the Ondrej PPA using add-apt-repository ppa:ondrej/php, then run apt update and apt install php8.4. This repository provides current stable PHP builds for older Ubuntu releases.

Run sudo apt install php php-fpm php-mysql php-xml php-curl php-mbstring php-zip php-gd. This bundle covers database drivers, XML parsing, HTTP clients, and image processing required by most modern Laravel applications.

Yes. Nginx cannot process PHP natively and requires PHP-FPM as a FastCGI backend. Install php-fpm and configure the upstream socket path in your Nginx site configuration block.

The CLI config lives at /etc/php/8.3/cli/php.ini while FPM uses /etc/php/8.3/fpm/php.ini. Always edit the FPM specific file when adjusting settings for web requests served through Nginx or Apache.

Use the phpenmod utility followed by the extension name, such as phpenmod redis. Restart the PHP-FPM service afterward to apply changes without rebooting the entire operating system.

Yes. Install separate packages like php8.2-fpm and php8.3-fpm, then assign different socket paths or ports per site in Nginx. This allows legacy and modern apps to coexist safely.

Conflicting PPAs or partial upgrades often cause this. Run apt full-upgrade to resolve held packages, or remove conflicting repositories before retrying the PHP installation command cleanly.

Create a temporary info.php file containing phpinfo() in your web root. Access it via browser to confirm the loaded version, active modules, and configuration paths match your expected setup.

Set ownership to www-data:www-data and mode 0660 in the FPM pool config. This ensures Nginx can communicate with PHP while preventing unauthorized local users from accessing the socket directly.

Check dmesg or journalctl for AppArmor denials related to php-fpm. You may need to adjust the profile in /etc/apparmor.d/ to allow access to non-standard document roots or binary locations.

Execute sudo apt purge 'php*' followed by apt autoremove. This removes binaries, configs, and unused dependencies, providing a clean slate before reinstalling a different PHP version stack.

No. PHP and Ubuntu are open source and free for commercial production use. Costs only arise from paid support contracts, managed hosting services, or proprietary third-party extensions you choose to purchase.

Apply security patches monthly via unattended-upgrades. Plan minor version upgrades quarterly after testing in staging, as Ubuntu backports critical fixes but rarely updates feature versions within a single release cycle.

Use update-alternatives --config php to interactively select the desired binary. Verify immediately with php -v to ensure scripts and Composer use the correct runtime environment.