这一阵子连着帮朋友处理了不少Nginx配置SSL证书的事,发现大家最容易卡住的点反而不在证书生成,而在“让浏览器信任证书”这一步。证书文件不就两个文件嘛,配上不就行了?实际搞起来你会发现,自签名证书、免费证书、证书链、中间证书、SAN扩展,每一环都可能让你在浏览器里看到一串看不懂的报错。这篇文章就把我在Nginx上生成SSL证书、配置HTTPS、最终让浏览器信任证书的完整流程讲清楚。从自签名到Let's Encrypt免费证书,从配置文件到信任库导入,从续期到排错,个人博客、小程序后端、企业测试环境都能直接照着做。
1. 先搞懂Nginx和SSL证书的配合逻辑
1.1 没有SSL证书时,请求到底在裸奔什么
很多人觉得HTTP和HTTPS的区别就是“多了个S”,但实际差距非常大。HTTP请求是明文传输,你的账号、密码、Cookie、表单提交内容,在传输链路上任何一个能抓到包的人都能直接看到。尤其现在WiFi环境复杂,公共网络里抓包门槛很低,开着Wireshark就能看到隔壁请求里的明文内容。HTTPS就是在HTTP外面包了一层TLS加密,让数据在传输过程中变成密文,即使被截获也无法直接解读。
Nginx在这套体系里的角色,是TLS握手时的“服务端主角”。当浏览器访问https://example.com时,Nginx需要把自己的证书和公钥发给浏览器,双方协商出一个对称加密密钥,之后的HTTP数据都使用这个密钥加密传输。没有证书,Nginx就没办法完成这套握手,浏览器自然也不会继续发请求。所以配置SSL证书并不是“为了合规”或“为了绿锁”,而是让数据从客户端到服务器这段路真正安全下来的前提。
1.2 TLS握手流程:Nginx只需要做好两件事
TLS握手完整流程比较长,但站在Nginx配置的角度,你只需要理解两个关键动作。
第一个动作,是Nginx向浏览器出示证书。这个证书里包含了域名信息、公钥、有效期、签发者等信息。第二个动作,是浏览器验证证书是否可信。浏览器收到证书后,会检查证书是不是由自己信任的根证书颁发机构签发的,域名是否匹配,证书是否过期,是否被吊销。如果都通过,浏览器才会继续后续的密钥协商。
所以“让浏览器信任证书”的本质,不是Nginx能控制的,而是取决于“证书链是否到达浏览器信任的根”。Nginx的职责只是把正确的证书文件(一般是一份fullchain.pem)完整地传给浏览器。如果你给它配置的证书链不完整,或者用了一个自签名证书但没导入信任库,那无论Nginx配置多完美,浏览器照样给你大红色警告。理解这一点之后,很多配置问题其实都能自己推出来了。
1.3 证书类型怎么选:自签名、免费DV、商业OV/EV
做技术选型前,先把三类证书的差异搞清楚。下面这个表格是我自己整理的,基本覆盖了常见场景。
| 证书类型 | 颁发对象 | 浏览器默认信任 | 成本 | 申请耗时 | 适合场景 |
|---|---|---|---|---|---|
| 自签名证书 | 自己给自己签发 | 不信任,需要手动导入 | 0 | 几分钟 | 本地开发、内网测试、临时环境 |
| 免费DV证书 | CA机构验证域名所有权 | 信任 | 0 | 几分钟到几小时 | 个人博客、中小站点、API服务 |
| 商业OV/EV证书 | CA机构验证企业身份 | 信任 | 每年几百到几千元 | 1-5个工作日 | 企业官网、电商、金融类站点 |
自签名证书不是不能用,但请务必把它限制在“你自己可控客户端”的环境里。我在内网测试环境用自签名证书用了很久,只要把所有客户端系统信任库导入一次,访问效果和正式证书几乎没有区别。生产环境我强烈建议直接用Let's Encrypt这类免费DV证书,自动续期做好之后,比商业证书省心得多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 生成SSL证书:自签名与ACME免费证书的完整实操
2.1 用OpenSSL生成自签名证书,注意SAN扩展
自签名证书的生成命令看起来很简单,但有个大坑:现代浏览器早就忽略了证书里的CN(Common Name)字段,不再把它作为域名校验依据,而是必须看subjectAltName(SAN)扩展。如果你只用一个简单的openssl req -x509 -nodes -days 365 -keyout key.pem -out cert.pem -subj "/CN=example.com"命令生成证书,Chrome和Firefox大概率会报“证书名称不匹配”或者“NET::ERR_CERT_COMMON_NAME_INVALID”。
正确的做法是准备一个带SAN扩展的配置文件。下面是我常用的方式,先创建一个目录保存证书文件:
bash复制mkdir -p /etc/nginx/ssl && cd /etc/nginx/ssl
然后生成私钥和CSR(证书签名请求):
bash复制openssl genrsa -out example.com.key 2048
cat > san.cnf <<'EOF'
[req]
distinguished_name = dn
req_extensions = v3_req
prompt = no
[dn]
C = CN
ST = Beijing
L = Beijing
O = Example Inc
CN = example.com
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
IP.1 = 192.168.1.10
EOF
openssl req -new -key example.com.key -out example.com.csr -config san.cnf
这里关键在[alt_names]段,你打算用哪个域名访问,就必须把哪个域名或IP加进去。IP地址要用IP.1这种格式,域名用DNS.1。然后基于CSR生成自签名证书:
bash复制openssl x509 -req -days 365 -in example.com.csr -signkey example.com.key -out example.com.crt -extensions v3_req -extfile san.cnf
生成完一定要验证一下SAN是否正确:
bash复制openssl x509 -text -noout -in example.com.crt | grep -A 2 "Subject Alternative Name"
看到DNS:example.com, DNS:www.example.com, IP Address:192.168.1.10之类的内容才算成功。自签名证书的私钥我建议用2048位即可,如果机器性能很好且安全要求高,也可以上4096位,但TLS握手阶段RSA密钥越长,CPU开销会随之增加,性能敏感场景要权衡。
2.2 申请Let's Encrypt免费证书:certbot一键搞定
自签名证书最大的问题是无法被外部用户直接信任,生产环境我更推荐Let's Encrypt免费证书。用certbot这个工具,安装配置都非常顺畅。
在Debian/Ubuntu上,先安装certbot和Nginx插件:
bash复制apt update
apt install -y certbot python3-certbot-nginx
然后执行:
bash复制certbot --nginx -d example.com -d www.example.com
这个过程会自动完成域名所有权验证、申请证书、修改Nginx配置、重载服务。如果你不想让certbot擅自改Nginx配置,可以用certonly模式只拿证书:
bash复制certbot certonly --nginx -d example.com -d www.example.com
生成的证书文件在/etc/letsencrypt/live/example.com/目录下。最重要的是fullchain.pem和privkey.pem,前者是完整证书链,后者是私钥。Nginx配置里直接引用这两个路径就行。Let's Encrypt证书有效期是90天,后面第5章我会专门讲自动续期。
除了Let's Encrypt,国内云厂商比如阿里云也有免费证书。流程一般是:控制台申请证书、补全域名信息、做DNS解析验证、审核通过后下载Nginx版本压缩包,解压得到.pem和.key文件,再上传到服务器。差别在于需要手动操作,到期后还要重新申请,自动化程度不如certbot。
2.3 生成证书时的关键参数:密钥长度、哈希算法、有效期
密钥长度直接影响安全性。RSA 2048位目前仍然是主流,绝大多数CA签发的默认密钥都是2048位。4096位安全性更高,但握手时RSA密钥交换的CPU消耗会明显增加,高并发站点不建议盲目上4096。如果你是个人项目,2048位完全够用。
哈希算法这个问题容易被忽略,但正是热词里说的CVE-2005-4900弱哈希算法漏洞。多年前的SHA-1签名算法已经被证明不安全,浏览器也早已不再信任SHA-1签名的证书。如果你手上的证书还是SHA-1,浏览器会报安全错误。解决办法不是改Nginx配置,而是重新生成证书,并用SHA-256签名。自签名命令默认使用SHA-256,但如果你用某些老旧工具或复制了老配置,最好在openssl x509命令里显式加-sha256参数:
bash复制openssl x509 -req -days 365 -in example.com.csr -signkey example.com.key -out example.com.crt -sha256 -extensions v3_req -extfile san.cnf
有效期方面,自签名证书我一般给365天,最长不要超过两年。Let's Encrypt证书固定是90天,到期前30天内可以续期。
3. Nginx配置SSL证书:从最小配置到加固实践
3.1 最小可用的HTTPS server块
证书拿到手,接下来就是Nginx配置。先给一个最小可用的配置,这里假设证书文件放在/etc/nginx/ssl/:
nginx复制server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
root /var/www/html;
index index.html;
}
注意listen 443 ssl这个写法,在老版本Nginx里经常看到ssl on;,但新版本已经废弃了ssl on,没必要再写。保存配置后,先做语法检查:
bash复制nginx -t
如果输出syntax is ok和test is successful,就可以重载Nginx:
bash复制systemctl reload nginx
然后访问https://example.com,如果能出现页面,说明基础配置已经通了。如果用的是自签名证书,浏览器会警告,你需要在客户端信任证书,这块第4章细说。
3.2 加固SSL配置:协议、加密套件、会话缓存
一个只能跑HTTPS的配置不算完整,还要考虑安全性。我整理了一套适合绝大多数站点的SSL加固配置:
nginx复制server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
}
这里解释几个关键点。ssl_protocols限制了只允许TLS1.2和TLS1.3,TLS1.0和TLS1.1都太老,存在已知漏洞,不建议开启。ssl_ciphers列出的是目前安全性较好的GCM套件,ssl_prefer_server_ciphers off让客户端优先选择自己的加密套件,兼容性更好。会话缓存能减少TLS握手的重复计算,同时在线用户量大的站点能明显降低CPU开销。
ssl_stapling开启OCSP装订,可以让Nginx在握手时直接把证书的在线吊销状态发给浏览器,省去浏览器再去CA查一次。不过需要Nginx能访问外网的OCSP服务器,内网环境如果DNS解析不了,建议先关掉,否则可能引发握手变慢。resolver是用于解析OCSP服务器地址的,我习惯用公共DNS,你也可以换成自己网络环境里可达的DNS。
3.3 HTTP自动跳转HTTPS和HSTS配置
证书配置好之后,最好让所有HTTP访问都自动跳到HTTPS。最简单的方式是单独写一个80端口的server块:
nginx复制server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
这里我特意用$server_name而不是$host。很多教程里用$host,但$host取的是请求头里的Host字段,如果用户或攻击者伪造Host头,跳转后的URL可能被带到意外位置。用$server_name则固定使用你配置里的域名,更安全。
如果你希望浏览器强制使用HTTPS,还可以加HSTS头:
nginx复制add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
max-age=31536000表示一年内该域名只能用HTTPS访问,includeSubDomains意思是对所有子域名同样生效。注意HSTS一旦下发,浏览器会记住,如果你以后要临时走HTTP调试,就得先清除浏览器状态或者减小max-age,否则会造成调试障碍。测试环境慎用大max-age。
3.4 反向代理场景下的SSL配置
Nginx大量被用作反向代理,比如前端页面和后端API分离的场景。这种情况下,浏览器和Nginx之间走HTTPS,Nginx和后端服务之间通常走HTTP就足够了。配置大概是:
nginx复制server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/api.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
X-Forwarded-Proto $scheme很重要,后端程序需要知道客户端请求是HTTP还是HTTPS,才能正确生成回调地址或做安全判断。如果你漏掉这个头,很多框架会误以为请求是HTTP,导致混合内容或回调地址错误。
如果后端服务也要求HTTPS,比如后端是另一个开启了证书的服务,那么proxy_pass里要写https://,并且可能需要额外处理证书校验。实际项目中,Nginx到后端走内网HTTP是最常见的做法,也能减少一层TLS加解密开销。
3.5 配置完的验证方法
配置完成后,不要急着说“好了”,一定要做几个简单验证。首先是nginx -t这个前面提过。然后是用curl检查首页状态:
bash复制curl -vI https://example.com
重点看SSL握手有没有成功,证书是否有效,比如输出里会有SSL connection using TLSv1.3和证书信息。如果想看证书链是否完整,可以借助openssl:
bash复制openssl s_client -connect example.com:443 -servername example.com -showcerts
这条命令会输出服务器返回的完整证书链。如果只有一张证书、缺少中间证书,浏览器就会报“证书链不完整”。看到输出的证书链包含至少两三层证书,才算完整。
4. 让浏览器信任证书:自签名导入与证书链原理
4.1 为什么自签名证书浏览器就是不认
这一点很多新手会困惑:我明明在Nginx里配好了证书,用手机浏览器访问为什么还是大红屏?原因很简单,浏览器内置了一个“受信任的根证书颁发机构”列表,你的自签名证书是“自己给自己签发的”,不在这个列表里。浏览器无法通过任何它信任的根来验证这张证书,于是只能红牌警告。
打个比方,你自己写了一张身份证,然后拿着它去过安检,安检当然不会认。除非安检系统里提前录入了你的“签发机构信息”,把你这个签发机构加入白名单,你写的那张“身份证”才有效。所以让浏览器信任自签名证书,本质就是把自己这个“CA”加到浏览器的信任库里。
4.2 自签名证书导入信任库的多种姿势
自签名证书的导入,不同系统做法不一样。我先讲常用的浏览器导入方式:直接访问https://你的域名或IP,浏览器会出现警告页。Chrome里点“高级”->“继续前往”,地址栏旁边会出现“不安全”,再点“证书无效”之类的入口,选择导入证书。这种导入只对当前浏览器生效,换一台机器又要重新导。
更规范的做法是导入操作系统信任库。Linux下可以这样:
bash复制cp example.com.crt /usr/local/share/ca-certificates/example.com.crt
update-ca-certificates
macOS是双击证书文件,在“钥匙串访问”里把证书设为“始终信任”。Windows则可以用certmgr.msc打开证书管理器,导入到“受信任的根证书颁发机构”。导入之后,同一台机器上的Chrome、Edge、Firefox(如果使用系统信任库)就都会信任。
这里有个我踩过好几次的坑:如果你用的是IP地址访问,比如https://192.168.1.10,那么生成证书时必须包含IP.1 = 192.168.1.10这个SAN条目,否则即使你导入了信任库,浏览器依然会报“证书名称不匹配”。证书导入只解决了“是否受信任”,域名/IP匹配是另外一道独立校验。
4.3 免费证书“自动被信任”的真相:证书链完整
Let's Encrypt证书之所以不需要手动导入,是因为它的根证书ISRG Root X1早已被主流浏览器和操作系统信任。但这里有个隐藏环节:服务器发给浏览器的常常不是“根证书直接签发”的叶证书,而是由中间证书签发的。中间证书的签发者最终指向根证书。
浏览器验证流程可以简化为:叶证书 -> 中间证书 -> 根证书 -> 内置信任库。如果Nginx只配置了叶证书,没有把中间证书一并返还给浏览器,浏览器在信任链中间断掉了,就会报NET::ERR_CERT_AUTHORITY_INVALID。
为什么很多人用certbot申请后配置的路径是fullchain.pem而不是cert.pem?因为fullchain.pem里面不仅包含叶证书,还包含中间证书,是一个完整链。你手动用阿里云等厂商证书时,下载的压缩包里通常也有一个类似fullchain.pem的文件,如果只有单个.pem,也要确认里面是否包含中间证书内容。可以用这段命令查看证书文件里包含几段证书:
bash复制grep -c "BEGIN CERTIFICATE" /path/to/fullchain.pem
正常完整链至少是2(叶证书+中间证书),如果只有1,说明只是单张证书,大概率浏览器不认。
4.4 内网多个服务统一信任:自建内部CA
如果你公司内网有多台服务器都要用HTTPS,逐台导入自签名证书太痛苦。更好的方案是自建一个内部根CA,用这个CA给每台服务器签发证书,然后只把根CA证书导入所有员工电脑的信任库。之后任何由这个CA签发的服务器证书都会被自动信任。
具体操作可以在任意一台内网Linux服务器上,用openssl创建根CA私钥和自签名根证书,再用这个根证书去签各个服务器的CSR。这个方案搭建一次,后续新增机器只需要生成CSR并签发,非常值得一做。不过内部CA的安全性要特别重视,根CA私钥泄漏等于整个内网HTTPS防线崩溃,建议离线保存或者加上强密码保护。
5. 证书续期、更新与Nginx服务维护
5.1 Let's Encrypt自动续期配置
Let's Encrypt证书只有90天有效期,手动续期不现实,必须做成自动化。certbot自带续期命令,先手动模拟执行一次:
bash复制certbot renew --dry-run
如果输出没有报错,说明续期流程可以正常走通。然后添加一个cron定时任务,每天凌晨跑一次续期检查。只有到期前30天才会真正续期,所以不用担心浪费。
cron复制0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
--post-hook在续期成功后会执行,这里用来重载Nginx。需要注意,重载和重启不一样,重载不会中断现有连接,对在线业务影响极小。如果你用的不是certbot改过的Nginx配置,而是自己维护配置,建议在续期后确认Nginx还能正常启动:
bash复制nginx -t
systemctl reload nginx
5.2 云厂商免费证书的“续期”实际上是重新申请
阿里云这类平台目前提供的免费证书有效期一般是3个月或1年。很多人在控制台点“续期”发现并不是直接延期,而是要重新申请、重新验证域名、重新下载证书文件,再替换到服务器上。本质是“重新签发”,不是“延长有效期”。
我常用的做法是用脚本半自动化处理:下载新证书后,SCP上传到服务器,替换/etc/nginx/ssl/下的对应文件,然后执行nginx -t && systemctl reload nginx。由于证书文件内容变了,直接覆盖即可。替换前最好备份旧证书,万一新证书有问题可以立即回滚。
5.3 借着证书维护顺便平滑升级Nginx
有时候证书没问题,但Nginx版本太老,不支持TLS1.3或者HTTP/2,需要升级。很多人不敢在生产环境升级Nginx,主要是怕影响在线请求。Nginx本身支持平滑升级,原理是启动新版本master进程,和旧master并存,然后逐步把旧worker进程退出。
简单流程是编译或准备好新版Nginx二进制文件后,先备份旧二进制,然后向旧master发送USR2信号启动新master,再发送WINCH信号让旧worker停止接受新连接,然后发送QUIT关闭旧master。实际操作中,很多发行版用apt upgrade nginx替换二进制后,再执行systemctl reload nginx就能实现平滑过渡。如果版本升级跨度很大,建议先在测试环境验证新版本的配置兼容性,特别是SSL配置指令有没有变化。
证书更新和Nginx升级可以同时进行:先把新版本Nginx二进制准备好,完成平滑升级后,再重新加载证书或执行续期脚本,这样可以减少一次服务重载窗口。不过这个操作需要谨慎,步骤较多,如果没有把握,建议分两步走。
6. 常见问题与排查急救包
6.1 高频报错对照表
我把实际中遇到最多的几类问题和解决办法整理成了一张速查表,方便大家直接对照。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 浏览器提示证书不受信任/警告 | 自签名证书未导入信任库 | 在客户端导入根证书,或使用受信任CA签发的证书 |
| 浏览器提示证书链不完整 | 只配置了叶证书,缺少中间证书 | 使用fullchain.pem,或在证书文件中追加中间证书 |
| 浏览器提示证书名称不匹配 | 证书SAN缺少当前访问域名或IP | 重新生成带有正确SAN扩展的证书 |
nginx -t报错找不到证书文件 |
证书路径写错或文件不在该路径 | 检查ssl_certificate和ssl_certificate_key路径 |
| 访问HTTPS返回ERR_SSL_PROTOCOL_ERROR | TLS协议版本或加密套件不兼容 | 开启TLSv1.2/TLSv1.3,检查ssl_ciphers |
| 浏览器提示证书使用了弱签名算法 | 证书使用SHA-1签名 | 重新生成使用SHA-256签名的证书 |
| HTTPS页面加载但部分资源不加载 | 页面里仍引用了HTTP资源 | 检查混合内容,统一替换为HTTPS或使用相对路径 |
6.2 排查工具与英文报错解读
遇到SSL问题,第一反应不是去翻日志,而是先用工具看证书链。openssl s_client是最常用的诊断命令,前面已经用过。它输出里的关键字段可以帮助定位问题:
subject:证书属于哪个域名。issuer:证书由谁签发。verify return code:如果返回是ok说明验证通过,如果返回self-signed certificate说明是自签名,如果返回unable to get local issuer certificate说明证书链不完整。
Nginx错误日志一般在/var/log/nginx/error.log,排查时看这里比看浏览器报错更直接。比如常见的no ssl_certificate is defined,就是配置文件里没找到证书;ssl_stapling相关的报错通常会提示OCSP连接失败,这时候可以先把ssl_stapling关掉再测试。
6.3 我最想强调的四个避坑习惯
第一个习惯是证书文件权限。私钥文件必须严格控制权限,否则Nginx会拒绝启动或者告警。建议设置成chmod 600 privkey.pem,让只有root和Nginx worker能读。我之前遇到过权限过宽导致Nginx报Permissions too open的问题,非常尴尬。
第二个习惯是修改Nginx配置前先备份。养成cp nginx.conf nginx.conf.bak的习惯,或者直接用git管理/etc/nginx/整个目录。我自己的服务器上,nginx -t不过绝不reload,改坏了随时回滚,这个习惯帮我避免了至少三次线上事故。
第三个习惯是证书文件路径不要随便挪。很多人在临时目录生成证书,然后Nginx配置指向临时路径,结果一清临时文件网站就崩。把证书统一放到/etc/nginx/ssl/或/etc/letsencrypt/live/下,路径固定,维护起来省心。
第四个习惯是不要忽视浏览器更新后的新规则。现代浏览器对证书的要求越来越严格,SAN缺失、SHA-1、有效期超过两年的证书都会逐步被限制。很多以前能用的自签名证书,现在用最新浏览器访问已经直接被拒绝。如果你的测试环境突然出现“之前能用现在不能用”,先检查证书是否符合新规范,而不是急着怀疑Nginx配置。
6.4 自签名证书在防火墙和客户端时间不同步时的坑
还有一个容易被忽略的隐形问题:客户端系统时间和服务器时间不同步。证书验证时,浏览器会检查证书的生效时间和过期时间。如果你自签名一个刚生成的证书,但客户端电脑时间快了半小时,就会报“证书尚未生效”或“证书过期”。别在这种问题上浪费时间,先校准时间再排查。同理,如果服务器时间在续期后和实际时间偏差过大,也会影响新证书的正常使用。
我在实际测试中遇到过一次很刁钻的情况:内网服务器用了自签名证书,所有手机浏览器都报错,但电脑浏览器正常。后来发现是手机系统根本没有导入证书。移动端导入根证书比桌面端麻烦一些,Android和iOS路径都不一样,所以如果你要大批量测试,建议直接部署内部CA,而不是逐台手机导入自签名证书。
结尾的一点个人体会
前前后后折腾过这么多套Nginx SSL证书配置,我最大的感受是:证书生成和Nginx配置只占很小一部分精力,真正的运维难点在证书链完整性和信任体系的搭建。测试环境用自签名证书导入信任库,开发调试很舒服,但别把它直接搬到生产环境;生产环境早点上Let's Encrypt自动续期,你的证书维护成本会低到一个令人安心的程度。
最后再分享一个小技巧:把证书申请、上传、替换、重载的流程尽量脚本化。哪怕你只是手动执行,也要把命令记到自己的笔记里,下次照着来就行。这套流程一旦运转起来,就不再是“配置SSL证书”这种一次性操作,而是一种可持续的、不用焦虑到期日期的工程习惯。
