Skip to content

用acme.sh实现ssl证书部署及自动续签

wandoubaba / 2024-11-04

介绍

acme.sh是一个实现了 acme 协议的客户端工作,使用它可以申请Let's EncrpyptTrustAsia等机构的免费SSL证书并可以实现自动部署与自动续签。

项目地址:https://github.com/acmesh-official/acme.sh

本文主要介绍如何使用 acme.sh 为域名申请免费的90天证书,并实现Nginx自动部署和自动续签。

本文的操作环境是 Debian 11/12 系统,域名从腾讯云注册(DNSPod提供解析)。

安装acme.sh客户端

使用发下命令安装,email可以换成自己的:

sh
curl https://get.acme.sh | sh -s email=my@example.com

如果上面的命令安装失败,可以换下面这种方式:

sh
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
. ~/.bashrc

整个安装过程只会把工具安装到~/.acme.sh/目录下,只是在~/.bashrc中添加了一句. "/root/.acme.sh/acme.sh.env",看一眼acme.sh.env内容,是这样的:

sh
cat /root/.acme.sh/acme.sh.env
# 结果
export LE_WORKING_DIR="/root/.acme.sh"
alias acme.sh="/root/.acme.sh/acme.sh"

建议再安装个socat(它本身功能也十分强大,是linux网络运维的瑞士军刀),可以用于以standalone mode申请证书时临时“伪装”一个服务器出来。

sh
apt-get install socat

确认证书申请方式

acme.sh的官方文档中可以看到分发证书的方式有很多种,比如文件验证、独立模式、手动DNS、自动DNS等等,我们为了实现全自动化和未来的自动续签,所以我们选择“自动DNS解析方式”。

我的域名注册商是腾讯云,解析服务由DNSPod提供,幸运的是acme.sh支持DNSPod平台的API密钥,所以我先到DNSPod平台上去创建一组密钥:

  • 登录网址:https://www.dnspod.cn/
  • 登录控制台
  • 我的账号 - API密钥
  • 切换到DNSPod Token(不要用腾讯云API密钥)
  • 记录IDToken(页面关闭后就再也看不见了)

执行下面命令:

sh
export DP_Id=<Id>
export DP_Key=<Token>

申请证书

sh
acme.sh --issue --dns dns_dp -d example.com

如果执行成功,最后可以看到类似下面的结果,说明已经将证书文件安装到了本地:

sh
[Mon Nov  4 01:12:52 PM CST 2024] Your cert is in: /root/.acme.sh/example.com/example.com.cer
[Mon Nov  4 01:12:52 PM CST 2024] Your cert key is in: /root/.acme.sh/example.com/example.com.key
[Mon Nov  4 01:12:52 PM CST 2024] The intermediate CA cert is in: /root/.acme.sh/example.com/ca.cer
[Mon Nov  4 01:12:52 PM CST 2024] And the full chain certs is there: /root/.acme.sh/example.com/fullchain.cer
[Mon Nov  4 01:12:52 PM CST 2024] _on_issue_success

部署证书

下面分别是在apache上和在nginx上部署证书的示例,需要替换的内容是example.com和相关文件的绝对路径,以及服务重新加载配置的命令

Apache示例:

sh
acme.sh --install-cert -d example.com \
--cert-file      /path/to/certfile/in/apache/cert.pem  \
--key-file       /path/to/keyfile/in/apache/key.pem  \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd     "service apache2 force-reload"

Nginx示例:

sh
acme.sh --install-cert -d example.com \
--key-file       /path/to/keyfile/in/nginx/key.pem  \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd     "service nginx force-reload"

修改配置文件

acme.sh只会重新部署证书文件,不会去更改任何其他配置文件(为了安全考虑),所以,要让web服务器应用证书,还需要手动去修改相关的配置文件。

我们以nginx为例,提供一个web站点加载ssl证书并提供https服务(开443端口)的示例:

nginx
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    # ssl
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate /etc/nginx/certs/cert.pem; # 证书文件路径
    ssl_certificate_key /etc/nginx/certs/key.pem; # 私钥文件路径
 
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;



    #access_log  /var/log/nginx/host.access.log  main;

    location / {
         root   /usr/share/nginx/html;
         index  index.html index.htm;
    }

    error_page  404              /404.html;
    location = /404.html {
        root   /usr/share/nginx/html;
    }

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

如果我们希望所有的http请求(80)都可以自动转到https(443)上,可以对上面的配置文件做一些修改:

nginx
server {  
    listen       80;  
    listen       [::]:80;  
    server_name  localhost;  

    # 重定向所有 HTTP 请求到 HTTPS  
    return 301 https://$host$request_uri;  
}  

server {  
    listen       443 ssl;  
    listen       [::]:443 ssl;  
    server_name  localhost;  

    ssl_certificate /etc/nginx/certs/cert.pem; # 证书文件路径  
    ssl_certificate_key /etc/nginx/certs/key.pem; # 私钥文件路径  

    ssl_session_cache shared:SSL:1m;  
    ssl_session_timeout  10m;  
    ssl_ciphers HIGH:!aNULL:!MD5;  
    ssl_prefer_server_ciphers on;  

    #access_log  /var/log/nginx/host.access.log  main;  

    location / {  
        root   /usr/share/nginx/html;  
        index  index.html index.htm;  
    }  

    error_page  404              /404.html;  
    location = /404.html {  
        root   /usr/share/nginx/html;  
    }  

    # redirect server error pages to the static page /50x.html  
    error_page   500 502 503 504  /50x.html;  
    location = /50x.html {  
        root   /usr/share/nginx/html;  
    }  
}

修改完配置文件后,再要重新启动服务或者重新加载一下配置,才会生效。

验证自动续签机制

sh
crontab -l

如果看到有下面这样的定时任务,说明acme.sh的自动续签机制是生效的

sh
43 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

Released under the MIT License.