在无公网独立主机 + 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 改写请求 Host
  • X-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
作者
QuietPhoenix
发布于
更新于
许可