Apache HTTPd and PHP security

Notes on setting up Apache and PHP to run under user account

Requirements: base installation with PHP using FPM for Apache

How things are connected

The pool configuration file is the file controlling the ‘server’ (proxy) for PHP. The ‘listen’ line in this file is telling where proxy requests should be accepted.
‘user’ and ‘group’ tells under which user account the process should be run. ‘listen.owner’, ‘listen.group’ and ‘listen.mode’ can be set to limit access to the proxy (by other users/sites).

Sample PHP FPM pool configuration
For each version of PHP that should be available, create a pool configuration file (in ‘/etc/php/<version>/fpm/pool.d/’) like:

[8001]
user = $pool
group = $pool

listen = /run/php/php8.2-fpm-$pool.sock

listen.owner = $pool
listen.group = $pool

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /fpm-status

(change the “listen =” line, so it matches the PHP version you wish to use, then change to listen to the same socket in the virtualhost configuration or in the override segment in .htaccess)

In the virtualhost configuration, that same listening socket must be used (the owner of the httpd process must have rights to talk to the proxy, so it could be set up as a per-user or per-group setting depending on how it was set up in the pool configuration).

Sample virtualhost, allows override of PHP version and access to /fpm-status

<VirtualHost *:80>
  <IfModule mpm_itk_module>
    AssignUserId #8001 #8001
  </IfModule>

  ServerName site8001.domain.com
  DocumentRoot /var/www/site8001/html

  <Directory /var/www/site8001/html>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
  </Directory>
  <LocationMatch "/fpm-status">
    ProxyPass  "unix:/var/run/php/php8.2-fpm-8001.sock|fcgi://localhost/fpm-status"
  </LocationMatch>
  <FilesMatch ".php$">
    SetHandler "proxy:unix:/var/run/php/php8.2-fpm-8001.sock|fcgi://localhost/"
  </FilesMatch>

  ErrorLog /var/www/site8001/logs/error.log
  CustomLog /var/www/site8001/logs/access.log combined
</VirtualHost>

mpm_itk (used above) allows the Apache HTTPd process to be run by another user:

apt install libapache2-mpm-itk
a2enmod mpm_itk

The following were probably done when installing php-fpm

apt install libapache2-mod-fcgid
a2enmod proxy_fcgi

File permissions

When running both Apache httpd and PHP as a specific user, the files on the web site only need to have user read/write(when needed) access if they are owned by the user running the processes.
To make a permanent change to the umask used by PHP, add ‘UMask=0077’ to the ‘Service’ section of each PHP FPM service:

systemctl edit php8.2-fpm.service

Add:

[Service]
UMask=0077

Then reload systemctl daemon and restart the fpm service:

systemctl daemon-reload && systemctl restart php8.2-fpm

Changing system-wide umask
To further tighten file access security, I usually change the default umask for user-owned files from 022 (owner rw and everyone read) to 077 (owner permissions only). This can be done in various places and can be overridden temporarily or permanently by the user if needed. One place to set the umask and do other customizations at login is in /etc/profile.d, where each file is a script (need no execute permissions and should have no script header, so simply a file there with the line “umask 0077” will do the trick.

References
https://serverok.in/apache-virtualhost-separate-user-with-mpm-itk