6

What is the correct way to set up Apache virtualhosts and PHP-FPM pools with different users, one user per project, so that

  • each user/project is independent from each other in file access
  • projects using normal Apache / www-data, can not access the pooled projects?

I have a set up where I'm using Apache with virtualhosts, and I want to set up each virtualhost with their own php-fpm pool:

  • Apache virtualhost site1.conf:
<VirtualHost *:443>
        DocumentRoot /var/www/site1/public

        <Directory /var/www/site1/public>
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
        </Directory>

    <FilesMatch \.php$>
        # 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/run/php/php-fpm.site1.sock|fcgi://localhost/"
    </FilesMatch>

</VirtualHost>

  • PHP pool for site1:
[site1]
user = site1
group = site1
listen.owner = site1
listen.group = www-data
listen.mode = 0660

  • The directory starting at /var/www/site1:
drwxr-xr-x 15 site1 site1 4,0K ago 31 11:48 .
drwxr-xr-x 15 site1 site1 4,0K ago 31 11:48 public

  • And the user:
id site1
uid=1007(site1) gid=1007(site1) grupos=1007(site1),33(www-data)

Ditto other configuration files for virtualhost site2, changing where adequate.


Now, this configuration works and all files are served, but it's too open for what it's intended.

For starters, the files and directories in the public area of site1 have to be served with world-readable permission (eg.: rwxr--r-- site1 site1 file). If I make the file readable only for site1 as it should be, I get HTTP 403 and EACCESS errors everywhere. I understand that at some point Apache has to have access to the files, but I thought the entire purpose of a FPM pool was to take care of that access.

This also means that, unless project users set up their umask adequately, new files they create might not have the adequate permissions and they must be made world-readable by hand before the webserver (or FPM?) can access them.

I thought that one potential solution would be to make www-data user, which runs Apache, a member of site1 (site2, etc...), but that would give other projects running on Apache full access to the project files anyway, including non-front facing elements such as Laravel config, backend connectors, etc. So in theory this doesn't work,

A second option would be to set up each project's public directory with either www-data setgid or with a read directive for ẁww-data via ACL (setfacl) to make them readable by Apache's user specifically, but I'm not sure if that's doable without first giving Apache full path access to read the project, since in Linux a directory path is only readable if all its parent paths are. It could work, but I'm not entirely sure what is the corresponding setup.

The only other option I could see would be to set up Apache itself so that the different virtualhosts are run with their own users, but I've found no usable documentation about such setups. The closest I've found is something called apache2-mpm-itk which advertises this capability, but I've found no usable configuration that actually lets an Apache service start while this module is enabled. In fact, the default configuration for itk in a Debian 9 machine right out segfaults Apache once started.

What am I missing here to achieve the correct configuration? I take it it has to be possible, at least I assume that's how any normal web hoster does it.

1 Answer 1

3

I was setting up similar configuration lately and just allowed Apache to read globally for performance reasons. I use mpm_event_module.

You must take into consideration that Apache and PHP-FPM are two separate processes. These two have separate settings and environments and don't influence each other in terms that PHP-FPM takes care permissions of Apache.

Apache needs to read static files or write permissions when you upload files with forms the old school way. If you upload files through PHP code then PHP-FPM kicks in. PHP-FPM handles only PHP code.

listen.owner = site1
listen.group = www-data
listen.mode = 0660

Is used for Apache process so it can pass (write) .php files to PHP-FPM unix socket.

user = site1
group = site1

In pool is real user/group which the PHP code is run under. User site1 MUST NOT be in www-data group, becouse an attack can use site1 to write on other vhost directory which has permission for www-data group.

The solution for your problem is apache-mpm-itk.

If you leave Apache to read globally then you can use any MPM (Multi-Processing Module). apache-mpm-itk is not compatible with threaded MPMs. The only option is mpm_prefork_module. Despite it's name apache-mpm-itk is technically not MPM. It's a modified prefork.

Don't forget to setup open_basedir directive per pool in PHP-FPM.

I recommend Debian 10 (buster) in 2020.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .