在无公网独立主机 + FRP 内网穿透场景下,让 MinIO 正确生成 HTTPS 下载 URL
8
🚀 在无公网独立主机 + FRP 内网穿透场景下,让 MinIO 正确生成 HTTPS 下载 URL
在 无公网 IP 的局域网机器 上部署 MinIO,并通过 FRP 进行内网穿透对外发布,是常见的生产部署方式。但很多用户会遇到一个非常典型的问题:
❌ 问题表现
明明外部访问是 HTTPS,例如:
curl https://minio.example.com/api/v1/buckets/test/...
但 MinIO 返回的共享下载链接却是:
http://127.0.0.1:9000/xxxx
或者:
http://minio.example.com/xxxx
换句话说:
MinIO 并不知道外部访问已经是 HTTPS,因此生成的 URL 全是 HTTP
这不仅容易导致链接不可访问,还在 Web 浏览器中引发跨协议安全限制。
本文讲解如何在:
MinIO → FRP → Nginx → HTTPS → 用户
这种复杂链路情况下,让 MinIO 自动正确生成 https:// 的下载 URL。
一、问题根因分析
MinIO 会根据 请求的 Host + 协议 推断共享下载链接。
但在以下架构中:
客户端 → HTTPS → Nginx → FRP → Docker 中 MinIO
MinIO 看到的永远是内部连接:
http://127.0.0.1:9000
因此它自然生成:
http://127.0.0.1:9000/xxx
二、目标效果
最终希望:
- MinIO 内部仍然监听 HTTP(不用额外配置证书)
- 外部通过 HTTPS 访问 MinIO(Nginx 负责 TLS)
- MinIO 自动返回 HTTPS 下载链接
比如:
https://minio.example.com/api/v1/download-shared-object/xxxx
三、Docker Compose 部署示例(MinIO)
version: '3.8'
services:
minio:
image: minio/minio:latest
container_name: minio
ports:
- "9000:9000" # MinIO API
- "9001:9001" # 控制台
volumes:
- /mnt/minio/data:/data
- /mnt/minio/config:/root/.minio
environment:
MINIO_ROOT_USER: "MY_ACCESS_KEY"
MINIO_ROOT_PASSWORD: "MY_SECRET_KEY"
# 🔥 关键:告诉 MinIO 外部访问 URL
MINIO_BROWSER_REDIRECT_URL: "https://console.example.com"
MINIO_PUBLIC_URL: "https://api.example.com"
command: minio server /data --console-address ":9001"
restart: always
核心参数:
| 参数 | 作用 |
|---|---|
MINIO_PUBLIC_URL |
让 MinIO API 生成 HTTPS URL |
MINIO_BROWSER_REDIRECT_URL |
控制台跳转进入 HTTPS |
只要这一步设置正确,MinIO 内部不需要证书也能生成 HTTPS 链接。
四、FRP HTTP 代理配置
通过内网穿透,让 MinIO 暴露外网 HTTPS 域名:
[[proxies]]
name = "minio-api"
type = "http"
localPort = 9000
customDomains = ["api.example.com"]
hostHeaderRewrite = "api.example.com"
requestHeaders.set.X-Forwarded-Proto = "https"
关键:
hostHeaderRewrite改写请求 HostX-Forwarded-Proto=https告诉 MinIO 真实外部协议是 HTTPS
否则 MinIO 还是会误以为自己是 HTTP。
五、Nginx 负责证书与反向代理
外部 Nginx 配置:
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
到这里,链路已经完整:
MinIO → FRP → Nginx → HTTPS → 用户
六、真实问题场景再现
用户访问:
curl 'https://console.example.com/api/v1/buckets/test/objects/share?...'
MinIO 返回:
http://127.0.0.1:9000/api/v1/download-shared-object/xxxx
原因就是 MinIO 不知道外部协议是 HTTPS。
当:
MINIO_PUBLIC_URL已设置为 HTTPS- FRP 传递
X-Forwarded-Proto=https - Nginx 又补了这一头
MinIO 返回的链接立刻变为:
https://api.example.com/api/v1/download-shared-object/xxxx
七、完整链路流程图
浏览器 → HTTPS → Nginx
↓
内网HTTP
↓
FRP → 内网 Docker → MinIO
MinIO 通过:
Host + X-Forwarded-Proto + MINIO_PUBLIC_URL
生成 HTTPS 下载链接
八、为什么不用让 MinIO 自己启用证书?
原因很简单:
- MinIO 自带证书管理麻烦
- 内网部署很难做到 DNS/SNI 完整直通
- 让 Nginx/Caddy 处理证书更稳定
MinIO 专心甩锅:
“只管生成 HTTPS 链接,不负责 TLS”
这是很多企业场景的默认架构。
九、结语
本文解决了 在无公网环境通过 FRP 暴露 MinIO 后,仍然自动生成 HTTPS 下载链接的问题,适用于:
- 局域网机器
- 没有公网 IP
- 通过内网穿透发布存储服务
- 需要 HTTPS、Presigned URL、跨域安全访问
关键三点:
| 层级 | 必须做什么 |
|---|---|
| MinIO | 设置 MINIO_PUBLIC_URL=https://外部域名 |
| FRP | 设置 X-Forwarded-Proto=https |
| Nginx | 做 HTTPS 终端 |
做到这三步,MinIO 就会乖乖生成:
https://api.example.com/xxxx
再也不是:
http://127.0.0.1:9000/xxxx
在无公网独立主机 + FRP 内网穿透场景下,让 MinIO 正确生成 HTTPS 下载 URL
https://www.quietphoenix.top/archives/wei-ming-ming-wen-zhang-6gTRDMsO