Contents

acme.sh使用教程

acme.sh是github上一个开源项目,具体功能是免费申请https证书并且自动续签,https://github.com/acmesh-official/acme.sh?tab=readme-ov-file

原理

acme的核心目标是实现“证明你对域名的控制权 -> 颁发证书 -> 自动续期” 的全自动化流程。

核心角色

  • Client:客户端,如acme.sh,运行在服务器上
  • Server:服务端/CA,如Let’s Encrypt、ZeroSSL等,负责验证和颁发证书

验证方式

  • HTTP-01:CA会给客户端一个随机的Token,客户端将Token放在网页的特定路径 /.well-known/acme-challenge/ 下,CA通过 80 端口访问该路径来验证域名控制权。这种方式必须拥有公网IP且80端口必须放开。
  • DNS-01:客户端在域名解析中添加一条随机的 TXT 记录。CA 向全球 DNS 服务器查询该记录来验证域名控制权。这个方法支持通配符证书且内网机也可以申请。
  • TLS-ALPN-01:在 TLS 握手阶段通过特定的 ALPN 协议验证。通常由 Nginx/Caddy 插件自动完成,acme.sh 使用较少。

工作流程

graph TD A[开始: 运行 acme.sh] --> B{选择验证方式} B -- HTTP-01 --> C[在 Webroot 创建验证文件] B -- DNS-01 --> D[在 DNS 添加 TXT 记录] C --> E[CA 访问文件验证] D --> F[CA 查询 DNS 验证] E -- 验证成功 --> G[CA 签发证书] F -- 验证成功 --> G G --> H[acme.sh 下载证书] H --> I[执行 --install-cert 拷贝证书] I --> J[执行 --reloadcmd 重启 Nginx] J --> K[完成: 证书生效] K --> L[定时任务: 每日检查是否需续期] L -- 距离过期 < 30天 --> A

安装命令

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

注意要记录安装的地址,如图

/img/acme.sh%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/acme.sh%E5%AE%89%E8%A3%85%E5%9B%BE%E7%A4%BA.jpg

签发证书

使用官方文档中的直接签发方式,描述如下:

只需要指定域名,并指定域名所在的网站根目录. acme.sh 会全自动的生成验证文件,并放到网站的根目录,验证完成后会聪明的删除验证文件,整个过程没有任何副作用。

acme.sh --issue -d mydomain.com -d www.mydomain.com --webroot /home/wwwroot/mydomain.com/

/root/.acme.sh/acme.sh --issue -d ruanshelab.cn -d www.ruanshelab.cn --webroot /home/nginx-alpine/html

这里需要注意几个点

  • 开头的 acme.sh 命令需要修改成实际的地址,也就是上述安装的地址:/root/.acme.sh/acme.sh
  • mydomain.com 替换成自己的域名
  • --webroot 指向的是网站的根目录,如果是用 docker 部署的 nginx,应该指向挂载的目录

证书签发成功输出示例:

/img/acme.sh%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/%E8%AF%81%E4%B9%A6%E7%AD%BE%E5%8F%91%E6%88%90%E5%8A%9F%E7%A4%BA%E4%BE%8B.jpg

复制证书

官方描述如下:

证书生成好以后,我们需要把证书复制给对应的 Apache、Nginx 或其他服务器去使用。

必须使用 --install-cert 命令来把证书复制到目标文件,请勿直接使用 ~/.acme.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 reload"

这里同样要注意几点:

  • acme.sh 同样要替换成实际的安装地址 /root/.acms.sh/acme.sh
  • example.com 替换成自己的域名
  • key.pemcert.pem 的命名不是固定的,Nginx 只关心文件内容格式,与文件名无关(只要配置路径正确)。cert 代表的是证书文件,key 是密钥文件,均是 pem 格式
  • reloadcmd 是配置完成证书后重启 nginx 的命令,要修改成 service nginx force-reload, 若为 docker 部署的 nginx 则需要修改成重启容器的命令,如:docker restart [容器名]

使用 docker 进行的证书复制:

/root/.acme.sh/acme.sh --install-cert -d your-domain.com \
  --key-file /home/nginx-alpine/ssl/your-domain.key \
  --fullchain-file /home/nginx-alpine/ssl/your-domain.crt \
  --reloadcmd "sudo docker restart my-nginx-alpine"

/root/.acme.sh/acme.sh --install-cert -d ruanshelab.cn \
  --key-file /home/nginx-alpine/ssl/ruanshelab.cn.key \
  --fullchain-file /home/nginx-alpine/ssl/ruanshelab.cn.crt \
  --reloadcmd "sudo docker restart my-nginx-alpine"

/root/.acme.sh/acme.sh --install-cert -d aetherial.cn \
  --key-file /home/nginx/ssl/aetherial.key \
  --fullchain-file /home/nginx/ssl/aetherial.crt \
  --reloadcmd "sudo docker restart nginx-"

安装证书到Nginx

这里的安装指的就是编辑 nginx 的配置文件应用 ssl 证书,下面是一个配置文件的例子( docker 部署的 nginx ):

server {
    listen 443 ssl;
    server_name ruanshelab.cn www.ruanshelab.cn;

    ssl_certificate /etc/nginx/ssl/ruanshelab.crt; # 应用证书
    ssl_certificate_key /etc/nginx/ssl/ruanshelab.key; # 应用密钥

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


server {
    listen       80;
    listen  [::]:80;
    server_name  ruanshelab.cn www.ruanshelab.cn;
    return 301 https://$host$request_uri; # HTTP强制跳转HTTPS

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

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

注意,采用 docker 部署的 nginx ,启动容器的时候要映射 80 和 443 两个端口:

sudo docker run --name my-nginx-alpine -d \
  -p 80:80 \
  -p 443:443 \
  -v /home/nginx-alpine/html:/usr/share/nginx/html:ro \
  -v /home/nginx-alpine/conf/default.conf:/etc/nginx/conf.d/default.conf:ro \
  -v /home/nginx-alpine/ssl:/etc/nginx/ssl:ro \
  -v /home/nginx-alpine/logs:/var/log/nginx \
  nginx:1.25-alpine

自动续签

执行命令:crontab -e, 会查看到一个定时脚本,它会每天检查证书,如果发现证书快过期了就会自动更新

/img/acme.sh%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B/%E8%87%AA%E5%8A%A8%E7%BB%AD%E7%AD%BE%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.jpg

手动更新证书

一行命令

/root/.acme.sh/acme.sh --renew -d domain.com --force

进阶命令

多CA自由签发

acme.sh 现在默认使用 ZeroSSL。如果你想换回 Let’s Encrypt:

# 切换默认 CA 为 Let's Encrypt
acme.sh --set-default-ca --server letsencrypt

# 针对单次申请指定 CA
acme.sh --issue -d domain.com --server buypass

管理与维护命令

  • 查看已经申请的证书列表
acme.sh --list
  • 查看某个证书的详细信息
acme.sh --info -d domain.com
  • 强制手动续期,一般用于测试
acme.sh --renew -d domain.com --force
  • 停止某个域名的自动续期
acme.sh --stop-auto-renew -d domain.com

代理模式

如果服务器无法直接访问 Let’s Encrypt 的验证服务器,可以使用代理模式:

# 设置 HTTP 代理
export http_proxy=http://proxy.example.com:8080
export https_proxy=http://proxy.example.com:8080

# 或者使用 acme.sh 的代理参数
acme.sh --issue -d domain.com --proxy http://proxy.example.com:8080