现象

www.cyk.pink 打不开,浏览器直接报证书错误。点「继续访问」之后又能看到完整站点。

先查再改

我一开始以为是 DNS 没做。查完发现想错了:

DNS        www.cyk.pink → 43.143.218.149       正常
80 端口 → 301 https://cyk.pink/ 正常
443 server_name cyk.pink www.cyk.pink 两个域名同一个块
证书 SAN DNS:cyk.pink 没有 www

两个问题叠在一起:证书不认 www,443 又把 www 和主域塞进同一个 server 块。所以用户在证书警告页点继续之后,看到的是同一个站。

同一份内容挂在两个域名下,这才是要修的地方。

扩证书失败

sudo certbot --nginx -d cyk.pink -d www.cyk.pink --expand
Domain: www.cyk.pink
Detail: During secondary validation: Timeout during connect (likely firewall problem)

报错里写着 firewall,就去翻防火墙,80 和 443 对 0.0.0.0/0 全开。又换四个公共 DNS 查解析,也都正常。

Let’s Encrypt 现在是多节点校验,主节点过了、某个 secondary 节点超时也会判失败。跟我这边没关系。

换成 webroot,同时把 ACME 的验证路径从跳转里单独捞出来:

server {
listen 80;
server_name cyk.pink www.cyk.pink;

location ^~ /.well-known/acme-challenge/ {
root /var/www/cyk.pink;
default_type "text/plain";
}

location / {
return 301 https://cyk.pink$request_uri;
}
}

这里踩了个坑。

80 端口原来是这么一句:

server {
listen 80;
server_name cyk.pink www.cyk.pink;
return 301 https://cyk.pink$request_uri;
}

我直接在下面加了 location,以为能把验证路径拦下来。没拦住。

server 级的 return 在 rewrite 阶段就执行完了,根本轮不到 location 匹配。放行必须把跳转挪进 location / 里。

改完一次过:

sudo certbot certonly --webroot -w /var/www/cyk.pink \
--cert-name cyk.pink -d cyk.pink -d www.cyk.pink --expand

443 拆成两块

主域的 server_name 只留裸域,www 单独一个块,只负责跳转:

server {
listen 443 ssl http2;
server_name www.cyk.pink;

ssl_certificate /etc/letsencrypt/live/cyk.pink/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cyk.pink/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

return 301 https://cyk.pink$request_uri;
}

验证

https://www.cyk.pink/                 → 301 → https://cyk.pink/
https://www.cyk.pink/posts/xxx.html → 301 → https://cyk.pink/posts/xxx.html
SAN: DNS:cyk.pink, DNS:www.cyk.pink

路径能带过去,不是一律回首页。

续期也验了一遍:certbot renew --dry-run 通过。签发方式自动改成 webroot 了,webroot_path 记在 renewal 配置里,以后不用再管。