You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu20.04 Apache多PHP版本多站点用户权限隔离配置问题

问题根因

配置不生效的核心原因共3点:

  • 安装php7.4时系统默认会启用libapache2-mod-php7.4模块,PHP直接作为Apache内置子进程运行,完全没有走预期的FCGI流程
  • 仅安装libapache2-mpm-itk包不会自动启用MPM-ITK,Ubuntu 20.04默认启用mpm_event模块,与MPM-ITK冲突,<IfModule itk.c>块内的AssignUserID规则根本没有被加载
  • mod_php模式本身不支持多PHP版本共存,同一时间Apache只能加载一个版本的PHP模块,无法满足多站点使用不同PHP版本的需求

正确配置方案(适配Ubuntu 20.04,同时满足多PHP版本+站点权限隔离)

1. 清理冲突配置

先卸载冲突组件,禁用无效模块:

# 卸载所有版本的mod_php,避免与FCGI模式冲突
sudo apt remove -y libapache2-mod-php*
# 禁用默认的MPM模块
sudo a2dismod mpm_event mpm_prefork mpm_worker
# 禁用残留的PHP模块
sudo a2dismod php7.4 php8.0 php8.1 php8.2 2>/dev/null

2. 启用必要的Apache模块

# 启用MPM-ITK实现静态文件访问的权限隔离
sudo a2enmod mpm_itk
# 启用FCGI相关模块用于对接PHP-FPM
sudo a2enmod actions fcgid alias proxy_fcgi setenvif
# 重启Apache加载模块
sudo systemctl restart apache2

3. 安装多版本PHP-FPM

所有PHP版本必须安装fpm包,禁止安装mod_php包。如果需要使用Ubuntu默认源以外的PHP版本,先添加PPA源:

sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt update

按需安装对应版本的PHP-FPM及扩展,示例为PHP7.4、PHP8.1两个版本:

# 安装PHP7.4组件
sudo apt install -y php7.4-fpm php7.4-cli php7.4-mbstring php7.4-mysql php7.4-curl
# 安装PHP8.1组件
sudo apt install -y php8.1-fpm php8.1-cli php8.1-mbstring php8.1-mysql php8.1-curl

4. 为每个站点配置独立PHP-FPM池

这是权限隔离的核心:每个站点对应一个独立的FPM运行池,以站点专属用户身份运行PHP进程,完全不共用进程资源。
以u-site1站点使用PHP7.4为例:

# 复制默认FPM池模板生成站点专属配置
sudo cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/u-site1.conf
# 编辑专属池配置
sudo vi /etc/php/7.4/fpm/pool.d/u-site1.conf

修改以下配置项,其余参数保持默认即可:

; 池名称改为对应站点标识
[u-site1]
; 监听路径设为专属sock文件,禁止多个站点共用
listen = /run/php/php7.4-u-site1.sock
; PHP进程运行身份设为站点专属用户/用户组
user = u-site1
group = u-site1
; sock文件权限配置,保证Apache可正常访问
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

保存后重启对应版本的PHP-FPM服务:

sudo systemctl restart php7.4-fpm
  • 其他站点、其他PHP版本的FPM池按相同逻辑配置即可,确保每个站点对应独立的池、独立的sock文件、独立的运行用户。

5. 配置Apache虚拟主机

修改站点虚拟主机配置,去掉包裹AssignUserID的<IfModule>判断(避免模块未加载时配置静默失效),同时添加PHP请求转发规则,示例配置如下:

<VirtualHost *:80>
    ServerName site1.local
    ServerAdmin info@site1.local
    DocumentRoot /home/u-site1/site1.local/html
    CustomLog ${APACHE_LOG_DIR}/site1.local.log combined
    ErrorLog ${APACHE_LOG_DIR}/site1.local-error.log

    # 控制Apache访问静态文件的运行身份,实现静态资源权限隔离
    AssignUserID u-site1 u-site1

    <Directory "/home/u-site1/site1.local/html">
        Options All -Indexes
        AllowOverride All
        Require all granted
    </Directory>

    # 将PHP请求转发到对应站点的专属FPM池
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php7.4-u-site1.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

如果站点需要使用其他PHP版本,只需要把SetHandler里的sock路径替换为对应版本、对应站点的FPM sock路径即可。

6. 配置站点目录权限

按最小权限原则设置目录权限,彻底杜绝跨站读写:

# 重置站点目录属主
sudo chown -R u-site1:u-site1 /home/u-site1/site1.local
# 目录权限设为750,其他用户完全无法读取、遍历目录内容
sudo chmod 750 /home/u-site1
sudo chmod 750 /home/u-site1/site1.local
sudo chmod -R 750 /home/u-site1/site1.local/html
# 仅对需要写入的子目录(如上传目录)单独配置写权限,禁止全局写
# sudo chmod 770 /home/u-site1/site1.local/html/uploads

配置完成后启用站点并重载Apache:

sudo a2ensite site1.local.conf
sudo systemctl reload apache2

有效性验证

配置完成后通过以下方式确认隔离生效:

  • 访问站点的phpinfo页面,Environment下的USER字段显示为站点专属用户(如u-site1)而非www-data
  • PHP脚本创建的文件属主、属组均为站点专属用户/用户组
  • 用站点专属用户尝试访问其他站点的目录,会直接返回Permission denied
  • 执行ps aux | grep php可看到每个站点的PHP进程都由对应专属用户运行
  • 不同站点配置不同版本的FPM转发规则后,phpinfo显示的PHP版本与配置一致

注意事项
  • 不要使用mod_php搭配MPM-ITK做权限隔离,一方面无法支持多PHP版本,另一方面Ubuntu 20.04源内的mpm-itk与mod_php存在setuid兼容问题,会出现文件属主异常的情况
  • 禁止多个站点共用同一个FPM默认池(www.conf),否则所有PHP进程都会以www-data身份运行,权限隔离完全失效
  • 站点用户的家目录权限不要设为700,否则Apache进程无法进入目录读取文件,会返回403错误,设为750即可

内容的提问来源于stack exchange,提问作者Maq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:12:22