原文由 Canonical / Ubuntu Server documentation contributors 编写:Obtain TLS certificates。本文为中文整理译文,依据 2026-10-05 读取版本,原页面显示最后更新于 2026-06-26;这不是首次发表日期。
TLS 证书用来验证服务器身份,并配合私钥建立加密连接。面向互联网的服务通常选择公开受信任的证书颁发机构,例如 Let’s Encrypt;内部网络或隔离环境也可以由自己管理 CA,为服务签发证书,但必须把 CA 证书加入每个客户端的信任链。

用 Let’s Encrypt 获取证书
Let’s Encrypt 由 Internet Security Research Group(ISRG)运营,通过 ACME 协议自动签发证书。原文描述的是 90 天有效期及自动续期机制;证书生命周期政策会变化,应以实际签发结果和当前 CA 文档为准,不能在运维系统里把原文天数写死。
原文 HTTP-01 流程要求先有域名,并让 DNS 记录指向服务器。签发和续期时,CA 必须能够从互联网访问该域名的 TCP 80 端口,防火墙、负载均衡和应用路由都需要放行对应的验证请求。
Ubuntu 文档推荐使用 Certbot 作为 ACME 客户端,通过 snap 安装:
sudo snap install --classic certbot
这条命令会安装具有 classic 权限的系统软件,后面的 Certbot 命令也会以管理员权限读写证书和服务配置。以下域名均为示例,需要替换成自己控制的域名。本次没有在任何服务器上执行这些操作。
选择与现有服务匹配的模式
已经运行 nginx 时,插件会寻找与域名匹配的 server block,通常位于 /etc/nginx/sites-enabled/,原地添加 TLS 指令并重新加载服务:
sudo certbot --nginx -d example.com -d www.example.com
Apache 插件会类似地寻找匹配的 VirtualHost,通常位于 /etc/apache2/sites-enabled/,修改配置并 reload:
sudo certbot --apache -d example.com -d www.example.com
这两种模式不仅申请证书,也会修改 Web 服务配置。实际操作前应保存配置副本,并确认使用的域名、虚拟主机和服务重载方式。
没有 Web 服务器时,可以使用 standalone 模式。Certbot 会临时监听 80 端口完成验证,因此同一端口不能已经被其他服务占用:
sudo certbot certonly --standalone -d example.com -d www.example.com
如需停掉现有服务,必须考虑停机窗口和续期时同样的端口条件。不要为了申请证书盲目停止生产服务。
已经有 Web 服务器,又希望自行管理 TLS 配置时,可以选择 webroot 模式。把 -w 指向该站点实际提供的文档根目录:
sudo certbot certonly --webroot -w /var/www/html -d example.com
这里的目录必须确实通过目标域名可访问;路由、重定向或认证规则不能挡住 ACME 验证文件。certonly 只负责获取证书,不替你完成服务接入。
每个 -d 增加一个 Subject Alternative Name(SAN)。需要扩展已有证书覆盖的域名时,应一次列出希望保留的旧域名与新增域名,并核对 Certbot 选择的证书:
sudo certbot --nginx -d example.com -d www.example.com -d mail.example.com
80 端口不可达,或需要通配符证书
上述示例采用 HTTP-01。无法开放 80 端口,或需要 *.example.com 通配符证书时,可以使用 DNS-01:在 DNS 中发布指定 TXT 记录供 CA 验证,不要求证书服务器开放入站端口。Certbot 为常见 DNS 服务商提供插件。
DNS 自动化所用凭据应限制到必要区域和记录操作,并避免写进公开配置或日志。内网服务器可以借助 DNS 验证域名控制权,但完全隔离的环境仍需要能与外部 CA 通信的受控代理或集中签发节点;“无入站端口要求”不等于“不需要任何外部连接”。
原文还提到 ACME 代理(如 step-ca)与集中运行的 acme.sh、lego。大规模主机可以集中签发、分发证书;需要自建信任体系时,也可以用内部 CA。代理或集中管理不会自动免除域名验证与客户端信任要求。
找到证书文件并接入服务
成功签发后,Certbot 通常把活动文件放在 /etc/letsencrypt/live/<domain>/:
| 文件 | 内容 |
|---|---|
fullchain.pem |
服务器证书和中间证书,多数服务应使用这一完整链。 |
privkey.pem |
服务器私钥,必须限制读取权限。 |
cert.pem |
仅服务器证书。 |
chain.pem |
仅中间证书。 |
nginx 中可以这样引用:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
不要为了让服务“读得到”就把私钥设为所有用户可读,也不要把 privkey.pem 放进 Web 根目录、代码仓库或共享备份。
自动续期与服务重载
原文 snap 安装方式会配置 systemd 定时器,每天尝试续期两次。可以查看定时器:
sudo systemctl status snap.certbot.renew.timer
原文还给出续期演练命令:
sudo certbot renew --dry-run
编辑校注:--dry-run 不会把正式证书替换成新签发的正式证书,但它仍会联系测试 ACME 服务、进行域名验证,并可能触发配置中的相关钩子或临时配置处理。不要把它理解为绝对无网络、无服务影响的纯只读检查。本次没有执行该命令。
通过 nginx 或 Apache 插件配置的服务,会在成功续期后由插件处理 reload。其他服务可能需要 deploy hook。原文要求创建 /etc/letsencrypt/renewal-hooks/deploy/reload-service.sh,其中的服务名需换成实际服务:
#!/bin/sh
systemctl reload <your-service>
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-service.sh
<your-service> 是说明用的占位参数,不能原样执行。应先确认服务支持 reload,并保证脚本及其父目录只能由可信管理员修改;这个钩子会在证书流程中以高权限运行。
为内部网络建立手动 CA
当多个内部服务都需要证书时,由一个内部 CA 统一签名通常比管理许多互不相关的自签名服务证书更方便。客户端仍必须信任这个 CA,Ubuntu 上的系统信任安装方法见安装根 CA 证书。只复制到一个目录并不保证所有程序自动信任它。
以下保留原文手动流程,同时标出需要修订之处。它适合理解 CA 数据库、CSR 和签名的关系,不是包含吊销、审计、离线根 CA、密钥恢复等机制的完整生产 PKI 方案。
创建目录和数据库
sudo mkdir /etc/ssl/CA
sudo mkdir /etc/ssl/newcerts
sudo sh -c "echo '01' > /etc/ssl/CA/serial"
sudo touch /etc/ssl/CA/index.txt
serial 记录下一次签发所用序列号,index.txt 是已签发证书的数据库。这些是新 CA 的初始化步骤,不能在已有 CA 上重复初始化或覆盖序列号与数据库。否则可能破坏签发记录或重用序列号。部署前先确认这些路径没有其他 CA 数据。
原文编辑系统 /etc/ssl/openssl.cnf 的 [ CA_default ]:
dir = /etc/ssl
database = $dir/CA/index.txt
certificate = $dir/certs/cacert.pem
serial = $dir/CA/serial
private_key = $dir/private/cakey.pem
编辑建议:系统级 OpenSSL 配置可能被其他工具共享,更稳妥的做法是复制为该 CA 的专用配置,并始终通过 -config 显式指定。本文保留原路径便于对照;应用时应检查权限、现有配置和回退方案。
生成根证书
openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650
sudo mv cakey.pem /etc/ssl/private/
sudo mv cacert.pem /etc/ssl/certs/
命令会询问根私钥口令和证书主题信息。-extensions v3_ca 依赖当前 OpenSSL 配置中相应扩展节;-days 3650 是原文选择的有效期,不是必须遵守的策略。根私钥应加密、严格控制访问,移动文件前要确认不会覆盖已有 CA。CA 私钥一旦泄漏,攻击者就能伪造该信任体系内的证书。
生成服务器密钥与 CSR
原文使用以下历史命令生成加密 RSA 私钥:
openssl genrsa -des3 -out server.key 2048
随后输入并确认口令。原文的“至少八个字符”及 -des3 是旧式建议,不能作为今天的完整密钥保护标准。实际项目应使用当前 OpenSSL 支持的密钥算法与现代加密方式,并采用足够强的口令。
为了让服务能无人值守启动,原文接着移除服务器私钥的口令。这会降低密钥落盘后的保护能力,必须依靠文件权限、进程隔离和宿主机安全控制。CA 私钥不应因此一起取消口令。
原文错误与修订:网页将“导出无口令密钥”和两条 mv 命令错误连成了带 > mv 的一行。> 是 shell 重定向,不是执行下一条命令的分隔符;照抄可能截断文件或失败。下面按原意拆成独立命令,并新增 umask 077:
umask 077
openssl rsa -in server.key -out server.key.insecure
mv server.key server.key.secure
mv server.key.insecure server.key
这段修订只解释原流程。必须在没有同名重要文件的受控目录中运行,并保护 server.key.secure;明文私钥不应进入共享位置。随后用无口令的 server.key 创建 CSR:
openssl req -new -key server.key -out server.csr
程序会要求填写证书主题信息。原文这里再次说会询问私钥口令,但若上一步确实已移除口令,就不会再询问这把私钥的口令。这一点在译文中作了更正。
签名时别漏掉服务域名扩展
原文用以下命令由 CA 签发:
sudo openssl ca -in server.csr -config /etc/ssl/openssl.cnf
输入 CA 私钥口令后,还需要确认签名和写入数据库。首张证书在原文示例中写到 /etc/ssl/newcerts/01.pem,后续按序列号增加。将其中从 -----BEGIN CERTIFICATE----- 到 -----END CERTIFICATE----- 的 PEM 部分保存为描述性名称,例如 mail.example.com.crt。
编辑补充:原文没有明确给服务器证书配置 SAN,不能据此保证现代客户端能通过域名校验。需要在签发证书中核实正确的 DNS 名和服务器用途扩展。以下是与原文不同的显式扩展示例,域名必须按实际服务替换,并由 CA 管理员核实 CSR 申请者的控制权:
[ server_cert ]
basicConstraints = critical,CA:FALSE
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:mail.example.com
若将该内容保存为 server-ext.cnf,签发时显式指定扩展文件:
sudo openssl ca -in server.csr -config /etc/ssl/openssl.cnf -extfile server-ext.cnf -extensions server_cert
该扩展示例针对前面的 RSA 服务器证书,是静态修订示例;没有测试特定 OpenSSL 版本或服务的兼容性。不要不经验证就把 CSR 中任意扩展复制成 CA 签发权限,尤其要避免把最终实体错误签成 CA。
安装证书并分发信任
把服务器证书和私钥复制到需要它们的主机,再配置应用使用相应文件。原文使用:
sudo cp server.key /etc/ssl/private/
sudo cp mail.example.com.crt /etc/ssl/certs/
证书可以公开分发,私钥不可以。应核对目标文件的属主和权限,只给实际服务需要的读取权限;简单复制命令并没有完成权限审核。
对于可以显式指定 CA 文件的应用,可向其提供 cacert.pem。需要系统范围信任时,则按 Ubuntu 的根证书安装流程配置并更新信任库;不能把 cakey.pem 分发给客户端。部署后还要检查证书链、SAN、有效期、服务读权限和真实客户端握手。
来源与审核边界
进一步阅读:Let’s Encrypt 文档、Certbot 文档、Ubuntu 证书概念说明。原文也链接了 TLS 的背景资料。
本次完成全文对照及静态命令审核,没有安装 snap、生成私钥、申请证书、修改服务器配置或执行续期演练。审核发现并标注了错误重定向、序列号覆盖、无口令私钥、缺少 SAN 和高权限钩子等实际风险;没有发现其他问题不等于不存在漏洞。所有输出描述来自原文,未伪造运行记录。
归属:Canonical / Ubuntu Server documentation contributors,原页面版权标注 © 2026。未从该页面确认额外独立许可证,不推定其许可条款。编辑校注和自绘图由未完纪提供。
原文密钥生成的历史提示
以下是源文展示的提示,不是本次运行。原文还提到-des3的四字符最低长度与至少八字符建议;这些旧阈值不作为当前安全标准。
Generating RSA private key, 2048 bit long modulus ..........................++++++ .......++++++ e is 65537 (0x10001) Enter pass phrase for server.key:












暂无评论内容