Introduction
When Apache is configured to serve PHP applications but the PHP handler is not properly set up, PHP files are served as downloads or displayed as raw text instead of being executed. This occurs when mod_php is not loaded, when PHP-FPM is misconfigured, when the SetHandler directive is missing, or when the configuration has been changed but Apache hasn't been restarted. This issue exposes source code to visitors, which is a serious security risk for applications containing credentials or sensitive logic. Understanding Apache's PHP handler configuration and properly setting up either mod_php or PHP-FPM is essential for serving PHP applications securely.
Symptoms
When Apache is not executing PHP files, you will observe:
- Browser downloads .php files instead of displaying the rendered page
- PHP source code visible in browser (serious security issue)
- "Open with" dialog appears for .php files
- Blank pages or no response from PHP pages
- Mixed behavior - some PHP works, some doesn't (multiple handlers)
Testing with a simple PHP file shows raw output:
``php
<?php
// test.php
echo "PHP is working: " . date('Y-m-d H:i:s');
phpinfo();
Expected: Rendered PHP output with timestamp and phpinfo table. Actual: Browser prompts to download or shows raw PHP code.
Apache error log may show:
``
[core:error] [pid 12345] AH00126: Invalid URI 'path/to/script.php'
[proxy_fcgi:error] AH01079: failed to make connection to backend: localhost:9000
Or no PHP-related errors at all, indicating handler not configured.
Common Causes
- 1.mod_php not loaded - PHP module not enabled in Apache
- 2.PHP-FPM not running - FastCGI process manager not started
- 3.SetHandler missing - No handler directive for .php files
- 4.ProxyPass misconfigured - Incorrect proxy configuration for PHP-FPM
- 5.Apache not restarted - Configuration changes not applied
- 6.Wrong PHP version - mod_php for different PHP version
- 7.Multiple PHP handlers - Conflicting handler configurations
- 8.Directory directive override - .htaccess disabling handler
- 9.MIME type wrong - Serving PHP as text/plain
- 10.FilesMatch directive missing - Pattern not matching .php extension
Step-by-Step Fix
Step 1: Check Current PHP Handler Configuration
Determine what PHP handler is configured:
```bash # Check if mod_php is loaded apachectl -M | grep php
# Check for proxy modules (needed for PHP-FPM) apachectl -M | grep -E "proxy|proxy_fcgi"
# Check PHP version php -v
# Find PHP configuration files ls -la /etc/apache2/mods-available/*php* ls -la /etc/apache2/conf-available/*php* ```
On Ubuntu/Debian: ```bash # Check enabled modules ls /etc/apache2/mods-enabled/ | grep php
# Check PHP configuration cat /etc/apache2/conf-available/php*-fpm.conf cat /etc/apache2/mods-available/php*.conf ```
On RHEL/CentOS: ```bash # Check loaded modules httpd -M | grep php
# Check PHP configuration cat /etc/httpd/conf.d/php.conf ```
Step 2: Configure mod_php Handler
If using mod_php (embedded PHP in Apache):
```bash # Install mod_php if not present # Ubuntu/Debian sudo apt install libapache2-mod-php8.2
# Enable the PHP module sudo a2enmod php8.2
# Disable PHP-FPM configuration if present sudo a2disconf php8.2-fpm
# Restart Apache sudo systemctl restart apache2 ```
Verify mod_php is working: ```bash # Check module is loaded apachectl -M | grep php # Expected: php_module (shared)
# Test PHP execution echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/test.php curl http://localhost/test.php | grep "PHP Version" ```
Step 3: Configure PHP-FPM Handler
If using PHP-FPM (recommended for performance):
```bash # Install PHP-FPM if not present # Ubuntu/Debian sudo apt install php8.2-fpm
# Enable proxy modules sudo a2enmod proxy proxy_fcgi
# Enable PHP-FPM configuration sudo a2enconf php8.2-fpm
# Start PHP-FPM service sudo systemctl start php8.2-fpm sudo systemctl enable php8.2-fpm
# Restart Apache sudo systemctl restart apache2 ```
Verify PHP-FPM is running: ```bash # Check PHP-FPM status sudo systemctl status php8.2-fpm
# Check PHP-FPM pool ls -la /var/run/php/php*-fpm.sock
# Test connection to socket cgi-fcgi -bind -connect /var/run/php/php8.2-fpm.sock ```
Step 4: Configure SetHandler Directive
Ensure proper SetHandler is configured:
# Check existing handler configuration
cat /etc/apache2/conf-enabled/php*-fpm.confFor PHP-FPM, the configuration should include:
``apache
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost/"
</FilesMatch>
Add manually if missing:
``bash
# Create or edit PHP configuration
sudo vim /etc/apache2/conf-available/php-handler.conf
Add configuration: ```apache # PHP-FPM handler configuration <FilesMatch \.php$> SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost/" </FilesMatch>
# Directory index <IfModule dir_module> DirectoryIndex index.php index.html </IfModule>
# Proxy configuration for PHP-FPM ProxyTimeout 300 ```
Enable and restart:
``bash
sudo a2enconf php-handler
sudo systemctl restart apache2
Step 5: Configure Virtual Host PHP Handler
For per-virtual-host PHP configuration:
sudo vim /etc/apache2/sites-available/example.com.confAdd PHP handler in VirtualHost: ```apache <VirtualHost *:80> ServerName example.com DocumentRoot /var/www/example.com/public
# PHP-FPM handler for this site <FilesMatch \.php$> SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" </FilesMatch>
<Directory /var/www/example.com/public> Options Indexes FollowSymLinks AllowOverride All Require all granted
# Fallback to index.php DirectoryIndex index.php index.html </Directory>
# Proxy timeout for long-running PHP ProxyTimeout 300
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined </VirtualHost> ```
Step 6: Fix Multiple Handler Conflict
Remove conflicting handlers:
```bash # Check all configurations for PHP handlers grep -r "SetHandler.*php|AddHandler.*php" /etc/apache2/
# Look for conflicting definitions grep -r "application/x-httpd-php" /etc/apache2/ ```
Remove old mod_php handler if using FPM:
``apache
# Remove these lines if using PHP-FPM:
AddHandler application/x-httpd-php .php
AddType application/x-httpd-php .php .html
Ensure only one handler per configuration: ```bash # Disable all PHP configurations first sudo a2dismod php* sudo a2disconf php*-fpm
# Enable only what you need (example for PHP-FPM) sudo a2enmod proxy proxy_fcgi sudo a2enconf php8.2-fpm sudo systemctl restart apache2 ```
Step 7: Test and Verify Configuration
Test configuration syntax and PHP execution:
```bash # Test Apache configuration sudo apachectl configtest # Expected: Syntax OK
# Check Apache status sudo systemctl status apache2
# Test PHP file echo '<?php echo "PHP Works: " . PHP_VERSION; ?>' | sudo tee /var/www/html/test.php
# Request via HTTP curl http://localhost/test.php # Expected: PHP Works: 8.2.x
# Check response headers curl -I http://localhost/test.php # Should NOT show: Content-Type: application/octet-stream # Should show: Content-Type: text/html; charset=UTF-8 ```
Step 8: Check .htaccess for Overrides
.htaccess may override handler settings:
```bash # Check for handler overrides in .htaccess find /var/www -name .htaccess -exec grep -l "SetHandler|AddHandler" {} \;
# Check specific .htaccess cat /var/www/html/.htaccess | grep -E "SetHandler|AddHandler|php" ```
Problematic .htaccess rules: ```apache # This forces download instead of execution <FilesMatch "\.php$"> ForceType application/octet-stream </FilesMatch>
# This uses old mod_php handler AddHandler application/x-httpd-php5 .php ```
Fix by removing or correcting:
``apache
# Correct .htaccess for PHP-FPM
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
Verification
After fixing, verify PHP execution works correctly:
```bash # Create comprehensive test file cat << 'EOF' | sudo tee /var/www/html/phpinfo.php <?php header('Content-Type: text/plain'); echo "PHP Version: " . PHP_VERSION . "\n"; echo "Server API: " . php_sapi_name() . "\n"; echo "Extensions: " . implode(', ', get_loaded_extensions()) . "\n"; echo "Time: " . date('Y-m-d H:i:s') . "\n"; EOF
# Test execution curl http://localhost/phpinfo.php
# Expected output: # PHP Version: 8.2.x # Server API: fpm-fcgi # Extensions: Core, date, libxml, ... ```
Verify proper headers: ```bash # Check content type curl -I http://localhost/phpinfo.php | grep Content-Type # Expected: Content-Type: text/plain; charset=UTF-8
# Ensure not downloading curl -I http://localhost/phpinfo.php | grep -i disposition # Should be empty (no Content-Disposition header) ```
Test with actual application: ```bash # Test a real PHP application file curl http://localhost/index.php
# Check for PHP source code leak curl http://localhost/test.php | grep -c "<?php" # Expected: 0 (no raw PHP code should be returned) ```
Prevention
To prevent PHP execution issues:
- 1.Standardize on one PHP handler (preferably PHP-FPM):
- 2.```bash
- 3.# Document which handler is used
- 4.echo "PHP Handler: PHP-FPM 8.2" | sudo tee /etc/apache2/PHP-CONFIG
- 5.
` - 6.Use version-independent configuration:
- 7.```apache
- 8.# Instead of specific version
- 9.SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost"
- 10.
` - 11.Monitor PHP-FPM health:
- 12.```bash
- 13.# Add to monitoring
- 14.systemctl is-active php8.2-fpm || echo "PHP-FPM down"
- 15.
` - 16.Test after configuration changes:
- 17.```bash
- 18.# Always test after changes
- 19.apachectl configtest && curl -s http://localhost/test.php | head -1
- 20.
` - 21.Set up health check endpoint:
- 22.```php
- 23.<?php
- 24.// /health.php - Simple health check
- 25.header('Content-Type: application/json');
- 26.echo json_encode([
- 27.'status' => 'ok',
- 28.'php' => PHP_VERSION,
- 29.'sapi' => php_sapi_name(),
- 30.'time' => time()
- 31.]);
- 32.
` - 33.Use proper Apache reload:
- 34.```bash
- 35.# Graceful restart to avoid dropping connections
- 36.sudo systemctl reload apache2
- 37.
` - 38.Lock down PHP configuration:
- 39.```apache
- 40.# Prevent .htaccess override of handler
- 41.<Directory /var/www/html>
- 42.AllowOverride None
- 43.# Or limit what can be overridden
- 44.AllowOverride Limit Indexes
- 45.</Directory>
- 46.
`
Related Articles
- [WordPress troubleshooting: Fix CloudFormation Access Denied 403 - C](fix-cloudformation-access-denied-403-u1p0)
- [WordPress troubleshooting: Fix EC2 Configuration Error - Complete T](fix-ec2-configuration-error-szi0)
- [WordPress troubleshooting: Fix CloudFormation Configuration Error -](fix-cloudformation-configuration-error)
- [WordPress troubleshooting: Fix ELB Configuration Error - Complete T](fix-elb-configuration-error-2d3l)
- [WordPress troubleshooting: Fix S3 Access Denied 403 - Complete Trou](fix-s3-access-denied-403-g5cv)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Apache Mod PHP Not Executing", "description": "Fix Apache not executing PHP files. Troubleshoot mod_php, PHP-FPM configuration, and proper handler setup.", "url": "https://www.fixwikihub.com/fix-apache-mod-php-not-executing", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-12-12T18:45:16.103Z", "dateModified": "2025-12-12T18:45:16.103Z" } </script>