前言

有两个服务域名证书到期了,导致访问页面异常,分别是 www.seasidecrab.comdocs.seasidecrab.com。刚好这两个域名指向的也是旧的服务器,旧服务器快到期了,需要指向到新服务器 A 上。博客和文档服务本身安装在另一个台服务器 B 上,当时临时通过永久重定向(301)和反向代理的形式将请求转发到 B 上。

从长远考虑肯定是要把所有服务都迁移到 A 上的,但因为 B 服务器还有一段时间,所以决定在 A 上先安装一个 steveltn/https-portal,然后用它通过重定向和反向代理来访问这两个服务。

翻车过程

原 httpd 服务配置:

# www 重定向到 blog,blog 直接解析到 B 上,再由 B 上安装的 https-portal 代理到具体的 docker 容器服务。
Redirect 301 / https://blog.seasidecrab.com/
# docs 设置反向代理,215 为 B 的 ip,4999 为容器映射出来的端口
ProxyRequests off
ProxyPass / http://139.224.207.215:4999/
ProxyPassReverse / http://139.224.207.215:4999/

先放一下最终版的 docker-compose.yml

services:
  https-portal:
    image: steveltn/https-portal:1
    container_name: https-portal
    env_file: ./.env
    ports:
      - '80:80'
      - '443:443'
    networks:
      - internal
      - shared
    restart: always
    volumes:
      - ./ssl-certs:/var/lib/https-portal
    healthcheck:
      test: ["CMD", "service", "nginx", "status"]
      interval: 30s
      timeout: 20s
      retries: 3
    environment:
      DOMAINS: DOMAINS: 'seasidecrab.com => https://blog.seasidecrab.com, www.seasidecrab.com => https://blog.seasidecrab.com, docs.seasidecrab.com -> http://139.224.207.215:4999'
      STAGE: 'production'
      WEBSOCKET: 'true'
      CLIENT_MAX_BODY_SIZE: '0'
    cap_add:
      - SYS_ADMIN
networks:
  internal:
    driver: bridge
  shared:
    external: true
    name: shared-services
volumes:
  https-portal-data:

在执行 docker compose up -d 生成容器之前,先要修改域名的解析到当前的 A,即需要先改解析的的取值,之后再生成证书,不然会生成失败。

deepseek 一开始给出的配置:

# A 服务器的 docker-compose.yml 或运行配置
DOMAINS: 'www.seasidecrab.com -> http://B服务器IP:80, docs.seasidecrab.com -> http://B服务器IP:80'

后者的端口是 4999,它没有完全理解,或者说,我提问有些问题吧,导致它认为我是反向代理问题。

之后说明 IP,给了一个新的配置,A 使用 HTTPS 连接到 B

# A 服务器的配置 - 禁用 SSL 验证
DOMAINS: 'www.seasidecrab.com -> https://139.224.207.215, docs.seasidecrab.com -> https://139.224.207.215'
EXTRA_NGINX_CONFIG: |
  proxy_ssl_verify off;
  proxy_set_header Host $host;

后面修改之后,访问 502 Bad Gateway。然后给了很多方法排查 A 到 B 以及 B 上的服务是否存在,是否正常等等。最后开始给出自定义的 nginx 配置,也不行。

这个时候我还没意思到 -> 表示什么,换成豆包跟我解释了一下这个是反向代理。但也还是额外增加配置来实现重定向功能。之后各种调整,把无限循环代理都搞出来了。

解释一下循环代理,www 直接代理到 blog 不行(可能证书冲突之类的 502 报错),然后把 blog 和 www 都解析在 A 上,结果就是 www 到 blog,blog 到 B 80 服务,然后再被 B 上的 https-portal 转成 https,再 DNS 解析到 A 上...

之后给的方案,就是访问 B 的 https 地址,并添加 X_FORWARDED_PROTO: https,让 A 告诉 B:这是 HTTPS 请求,B 收到后不会触发 HTTP → HTTPS 重定向...这个方案没有独立测试过,不确定是否可行。

豆包的回复每次开头都是「终极方案」、「彻底解决」、「唯一正确解法」,情绪价值拉满了,结果就是不行。

在我看来这个 https-portal 就是一个基于 nginx 生成的容器服务,应该是具备 nginx 的主要功能的。查了一下 dockerhub 上的 https-portal 使用文档,发现里面清楚地写着重定向的写法为 =>。但 deepseek 和豆包就是不知道,或者 dockerhub 不在它们的阅读范围内,或者 web 版的属于落后版本,没有更新。

然后删掉所有的冗余配置,就有了上面的那个 docker compose 配置文件。

总结一下:steveltn/https-portal 默认的 -> 表示反向代理,=> 表示重定向。

文章目录