PHP 8.3 Hardening and Optimization Guide

Comprehensive Guide for Ubuntu 20.04/24.04 with Nginx

Introduction to PHP 8.3

Ubuntu 20.04/24.04 was released with PHP 8.3 as the default PHP version available in the Ubuntu repositories. This guide covers the essential steps to harden and optimize PHP 8.3 for production environments, particularly for WordPress hosting with Nginx.

Installation Options:
  • Ondřej Surý Repository: Allows multiple PHP versions to be installed side by side
  • Official Ubuntu Repository: Only allows PHP 8.3 installation

PHP 8.3 Support Timeline

November 2026

Standard PHP 8.3 support ends (php.net)

April 2029

Ubuntu/Ondřej repository support ends (5-year support cycle)

2034

Extended support with Ubuntu Pro (free tier available)

Important Note: The November 2026 date refers to upstream PHP support from php.net, not the Ubuntu or Ondřej releases. Ubuntu and Ondřej provide extended support periods.

Performance Improvements

vs PHP 7.4

↑ 50%

Performance improvement over PHP 7.4

vs PHP 8.1/8.2

↑ 15%

Performance improvement over PHP 8.1 and 8.2

Recommendation: Set up a development server to test all themes and plugins with PHP 8.3 before moving to production. This ensures compatibility and helps identify potential issues early.

PHP Configuration File Structure

Directory Structure

/etc/php/
└── 8.3/
├── cli/
├── fpm/
│ ├── php.ini (main configuration file)
│ └── conf.d/ (override files directory)
│ └── *.ini (custom override files)
└── mods-available/

Configuration Hierarchy

php.ini
(Main Config)
conf.d/*.ini
(Server Overrides)
PHP-FPM Pool
(Site-Specific)
Best Practice: Instead of modifying the main php.ini file directly, create override files in the /etc/php/8.3/fpm/conf.d/ directory. This approach makes it easier to manage updates and quickly identify custom configurations.

Configuration Override Methods

Method Scope Use Case Can Be Overridden
conf.d/*.ini Server-wide Default settings for all sites Yes
PHP-FPM Pool Per-site Site-specific configurations Depends on directive
php_admin_value Per-site (pool) Locked site-specific settings No
.user.ini Per-site (document root) User-level overrides Yes

PHP Admin Value Directive

The php_admin_value directive is used within PHP-FPM pool configurations and provides the highest level of security for configuration settings. When used, the specified setting:

; Example in PHP-FPM pool configuration [example-site] php_admin_value[allow_url_fopen] = Off php_admin_value[disable_functions] = exec,system,passthru

Security Hardening Directives

Hardening involves removing dangerous default settings applied during installation. The following directives must be configured to enhance security:

1. allow_url_fopen

allow_url_fopen = Off

Purpose: Prevents PHP from including files from external sources (URLs). This setting blocks potential security vulnerabilities where attackers could include malicious code from remote servers.

Warning: Some WordPress plugins require allow_url_fopen to be enabled. Always check plugin documentation and test thoroughly. If needed, enable this on a per-site basis using PHP-FPM pools.

2. cgi.fix_pathinfo

cgi.fix_pathinfo = 0

Purpose: Prevents PHP from attempting to execute parts of the URL path if the requested file is not found. This blocks attackers from exploiting path manipulation to execute arbitrary code.

3. expose_php

expose_php = Off

Purpose: Prevents PHP from sending version information in HTTP response headers. This reduces information leakage that attackers could use for reconnaissance.

Before Hardening

Vulnerable
Configuration

↓ Apply Hardening ↓

Secure
Configuration

Dangerous PHP Functions

PHP functions are reusable code blocks that perform specific tasks. However, certain functions pose security risks if misused or if they enable harmful behavior. These "dangerous" functions often involve:

Common Dangerous Functions

Function Risk Attack Vector
exec() Command Injection Executes shell commands directly
system() Command Injection Executes shell commands and outputs result
passthru() Command Injection Executes commands and passes raw output
shell_exec() Command Injection Executes commands via shell
eval() Code Injection Executes arbitrary PHP code
assert() Code Injection Can execute arbitrary code in older PHP versions
Security Risk Example: If user-supplied input is passed to functions like exec() or system() without proper sanitization, attackers can inject malicious commands that execute on the server.

Example Attack Scenario

// Vulnerable Code $filename = $_GET['file']; exec("cat " . $filename); // Attacker Input: // file=document.txt; rm -rf / // Result: Executes file deletion command!
Implementation Strategy: Function restrictions will be implemented at the site level using PHP-FPM pools. This approach is covered in detail in the WordPress hardening section of this course.

Plugin Compatibility and Troubleshooting

Blocking certain PHP functions can impact WordPress plugins that rely on those functions for their features. When troubleshooting plugin issues, the Nginx error log is your primary diagnostic tool.

Error Log Example

; Nginx Error Log Extract [2026-01-19 10:23:45] PHP Warning: exec() has been disabled for security reasons in /var/www/example.com/public_html/ wp-content/plugins/some-plugin/includes/class-processor.php on line 127

Troubleshooting Workflow

Plugin Error Occurs
Check Error Log
Identify Blocked Function
Evaluate Risk


Keep Blocked
OR
Allow for Specific Site
Security Consideration: If you must enable a blocked function for a specific plugin, only enable it for that particular site using PHP-FPM pool configuration. Never enable dangerous functions globally across all sites.

Implementation: Creating Server Override File

Step 1: Navigate to Configuration Directory

# Change to PHP directory cd /etc/php/ # List available PHP versions ls # Output: 8.3 # Change to PHP 8.3 directory cd 8.3 # List contents ls # Output: cli fpm mods-available # Change to FPM directory cd fpm # Verify main configuration file ls # Output: php.ini conf.d pool.d # Navigate to override directory cd conf.d

Step 2: Create Override Configuration File

# Create new override file (must end with .ini) sudo nano server_override.ini

Step 3: Add Hardening Directives

; Server Override Configuration ; Purpose: Harden PHP security settings ; Applied to all sites on this server ; Prevent remote file inclusion allow_url_fopen = Off ; Disable path info fixing to prevent execution attacks cgi.fix_pathinfo = 0 ; Hide PHP version information expose_php = Off
File Naming Convention: The override file must have a .ini extension. Use descriptive names like server_override.ini, 99-custom.ini, or security-hardening.ini.

Step 4: Save and Exit

In nano editor:

Step 5: Reload PHP-FPM Service

# Full command to reload PHP-FPM sudo systemctl reload php8.3-fpm # Or using bash alias (if configured) fpmr
Important: After making any changes to PHP configuration files, you must reload the PHP-FPM service for the changes to take effect. The service reload applies new configurations without interrupting existing connections.

Verifying Configuration Changes

Method 1: Check PHP Info

# Create a temporary phpinfo file echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php # Access via browser: http://your-server-ip/info.php # Search for the directives to verify changes # Remove the file after verification sudo rm /var/www/html/info.php

Method 2: Command Line Verification

# Check specific PHP configuration values php -i | grep allow_url_fopen php -i | grep cgi.fix_pathinfo php -i | grep expose_php

Method 3: Test Configuration Syntax

# Test PHP-FPM configuration for syntax errors sudo php-fpm8.3 -t # Expected output if configuration is valid: # [19-Jan-2026 10:30:15] NOTICE: configuration file /etc/php/8.3/fpm/php-fpm.conf test is successful

Best Practices and Recommendations

Testing Environment

Always test configuration changes on a development server before applying them to production. This helps identify compatibility issues without affecting live sites.

Documentation

Document all custom configurations and the reasons for each change. This makes troubleshooting easier and helps team members understand the setup.

Backup Strategy

Before making configuration changes, create backups of existing configuration files. This allows quick rollback if issues arise.

Gradual Deployment

Apply hardening measures gradually, testing after each change. This approach makes it easier to identify which setting causes issues if they occur.

Monitor Logs

Regularly check error logs after implementing changes. This helps catch issues early and understand how applications interact with new settings.

Site Isolation

Use PHP-FPM pools to isolate different sites. This provides security boundaries and allows site-specific configurations without affecting others.

Next Steps: PHP Optimization

Now that we have hardened the PHP configuration, the next phase involves optimizing PHP performance. The optimization section will cover:

Course Structure: This guide is part of a comprehensive course on hardening and optimizing PHP 8.3 with Nginx on Ubuntu. Future sections will cover WordPress-specific hardening, PHP-FPM pool configurations, and advanced optimization techniques.

Summary

Topic Key Takeaway
PHP 8.3 Support Extended support until 2029 (Ubuntu/Ondřej) or 2034 (Ubuntu Pro)
Performance Up to 50% faster than PHP 7.4, 15% faster than PHP 8.1/8.2
Configuration Method Use override files in conf.d directory instead of modifying php.ini
Critical Directives allow_url_fopen = Off, cgi.fix_pathinfo = 0, expose_php = Off
Dangerous Functions Will be disabled at site level using PHP-FPM pools
Service Management Always reload PHP-FPM after configuration changes