43 分钟
部署与基础设施工程

HTTPS(下):免费证书申请、Nginx 部署、强制跳转与到期治理

讲清 DV/OV/EV 与各类证书区别,用 Let's Encrypt + certbot 完成免费证书的签发与自动续期,部署到 Nginx、做 HTTP 强制跳转 HTTPS、HSTS 与混合内容治理,并说明 iOS ATS 等客户端要求

  • 分清 DV/OV/EV、单域名/泛域名/多域名证书,知道独立开发者该选哪种
  • 会用 Let's Encrypt + certbot 签发证书并配置自动续期
  • 会在 Nginx 部署证书链、把 HTTP 301 跳转到 HTTPS、配置 HSTS
  • 理解混合内容、证书到期监控与 iOS ATS 对 HTTPS 的硬性要求

证书不神秘,免费的就足够绝大多数产品用

上一课讲了原理,这一课把 HTTPS 真正部署上线。先破除一个误区:证书不是越贵越安全——加密强度取决于算法和密钥,而不是价格。不同等级证书的差别主要在「CA 对你身份核验到什么程度」以及浏览器展示形态。

证书等级与覆盖范围怎么选

按核验程度分DV 域名验证:只证明你控制这个域名,签发快(分钟级)、免费,浏览器有小锁OV 组织验证:核验企业真实身份,证书里含组织名,收费EV 扩展验证:核验最严,早年浏览器显公司名(现已弱化),贵、流程重 按覆盖域名分单域名 :只保护一个确切域名泛域名 :*.pygood.com 覆盖所有一级子域,子域多时划算多域名 :一张证书列多个不相关域名(SAN)

💡独立开发者的选择

个人和绝大多数中小产品用 DV 证书完全足够,Let's Encrypt 就是被全球广泛使用的免费 DV CA;只有 To-B、金融等需要对外展示企业可信身份时才考虑 OV。子域很多时用泛域名证书省事,但注意 *.pygood.com 只覆盖一级子域(a.pygood.com),不覆盖 a.b.pygood.com。

Let's Encrypt + certbot:免费且自动续期

Let's Encrypt 证书免费、自动化,但有效期只有 90 天(刻意设短以推动自动化续期、降低密钥泄露影响)。官方推荐用 certbot 工具,它能自动验证域名、签发、改 Nginx 配置、并装一个定时任务在到期前自动续期。验证你对域名控制权有两种常见方式:HTTP-01(在网站放一个临时文件,要求 80 可访问)和 DNS-01(加一条 TXT 记录,适合泛域名或 80 不方便的场景)。

Shell
# Ubuntu 上安装 certbot 与 Nginx 插件(包名以官方文档当前为准)
sudo apt install -y certbot python3-certbot-nginx

# 方式一:自动改 Nginx(含签发+部署+跳转,最省心)
sudo certbot --nginx -d pygood.com -d www.pygood.com

# 方式二:只签发证书、Nginx 自己配(webroot 验证)
sudo certbot certonly --webroot -w /var/www/html -d pygood.com

# 测试自动续期流程是否正常(不会真的提前换)
sudo certbot renew --dry-run
# certbot 安装时通常已注册 systemd timer / cron 自动 renew
⚠️90 天有效期:不自动续期等于埋雷

证书过期后网站会直接报「连接不安全」、App 的网络请求会失败,这是非常常见的线上事故。务必:装好自动续期定时任务并用 --dry-run 验证;另加一个外部到期监控(在证书到期前 15~30 天告警)作为双保险;续期后要 reload Nginx 新证书才生效(certbot 通常会配好部署钩子)。

在 Nginx 部署并强制 HTTPS

示例
# HTTP:全部 301 永久跳转到 HTTPS(同时保留 80 供续期验证)
server {
    listen 80;
    server_name pygood.com www.pygood.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name pygood.com www.pygood.com;
    ssl_certificate     /etc/letsencrypt/live/pygood.com/fullchain.pem; # 证书链
    ssl_certificate_key /etc/letsencrypt/live/pygood.com/privkey.pem;    # 私钥
    ssl_protocols TLSv1.2 TLSv1.3;
    # 首次成功走 HTTPS 后,让浏览器在一段时间内自动用 HTTPS(HSTS)
    add_header Strict-Transport-Security "max-age=31536000" always;
}

注意 ssl_certificate 要用 fullchain(站点证书+中间证书拼起来的完整链),只给站点证书时,部分客户端因为补不全中间链会报证书错误。return 301 是永久跳转,把误输 http 的用户和搜索引擎都导向 https。

混合内容、HSTS 与移动端 ATS

页面本身是 HTTPS,却引用了 http:// 的图片/脚本/接口,叫混合内容(Mixed Content),浏览器会拦截或告警、App 也可能请求失败——上了 HTTPS 就要让所有子资源、API、图片全部走 https。HSTS(Strict-Transport-Security)让浏览器记住「这个站以后只许 HTTPS 访问」,从源头杜绝用户被降级到 http。

🚫iOS 的 App Transport Security 是硬要求

苹果 App 默认开启 ATS:网络请求必须走 TLS1.2 以上、用合规证书和足够强度的加密,否则请求直接被系统拒绝(要豁免需在 Info.plist 声明并在审核时说明理由,越来越难过审)。Android 从 Android 9 起也默认禁止明文流量。所以「以后要上 App」从第一天起就把后端做成 HTTPS,是最省事的路径——这也是朋友好学计划备案通过后把接口域名切到 https://pygood.com 的原因。

🐍资深杂谈:把证书当成会到期的「流水线」而不是一次性配置

新手把申请证书当成「做一次就完」,老手把它当成一条需要自动化和监控的流水线:签发自动化、续期自动化、续期后自动 reload、再加外部到期监控兜底。凡是依赖人工记忆的证书,迟早会在某个假期凌晨过期。你要建立的心智是:任何有有效期的凭证(证书、密钥、Token)都需要「自动续期 + 到期告警」双保险,这套思路在后面支付证书、API 密钥轮换里会反复出现。

选择题

关于 Let's Encrypt 免费 DV 证书,下列做法正确的是?

本节小结

证书按核验分 DV(只验域名、免费分钟级)/OV(验组织)/EV(最严),按覆盖分单域/泛域(*只覆盖一级子域)/多域SAN,独立开发者用免费DV足够。Let's Encrypt 免费但90天,用 certbot 自动签发(HTTP-01放文件/DNS-01加TXT)、装定时续期、certbot renew --dry-run 验证、续期后reload并加外部到期监控。Nginx 80端口301跳HTTPS、443配 fullchain.pem+privkey.pem、只开TLS1.2/1.3、加HSTS。混合内容要求所有子资源/API全走HTTPS;iOS ATS、Android9+默认禁明文,后端应第一天就做HTTPS。证书是要自动续期+告警的流水线,凡有有效期凭证都需双保险。

资深工程师加餐

底层原理 · 大厂视角 · 工程经验,点卡片展开

把会话、上传文件、定时任务状态从应用进程里挪到 Redis、对象存储或数据库后,任何一台应用实例都能处理任何请求,扩容就是多开几个实例挂到负载均衡后面。反过来,只要状态留在某台机器的内存里,它就既无法横向扩容,也无法滚动更新(一重启用户就掉线)。面试答「如何支撑更高并发」,先讲无状态化,再谈加机器和缓存。