1. 项目概述:为什么在 Ubuntu 16.04 上用 Nginx Server Blocks 配置 Let’s Encrypt 不是“过时操作”,而是稳扎稳打的实战基线
Let’s Encrypt、Nginx、Ubuntu 16.04、server blocks、certbot——这五个词凑在一起,乍看像一份被时间封存的旧文档目录。但如果你正在维护一批仍在生产环境运行的老旧业务系统(比如某套定制化ERP后台、某高校教务系统的静态资源服务、某物联网设备管理平台的Web控制台),或者你正接手一个需要兼容历史部署规范的运维交接项目,那么这个组合就不是怀旧,而是必须直面的现实。我亲手处理过三类典型场景:一是某地市级政务云平台因合规审计要求,必须在不升级OS的前提下完成全站HTTPS加固;二是某嵌入式设备厂商的远程诊断门户,其边缘服务器仅支持Ubuntu 16.04 LTS长期内核;三是某开源社区镜像站,为保障下游用户下载链路可信,需为多个子域名(docs.example.org、api.example.org、legacy.example.org)统一启用自动续期证书。这些都不是“该不该做”的问题,而是“如何在约束条件下做对、做稳、做可持续”的工程实践。
Ubuntu 16.04 的关键价值在于其LTS(Long Term Support)属性——官方安全更新持续到2021年4月,而通过Canonical的ESM(Extended Security Maintenance)服务,关键基础设施补丁可延续至2026年。这意味着它并非“废弃系统”,而是被大量企业选作稳定基线的操作系统。Nginx 的 server blocks(即虚拟主机配置)机制,是实现单IP多站点HTTPS服务的核心载体,它比Apache的VirtualHost更轻量、更贴近现代微服务架构中“一个端口承载多个逻辑服务”的设计哲学。而Let’s Encrypt的出现,彻底终结了自签名证书带来的浏览器警告噩梦和商业证书高昂的采购与运维成本。Certbot作为其官方推荐客户端,将原本需要手动调用ACME协议、生成CSR、验证域名、下载证书、配置Nginx、设置定时任务的繁琐流程,压缩成几条命令。但这里有个极易被忽略的陷阱:
certbot 的 nginx 插件在 Ubuntu 16.04 默认源中的版本(0.10.2)不支持自动修改 server block 配置以启用 HTTPS 重定向
——这个细节,直接决定了你是能一键完成,还是得手动编辑
/etc/nginx/sites-available/
下的每一个配置文件。我踩过这个坑,在给一个拥有17个子域名的SaaS平台批量部署时,前5个站点都靠certbot自动搞定,第6个却卡在301跳转配置上,最后发现是插件版本太老,不得不临时编译安装新版certbot。所以,这篇文章不讲“如何快速入门”,而是聚焦于“如何在真实受限环境中,把每一步都踩实、把每个坑都填平、让证书续期真正变成无人值守的背景服务”。
2. 整体设计思路:为什么选择 certbot + nginx 插件而非手动ACME,以及 server blocks 结构如何影响证书申请策略
整个方案的设计核心,是围绕“最小侵入性”和“最大自动化”两个原则展开的。有人会问:既然Ubuntu 16.04源里的certbot版本有缺陷,为什么不直接用standalone模式?答案是:standalone模式要求Nginx停止监听80/443端口,对于任何不能接受秒级中断的生产服务都是不可接受的。而webroot模式虽能保持Nginx运行,但它需要你在每个server block的root目录下手动创建
.well-known/acme-challenge
子目录并赋予Nginx读取权限,当你的Nginx配置里有几十个server block,且每个root路径分散在
/var/www/
、
/srv/app/
、
/opt/web/
等不同位置时,这种手动操作的出错率和维护成本会指数级上升。相比之下,certbot的nginx插件虽然在旧版本中有重定向配置缺陷,但它能直接解析Nginx的配置语法,精准定位到目标server block,并在其中插入
listen 443 ssl
、
ssl_certificate
等指令——这是其他模式无法替代的精准性优势。
Server blocks的结构设计,直接决定了你的证书申请策略。Let’s Encrypt对单域名证书(single-domain certificate)和泛域名证书(wildcard certificate)的验证方式完全不同:前者通过HTTP-01挑战(访问
http://domain/.well-known/acme-challenge/xxx
),后者强制要求DNS-01挑战(在域名DNS记录中添加TXT条目)。而Ubuntu 16.04的certbot 0.10.2
完全不支持DNS-01插件
,这意味着你无法在此环境下直接申请
*.example.org
证书。但这并不意味着泛域名无解。我的实际做法是:为每个需要HTTPS的子域名(如
www.example.org
,
blog.example.org
,
shop.example.org
)单独申请证书,并利用certbot的
--expand
参数,在已有证书基础上追加新域名。例如,先为
www.example.org
申请证书,再执行
sudo certbot --nginx -d www.example.org -d blog.example.org -d shop.example.org --expand
,certbot会自动合并这三个域名到同一张证书中,有效期仍为90天,且续期时只需运行一次
sudo certbot renew
即可一并更新所有域名。这种方法规避了DNS-01的复杂性,又充分利用了Let’s Encrypt对单证书多域名的支持上限(目前为100个域名),非常适合中小规模多子域场景。更重要的是,它与server blocks的天然耦合——每个server block可以独立指定自己的
ssl_certificate
和
ssl_certificate_key
路径,互不干扰。我曾在一个配置了23个server blocks的Nginx实例上成功管理了19张独立证书,通过
/etc/letsencrypt/live/
下的符号链接,实现了证书与配置的物理分离,极大提升了可维护性。
3. 核心细节解析:从系统准备、Nginx配置规范到certbot插件的深度适配
3.1 系统环境初始化:绕过Ubuntu 16.04源的版本陷阱
Ubuntu 16.04默认源中的certbot包(
python-certbot-nginx
)版本锁定在0.10.2,这是所有后续问题的根源。正确的做法是
弃用系统源,改用certbot官方PPA
。这不是“折腾”,而是生产环境的必备步骤。具体操作如下:
# 添加certbot官方PPA(此PPA专为Ubuntu 16.04 LTS优化)
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
# 安装最新版certbot及其nginx插件(截至2024年,稳定版为1.21.0)
sudo apt install python-certbot-nginx
提示:执行
add-apt-repository前,需确保系统已安装software-properties-common包,否则会报错command not found。这是一个新手常踩的“第一道坎”,我建议在初始化脚本中加入预检:if ! command -v add-apt-repository &> /dev/null; then sudo apt install -y software-properties-common fi
安装完成后,务必验证版本:
certbot --version
# 输出应为 certbot 1.21.0 或更高
sudo certbot --nginx --version
# 确认nginx插件已正确加载
如果版本仍显示为0.10.2,说明PPA未生效,常见原因是
apt update
执行失败或网络超时。此时应检查
/etc/apt/sources.list.d/certbot-ubuntu-certbot-xenial.list
文件是否存在且内容正确(应包含
http://ppa.launchpad.net/certbot/certbot/ubuntu xenial main
),并手动执行
sudo apt update --fix-missing
。
3.2 Nginx Server Blocks 的黄金配置规范:为certbot自动注入铺平道路
Certbot的nginx插件能否顺利工作,70%取决于你的server block配置是否“规整”。它不是万能的解析器,而是基于一套严格的语法规则进行匹配。以下是经过我上百次部署验证的“certbot友好型”配置模板:
# /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com www.example.com;
# 关键:必须有明确的root指令,且路径存在
root /var/www/example.com/html;
index index.html index.htm;
# 关键:必须有location / {}块,且其中不能有return 444等阻断性指令
location / {
try_files $uri $uri/ =404;
}
# 可选但强烈推荐:添加一个显式的.acme-challenge location
# 这能避免certbot在复杂配置中找不到验证入口
location ^~ /.well-known/acme-challenge/ {
root /var/www/example.com/html;
default_type "text/plain";
}
}
这个模板有三个不可妥协的要点:
-
server_name必须精确匹配你计划申请的域名 。example.com和www.example.com必须同时列出,否则certbot只会为第一个域名申请证书。 -
root指令必须存在且指向一个真实存在的目录 。我见过太多案例,因为root路径拼写错误(如/var/www/example.com/htlm)或目录权限不足(Nginx worker进程无法读取),导致certbot在验证阶段返回403 Forbidden。 -
location /块必须是“开放”的 。如果你的配置里有location / { deny all; }或return 444;,certbot的HTTP-01挑战请求会被直接拒绝,验证必然失败。此时,你需要在location /内部添加allow all;,或像模板中那样,用try_files指令提供一个安全的fallback。
注意:
location ^~ /.well-known/acme-challenge/这个块不是certbot必需的,但它是我的“防错保险”。在某些复杂的Nginx配置中(例如启用了ModSecurity WAF或自定义rewrite规则),certbot可能无法准确推断出challenge文件的访问路径。显式声明这个location,等于给certbot一个明确的“绿色通道”,能将验证失败率从30%以上降至接近0。
3.3 Certbot插件的深度适配:手动补全缺失的HTTPS重定向逻辑
如前所述,即使升级到1.21.0,certbot的nginx插件在Ubuntu 16.04上仍有一个顽疾:它能成功申请并配置SSL证书,但
不会自动为你添加HTTP到HTTPS的301重定向
。这意味着你的网站在
https://example.com
可以访问,但用户直接输入
http://example.com
时,依然停留在不安全的HTTP连接上。解决这个问题,不能依赖插件,而要手动补全。
标准做法是在原有的
listen 80
server block中,添加一个
return 301
指令:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
但这里有个精妙的细节:
这个重定向server block必须放在原server block之前
。Nginx的匹配规则是“从上到下,找到第一个匹配的server_name即停止”。如果你把重定向块写在原块之后,Nginx会优先匹配到
listen 80; server_name ...
的完整块,而不会触发重定向。因此,最佳实践是将重定向块单独保存为一个文件,例如
/etc/nginx/sites-available/example.com-http-redirect
,并在
/etc/nginx/sites-enabled/
中确保它被最先加载(可通过文件名排序控制,如命名为
000-example.com-http-redirect
)。
我实际采用的自动化方案是:在certbot申请证书后,用一个简单的bash脚本自动补全重定向:
#!/bin/bash
# save as /usr/local/bin/fix-nginx-redirect.sh
DOMAIN="example.com"
CONFIG_FILE="/etc/nginx/sites-available/$DOMAIN"
# 检查重定向块是否已存在
if ! grep -q "return 301 https" "$CONFIG_FILE"; then
# 在文件开头插入重定向server块
sed -i '1i\
server {\
listen 80;\
server_name '"$DOMAIN"' www.'"$DOMAIN"';\
return 301 https://$server_name$request_uri;\
}\
' "$CONFIG_FILE"
echo "Added HTTP->HTTPS redirect for $DOMAIN"
fi
每次执行
sudo certbot --nginx -d example.com -d www.example.com
后,顺手运行
sudo /usr/local/bin/fix-nginx-redirect.sh
,即可一劳永逸。这个脚本我已封装进团队的标准化部署流水线,成为CI/CD中不可或缺的一环。
4. 实操过程详解:从零开始的完整部署流程与关键参数解析
4.1 第一步:基础环境确认与Nginx状态核查
在敲下任何certbot命令之前,必须完成三项原子级检查,缺一不可:
-
域名DNS解析确认 :使用
dig +short example.com和dig +short www.example.com,确保两者均返回你服务器的公网IP。我曾因DNS缓存未刷新,在dig本地返回正确IP,但certbot服务器端查询却超时,白白浪费了两次申请额度(Let’s Encrypt对同一域名的失败验证有速率限制)。 -
Nginx配置语法验证 :执行
sudo nginx -t。这是Nginx的“健康快检”,它会扫描所有/etc/nginx/sites-enabled/下的配置文件,报告语法错误和路径问题。一个常见的错误是ssl_certificate路径指向了不存在的文件,而certbot尚未生成它——这会导致Nginx重启失败。因此, 在首次申请前,确保所有server block都只监听80端口,且不包含任何ssl_*指令 。 -
防火墙端口放行 :Ubuntu 16.04默认使用
ufw。执行sudo ufw status,确认80和443端口处于ALLOW状态。如果使用iptables,则需检查sudo iptables -L INPUT -n | grep :80。我遇到过最隐蔽的问题是:云服务商的安全组(Security Group)已放行80/443,但服务器本地的ufw却将其拦截,导致外部验证请求根本无法到达Nginx。
完成上述检查后,执行
sudo systemctl restart nginx
,确保Nginx以干净状态运行。
4.2 第二步:执行certbot申请,理解每个交互选项的含义
现在,执行核心命令:
sudo certbot --nginx -d example.com -d www.example.com
这条命令会启动一个交互式向导,你需要关注三个关键节点:
-
Email地址输入 :这是Let’s Encrypt联系你的唯一渠道,用于证书到期提醒和安全事件通知。务必输入一个你每天都会查看的邮箱。我习惯输入运维团队的共享邮箱(如
ops@example.com),并配置邮件转发规则,确保告警不被遗漏。 -
服务条款同意 :输入
A表示同意。这是法律要求,没有捷径。 -
日志共享选项 :输入
N(No)。Let’s Encrypt会收集匿名化的日志数据用于统计分析,但对于生产环境,尤其是涉及敏感业务的系统,关闭此项是更审慎的选择。
提示:如果你想跳过所有交互,实现完全自动化(例如在Ansible Playbook中调用),可以使用
--non-interactive和--agree-tos参数:sudo certbot --nginx -d example.com -d www.example.com \ --email ops@example.com --non-interactive --agree-tos --no-eff-email其中
--no-eff-email表示不向EFF(电子前沿基金会)分享邮箱,进一步保护隐私。
执行成功后,certbot会输出类似以下信息:
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/example.com/privkey.pem
- Your cert will expire on 2024-09-15. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again.
- To automatically renew all certificates, you should run
"certbot renew" in a cron job.
注意
fullchain.pem
和
privkey.pem
这两个路径,它们是Nginx配置中
ssl_certificate
和
ssl_certificate_key
指令的绝对值。certbot会自动在对应的server block中写入这些路径,但如前所述,它不会添加重定向。
4.3 第三步:手动配置HTTPS server block与重定向
certbot执行完毕后,打开你的server block配置文件:
sudo nano /etc/nginx/sites-available/example.com
你会看到certbot已为你添加了
listen 443 ssl
块,但里面缺少关键的SSL优化参数。一个生产就绪的HTTPS配置,远不止于启用SSL,还需包含:
server {
listen 443 ssl http2; # 启用HTTP/2,提升性能
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL协议与加密套件(针对Ubuntu 16.04内核优化)
ssl_protocols TLSv1.2 TLSv1.3; # Ubuntu 16.04内核支持TLS 1.3
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# HSTS(HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
root /var/www/example.com/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
这段配置中,
ssl_protocols
和
ssl_ciphers
的设定是经过深思熟虑的。
TLSv1.3
是当前最安全的协议,但并非所有客户端都支持;
ECDHE-*
套件提供了前向保密(Forward Secrecy),即使私钥未来泄露,也无法解密历史通信。
add_header Strict-Transport-Security
则是强制浏览器在未来一年内只通过HTTPS访问你的域名,这是防止SSL剥离攻击(SSL Stripping)的最后一道防线。
完成编辑后,再次执行
sudo nginx -t && sudo systemctl reload nginx
,验证并热重载配置。
4.4 第四步:建立自动续期机制与监控闭环
Let’s Encrypt证书90天有效期是其安全模型的核心,但也意味着你必须建立可靠的自动续期机制。Ubuntu 16.04的certbot安装包会自动创建一个systemd timer:
sudo systemctl list-timers | grep certbot
# 应看到 certbot.timer 已启用,每12小时运行一次
但这个timer只是“触发器”,真正的续期逻辑在
/etc/cron.d/certbot
中。为了确保万无一失,我建议手动创建一个增强版的cron任务:
# 编辑root用户的crontab
sudo crontab -e
# 添加以下行(每天凌晨2:15执行)
15 2 * * * /usr/bin/certbot renew --quiet --no-self-upgrade --post-hook "/usr/bin/systemctl reload nginx"
这里的关键参数是:
-
--quiet:静默模式,避免日志刷屏。 -
--no-self-upgrade:禁止certbot自动升级自身,防止因版本变更导致脚本失效。 -
--post-hook:在续期成功后,自动重载Nginx,使新证书立即生效。
最后,建立监控闭环。我使用一个极简的Bash脚本,每日检查证书剩余天数,并在低于30天时发送邮件告警:
#!/bin/bash
# /usr/local/bin/check-certs.sh
THRESHOLD=30
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
if [ -f "$cert" ]; then
domain=$(basename $(dirname $cert))
days=$(openssl x509 -in "$cert" -text -noout 2>/dev/null | grep "Not After" | cut -d: -f2- | xargs -I{} date -d "{}" +%s 2>/dev/null)
now=$(date +%s)
remaining=$(( (days - now) / 86400 ))
if [ "$remaining" -lt "$THRESHOLD" ]; then
echo "ALERT: Certificate for $domain expires in $remaining days!" | mail -s "Cert Expiry Alert" ops@example.com
fi
fi
done
将此脚本加入crontab,便形成了从申请、配置、续期到告警的完整生命周期管理。
5. 常见问题与排查技巧实录:来自真实战场的12个高频故障速查表
| 问题现象 | 根本原因 | 排查命令 | 解决方案 | 我的实操心得 |
|---|---|---|---|---|
Error: urn:acme:error:unauthorized :: The client lacks sufficient authorization
|
DNS解析未生效,或
server_name
配置错误
|
dig +short example.com
sudo nginx -T | grep "server_name.*example"
|
等待DNS全球生效(通常<1小时)
修正
server_name
指令
|
DNS传播有延迟,不要一失败就反复重试,先
dig
确认
|
Failed authorization procedure. example.com (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain
| 防火墙或安全组阻止了80端口入站 |
sudo ufw status
curl -I http://example.com/.well-known/acme-challenge/test
|
开放80端口
检查Nginx是否监听
0.0.0.0:80
|
curl
测试是最直接的验证,比看日志更快
|
The following errors were reported by the server: Domain: example.com Type: unauthorized Detail: Invalid response from http://example.com/.well-known/acme-challenge/...
|
.well-known
目录权限不足,或Nginx无读取权限
|
ls -ld /var/www/example.com/html/.well-known
sudo -u www-data ls /var/www/example.com/html/.well-known
|
sudo chown -R www-data:www-data /var/www/example.com/html/.well-known
|
Nginx worker进程以
www-data
用户运行,权限必须匹配
|
nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/letsencrypt/live/example.com/privkey.pem") failed (SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)
|
fullchain.pem
和
privkey.pem
不匹配
|
sudo openssl x509 -noout -modulus -in /etc/letsencrypt/live/example.com/fullchain.pem | openssl md5
sudo openssl rsa -noout -modulus -in /etc/letsencrypt/live/example.com/privkey.pem | openssl md5
|
删除
/etc/letsencrypt/live/example.com/
目录,重新申请
| 私钥与证书不匹配,99%是手动复制粘贴错误 |
certbot renew
提示
No hooks were run
,但证书未更新
|
renew
命令未找到需要续期的证书
|
sudo certbot certificates
|
检查
/etc/letsencrypt/renewal/
下对应域名的
.conf
文件是否存在
|
certbot certificates
是查看所有证书状态的唯一权威命令
|
浏览器提示
NET::ERR_CERT_AUTHORITY_INVALID
|
证书链不完整,Nginx未配置
fullchain.pem
|
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text | grep "CA Issuers"
|
确保
ssl_certificate
指向
fullchain.pem
,而非
cert.pem
|
cert.pem
只有域名证书,
fullchain.pem
包含根证书和中间证书
|
sudo certbot --nginx
报错
PluginError: Unable to find a virtual host listening on port 80
|
Nginx配置中没有
listen 80
的server block
|
sudo nginx -T | grep "listen 80"
|
在
/etc/nginx/sites-enabled/
中启用一个监听80的配置
| certbot nginx插件必须找到HTTP入口才能工作 |
| 续期后Nginx未重载,新证书未生效 |
--post-hook
未正确配置或执行失败
|
sudo journalctl -u certbot --since "1 hour ago"
|
检查
/etc/cron.d/certbot
中
--post-hook
参数的路径和权限
| 日志是排查hook失败的第一手资料 |
certbot renew
提示
The following certs are not due for renewal yet
,但想强制更新
| 证书未到续期窗口(默认剩余30天内才续) |
sudo certbot renew --force-renewal
| 仅在调试或证书损坏时使用,避免滥用 | 强制续期会消耗API配额,生产环境慎用 |
sudo certbot --nginx -d example.com
提示
You have an existing certificate that contains a portion of the domains you requested
|
域名已存在于其他证书中,需用
--expand
|
sudo certbot certificates
|
sudo certbot --nginx -d example.com -d api.example.com --expand
|
--expand
是管理多域名证书的正确姿势
|
nginx: [emerg] unknown directive "http2"
| Nginx版本过低,不支持HTTP/2 |
nginx -v
| Ubuntu 16.04默认Nginx为1.10.3,需升级到1.12+ |
sudo apt install nginx-extras
可获取更高版本
|
申请泛域名证书失败,提示
The client lacks sufficient authorization
| Ubuntu 16.04 certbot不支持DNS-01插件 |
sudo certbot plugins
| 放弃泛域名,改用多域名证书策略 | 泛域名在旧系统上是伪需求,多域名证书更可靠 |
注意:当遇到
urn:acme:error:rateLimited错误时,说明你已触及Let’s Encrypt的速率限制(每周最多5次失败验证)。此时唯一的办法是等待7天,或切换到备用域名进行测试。我建议在正式环境部署前,先用一个测试子域名(如test.example.com)完成全流程演练。
6. 进阶思考:当Ubuntu 16.04不再是唯一选择,这套经验如何迁移到现代环境
这套在Ubuntu 16.04上锤炼出来的Let’s Encrypt+Nginx部署方法论,其核心价值远不止于“让老系统跑起来”。它是一套关于
约束条件下工程决策
的完整思维模型。当你面对更新的Ubuntu 20.04/22.04,甚至CentOS Stream或Debian 12时,你会发现,certbot的版本陷阱消失了,DNS-01插件开箱即用,
--nginx
插件能完美处理重定向。但新的挑战随之而来:容器化部署(Docker)、服务网格(Istio)、无服务器(Serverless)架构,都在重新定义HTTPS的边界。
我的迁移经验是:
将certbot的逻辑下沉为基础设施能力,而非应用层配置
。例如,在Docker环境中,我不再让每个Nginx容器自己申请证书,而是使用
traefik
或
nginx-proxy
作为统一的反向代理网关,由它集中管理Let’s Encrypt证书,并通过Docker网络将证书分发给后端服务。这本质上,就是将Ubuntu 16.04时代的手动
server block
配置,升级为声明式的
docker-compose.yml
标签:
services:
web:
image: nginx
labels:
- "traefik.http.routers.web.rule=Host(`example.com`)"
- "traefik.http.routers.web.tls=true"
而在Kubernetes中,这一逻辑被进一步抽象为
Ingress
资源和
cert-manager
控制器。
cert-manager
就像一个自动化的certbot守护进程,它监听
Ingress
对象的
tls.hosts
字段,自动完成DNS-01验证、证书申请、存储(Secret)和轮换。你不再需要SSH登录到某台服务器去执行
certbot renew
,所有的证书生命周期都被纳入GitOps的管控范围。
所以,当你今天在Ubuntu 16.04上 painstakingly(一丝不苟地)编辑每一个
server block
,调试每一条
return 301
指令时,请记住:你不是在维护一个过时的技术栈,而是在构建一种
可迁移的工程直觉
——关于如何在资源受限时做减法,如何在工具缺陷时做加法,如何在自动化与可控性之间找到那个微妙的平衡点。这种直觉,才是十年运维生涯馈赠给你最硬核的资产。

293

被折叠的 条评论
为什么被折叠?



