跳转至

nginx + HTTPS 站点

结论

一条命令搞定证书和跳转,不用手写 443 配置:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com --redirect

--redirect 会自动把 80 设置成 301 跳 443,并把证书路径写进你的 server 块。

前置检查(顺序别乱)

  1. DNS:dig +short example.com 必须返回这台机器的 IP
  2. 安全组:80 和 443 都要放行,只开 80 会在签发时报 Timeout during connect
  3. nginx 能起来:sudo nginx -t && sudo systemctl reload nginx
  4. 大陆服务器:域名需已备案,否则 80/443 访问会被拦

站点配置模板

server {
    listen 80;
    server_name example.com www.example.com;

    # 续期验证路径,不要加认证,否则 certbot 会失败
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    root /var/www/mysite;
    index index.html;

    location / {
        try_files $uri $uri/ $uri.html =404;
    }

    error_page 404 /404.html;
    location = /404.html { internal; }
}

certbot 会在这个块里追加 listen 443 ssl、证书路径和 301 规则。

几个容易踩的点

现象 原因 处理
Timeout during connect 80 未放行 / DNS 未生效 / 备案拦截 逐项排查,先 curl -I http://域名
证书签了但浏览器仍报警 证书只含 example.com,你访问的是 www 签发时把两个域名都写上
续期失败 .well-known 路径被 Basic Auth 挡住 该 location 不设 auth_basic
上传大文件 413 默认 body 限制 1M client_max_body_size 100m;

静态站 + 自定义缓存

location ~* \.(css|js|woff2?|png|svg)$ {
    expires 7d;
    add_header Cache-Control "public";
}

# 需要频繁改的文件单独降缓存,否则改完看不到效果
location = /stylesheets/extra.css {
    expires 5m;
}

location = 优先级高于正则匹配,可以精确覆盖单个文件。

验证清单

curl -sI https://example.com | head -3          # 200
curl -sI http://example.com | grep -i location  # 301 到 https
sudo certbot certificates                       # 到期时间
sudo certbot renew --dry-run                    # 续期演练
systemctl list-timers certbot.timer             # 自动续期是否在跑