expose_php = off 仅禁用 php 自动添加的 x-powered-by 头,而 phpmyadmin 会主动调用 header() 函数设置该头,因此需在 nginx 的 fastcgi_pass 所在 location 块中配置 fastcgi_hide_header x-powered-by 才能彻底屏蔽。

直接改 php.ini 里的 expose_php = Off 就能关掉 PHP 版本号暴露,但 phpMyAdmin 本身还会在 HTTP 响应头里塞一个 X-Powered-By: PHP/8.1.2(或类似),这个得靠 Nginx 拦住。
为什么 expose_php = Off 不够用?
phpMyAdmin 是个 PHP 应用,它默认会调用 header() 函数主动设置 X-Powered-By 响应头。即使 PHP 层不自动加,它自己也会加——这是它的行为,不是 PHP 解释器的默认输出。
常见错误现象:你确认了 expose_php = Off,重启了 PHP-FPM,但用 curl -I https://your-site/phpmyadmin/ 仍然看到 X-Powered-By: PHP/...。
所以光关 PHP 配置没用,得在 Nginx 这一层做响应头清理。
在 Nginx 配置中移除 X-Powered-By
Nginx 不能直接“删除”已有响应头,但可以用 proxy_hide_header(反向代理场景)或 fastcgi_hide_header(FastCGI 场景)来屏蔽它。绝大多数 phpMyAdmin 是通过 fastcgi_pass 接入的,所以用后者。
在你的 phpMyAdmin location 块里加上这行:
location /phpmyadmin {
alias /usr/share/phpmyadmin/;
index index.php;
# ... 其他 fastcgi 配置
fastcgi_hide_header X-Powered-By;
}
注意点:
-
fastcgi_hide_header必须写在fastcgi_pass所在的 location 或其上级作用域内才生效 - 它只对 FastCGI 后端返回的响应头起作用,对 Nginx 自己加的头(如
Server)无效 - 如果用了
proxy_pass(比如把请求转给另一个 PHP 服务),就得换成proxy_hide_header X-Powered-By
顺手也隐藏 Nginx 的 Server 头?
虽然问题只问 PHP 版本号,但实际安全加固常一起处理。Nginx 默认返回 Server: nginx/1.18.0,这个可以通过 server_tokens off; 关掉——但它只影响错误页(404/500 等)和响应头中的 Server 字段,且必须放在 http、server 或 location 块里。
不过要注意:
-
server_tokens off;对正常 200 响应里的Server头**不一定生效**(取决于 Nginx 版本和编译选项) - 若要彻底隐藏,得用
more_clear_headers "Server";(需安装headers-more-nginx-module)或升级到 Nginx 1.23.0+ 并用underscores_in_headers on;配合自定义逻辑(不推荐为这点折腾) - phpMyAdmin 的核心风险不在
Server头,优先确保X-Powered-By被fastcgi_hide_header拦掉
真正容易被忽略的是:改完配置后必须 nginx -t && nginx -s reload,而且要确认 phpMyAdmin 请求确实走的是你加了 fastcgi_hide_header 的那个 location——比如别被其他通配 location(如 location ~ \.php$)提前匹配走了,导致新配置没生效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











