单元六 域名与上线 · 第 24 课

HTTPS:正式上线

最后一步:在服务器上安排一个“前台”接收网页请求,配好加密证书,让 https://report.你的域名 正式对外开放。

本课目标

  • 理解 HTTPS 的两段加密,以及 Cloudflare 的 SSL 模式。
  • 申请 Cloudflare 源站证书,放到服务器上。
  • 用 Caddy 做反向代理,开放 80/443 端口,正式上线。

先懂概念:两段路,两段加密

开了橙色云朵以后,一次访问要走两段路:

访问者 ──HTTPS──▶ Cloudflare ──HTTPS──▶ 你的服务器(Caddy)──▶ 周报助手(app:3000)
        第一段                  第二段
  • 第一段:访问者到 Cloudflare。证书由 Cloudflare 自动提供,你不用管。
  • 第二段:Cloudflare 到你的服务器。需要在服务器上放一张证书。Cloudflare 免费签发一种源站证书(Origin Certificate),有效期可以长达 15 年,专门用于这一段。

Cloudflare 的 SSL 模式决定第二段怎么走,我们用最安全的 Full (strict):第二段也加密,并且严格校验服务器的证书。不要用 Flexible,它的第二段是明文的。

Caddy 是一个网页服务器,在这里充当“前台”:它在 80 和 443 端口接收所有网页请求,用证书完成加密,再把请求转交给后面的周报助手。这种角色叫反向代理。

跟着做

1. 申请源站证书

在 Cloudflare 里进入你的域名:

  1. 打开 SSL/TLS → Origin Server,点 Create Certificate。
  2. 私钥类型保持 RSA (2048);主机名保持默认的 *.example.com 和 example.com;有效期保持 15 年。点 Create。
  3. 页面显示两段内容:Origin Certificate(证书)和 Private key(私钥)。

私钥只显示这一次。 先别关页面,进行下一步。

2. 把证书放到服务器上

ssh ai-server

看到服务器的提示符后,再运行:

mkdir -p ~/apps/weekly-report/certs
cd ~/apps/weekly-report/certs
vim origin.pem

按 i,粘贴 Origin Certificate 的全部内容(从 -----BEGIN CERTIFICATE----- 到 -----END CERTIFICATE-----),Esc、:wq 保存。同样地:

vim origin.key

粘贴 Private key 的全部内容,保存。然后设置权限:

chmod 600 origin.pem origin.key
ls -l

两个文件都是 -rw-------。现在可以关掉 Cloudflare 的证书页面了。

私钥和 API Key 一样重要:不要发给别人,不要放进代码仓库。

3. 写 Caddy 的配置

cd ~/apps/weekly-report
cat > Caddyfile <<'EOF'
report.example.com {
	tls /certs/origin.pem /certs/origin.key
	reverse_proxy app:3000
}
EOF

把 report.example.com 改成你的域名。意思是:收到这个域名的请求,用这两个证书文件加密,然后转交给名叫 app 的服务的 3000 端口。

4. 把 Caddy 加进 compose.yaml

用下面的内容替换整个 compose.yaml,把 你的用户名 换成你的 Docker Hub 用户名,镜像版本和你当前用的保持一致:

cat > compose.yaml <<'EOF'
services:
  app:
    image: 你的用户名/weekly-report:v2
    env_file: .env
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./certs:/certs:ro
      - caddy_data:/data

volumes:
  caddy_data:
EOF
docker compose config --quiet && echo 配置正确
  • 同一个 compose.yaml 里的服务可以用名字互相访问,所以 Caddy 能通过 app:3000 找到周报助手。
  • volumes 把服务器上的 Caddyfile 和 certs 文件夹交给 Caddy 容器使用,:ro 表示只读。

5. 开放 80 和 443 端口

到云服务商控制台的防火墙页面,添加两条规则:允许 TCP 80 和 TCP 443。

6. 启动

docker compose up -d
docker compose ps
docker compose logs caddy

app 和 caddy 都是 Up,Caddy 的日志里没有 error 字样。

7. 在 Cloudflare 里启用 Full (strict)

  1. 打开 SSL/TLS → Overview,把加密模式改为 Full (strict)。
  2. 打开 SSL/TLS → Edge Certificates,开启 Always Use HTTPS,让所有 http:// 访问自动跳转到 https://。

你应该看到

在浏览器访问 https://report.example.com:

  1. 地址栏有锁形图标;
  2. 弹出登录框,输入 .env 里的用户名和密码;
  3. 周报助手正常工作。

用手机打开同一个网址试试。恭喜,你的网站正式上线了。

排错:Cloudflare 的错误代码

错误意思检查
521服务器拒绝连接Caddy 有没有运行(docker compose ps)
522连接超时防火墙有没有开放 80/443
525加密握手失败Caddyfile 里的域名是否正确,证书文件内容是否完整
526源站证书校验失败证书是否过期、是否包含这个域名、Caddy 加载的是不是那两个文件;使用 Cloudflare 源站证书最省事
重定向次数过多来回跳转SSL 模式误设成了 Flexible,改为 Full (strict)

排查时先看 docker compose logs caddy,再对照上表。

更进一步(可选)

现在任何 IP 都能直接连接你服务器的 80/443 端口。可以在防火墙里把这两个端口的来源限制为 Cloudflare 的 IP 段,让所有访问都必须经过 Cloudflare。IP 段偶尔会变化,需要定期核对。

自检

  • 我能解释两段加密,以及为什么用 Full (strict) 而不是 Flexible。
  • 证书和私钥在服务器上,权限是 -rw-------。
  • https://report.example.com 有锁形图标,需要登录才能使用。
  • 我知道 521、522、525、526 分别该查什么。