acme.sh + CloudFlare + Nginx

准备工作

你首先需要一个 CloudFlare 的账号,由于申请证书的缘故,你还需要一个域名。

接着你需要将域名的 NameServer 设置成 CloudFlare 提供的 NS ,这样才能透过 CloudFlare 管理您域名的 DNS 记录。

安装 Nginx 这里就不再赘述,对于安装 acme.sh , Arch linux 用户可以直接使用 pacman 安装1:

$ sudo pacman -S acme.sh

也可以参考其他的安装方法来安装

申请证书2

注意: 连通性较差地区的用户建议使用代理

准备工作

以下两种方法使用其中一种即可

使用 Global Key

Global Key 可以在这个页面看到,将这个 Key 导入到环境变数中

export CF_Key="example_key"
export CF_Email="[email protected]"

使用 API Token

API Token 同样也可以在这个页面看到,你需要新建一个 API Token,这个 Token 需要 Zone.ZoneRead 权限,和对于各个你需要的 ZoneZone.DNSWrite 权限。

Accound ID 在 Dashboard 重定向的网址中可以看到,如: https://dash.cloudflare.com/faaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 中的 faaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3

或者点选你的域名(Zone),在右下角可以看到

export CF_Token="example_token"
export CF_Account_ID="account_id"

当然,你可能也只需要改一个 Zone 的 DNS 即可,这时候可以再指定上 Zone 的 ID

Zone 的 ID 在 Zone 页面的右下角(和Account ID位置相同)

export CF_Zone_ID="xxxxxxxxxxxxx"

目前 acme.sh 官方尚不支援多 Zone 不同 Token

开始申请

配置完环境变数后,就可以开始申请证书了。

acme.sh --issue --dns dns_cf -d example.com -d www.example.com

Sample output:

$ acme.sh --issue --dns dns_cf -d example.com
[Sat 17 Apr 13:51:58 CST 2021] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Sat 17 Apr 13:51:58 CST 2021] Creating domain key
[Sat 17 Apr 13:51:58 CST 2021] The domain key is here: /home/user/.acme.sh/example.com/example.com.key
[Sat 17 Apr 13:51:58 CST 2021] Single domain='example.com'
[Sat 17 Apr 13:51:58 CST 2021] Getting domain auth token for each domain
[Sat 17 Apr 13:51:59 CST 2021] Getting webroot for domain='example.com'
[Sat 17 Apr 13:51:59 CST 2021] Adding txt value: **MASKED** for domain:  _acme-challenge.example.com
[Sat 17 Apr 13:51:59 CST 2021] Adding record
[Sat 17 Apr 13:52:00 CST 2021] Added, OK
[Sat 17 Apr 13:52:00 CST 2021] The txt record is added: Success.
[Sat 17 Apr 13:52:00 CST 2021] Let's check each DNS record now. Sleep 20 seconds first.
[Sat 17 Apr 13:52:21 CST 2021] Checking example.com for _acme-challenge.example.com
[Sat 17 Apr 13:52:21 CST 2021] Domain example.com '_acme-challenge.example.com' success.
[Sat 17 Apr 13:52:21 CST 2021] All success, let's return
[Sat 17 Apr 13:52:21 CST 2021] Verifying: example.com
[Sat 17 Apr 13:52:23 CST 2021] Success
[Sat 17 Apr 13:52:23 CST 2021] Removing DNS records.
[Sat 17 Apr 13:52:23 CST 2021] Removing txt: **MASKED** for domain: _acme-challenge.example.com
[Sat 17 Apr 13:52:24 CST 2021] Removed: Success
[Sat 17 Apr 13:52:24 CST 2021] Verify finished, start to sign.
[Sat 17 Apr 13:52:24 CST 2021] Lets finalize the order.
[Sat 17 Apr 13:52:24 CST 2021] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/**MASKED**/**MASKED**'
[Sat 17 Apr 13:52:25 CST 2021] Downloading cert.
[Sat 17 Apr 13:52:25 CST 2021] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/**MASKED**'
[Sat 17 Apr 13:52:25 CST 2021] Cert success.
-----BEGIN CERTIFICATE-----
**MASKED**
-----END CERTIFICATE-----
[Sat 17 Apr 13:52:25 CST 2021] Your cert is in  /home/user/.acme.sh/example.com/example.com.cer
[Sat 17 Apr 13:52:25 CST 2021] Your cert key is in  /home/user/.acme.sh/example.com/example.com.key
[Sat 17 Apr 13:52:25 CST 2021] The intermediate CA cert is in  /home/user/.acme.sh/example.com/ca.cer
[Sat 17 Apr 13:52:25 CST 2021] And the full chain certs is there:  /home/user/.acme.sh/example.com/fullchain.cer

配置 Nginx

Nginx 只需要两个文件 cert keyfull chain certs 也就是 example.com.keyfullchain.cer

我们先把这两个文件扔到 Nginx 的目录下,方便它可以读到这两个文件

# 假设 nginx 的配置文件在该目录下
cd /etc/nginx
# 建立一个专门用来存放证书的目录
sudo mkdir certs
cd certs
# 建一个域名专用的目录
mkdir example.com
# 用 acme.sh 脚本将文件 cp 到这两个目录中
acme.sh --install-cert -d example.com --key-file example.com/example.com.key --fullchain-file example.com/fullchain.cer

打开需要配置的服务端部分,添加以下行3

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name leanhe.dev;

    ssl_certificate /etc/nginx/certs/example.com/fullchain.cer;
    ssl_certificate_key /etc/nginx/certs/example.com/example.com.key;
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

如需 HSTS ,可以再添加以下行

    add_header Strict-Transport-Security "max-age=63072000" always;

最后测试一下 Nginx

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

这样就可以放心的重载 Nginx 了

$ sudo systemctl reload nginx