如何为 Nginx 配置一个 Let`s Encrypt 通配符证书(个人网站免费的SSL证书)

harryshharrysh 网络技术 2026-06-14 9 0

一个天大的好消息,Let’s Encrypt 已经发布了通配符版本 SSL 证书。顾名思义,通配符 SSL 证书不再需要为每一个二级域名重复申请 SSL 证书,以域名 bugprogrammer.tk 为例,只需要申请 *.bugprogrammer.tk 以及 bugprogrammer.tk 即可用于根域名以及所有二级域名,非常方便。申请教程如下。

如何为 Nginx 配置一个 Let`s Encrypt 通配符证书(个人网站免费的SSL证书)

为 Nginx 配置 Let's Encrypt ‌通配符证书‌(Wildcard Certificate,如 *.example.com)与配置普通单域名证书有本质区别:‌通配符证书必须使用 DNS-01 验证方式‌,无法使用传统的 HTTP-01(即无法通过 Web 服务器自动验证)。


以下是基于最佳实践的配置全流程,以 ‌Certbot‌ 配合 ‌Cloudflare‌ DNS 插件为例(其他 DNS 服务商如阿里云、腾讯云、AWS Route53 原理类似,只需更换对应的 Certbot 插件)。


1. 核心前置条件

域名控制权‌:你必须能够修改域名的 DNS 记录(添加 TXT 记录)。

DNS API 权限‌:为了实现自动化续期,建议在 DNS 服务商处生成 API Token 或 Key。

覆盖范围注意‌:

*.example.com ‌仅覆盖一级子域名‌(如 api.example.com, www.example.com)。

不覆盖根域名‌(example.com),申请时需同时指定 -d example.com -d *.example.com。

不覆盖多级子域名‌(如 dev.api.example.com),如需支持需单独申请 *.api.example.com。

2. 安装 Certbot 及 DNS 插件


根据你的操作系统和 DNS 服务商安装对应的插件。以下以 Ubuntu/Debian 和 Cloudflare 为例:


bash

# 更新包列表

sudo apt update


# 安装 Certbot 和 Cloudflare DNS 插件

sudo apt install certbot python3-certbot-dns-cloudflare -y


其他常见插件‌:


阿里云:python3-certbot-dns-aliyun

腾讯云(DNSPod):python3-certbot-dns-dnspod

AWS Route53:python3-certbot-dns-route53

3. 配置 DNS API 凭证


为了安全且自动化地通过 DNS 验证,需要创建一个凭证文件。


获取 API Token‌:

登录 Cloudflare 控制台 -> 我的个人资料 -> API 令牌 -> 创建令牌。

使用模板“编辑区域 DNS”,选择你的域名,生成 Token。

创建凭证文件‌:

bash

sudo mkdir -p /etc/letsencrypt/cloudflare

sudo nano /etc/letsencrypt/cloudflare/credentials.ini


填入内容‌:

ini

dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN


(注:如果使用 Global API Key,字段名为 dns_cloudflare_email 和 dns_cloudflare_api_key,但推荐使用 API Token 以提高安全性)

设置严格权限‌(至关重要,否则 Certbot 会拒绝运行):

bash

sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini


4. 申请通配符证书


执行以下命令申请证书。注意必须包含根域名和通配符域名。


bash

sudo certbot certonly \

  --dns-cloudflare \

  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \

  --dns-cloudflare-propagation-seconds 30 \

  -d example.com \

  -d "*.example.com" \

  --email your-email@example.com \

  --agree-tos \

  --no-eff-email


--dns-cloudflare-propagation-seconds 30:等待 DNS 记录全球传播的时间,若申请失败可适当增加至 60 或 120。

成功后,证书文件将保存在 /etc/letsencrypt/live/example.com/ 目录下。


验证证书内容‌:


bash

sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep "Subject Alternative Name"


输出应包含 DNS:*.example.com, DNS:example.com。


5. 配置 Nginx


通配符证书的优势在于只需配置一次,即可服务于所有匹配的子域名。


方案 A:统一配置(推荐,适合子域名行为一致的场景)


使用正则表达式匹配所有一级子域名。


nginx

# /etc/nginx/sites-available/wildcard.conf


# 1. HTTP 强制跳转 HTTPS

server {

    listen 80;

    server_name example.com *.example.com;

    return 301 https://$host$request_uri;

}


# 2. HTTPS 主配置

server {

    listen 443 ssl http2;

    # 使用正则匹配所有一级子域名

    server_name ~^(?<subdomain>.+)\.example\.com$;


    # 证书路径

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;


    # SSL 优化配置

    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;


    # 示例:根据子域名转发到不同后端或目录

    location / {

        root /var/www/html/$subdomain; # 动态根目录

        index index.html;

        try_files $uri $uri/ =404;

    }

}


# 3. 根域名单独配置(因为正则不匹配根域名)

server {

    listen 443 ssl http2;

    server_name example.com;


    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    

    root /var/www/html/root;

    index index.html;

}


方案 B:独立 Server 块(适合子域名差异大的场景)


如果每个子域名指向完全不同的应用(如 blog 是 WordPress,api 是 Node.js),建议为每个子域名写独立的 server 块,但‌共用同一组证书文件‌。


nginx

server {

    listen 443 ssl http2;

    server_name api.example.com;


    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;


    location / {

        proxy_pass http://127.0.0.1:3000;

    }

}


server {

    listen 443 ssl http2;

    server_name blog.example.com;


    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;


    root /var/www/blog;

    index index.php;

    # ... PHP 配置

}


6. 测试与重载

检查 Nginx 配置语法‌:

bash

sudo nginx -t


重载 Nginx‌:

bash

sudo systemctl reload nginx


浏览器访问测试‌:

访问 https://test.example.com(确保该子域名已解析到服务器 IP),点击地址栏锁图标,确认证书有效且覆盖 *.example.com。

7. 配置自动续期


Let's Encrypt 证书有效期为 90 天。由于使用了 DNS 插件,Certbot 可以自动完成续期,无需人工干预。


测试续期命令‌:


bash

sudo certbot renew --dry-run


如果显示 Congratulations, all simulated renewals succeeded,则配置正确。


确认定时任务‌:

Certbot 安装时会自动创建 systemd timer 或 cron job。


bash

sudo systemctl list-timers | grep certbot


通常每天会检查两次,若证书剩余时间少于 30 天则自动续期并重新加载 Nginx(需在 /etc/letsencrypt/renewal-hooks/deploy/ 中添加重载脚本,或确保证书路径未变,Nginx reload 即可识别新证书)。


若需手动确保重载,可创建部署钩子:


bash

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh


内容:


bash

#!/bin/bash

systemctl reload nginx


赋予执行权限:


bash

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh


常见问题排查

错误:PluginError 或 Credentials error‌:检查 /etc/letsencrypt/cloudflare/credentials.ini 的权限是否为 600,且文件格式正确(无多余空格)。

错误:DNS problem: NXDOMAIN‌:检查域名解析是否正确,以及 API Token 是否有权限编辑该域名的 DNS 记录。

浏览器提示证书不安全‌:确保证书链完整,Nginx 中必须使用 fullchain.pem 而不是 cert.pem。

根域名无法访问‌:确保证书申请时包含了 -d example.com,且 Nginx 中有针对 example.com 的独立 server_name 配置。


版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权本站发表,未经许可,不得转载。

喜欢0发布评论

评论列表

发表评论

  • 昵称(必填)
  • 邮箱
  • 网址
请先 登录 再评论,若不是会员请先 注册