
当 nginx 访问 php 文件(如 index.php)时直接触发浏览器下载,本质是请求未被正确转发至 php-fpm 处理,而是被当作静态文件返回原始代码;常见于 location 配置逻辑错误、fastcgi 参数缺失、php-fpm 未运行或路径不匹配。
当 nginx 访问 php 文件(如 index.php)时直接触发浏览器下载,本质是请求未被正确转发至 php-fpm 处理,而是被当作静态文件返回原始代码;常见于 location 配置逻辑错误、fastcgi 参数缺失、php-fpm 未运行或路径不匹配。
这个问题在轻量级环境(如 Raspberry Pi 1B)中尤为典型——资源受限叠加配置疏漏,极易导致 PHP 解析链断裂。从你提供的配置可见,核心症结并非 PHP-FPM 服务异常(php -v 正常、socket 路径 unix:/run/php/php7.4-fpm.sock 也合理),而在于 location / 块中 try_files 指令的误用。
? 关键问题定位:try_files 的陷阱
你当前的配置片段:
location / {
try_files $uri /public/$uri /index.php$is_args$args =404;
}表面看是为支持静态资源回退与 PHP 入口路由,但末尾的 =404 是致命错误:它强制将所有未能命中 $uri 或 /public/$uri 的请求(包括最终重写到 /index.php 的请求)直接返回 404 状态码,并中断后续 location 匹配流程。更严重的是,Nginx 在 try_files 中遇到 =404 时,不会继续尝试匹配 location ~ \.php$,导致 /index.php 请求被当作普通文件处理——于是浏览器收到 Content-Type: application/octet-stream 响应头,触发下载行为。
✅ 正确做法是:移除 =404,改用 @php 内部重定向或确保 PHP location 可被捕获:
立即学习“PHP免费学习笔记(深入)”;
location / {
try_files $uri /public/$uri @php;
}
location @php {
rewrite ^(.*)$ /index.php?$args last;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# 注意:snippets/fastcgi-php.conf 已含 fastcgi_index 和 PATH_INFO 处理
# 无需重复 include fastcgi_params(避免参数冲突)
}✅ 完整加固配置建议(适配 Raspberry Pi 1B)
server {
server_name rss.getty.nz;
root /var/www/rss.getty;
index index.php;
# 日志路径保持不变
access_log /var/www/rss.getty/rss.accesss.log;
error_log /var/www/rss.getty/rss.error.log warn; # 提升日志级别便于排错
# 主路由:优先匹配静态文件,再 fallback 到 PHP 入口
location / {
try_files $uri /public/$uri /index.php?$query_string;
}
# PHP 处理入口(必须存在且位置合理)
location ~ \.php$ {
# 使用系统标准 fastcgi-php.conf(已含 split_path_info + try_files)
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# 强制 SCRIPT_FILENAME 绝对路径(防 root 不一致)
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# 静态资源缓存
location ~* \.(gif|jpg|png)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 敏感路径禁止访问
location ~ ^/(favicons|thumbnails)/ {
try_files $uri /data/$uri;
}
location ~* ^/(data/logs|data/sqlite|config\.ini|\.ht) {
deny all;
}
# SSL 配置(Certbot 管理部分保持不变)
listen [::]:443 ssl;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/rss.getty.nz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rss.getty.nz/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}⚠️ 必须验证的 4 项关键点
-
PHP-FPM 运行状态
sudo systemctl is-active php7.4-fpm # 应返回 'active' sudo ss -ltnp | grep ':9000\|php' # 确认 socket 监听
-
Nginx 用户权限
Raspberry Pi 默认使用www-data用户,需确保其对 socket 和网站目录有读取权限:ls -l /run/php/php7.4-fpm.sock # 输出应类似:srw-rw---- 1 www-data www-data ... sudo chown www-data:www-data /var/www/rss.getty -R
fastcgi_params无重复引入snippets/fastcgi-php.conf已include fastcgi.conf(等价于fastcgi_params),若额外include fastcgi_params会导致参数覆盖(如SCRIPT_NAME被重置),引发 selfoss 路由异常。-
selfoss 特定要求
selfoss 依赖PATH_INFO解析路由(如/feed/123),务必保留fastcgi_split_path_info配置,并在php.ini中设置:cgi.fix_pathinfo = 0 ; 防止路径遍历风险(Nginx 官方强烈推荐)
? 总结
浏览器下载 index.php 不是“PHP 不工作”,而是 Nginx 请求分发逻辑中断。解决核心在于:
✅ 删除 try_files 末尾的 =404,改用 ?args 或 @named_location 保证 PHP 路由可达;
✅ 确保 location ~ \.php$ 块真实生效(检查配置语法 nginx -t、重载 sudo nginx -s reload);
✅ 权限、服务状态、参数一致性三者缺一不可。
完成修复后,访问 https://rss.getty.nz 将正常加载 selfoss 界面,而非弹出下载框——这是 Nginx 与 PHP-FPM 协同工作的最基础也是最关键的信号。



















