Resolving Apache2 Proxy Timeout Issues with PHP-FPM Long-Running Scripts


1 views

When working with Apache2's mod_proxy_fcgi to handle PHP requests through PHP-FPM, many developers encounter an unexpected 30-second timeout barrier, even when explicit timeout values are configured much higher. The error typically appears in logs as:

[proxy_fcgi:error] (70007)The timeout specified has expired: AH01075: Error dispatching request

Apache's proxy architecture actually implements several independent timeout mechanisms:

  1. Core Apache Timeout directive
  2. mod_proxy's ProxyTimeout
  3. mod_proxy_fcgi's internal timeout
  4. PHP-FPM's request_terminate_timeout

The 30-second default comes from PHP-FPM's configuration, not Apache's directives.

Here's the full set of configurations needed across all layers:

# In Apache configuration (httpd.conf or virtual host)
Timeout 600
ProxyTimeout 600

<IfModule proxy_module>
    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9001/var/www/$1 timeout=600 retry=0
</IfModule>

# In PHP-FPM pool configuration (www.conf)
request_terminate_timeout = 600
request_slowlog_timeout = 300

When troubleshooting, check these critical points:

  • Verify which PHP-FPM pool is being used with ps aux | grep php-fpm
  • Confirm the loaded Apache modules with apachectl -M | grep proxy
  • Test with a simple sleep script to isolate the issue:
<?php
// test-timeout.php
sleep(35); // Should work with proper configuration
echo "Completed after 35 seconds";
?>

For high-traffic systems, you'll need to adjust keepalive settings:

# In Apache configuration
KeepAlive On
KeepAliveTimeout 15
MaxKeepAliveRequests 100

# In PHP-FPM pool
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

Here's a working configuration from a production Laravel application handling long-running reports:

# Virtual Host Configuration
<VirtualHost *:443>
    Timeout 1800
    ProxyTimeout 1800
    
    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://127.0.0.1:9002"
        ProxySet connectiontimeout=1800 timeout=1800
    </FilesMatch>
    
    # Additional directives...
</VirtualHost>

# Corresponding PHP-FPM pool
[reports]
listen = 127.0.0.1:9002
request_terminate_timeout = 1800
pm = static
pm.max_children = 4

Many developers encounter this frustrating scenario: your PHP script works perfectly when it completes within 30 seconds, but anything longer triggers a 503 Service Unavailable error. The Apache error log shows:

[proxy_fcgi:error] (70007)The timeout specified has expired: AH01075: Error dispatching request

You've probably already tried these standard timeout settings in your VirtualHost configuration:


Timeout 600
<IfModule proxy_module>
    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9001/path/to/scripts/$1 timeout=600
    ProxyTimeout 600
</IfModule>

Yet the 30-second timeout persists, suggesting there's another layer to this problem.

While Apache's timeout settings appear correct, PHP-FPM has its own execution time limit that overrides these settings. Check your PHP-FPM pool configuration (typically in /etc/php-fpm.d/www.conf):


; Default timeout for worker processes
request_terminate_timeout = 30s

This is likely set to 30 seconds by default. Change it to match your Apache timeout:


request_terminate_timeout = 600s

For long-running scripts, you need to configure timeouts at multiple levels:

  1. Apache Core:
    Timeout 600
  2. mod_proxy:
    ProxyTimeout 600
  3. PHP-FPM:
    request_terminate_timeout = 600s
  4. PHP Script (optional):
    set_time_limit(600);

Create a simple test script to verify your changes:


<?php
// test-timeout.php
$start = time();
$duration = 120; // 2 minutes

while (time() - $start < $duration) {
    echo "Running for " . (time() - $start) . " seconds\n";
    flush();
    sleep(5);
}

echo "Script completed successfully after $duration seconds";
?>

If all configurations are correct, this script should run to completion without timing out.

For production environments, consider these best practices:

  • Implement proper error handling in long-running scripts
  • Use background processing for extremely long operations
  • Monitor resource usage during extended execution
  • Consider implementing progress tracking for user feedback