使用不同用户(每个项目一个用户)设置 Apache 虚拟主机和 PHP-FPM 池的正确方法是什么?
- 每个用户/项目在文件访问方面彼此独立
- 使用普通 Apache / 的项目
www-data
,无法访问池化项目?
我有一个将 Apache 与虚拟主机一起使用的设置,并且我想为每个虚拟主机设置自己的php-fpm
池:
- 阿帕奇虚拟主机
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 池
site1
:
[site1]
user = site1
group = site1
listen.owner = site1
listen.group = www-data
listen.mode = 0660
- 目录起始于
/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
- 和用户:
id site1
uid=1007(site1) gid=1007(site1) grupos=1007(site1),33(www-data)
同上 virtualhost 的其他配置文件site2
,在适当的地方进行更改。
现在,此配置有效并且所有文件均已提供,但它对于其预期目的来说过于开放。
对于初学者来说,公共区域中的文件和目录site1
必须使用世界可读许可(例如:rwxr--r-- site1 site1 file
)。如果我将文件设置为仅对 site1 可读,则到处都会出现HTTP 403
错误EACCESS
。我知道 Apache 在某些时候必须有权访问这些文件,但我认为 FPM 池的全部目的就是处理该访问。
这也意味着,除非项目用户进行了充分的设置umask
,否则他们创建的新文件可能没有足够的权限,并且必须先将它们手动设置为全局可读,然后网络服务器(或 FPM?)才能访问它们。
我认为一个潜在的解决方案是让运行 Apache 的用户成为(等...)www-data
的成员,但这将使在 Apache 上运行的其他项目能够完全访问项目文件,包括非前端元素比如 Laravel 配置、后端连接器等。所以理论上这是行不通的,site1
site2
第二个选项是使用或通过 ACL ( )的读取指令设置每个项目的public
目录,以使 Apache 用户可以专门读取它们,但我不确定如果不首先授予 Apache 读取的完整路径访问权限,这是否可行项目,因为在 Linux 中目录路径只有在以下情况下才可读www-data
setgid
ẁww-data
setfacl
全部它的父路径是。它可以工作,但我不完全确定相应的设置是什么。
我能看到的唯一其他选择是设置 Apache 本身,以便不同的虚拟主机由自己的用户运行,但我没有找到有关此类设置的可用文档。我发现的最接近的是名为 的东西,apache2-mpm-itk
它宣传了此功能,但我没有发现任何可用的配置实际上可以让 Apache 服务开始当该模块启用时。事实上,Debian 9 机器中 itk 的默认配置一旦启动就会出现段错误。
为了实现正确的配置,我缺少什么?我接受它有这是可能的,至少我认为任何普通的网络托管服务商都是这样做的。
答案1
我最近设置了类似的配置,只是出于性能原因允许 Apache 全局读取。我使用 mpm_event_module。
您必须考虑到 Apache 和 PHP-FPM 是两个独立的进程。这两者具有独立的设置和环境,并且不会相互影响,因为 PHP-FPM 照顾 Apache 的权限。
当您以老式方式使用表单上传文件时,Apache 需要读取静态文件或写入权限。如果您通过 PHP 代码上传文件,则 PHP-FPM 启动。PHP-FPM 仅处理 PHP 代码。
listen.owner = site1
listen.group = www-data
listen.mode = 0660
用于 Apache 进程,因此它可以将 .php 文件传递(写入)到 PHP-FPM unix 套接字。
user = site1
group = site1
池中是运行 PHP 代码的真实用户/组。用户site1
一定不位于www-data
组中,因为攻击可以site1
在具有组权限的其他虚拟主机目录上进行写入www-data
。
您的问题的解决方案是 apache-mpm-itk。
如果您让 Apache 全局读取,那么您可以使用任何 MPM(多处理模块)。 apache-mpm-itk 与线程 MPM 不兼容。唯一的选项是 mpm_prefork_module。尽管它的名称是 apache-mpm-itk,但从技术上讲它并不是 MPM。这是一个改进的预叉。
不要忘记在 PHP-FPM 中为每个池设置 open_basedir 指令。
我推荐 2020 年的 Debian 10(buster)。