Linux 服务器

无需面板申请免费 SSL 证书:Certbot/acme.sh 配置 Nginx、Cloudflare 泛域名证书与自动续期

7 个步骤 11 分钟阅读 10 次阅读 0
本文目录

部署 HTTPS 并不一定需要控制面板。使用 Certbot 或 acme.sh,就能为 Nginx 上的任何网站申请 Let's Encrypt 免费证书,通过 Cloudflare DNS API 签发 *.example.com 这样的泛域名证书,并实现自动续期。本文介绍在 Debian/Ubuntu 和 Rocky Linux/AlmaLinux 上使用这两个工具的方法、Nginx 的 HTTPS 配置、开启了 Cloudflare 代理的网站如何处理,以及如何确认自动续期真正生效。

Let's Encrypt 证书的有效期为 90 天,并且 Let's Encrypt 已于 2025 年停止发送到期提醒邮件。配置完成后,务必用 dry run(模拟续期)确认自动续期正常,否则证书一旦过期,网站就会在毫无提醒的情况下无法正常访问。

准备工作

  • 域名的 A 记录(如使用 IPv6,还包括 AAAA 记录)已指向服务器 IP,可用 dig +short example.com 检查。
  • 服务器防火墙已放行 80 和 443 端口(参见使用 firewalld 和 ufw 开放端口)。
  • 已安装 Nginx,并且网站已能通过 HTTP 正常访问。

方式 A:Certbot + Nginx 插件(最简单)

Certbot 可以自动申请证书并修改 Nginx 的 server 配置块,包括设置 HTTP 跳转 HTTPS。

# Debian / Ubuntu
apt update
apt install -y certbot python3-certbot-nginx

# Rocky Linux / AlmaLinux (EPEL)
dnf install -y epel-release
dnf install -y certbot python3-certbot-nginx

# Request and install a certificate for the domain and www
certbot --nginx -d example.com -d www.example.com \
  --agree-tos -m [email protected] --redirect

# Renewal is scheduled automatically; confirm the timer and run a test renewal
systemctl list-timers | grep -i certbot
certbot renew --dry-run

证书保存在 /etc/letsencrypt/live/example.com/ 目录下。如果不希望 Certbot 改动你的 Nginx 配置文件,可以使用 certbot certonly --nginx -d example.com,然后按照下文“Nginx HTTPS 配置”自行添加证书路径。

方式 B:acme.sh(轻量,无需 Python)

acme.sh 是一个以 cron 任务方式运行的 Shell 脚本。注意它默认的证书颁发机构(CA)是 ZeroSSL,如有需要可以切换为 Let's Encrypt。

# Install (creates ~/.acme.sh and a daily cron job)
curl https://get.acme.sh | sh -s [email protected]
source ~/.bashrc

# Use Let's Encrypt as the default CA
acme.sh --set-default-ca --server letsencrypt

# Issue using your site's web root (HTTP-01 validation)
acme.sh --issue -d example.com -d www.example.com -w /var/www/example

# Install the certificate where Nginx expects it and reload Nginx on every renewal
mkdir -p /etc/nginx/ssl
acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.crt \
  --reloadcmd      "systemctl reload nginx"

不要让 Nginx 直接引用 ~/.acme.sh 目录中的文件;请始终使用 --install-cert,它会复制证书文件,并在每次续期后执行重载命令。

通过 Cloudflare DNS API 签发泛域名证书

泛域名证书(*.example.com)必须使用 DNS 验证。如果域名使用 Cloudflare DNS,请在 Cloudflare 控制台的 My Profile → API Tokens 中,使用“Edit zone DNS”模板创建 API 令牌,并将权限限定在需要的域名(zone)上。

# acme.sh: dns_cf reads the token from the environment and saves it for renewals
export CF_Token="your-cloudflare-api-token"
export CF_Zone_ID="your-zone-id"        # shown on the domain's Overview page in Cloudflare
acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

# Certbot alternative
apt install -y python3-certbot-dns-cloudflare
mkdir -p ~/.secrets && chmod 700 ~/.secrets
echo 'dns_cloudflare_api_token = your-cloudflare-api-token' > ~/.secrets/cloudflare.ini
chmod 600 ~/.secrets/cloudflare.ini
certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

即使 80 端口未开放或网站暂时无法访问,DNS 验证同样可以完成,因此也适用于内部服务和新开通的服务器。

Nginx HTTPS 配置

如果使用 certonly 或 acme.sh 签发证书,需要自行添加 HTTPS 的 server 配置块。请根据所用工具调整证书路径。

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;                      # Nginx 1.25.1+; older versions: "listen 443 ssl http2;"
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;   # acme.sh: /etc/nginx/ssl/example.com.crt
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;     # acme.sh: /etc/nginx/ssl/example.com.key
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:10m;

    root /var/www/example;
    index index.html index.php;
}
nginx -t && systemctl reload nginx

开启 Cloudflare 代理的网站

开启橙色云朵(代理)后,HTTP 验证通常仍然可用,因为 Cloudflare 会把 /.well-known/acme-challenge/ 请求转发到你的服务器。源站拥有有效证书后,请将 Cloudflare 的 SSL/TLS 加密模式设置为 Full (strict)(完全/严格);“Flexible”(灵活)模式下 Cloudflare 到源站的流量不加密,而且经常导致重定向循环。也可以改用 DNS 验证;如果网站只通过 Cloudflare 访问,还可以使用免费的 Cloudflare Origin Certificate(源服务器证书)。如需防止访客绕过 Cloudflare 直接访问源站,请参见隐藏源站 IP。

检查证书到期时间与续期

# Expiry date of the certificate your site actually serves
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

# Certbot: all certificates and their expiry
certbot certificates

# acme.sh: list certificates and force a test renewal
acme.sh --list
acme.sh --renew -d example.com --force

常见问题

验证失败,提示“Timeout during connect”或 404 错误?

原因通常是 80 端口被拦截、DNS 记录指向了其他地址,或者有其他 server 配置块响应了该域名。请检查防火墙,运行 dig +short example.com,并确认 Nginx 配置中没有对 /.well-known/acme-challenge/ 做重定向或拒绝访问。如果仍然不行,请改用 DNS 验证。

测试时触发了频率限制?

Let's Encrypt 限制了同一组域名每周可签发的证书数量。调试期间请使用 --dry-run(Certbot)或 --staging(acme.sh),确认配置无误后再申请正式证书。

一张证书能用于多个域名吗?

可以。每个域名单独加一个 -d 参数即可。泛域名只匹配一级子域名,因此 *.example.com 能匹配 shop.example.com,但不能匹配 a.shop.example.com 或 example.com 本身;主域名需要单独添加。

如果按以上步骤操作后问题仍未解决,请提交工单联系 IMIDC 7×24 技术支持,并附上服务器 IP、系统版本、域名、执行过的命令和完整报错信息,方便工程师快速定位。

这篇文章有帮助吗?

相关教程