🌐 Ubuntu 服务器 Let's Encrypt 免费 SSL 证书完整部署指南(支持多域名及复杂反向代理场景)
适用系统:Ubuntu 22.04 LTS / 20.04 LTS(兼容 Debian)
Web 服务器:Nginx
更新时间:2026 年 6 月
作者:DevOps Guide
✅ 一、前提条件
| 要求 | 说明 |
|---|---|
| 1. 云服务器(任意厂商) | 已创建,操作系统为 Ubuntu 22.04 或 20.04 |
| 2. 域名解析 | 需要申请证书的所有域名(含子域名)的 A 记录均指向服务器公网 IP |
| 3. 安全组/防火墙开放端口 | 入方向允许 80 (HTTP) 和 443 (HTTPS) |
| 4. 域名备案(中国大陆地域) | 若服务器位于中国内地,所有域名必须完成 ICP 备案 |
| 5. 已安装 Nginx | 可通过 http://每个域名 访问(或至少配置好 server_name) |
🔍 验证域名解析(每个域名):
dig yourdomain.com +short dig www.yourdomain.com +short # 均应返回服务器公网 IP
🚀 二、完整操作流程
步骤 1:更新系统并安装 Nginx
# 更新软件包索引
sudo apt update
# 安装 Nginx
sudo apt install -y nginx
# 启动并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx
步骤 2:配置 Nginx 站点(支持多域名及复杂反向代理)
您可以选择单配置文件包含所有域名,或每个域名独立配置文件。以下以单配置文件为例。
2.1 创建配置文件
sudo vim /etc/nginx/conf.d/yourdomain.conf # 或使用 sites-available 方式
2.2 基础配置(用于初次申请证书)
如果您已有复杂的反向代理或缓存规则,请务必添加以下 location 块,确保 Let's Encrypt 的验证请求由 Nginx 本地处理,而不是被代理到后端:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# ===== 重要:为 Let's Encrypt 验证提供本地目录 =====
location /.well-known/acme-challenge/ {
root /var/www/html; # 确保该目录存在
}
# 其他您自己的 location(如反向代理、静态资源等)
# 例如:
location / {
# 您的代理或根目录配置
proxy_pass http://127.0.0.1:8080; # 假设后端服务
# ... 其他代理设置 ...
}
}
说明:
/.well-known/acme-challenge/的root必须指向一个实际存在的目录(如/var/www/html),Nginx 会在此目录下提供验证文件。请确保该目录可被 Nginx 用户读取。
2.3 启用站点(若使用 sites-available 方式)
sudo ln -s /etc/nginx/sites-available/yourdomain.conf /etc/nginx/sites-enabled/
2.4 测试并重载 Nginx
sudo nginx -t
sudo systemctl reload nginx
✅ 此时应能通过浏览器访问
http://yourdomain.com和http://www.yourdomain.com(如果已配置后端,则需确保后端正常)。
步骤 3:清理旧的 SSL 配置(重要!)
如果您之前曾经尝试过配置 SSL,但证书文件已不存在或路径错误,nginx -t 会报错,导致无法继续。请执行以下清理操作:
3.1 检查并注释/删除所有 listen 443 相关指令
在您的配置文件中,查找 listen 443 ssl 或 ssl_certificate 等行,将其注释掉(在行首加 #),或者直接删除整个 HTTPS server 块。例如:
# server {
# listen 443 ssl;
# server_name yourdomain.com;
# ssl_certificate /path/to/old/cert.pem;
# ssl_certificate_key /path/to/old/key.pem;
# ...
# }
3.2 确保 80 端口配置没有 return 301 https://...
如果您的 80 端口配置中有强制跳转到 HTTPS 的 return 301 或 rewrite,请暂时移除或注释掉,否则 Certbot 的 HTTP-01 验证请求会被重定向,导致验证失败。可以临时改为直接提供内容或代理。
例如,将:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
改为:
server {
listen 80;
server_name yourdomain.com;
root /var/www/html; # 或保留您的代理
# 并包含 /.well-known 的 location(见步骤 2.2)
}
3.3 测试并重载 Nginx
sudo nginx -t
sudo systemctl reload nginx
步骤 4:安装 Certbot(Let's Encrypt 客户端)
推荐使用 snap 安装最新版:
# 安装 snap(如未安装)
sudo apt install -y snapd
# 确保 snap 最新
sudo snap install core; sudo snap refresh core
# 安装 Certbot 并关联 Nginx 插件
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot # 创建软链接(可选)
若您更习惯 apt,也可使用:
sudo apt install -y certbot python3-certbot-nginx
⚠️ apt 版本可能稍旧,但功能完整。
步骤 5:申请并安装 SSL 证书(支持多域名)
使用 --nginx 插件自动修改 Nginx 配置:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
如果有更多子域名,继续添加 -d 参数,例如:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com -d api.yourdomain.com
执行时会提示:
- 输入邮箱(用于过期提醒)
- 同意服务条款(按
A) - 是否重定向 HTTP → HTTPS(建议选 2 全部重定向)
✅ 成功后,Certbot 会自动修改您的配置文件,添加 HTTPS 支持,并重载 Nginx。访问
https://yourdomain.com应显示安全锁。
步骤 6:验证证书信息
sudo certbot certificates
输出示例:
Certificate Name: yourdomain.com
Domains: yourdomain.com www.yourdomain.com
Expiry Date: 2026-09-20 12:34:56+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/yourdomain.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/yourdomain.com/privkey.pem
步骤 7:配置自动续期
7.1 测试续期流程(模拟运行)
sudo certbot renew --dry-run
✅ 应看到:Congratulations, all simulated renewals succeeded.
7.2 设置定时任务(cron)
sudo crontab -e
添加以下行(每天凌晨 2 点执行):
0 2 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
7.3 验证 cron 任务
sudo crontab -l
应显示上述内容。
🔍 三、常见问题排查
❌ 问题 1:申请证书时超时(Timeout)
错误示例:
Fetching http://yourdomain.com/.well-known/acme-challenge/...: Timeout
原因与解决:
| 原因 | 解决方案 |
|---|---|
| 安全组/防火墙未开 80 端口 | 云控制台添加 80 入站规则;检查 sudo ufw status |
| 域名未备案(中国内地服务器) | 备案域名,或改用 DNS 验证(见附录) |
| DNS 未解析到公网 IP | 使用 dig yourdomain.com 核对 |
配置中缺少 location /.well-known/acme-challenge/ 或该路径被代理/重定向 | 添加或检查该 location,确保它指向本地目录且没有被 return 或 proxy_pass 拦截 |
80 端口存在 return 301 强制跳转 HTTPS | 临时注释或移除该跳转,待证书申请成功后再恢复(Certbot 会自动添加) |
❌ 问题 2:Certbot 找不到 server_name
错误:No matching server blocks located
解决:
- 确保 Nginx 配置中
server_name包含你申请证书的所有域名。 - 检查配置文件是否被 Nginx 加载(对于
sites-available,需有软链接到sites-enabled;对于conf.d,文件必须以.conf结尾)。
❌ 问题 3:nginx -t 报错 no "ssl_certificate" is defined
原因:配置中写有 listen 443 ssl; 但未提供 ssl_certificate 和 ssl_certificate_key 指令,或者证书文件不存在。
解决:在申请证书前,暂时注释掉整个 HTTPS server 块,或删除 listen 443 ssl; 行。申请成功后,Certbot 会自动添加正确配置。
❌ 问题 4:变量 $connection_upgrade 未定义
错误:unknown "connection_upgrade" variable
解决:在配置文件的 http 块(或当前文件顶层,但必须位于 server 块之外)添加 map 定义:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
❌ 问题 5:自动续期失败
排查步骤:
# 查看 cron 执行日志
sudo grep CRON /var/log/syslog
# 查看 certbot 日志
sudo tail -n 20 /var/log/letsencrypt/letsencrypt.log
# 手动运行续期(观察输出)
sudo certbot renew
📎 附录:替代方案 —— DNS 验证(无需 80 端口,也支持多域名)
适用于:未备案域名 或 无法开放 80 端口 的场景,且可以自动化添加 TXT 记录。
步骤 A:获取云厂商 DNS API 凭证(以阿里云为例)
- 进入 RAM 控制台
- 创建用户,授权
AliyunDNSFullAccess - 获取
AccessKey ID和AccessKey Secret
步骤 B:安装 DNS 插件并配置凭证
# 安装阿里云 DNS 插件(需 pip)
sudo apt install -y python3-pip
sudo pip3 install certbot-dns-alidns
# 创建凭证文件
mkdir -p ~/.secrets
cat > ~/.secrets/alidns.ini <<EOF
dns_alidns_access_key = YOUR_ACCESS_KEY_ID
dns_alidns_secret_key = YOUR_ACCESS_KEY_SECRET
EOF
chmod 600 ~/.secrets/alidns.ini
步骤 C:申请证书(多域名)
sudo certbot certonly \
--dns-alidns \
--dns-alidns-credentials ~/.secrets/alidns.ini \
-d yourdomain.com -d www.yourdomain.com -d api.yourdomain.com
步骤 D:手动配置 Nginx HTTPS
编辑配置文件,添加 HTTPS 监听:
server {
listen 443 ssl;
server_name yourdomain.com www.yourdomain.com;
root /var/www/html;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
}
# 可选:强制 HTTP 重定向到 HTTPS
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
重载 Nginx:
sudo nginx -t && sudo systemctl reload nginx
⚠️ DNS 验证方式 仍需配置自动续期 cron(同上)。
✅ 四、总结
| 步骤 | 命令/操作 | 关键点 |
|---|---|---|
| 1. 安装 Nginx | sudo apt install nginx | - |
| 2. 配置站点 | 创建配置文件,务必添加 location /.well-known/acme-challenge/ | 确保验证路径可被 Nginx 本地处理 |
| 3. 清理旧 SSL 配置 | 注释掉 listen 443 ssl 及 ssl_certificate 行 | 避免配置测试失败 |
| 4. 安装 Certbot | 使用 snap 或 apt | - |
| 5. 申请证书(多域名) | sudo certbot --nginx -d domain1 -d domain2 ... | Certbot 自动修改配置 |
| 6. 设置自动续期 | sudo crontab -e 添加任务 | 每天执行 |
| 7. 测试续期 | sudo certbot renew --dry-run | 确认自动续期正常 |
🎉 完成!您的网站现在拥有免费、自动更新的 HTTPS 加密,并支持多域名共用一张证书。
若使用反向代理或复杂配置,遵循上述添加/.well-known和清理 SSL 的步骤,可避免常见的申请失败问题。
🔗 官方参考:
💡 提示:建议定期(每月)手动执行
sudo certbot certificates查看证书到期时间,确保自动续期正常运行。若后续修改 Nginx 配置,请确保location /.well-known/acme-challenge/仍被保留,以免续期失败。