phpMyAdmin循环重定向的根本原因是Nginx未正确透传X-Forwarded-Proto头且phpMyAdmin未识别真实协议,需同时配置代理透传(含map兜底、X-Forwarded-Host/Port)和在index.php中手动读取该头以覆盖$_SERVER['HTTPS']。
直接结论:循环重定向不是 phpmyadmin 自身的问题,而是 nginx(或类似反向代理)没透传 x-forwarded-proto,且 phpmyadmin 没识别到真实协议,导致它反复跳回 http —— 解决必须同时改代理配置和 php 运行时逻辑。
为什么 phpMyAdmin 会自己跳 HTTPS?
phpMyAdmin 默认不信任代理头,它只看 $_SERVER['HTTPS'] 或 $_SERVER['REQUEST_SCHEME']。如果这两个值是空或 http,而你数据库里或配置中又设了 $cfg['ForceSSL'] = true(或宝塔/面板自动启用了强制 HTTPS),它就会 302 跳转到 https://...。但这个跳转地址可能仍是错的(比如带内部端口),或者跳完后代理又把请求当 HTTP 处理,触发下一轮判断 —— 死循环就此开始。
- 典型现象:访问
https://example.com/phpmyadmin→ 看到地址栏瞬间变成http://example.com/phpmyadmin/→ 又跳回 HTTPS → 循环 - 关键线索:Nginx access log 里能看到连续多个
302响应,且Location头在 http 和 https 之间来回切换 - 注意:即使你关了宝塔“强制 HTTPS”,只要 phpMyAdmin 配置或数据库里留着
ForceSSL,它仍会自己跳
Nginx 必须透传并兜底 X-Forwarded-Proto
不能只写 proxy_set_header X-Forwarded-Proto $scheme —— 如果前面还有 Cloudflare、APISIX 或其他代理,它们可能已经设了这个头,Nginx 直接覆盖反而丢原始值。
- 先开启头名支持:
underscores_in_headers on;(防旧版 Cloudflare 用X_Forwarded_Proto被 Nginx 丢弃) - 用
map智能兜底:map $http_x_forwarded_proto $real_scheme { default $http_x_forwarded_proto; "" $scheme; }然后写proxy_set_header X-Forwarded-Proto $real_scheme; - 同步传
X-Forwarded-Host和X-Forwarded-Port:proxy_set_header X-Forwarded-Host $host;、proxy_set_header X-Forwarded-Port $server_port;,否则 phpMyAdmin 生成跳转 URL 时可能拼出https://localhost:8443 - 别漏掉
proxy_set_header Host $host;—— 用$host,不是$http_host(后者可能带端口)
phpMyAdmin 必须主动读取 X-Forwarded-Proto
光传头没用。phpMyAdmin 默认忽略这些头,得在运行时手动干预。最可靠方式是在其入口文件(通常是 index.php 或 libraries/common.inc.php)顶部插入判断逻辑。
- 打开 phpMyAdmin 安装目录下的
index.php,在<?php后第一行加:if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on'; } - 如果你用的是宝塔插件版,路径通常是
/www/server/phpmyadmin/;Docker 版需挂载修改或进容器改 - 确认
$cfg['ForceSSL']设为true是安全的 —— 因为现在$_SERVER['HTTPS']已被正确赋值,不会误判 - 检查
config.inc.php中是否硬编码了$cfg['PmaAbsoluteUri'],如果有,删掉或注释掉 —— 它会覆盖所有自动推导逻辑
拦截并重写错误的 Location 响应头
即使上面都做了,phpMyAdmin 仍可能返回形如 Location: http://127.0.0.1:8080/xxx 的绝对跳转地址。Nginx 默认不改写这类响应头,浏览器直接跳过去就绕过代理了。
立即学习“PHP免费学习笔记(深入)”;
- 在对应
location块里加:proxy_redirect ~^http://[^/]+(/.*)$ $scheme://$host$1; - 如果 phpMyAdmin 固定返回某个内部地址(比如
http://localhost:8000),可精准替换:proxy_redirect http://localhost:8000/ $scheme://$host/; - 注意:
proxy_redirect必须放在proxy_pass之后,否则无效 - 测试时 curl -I 看响应头:
curl -I https://example.com/phpmyadmin/,确认Location头已是正确的 HTTPS 地址且不含内部 IP 或端口
最容易被忽略的点是:Cloudflare 的 SSL 模式设成“灵活”时,它会以 HTTP 回源,而你的 Nginx 又写了 return 301 https://... —— 两段跳转叠加,连 X-Forwarded-Proto 都来不及传就被重定向截断了。所以排查时,务必先确认 CDN 层没有和 Nginx 规则形成双重跳转。



















