Best Apache and PHP-FPM Configuration for a PHP Website on Ubuntu

Linux September 23, 2026 22 Views 5 min read
Best Apache and PHP-FPM Configuration for a PHP Website on Ubuntu

Best Apache and PHP-FPM Configuration for a PHP Website on Ubuntu

This tutorial provides a practical per-subdomain Apache and PHP-FPM configuration for a PHP website on Ubuntu. A separate PHP-FPM pool and Unix socket are used for the site, which helps isolate its PHP settings and worker limits from other websites on the same server.

Suggested categories: Linux, Apache, PHP, Performance, DevOps

1. Example Environment

Replace the example values with your actual domain, document root and email address.

Domain: subdomain.example.com
Document Root: /var/www/vhost/subdomain.example.com
PHP Version: 8.3
PHP-FPM Socket: /var/run/php/subdomain.example.com.sock

2. Create the Apache Virtual Host

Create a dedicated Apache virtual-host file:

sudo vim /etc/apache2/sites-available/subdomain.example.com.conf
<VirtualHost *:80>

    ServerAdmin hosting@example.com
    ServerName subdomain.example.com

    DocumentRoot /var/www/vhost/subdomain.example.com

    <Directory /var/www/vhost/subdomain.example.com/>
        Options +FollowSymlinks
        AllowOverride All
        Require all granted
    </Directory>

    # Send PHP requests to the dedicated PHP-FPM socket
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/subdomain.example.com.sock|fcgi://localhost/"
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/subdomain.example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/subdomain.example.com-access.log combined

</VirtualHost>

3. Enable the Required Apache Modules

sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo a2enmod rewrite

4. Create a Dedicated PHP-FPM Pool

Create a separate PHP-FPM pool for the website:

sudo vim /etc/php/8.3/fpm/pool.d/subdomain.example.com.conf
[subdomain.example.com]

user = www-data
group = www-data

listen = /var/run/php/subdomain.example.com.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; ---------------------------------------------------------
; PHP application settings
; ---------------------------------------------------------

php_admin_value[disable_functions] = passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = on
php_admin_value[short_open_tag] = on

php_admin_value[max_execution_time] = 360
php_admin_value[max_file_uploads] = 200
php_admin_value[max_input_time] = 600
php_admin_value[max_input_vars] = 100000
php_admin_value[memory_limit] = 256M
php_admin_value[session.gc_maxlifetime] = 7200
php_admin_value[upload_max_filesize] = 128M
php_admin_value[post_max_size] = 128M
php_admin_value[date.timezone] = Asia/Kolkata

; ---------------------------------------------------------
; PHP-FPM slow request logging
; ---------------------------------------------------------

request_slowlog_timeout = 10s
slowlog = /var/log/php8.3-fpm-slow.log
request_terminate_timeout = 300s
catch_workers_output = yes

; ---------------------------------------------------------
; PHP-FPM process manager
; ---------------------------------------------------------

pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 300

chdir = /

5. Why Use a Separate PHP-FPM Pool?

  • Dedicated PHP-FPM workers and Unix socket
  • Site-specific PHP limits
  • Independent slow-request logging
  • Worker recycling using pm.max_requests
  • Better isolation between multiple PHP applications

6. Enable the Virtual Host

sudo a2ensite subdomain.example.com.conf

7. Validate PHP-FPM

sudo php-fpm8.3 -t

You should see a successful configuration test.

8. Validate Apache

sudo apache2ctl configtest

Expected result:

Syntax OK

9. Restart or Reload the Services

sudo systemctl restart php8.3-fpm
sudo systemctl reload apache2

10. Verify the PHP-FPM Socket

ls -l /var/run/php/subdomain.example.com.sock

The socket should normally be owned by www-data and use mode 0660.

11. Verify the Apache Virtual Host

sudo apache2ctl -S

Confirm that the hostname is mapped to the expected virtual host.

12. Test PHP

For a temporary test, create:

sudo tee /var/www/vhost/subdomain.example.com/info.php > /dev/null <<'PHP'
<?php
phpinfo();
PHP

Open:

http://subdomain.example.com/info.php

Confirm that PHP 8.3 is running through the expected PHP-FPM configuration.

Remove the test file immediately after testing:

sudo rm -f /var/www/vhost/subdomain.example.com/info.php

13. Check PHP-FPM Processes

ps aux | grep '[p]hp-fpm'
sudo systemctl status php8.3-fpm --no-pager

14. Check Slow PHP Requests

The configuration records requests that take 10 seconds or longer in the PHP-FPM slow log.

sudo tail -f /var/log/php8.3-fpm-slow.log

15. Important PHP-FPM Sizing Note

Do not copy pm.max_children = 50 blindly to every server. The correct value depends on available RAM, application memory usage and other services running on the server.

Also, memory_limit = 1024M is a maximum PHP memory limit per request. It does not mean that every worker continuously consumes 1 GB of RAM. Measure actual PHP-FPM worker memory usage before deciding the final worker count.

16. Example Baseline Configuration

pm = dynamic

pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 300

Monitor memory usage, response time and PHP-FPM queueing, then adjust the values for the workload.

17. Useful Monitoring Commands

# PHP-FPM
sudo systemctl status php8.3-fpm --no-pager

# Apache
sudo systemctl status apache2 --no-pager

# PHP-FPM log
sudo tail -f /var/log/php8.3-fpm.log

# PHP-FPM slow log
sudo tail -f /var/log/php8.3-fpm-slow.log

# Apache error log
sudo tail -f /var/log/apache2/subdomain.example.com-error.log

# Apache access log
sudo tail -f /var/log/apache2/subdomain.example.com-access.log

# PHP-FPM processes
ps aux | grep '[p]hp-fpm'

# Memory
free -h

# Load
uptime

18. Quick Deployment Checklist

[✓] Apache virtual host created
[✓] Dedicated document root configured
[✓] Dedicated PHP-FPM pool created
[✓] Dedicated Unix socket configured
[✓] proxy and proxy_fcgi enabled
[✓] Slow request logging enabled
[✓] Request timeout configured
[✓] Worker recycling configured
[✓] PHP-FPM configuration tested
[✓] Apache configuration tested
[✓] Services restarted/reloaded
[✓] PHP-FPM socket verified
[✓] Test info.php removed

19. Quick Copy-Paste Commands

sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo a2enmod rewrite

sudo a2ensite subdomain.example.com.conf

sudo php-fpm8.3 -t
sudo apache2ctl configtest

sudo systemctl restart php8.3-fpm
sudo systemctl reload apache2

ls -l /var/run/php/subdomain.example.com.sock

Important

Before using this configuration in production, replace:

subdomain.example.com
hosting@example.com
/var/www/vhost/subdomain.example.com

Note: the original command had sudo vim vim .... The correct command is sudo vim ....

Discussion (0)