Debian Nginx + PHP-FPM 配置:FastCGI、站点目录与访问验证
1. 服务介绍
Nginx 负责接收 HTTP/HTTPS 请求、提供静态文件和反向代理;PHP-FPM 负责运行 PHP 程序。Nginx 本身不会执行 PHP,而是通过 FastCGI 将 PHP 请求转发给 PHP-FPM,再把执行结果返回给客户端。
这种组合适合部署 PHP 网站、内容管理系统和内部测试接口。静态资源由 Nginx 直接返回,动态请求交给 PHP-FPM 处理,可以分别调整 Web 服务和 PHP 进程池的参数。
2. 准备运行环境
• 操作系统:Debian 10 实验环境;其他 Debian 版本以软件源中实际可用的 PHP-FPM 版本为准。
• 权限:root 或具备 sudo 权限的管理员账号。
• 软件源:能够执行 apt update,并可安装 Nginx、PHP-FPM 和 PHP CLI。
• 网络:服务器与客户端互通,TCP 80 端口可访问;配置 HTTPS 时再准备域名、证书和 TCP 443 端口。
• 站点信息:确定站点目录、访问域名和 PHP-FPM 的监听方式。PHP-FPM 既可以监听 Unix Socket,也可以监听 TCP 地址。
• 权限边界:站点文件应允许 Nginx/PHP-FPM 进程读取,日志目录和上传目录按需单独授权。
• 版本说明:原实验使用 PHP 7.3;如果当前系统安装的是其他版本,需要把服务名和 Socket 文件名替换为实际版本。
3. 相关知识
3.1 FastCGI 请求链路
客户端请求 PHP 文件后,Nginx 根据 location ~ \.php$ 匹配规则,把请求交给 PHP-FPM。fastcgi_pass 指定 PHP-FPM 的 Socket 或 TCP 地址,SCRIPT_FILENAME 用于告诉 PHP-FPM 要执行的文件路径。
3.2 Socket、服务名与版本必须一致
常见 Socket 类似 /run/php/php7.3-fpm.sock。如果 Nginx 配置写成 PHP 7.3,但系统实际运行的是 PHP 8.2,就会出现 502 或连接不到上游。修改配置前先查看 /run/php/ 和 systemd 服务列表,不要只按文章标题猜版本。
3.3 `try_files` 与权限
try_files $uri =404 可以阻止不存在的 PHP 文件被转发给 PHP-FPM;站点根目录需要让 Nginx 进程能够遍历和读取。上传目录、缓存目录等需要写权限时,只给对应目录授权,不要直接把整个站点目录设置为所有用户可写。
3.4 排错与安全注意点
• 修改 Nginx 配置后先运行 nginx -t,通过后再 reload。
• 502 优先检查 PHP-FPM 是否运行、Socket 是否存在、fastcgi_pass 是否写对。
• 403 优先检查站点目录、父目录遍历权限和 Nginx 配置中的 deny 规则。
• 不要长期暴露 phpinfo()、调试页面、数据库密码或应用配置文件。
• 同时查看 Nginx error log、PHP-FPM 日志和客户端 HTTP 状态码。
• 更改 PHP-FPM 用户或 Nginx 用户后,要同步检查站点目录、证书目录和 /run/php 的访问权限。
4. 实验步骤
4.1 安装并确认软件版本
先确认 Debian 版本和软件源,再安装 Nginx、PHP-FPM、PHP CLI。Debian 10 原实验使用 PHP 7.3;若软件源提供其他版本,后续命令使用实际版本。
bash
cat /etc/debian_version
sudo apt update
sudo apt install -y nginx php-fpm php-cli
php -v
nginx -v
systemctl list-unit-files 'php*-fpm.service'
ls -l /run/php/

如果确认服务名为 php7.3-fpm,启动服务;如果版本不同,把服务名替换为实际名称。
bash
sudo systemctl enable --now nginx
sudo systemctl enable --now php7.3-fpm
sudo systemctl is-active nginx
sudo systemctl is-active php7.3-fpm

4.2 创建站点目录和 PHP 测试页
创建独立站点目录。测试页只输出 PHP 版本和运行时间,验证完成后应删除或限制访问,避免公开暴露调试信息。
bash
sudo mkdir -p /var/www/example
sudo tee /var/www/example/index.php >/dev/null <<'PHP'
<?php
header('Content-Type: text/plain; charset=UTF-8');
echo "nginx + php-fpm is working\n";
echo "PHP version: " . PHP_VERSION . "\n";
PHP
sudo chown -R www-data:www-data /var/www/example
sudo find /var/www/example -type d -exec chmod 755 {} \;
sudo find /var/www/example -type f -exec chmod 644 {} \;


4.3 配置 Nginx 虚拟主机
先确认 PHP-FPM Socket 名称:
bash
ls -l /run/php/php*-fpm.sock
下面示例使用 php7.3-fpm.sock。如果 ls 输出的是其他版本,替换 fastcgi_pass 中的文件名。
bash
sudo tee /etc/nginx/sites-available/example >/dev/null <<'NGINX'
server {
listen 80;
server_name example.test;
root /var/www/example;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}
location ~ /\. {
deny all;
}
}
NGINX
如果通过 IP 访问,可暂时把 server_name 改为服务器 IP;正式环境应使用实际域名,并按需配置 HTTPS。


4.4 启用站点并检查配置
停用默认站点不是必需操作,但独立实验站点需要避免默认虚拟主机抢先匹配。启用新站点后先检查语法,再 reload。
bash
sudo rm -f /etc/nginx/sites-enabled/default
sudo ln -sfn /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example
sudo nginx -t
sudo systemctl reload nginx


4.5 重启服务并检查监听状态
配置变更后,重启或 reload 对应服务,并确认 Nginx 正在监听 80 端口,PHP-FPM Socket 存在。
bash
sudo systemctl restart php7.3-fpm
sudo systemctl reload nginx
sudo systemctl is-active nginx
sudo systemctl is-active php7.3-fpm
ss -lntp | grep ':80'
test -S /run/php/php7.3-fpm.sock && echo 'PHP-FPM socket OK'

4.6 客户端访问测试
客户端可以使用域名、服务器 IP 或临时 hosts 映射访问。先使用 curl 查看响应,再用浏览器确认页面内容。
bash
curl -i http://服务器IP/index.php
curl -i http://example.test/index.php
如果使用域名测试,客户端 DNS 或 hosts 需要把域名解析到服务器 IP。返回 200 OK,并能看到 PHP 版本文本,说明 Nginx 到 PHP-FPM 的 FastCGI 链路已经打通。

5. 验证结果
在服务器端执行以下检查:
bash
nginx -t
systemctl is-active nginx
systemctl is-active php7.3-fpm
ss -lntp | grep -E ':80|:443'
test -S /run/php/php7.3-fpm.sock
php -v
在客户端执行:
bash
curl -i http://服务器IP/
curl -i http://服务器IP/index.php
预期结果:
• nginx -t 输出配置文件语法检查成功。
• Nginx 和 PHP-FPM 均返回 active。
• TCP 80 端口处于监听状态。
• PHP-FPM Socket 文件存在,且 Socket 版本与 fastcgi_pass 一致。
• 访问静态页面和 index.php 均返回 HTTP 200。
• PHP 页面输出测试文本,响应中没有下载 PHP 源码或显示配置文件内容。
遇到异常时查看最近日志:
bash
sudo journalctl -u nginx -n 50 --no-pager
sudo journalctl -u php7.3-fpm -n 50 --no-pager
sudo tail -n 50 /var/log/nginx/error.log
6. 常见问题
6.1 访问返回 502 Bad Gateway
检查 PHP-FPM 服务是否运行、Socket 是否存在,并确认 Nginx 配置中的版本号一致:
bash
systemctl status php7.3-fpm --no-pager
ls -l /run/php/
grep -R "fastcgi_pass" /etc/nginx/sites-enabled/
6.2 访问 PHP 文件返回 404
检查 root 指向的目录、PHP 文件是否真实存在,以及 try_files $uri =404 是否把请求拦截:
bash
ls -l /var/www/example/index.php
nginx -T | grep -A8 -B3 'location ~ \\.php'
6.3 浏览器显示 PHP 源码或直接下载文件
说明 PHP 请求没有正确进入 PHP-FPM。检查 PHP location 是否生效、include snippets/fastcgi-php.conf 是否存在,并确认已 reload Nginx。不要在生产环境继续公开测试页。
6.4 返回 403 Forbidden
检查站点目录和父目录的遍历权限、文件权限、Nginx deny 规则以及是否命中了其他虚拟主机:
bash
namei -l /var/www/example/index.php
nginx -T | grep -nE 'server_name|root|deny'
6.5 修改用户后服务无法读取文件
如果更改 Nginx 或 PHP-FPM 运行用户,需要重新检查 /etc/nginx/、站点根目录、证书目录和 /run/php 的读取/遍历权限。优先使用最小权限修复,不要对整个文件系统执行递归放权。