acme.sh是一个基于Shell脚本编写的开源项目,用于获取SSL/TLS证书,可以实现自动申请、续签、安装证书,让网站实现https访问。
acme.sh的命令格式:
acme.sh 命令 ... [参数] ...
主要命令
--help
或-h
:显示帮助信息--version
或-v
:显示版本信息--upgrade
:检查更新--list
:列出证书--issue
:申请证书--renew
或-r
:更新证书--revoke
:吊销证书--remove
:删除证书--install-cert
:安装证书
acme.sh的高级功能较多,它们的具体使用可用查阅官方Wiki和参数说明
但是它的使用非常简单,主要分为
安装脚本
、申请证书
、安装证书
三部分。
安装acme.sh
使用如下命令自动安装
使用 curl 或 wget 方式获取,系统需要安装软件
curl https://get.acme.sh | sh
wget -O - https://get.acme.sh | sh
安装完成后,重启窗口让 acme.sh
指向 ~/.acme.sh/acme.sh
,此后就可直接使用 acme.sh
命令
接着重新加载 Bash
source ~/.bashrc
acme.sh的安装不需要root权限,安装过程不会污染已有的系统任何功能和文件,所有的修改都被限制在
~/.acme.sh/
中
如果你想在安装的时候指定各种参数,也可以克隆GitHub仓库手动安装,更多详细参数可参考官方说明
shell> git clone https://github.com/acmesh-official/acme.sh.git
# 如果国内速度连接失败或者速度太慢,可换用如下命令
# shell> git clone https://hub.fastgit.org/acmesh-official/acme.sh.git
shell> cd ./acme.sh
shell> ./acme.sh --install \
--home ··· \
--config-home ··· \
--cert-home ··· \
--accountemail ··· \
···
输入 acme.sh --help
即可查看 acme.sh 的帮助命令
root@sb-blog ~ # acme.sh --help
https://github.com/Neilpang/acme.sh
v2.7.8
Usage: acme.sh command ...[parameters]....
Commands:
--help, -h Show this help message.
--version, -v Show version info.
--install Install acme.sh to your system.
--uninstall Uninstall acme.sh, and uninstall the cron job.
--upgrade Upgrade acme.sh to the latest code from https://github.com/Neilpang/acme.sh.
--issue Issue a cert.
--signcsr Issue a cert from an existing csr.
--deploy Deploy the cert to your server.
--install-cert Install the issued cert to apache/nginx or any other server.
--renew, -r Renew a cert.
--renew-all Renew all the certs.
--revoke Revoke a cert.
--remove Remove the cert from list of certs known to acme.sh.
--list List all the certs.
--showcsr Show the content of a csr.
--install-cronjob Install the cron job to renew certs, you don't need to call this. The 'install' command can automatically install the cron job.
--uninstall-cronjob Uninstall the cron job. The 'uninstall' command can do this automatically.
--cron Run cron job to renew all the certs.
--toPkcs Export the certificate and key to a pfx file.
--toPkcs8 Convert to pkcs8 format.
--update-account Update account info.
--register-account Register account key.
--deactivate-account Deactivate the account.
--create-account-key Create an account private key, professional use.
--create-domain-key Create an domain private key, professional use.
--createCSR, -ccsr Create CSR , professional use.
--deactivate Deactivate the domain authz, professional use.
Parameters:
--domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc.
--challenge-alias domain.tld The challenge domain alias for DNS alias mode: https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode
--domain-alias domain.tld The domain alias for DNS alias mode: https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode
--force, -f Used to force to install or force to renew a cert immediately.
--staging, --test Use staging server, just for test.
--debug Output debug info.
--output-insecure Output all the sensitive messages. By default all the credentials/sensitive messages are hidden from the output/debug/log for secure.
--webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
--standalone Use standalone mode.
--stateless Use stateless mode, see: https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode
--apache Use apache mode.
--dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
--dnssleep [120] The time in seconds to wait for all the txt records to take effect in dns api mode. Default 120 seconds.
--keylength, -k [2048] Specifies the domain key length: 2048, 3072, 4096, 8192 or ec-256, ec-384.
--accountkeylength, -ak [2048] Specifies the account key length.
--log [/path/to/logfile] Specifies the log file. The default is: "/root/.acme.sh/acme.sh.log" if you don't give a file path here.
--log-level 1|2 Specifies the log level, default is 1.
--syslog [0|3|6|7] Syslog level, 0: disable syslog, 3: error, 6: info, 7: debug.
These parameters are to install the cert to nginx/apache or anyother server after issue/renew a cert:
--cert-file After issue/renew, the cert will be copied to this path.
--key-file After issue/renew, the key will be copied to this path.
--ca-file After issue/renew, the intermediate cert will be copied to this path.
--fullchain-file After issue/renew, the fullchain cert will be copied to this path.
--reloadcmd "service nginx reload" After issue/renew, it's used to reload the server.
--server SERVER ACME Directory Resource URI. (default: https://acme-v01.api.letsencrypt.org/directory)
--accountconf Specifies a customized account config file.
--home Specifies the home dir for acme.sh .
--cert-home Specifies the home dir to save all the certs, only valid for '--install' command.
--config-home Specifies the home dir to save all the configurations.
--useragent Specifies the user agent string. it will be saved for future use too.
--accountemail Specifies the account email, only valid for the '--install' and '--update-account' command.
--accountkey Specifies the account key path, only valid for the '--install' command.
--days Specifies the days to renew the cert when using '--issue' command. The max value is 60 days.
--httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
--local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
--listraw Only used for '--list' command, list the certs in raw format.
--stopRenewOnError, -se Only valid for '--renew-all' command. Stop if one cert has error in renewal.
--insecure Do not check the server certificate, in some devices, the api server's certificate may not be trusted.
--ca-bundle Specifies the path to the CA certificate bundle to verify api server's certificate.
--ca-path Specifies directory containing CA certificates in PEM format, used by wget or curl.
--nocron Only valid for '--install' command, which means: do not install the default cron job. In this case, the certs will not be renewed automatically.
--no-color Do not output color text.
--ecc Specifies to use the ECC cert. Valid for '--install-cert', '--renew', '--revoke', '--toPkcs' and '--createCSR'
--csr Specifies the input csr.
--pre-hook Command to be run before obtaining any certificates.
--post-hook Command to be run after attempting to obtain/renew certificates. No matter the obtain/renew is success or failed.
--renew-hook Command to be run once for each successfully renewed certificate.
--deploy-hook The hook file to deploy cert
--ocsp-must-staple, --ocsp Generate ocsp must Staple extension.
--always-force-new-domain-key Generate new domain key when renewal. Otherwise, the domain key is not changed by default.
--auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future.
--listen-v4 Force standalone/tls server to listen at ipv4.
--listen-v6 Force standalone/tls server to listen at ipv6.
--openssl-bin Specifies a custom openssl bin location.
--use-wget Force to use wget, if you have both curl and wget installed.
更新acme.sh
acme变得挺快的,更新就用这个
acme.sh --upgrade
# 自动更新
acme.sh --upgrade --auto-upgrade
# 关闭自动更新
acme.sh --upgrade --auto-upgrade 0
DNS API模式
这个模式只需要你输入域名服务商提供的
Key
(有的还需要Secret
),其余工作由acme.sh自动完成(包括申请、续签、安装等)
各家对域名的 API Key
的称呼不大相同,acme.sh的文档中给出了各服务商的申请方式。
一般情况下,你会从域名服务商拿到访问许可,然后执行如下命令:
# 将许可信息写入临时环境变量,可用env命令查看
shell> export ···=···
shell> export ···=···
# 执行申请
shell> acme.sh --issue --dns dns_··· -d 域名1 -d 域名2 ···
腾讯云
export DP_Id="API Token 的 ID"
export DP_Key="API Token"
acme.sh --issue --dns dns_dp -d example.com -d *.example.com
阿里云
export Ali_Key="xxx"
export Ali_Secret="xxxx"
acme.sh --issue --dns dns_ali -d example.com -d *.example.com
Cloudflare
export CF_Key="Global API Key"
export CF_Email="Cloudflare Email"
acme.sh --issue --dns dns_dp -d example.com -d *.example.com
# 阿里云域名访问的AccessKey
shell> export Ali_Key="···"
shell> export Ali_Secret="···"
# 申请主域名证书和泛域名证书
shell> acme.sh --issue --dns dns_ali -d example.com -d *.example.com
···
Cert success.
···
Your cert is in /root/.acme.sh/xxx.com/xxx.com.cer
Your cert key is in /root/.acme.sh/xxx.com/xxx.com.key
The intermediate CA cert is in /root/.acme.sh/xxx.com/ca.cer
And the full chain certs is there: /root/.acme.sh/xxx.com/fullchain.cer
注意:域名服务商给你的访问许可非常重要,千万不要泄露,否则其他人将会拿到你的域名控制权;建议执行完上述命令请重启窗口销毁临时环境变量。
DNS手动模式
这个模式需要你填入要申请的域名,acme.sh会返回一个子域名和一串TXT数据,你需要手动把它们添加到你的域名解析中,然后回来申请证书。
如果你是第一次申请该域名,需要你加上 --yes-I-know-dns-manual-mode-enough-go-ahead-please
参数,其他要求可用参考官方文档。
执行如下命令:
# 发起申请
shell> acme.sh --issue --dns -d 域名1 -d 域名2 ···
# 第一次申请在后面加上"--yes-I-know-dns-manual-mode-enough-go-ahead-please"
···
Add the following TXT record:
Domain: '_acme-challenge.···'
TXT value: '···'
···
# 手动把它们添加到你的域名解析中再执行下列步骤
# 申请证书
shell> acme.sh --issue --renew -d 域名1 -d 域名2 ···
# 第一次也要加上"--yes-I-know-dns-manual-mode-enough-go-ahead-please"
···
Cert success.
···
此处以 example.com
为例,申请该域名的全部证书。
# 发起申请
shell> acme.sh --issue --dns -d example.com -d *.example.com
···
Add the following TXT record:
Domain: '_acme-challenge.example.com'
TXT value: '···'
···
# 将TXT记录添加到域名解析中
# 申请证书
shell> acme.sh --issue --renew -d example.com -d *.example.com
···
Cert success.
···
Your cert is in /root/.acme.sh/xxx.com/xxx.com.cer
Your cert key is in /root/.acme.sh/xxx.com/xxx.com.key
The intermediate CA cert is in /root/.acme.sh/xxx.com/ca.cer
And the full chain certs is there: /root/.acme.sh/xxx.com/fullchain.cer
注意:这个模式需要你手动添加TXT记录做验证,由于Let’s Encrypt的证书需要每三个月续签一次,忘记续签就会导致证书过期从而使https连接出错,因此不建议本方式长期使用。
Web服务器模式
这个模式需要你将域名指向你的Web服务器,并将网站根目录地址提交给acme.sh,之后若需要正常续签需要保持该目录不变。
注意:本方式不支持泛域名证书。
执行命令如下:
shell> acme.sh --issue -d 域名 --webroot 网站根目录地址
···
Cert success.
···
此处以 example.com
为例,申请该域名的证书;申请前先将 example.com
指向本机,并用nginx代理到 /var/www/example.com/
下面。
shell> acme.sh --issue -d example.com --webroot /var/www/example.com/
···
Cert success.
···
Your cert is in /root/.acme.sh/xxx.com/xxx.com.cer
Your cert key is in /root/.acme.sh/xxx.com/xxx.com.key
The intermediate CA cert is in /root/.acme.sh/xxx.com/ca.cer
And the full chain certs is there: /root/.acme.sh/xxx.com/fullchain.cer
如果你本机没有web代理工具,可以使用
--standalone
参数自动获取(需安装socat
工具),同时可用--httpport
指定http端口;如果你是TLS服务器,可用使用--alpn
参数自动获取,同时可用--tlsport
指定https端口。如果你本机有Nginx或者Apache服务,使用
--nginx
或--apache
参数可用自动识别其配置文件并找到网站根目录。更多用法请参考官方文档
安装证书
注意:不要直接用
.acme.sh/
内的证书文件,里面目录结构随使可能会因为脚本自动更新而变动。
官方有提供了关于Nginx/Apache的安装方法
需要的命令:
--install-cert
:安装证书--list
:列出所有申请的证书
对应的参数:
--key-file
:私钥文件安装地址--cert-file
:证书文件安装地址--fullchain-file
:证书链文件安装地址--reloadcmd
:重启命令内容
下面以nginx证书安装为例:
先配置nginx
存放配置的文件夹一般为
/etc/nginx/conf.d/
,在其下新建example.com.conf
文件;
server {
listen 80; # 监听80端口(http)
server_name example.com;
return 301 https://$server_name$request_uri; # 返回301命令,将地址重写到https上
}
server {
listen 443 ssl; # 监听443端口(https)
server_name example.com;
root /var/www/example.com; # 指定网站根目录
ssl_certificate /etc/nginx/ssl/fullchain.pem; # 指定SSL/TLS证书
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
index index.html; # 默认加载文件
}
}
注意,请确认你的服务器防火墙是否拦截
80
和443
端口,包括云服务商提供的防火墙和系统上安装的防火墙。
将 example.com.key
的 A记录
指向本机IP地址,此配置将让其代理到 /var/www/example.com.key/
文件夹下,同时使用 /etc/nginx/ssl/
内的证书文件;
注意:若nginx版本低于v1.15.x,务必将
listen 443 ssl
改为listen 443
,并在下方加入命令ssl on
;
查看证书申请状态:
# 列出全部证书
shell> acme.sh --list
Main_Domain KeyLength SAN_Domains CA Created Renew
example.com *.example.com LetsEncrypt.org ··· ···
安装证书到nginx,安装完成后会重启nginx使命令生效。
注意此处要用
force-reload
命令,否则nginx不会自动更新证书文件。
# 创建文件夹
shell> mkdir -p /etc/nginx/ssl
# 安装证书
shell>
acme.sh --install-cert -d example.com \
--cert-file /etc/nginx/ssl/cert.pem \
--key-file /etc/nginx/ssl/privkey.pem \
--fullchain-file /etc/nginx/ssl/fullchain.pem \
--reloadcmd "service nginx force-reload"
···
Installing key to:/etc/nginx/ssl/example.com/privkey.pem
Installing full chain to:/etc/nginx/ssl/example.com/fullchain.pem
Run reload cmd: systemctl force-reload nginx
Reload success
为了确保服务启动成功,可以查看nginx监听端口的状态
# 查看80端口(http)状态
shell> netstat -tlnp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 7227/nginx: master
tcp6 0 0 :::80 :::* LISTEN 7227/nginx: master
# 查看443端口(https)状态
shell> netstat -tlnp | grep 443
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 7227/nginx: master
证书安装信息会记录在 ~/.acme.sh/example.com/example.com.conf
中,可以发现该文件末尾添加了如下信息:
Le_ReloadCmd
中将命令记录为base64
格式
# 查看安装信息
shell> cat ~/.acme.sh/example.com/example.com.conf
···
Le_RealCertPath=''
Le_RealCACertPath=''
Le_RealKeyPath='/etc/nginx/ssl/example.com/privkey.pem'
Le_ReloadCmd='__ACME_BASE64__START_c3lzdGVtY3RsIGZvcmNlLXJlbG9hZCBuZ2lueA==__ACME_BASE64__END_'
Le_RealFullChainPath='/etc/nginx/ssl/example.com/fullchain.pem'
# 查看安装目录情况
shell> ls /etc/nginx/ssl/example.com/
fullchain.pem privkey.pem
如果你想修改安装配置,可修改上述文件,或直接运行新的安装命令,即可覆盖上一次的配置;如果想删除安装配置,可直接运行无参数的安装命令:
# 删除之前的安装信息
shell> acme.sh --install-cert -d example.com
# 但是不会删除已安装的证书,需要你手动删除
如果是 Apache 2.4.8 以上版本的话,可以使用这个命令
acme.sh --install-cert -d example.com \
--key-file /etc/apache2/ssl/example.com.key \
--fullchain-file /etc/apache2/ssl/example.com.crt \
--reloadcmd "service apache2 force-reload"
更新证书
你可以手动更新证书,但是如果时间还没到你需要加上
--force
参数
命令:
--renew
或-r
:更新证书
对应参数:
--domain
或-d
:指定域名--force
:强制更新
# 更新证书
shell> acme.sh --renew -d example.com --force
Renew: 'example.com'
···
Cert success.
···
Your cert is in /root/.acme.sh/xxx.com/xxx.com.cer
Your cert key is in /root/.acme.sh/xxx.com/xxx.com.key
The intermediate CA cert is in /root/.acme.sh/xxx.com/ca.cer
And the full chain certs is there: /root/.acme.sh/xxx.com/fullchain.cer
吊销证书
如果你的私钥文件泄露或者不再使用,可以选择吊销该证书
注意:关于OCSP服务器被墙问题,请查看下方OCSP的内容
命令:
--revoke
:吊销证书
对应参数:
--domain
或-d
:指定域名
# 吊销证书
shell> acme.sh --revoke -d example.com
Try domain key first.
Revoke success.
更多详细信息可参考官方文档
删除证书
用于从acme.sh中移除该证书,但并不吊销该证书
命令:
--remove
:移除证书
对应参数:
--domain
或-d
:指定域名
# 移除证书
shell> acme.sh --remove -d example.com
example.com is removed, the key and cert files are in /root/.acme.sh/xxx.com/example.com
You can remove them by yourself.
执行证书移除命令后,acme.sh仅不再参与该证书的工作,但证书文件仍然在
~/acme.sh
文件夹下,需要用户手动删除。
ECC证书
目前最常用的密钥交换算法有 RSA
和 ECDHE
:
- RSA历史悠久,兼容性好,但计算相对较慢;
- ECDHE使用了ECC算法,计算速度快,但兼容性相对较差;
内置ECDSA公钥的证书一般被称之为ECC证书,内置RSA公钥的证书称为RSA证书;ECC算法在计算复杂度远小于RSA,但是却能在更小的长度上得到RSA的同款安全等级,一般认为 256 位 ECC Key
在安全性上等同于 3072 位 RSA Key
,所以ECC证书不仅体积小,运算速度也更快。
诚然,ECC证书有压倒性的优势,但是由于历史原因,它在旧系统的兼容性上存在不少问题,比如XP及之前的Windows系统都原生不支持(火狐浏览器除外),但是如果你不打算兼容老系统,使用ECC无疑更有优势。
你可以在这里获取更多关于ECC证书的知识。
acme.sh也申请ECC证书,仅需加上一些参数,操作上并无太大变化;目前acme.sh支持以下三类可选长度:
- ec-256(推荐使用)
- ec-384
- ec-521(不完善)
同样使用上面的示例,我们尝试为 example.com
申请主域名和泛域名证书:
申请证书使用DNS API模式:
# 添加AccessKey
shell> export Ali_Key="···"
shell> export Ali_Secret="···"
# 使用DNS API申请ECC证书,这里使用ec-256,仅需添加--keylength参数
shell> acme.sh --issue --dns dns_ali -d example.com -d *.example.com --keylength ec-256
···
Your cert is in /root/.acme.sh/xxx.com/xxx.com.cer
Your cert key is in /root/.acme.sh/xxx.com/xxx.com.key
The intermediate CA cert is in /root/.acme.sh/xxx.com/ca.cer
And the full chain certs is there: /root/.acme.sh/xxx.com/fullchain.cer
# 生成在 `~/.acme.sh/` 下的证书文件夹会加上 `_ecc` 后缀
证书安装:
# 创建证书文件夹
shell> mkdir -p /etc/ssl/certs/example.com/
# 安装时加上--ecc参数
shell> acme.sh --install-cert -d example.com --ecc \
--key-file /etc/ssl/certs/example.com/privkey.pem \
--fullchain-file /etc/ssl/certs/example.com/fullchain.pem \
--reloadcmd "systemctl force-reload nginx"
···
Installing key to:/etc/ssl/certs/example.com/privkey.pem
Installing full chain to:/etc/ssl/certs/example.com/fullchain.pem
Run reload cmd: systemctl force-reload nginx
Reload success
其他几个命令也都是加上 --ecc
参数:
# 更新证书,加上--ecc参数
shell> acme.sh --renew -d example.com --force --ecc
Renew: 'example.com'
···
Cert success.
···
Your cert is in /root/.acme.sh/xxx.com/xxx.com.cer
Your cert key is in /root/.acme.sh/xxx.com/xxx.com.key
The intermediate CA cert is in /root/.acme.sh/xxx.com/ca.cer
And the full chain certs is there: /root/.acme.sh/xxx.com/fullchain.cer
# 吊销证书,加上--ecc参数
shell> acme.sh --revoke -d example.com --ecc
Try domain key first.
Revoke success.
# 移除证书,加上--ecc参数
shell> acme.sh --remove -d example.com --ecc
example.com is removed, the key and cert files are in /root/.acme.sh/example.com
You can remove them by yourself.
nsupdate方式
如果域名使用自建DNS服务器解析(以BIND为例),由于没有特定的API接口,我们一般借助于
nsupdate
方式添加验证记录。
这种方式本质是上文讲的 DNS API模式
,即使用域名DNS解析中的TXT记录来验证所有权,而 nsupdate
指令正是设计用来向权威名称服务器添加DNS记录的。
首先,我们必须先配置Bind服务,生成 TSIG key
验证密钥,建议使用 HMAC-SHA512
加密方式
# 保存为.sh文件执行即可生成密钥
# 指定urandom作为随机数发生器可以避免部分机子长时间无法生成
# 若有高安全性要求,请替换为random发生器
read -p "KEY_NAME: " KEY_NAME
read -p "FILE_NAME: " FILE_NAME
b=$(dnssec-keygen -a hmac-sha512 -b 512 -r /dev/urandom -n USER -K /tmp foo)
cat > \./$FILE_NAME\.key <<EOF
key "$KEY_NAME" {
algorithm hmac-sha512;
secret "$(awk '/^Key/{print $2}' /tmp/$b.private)";
};
EOF
rm -f /tmp/$b.{private,key}
echo "Output as $(pwd)/$FILE_NAME.key"
将生成的密钥文件包含到Bind的配置文件中,并在对应域里信任该密钥,示例如下
···
zone "example.com" {
type master;
allow-update { key "update"; };
};
# 上下两种方式均可行,下面方案权限较为细化
zone "example.com" {
type master;
update-policy {
grant update subdomain example.com.;
};
}
···
# 添加上一步生成的密钥
include "/var/named/tsig_keys/acme.key";
···
修改完毕后重启Bind服务生效,并将密钥文件复制到申请证书的机子上,下方以 /root/.acme.sh/nsupdate.key
为例
# 先手动测试工作状态
shell> nsupdate -k /root/.acme.sh/nsupdate.key
# 指定运行Bind的名称服务器
> server ns1.example.com
# 尝试添加TXT记录
> update add demo.example.com 600 TXT "test ok"
# 显示即将添加的请求
> show
# 发送添加请求
> send
# 执行dig TXT demo.example.com命令测试是否成功添加
# 移除添加的记录
> update delete demo.example.com TXT
# 发送请求
> send
> quit
测试成功后,使用 acme.sh
申请证书
# 指定名称服务器
shell> export NSUPDATE_SERVER="ns1.example.com"
# 指定TSIG密钥
shell> export NSUPDATE_KEY="/root/.acme.sh/nsupdate.key"
# 指定验证的域名
shell> export NSUPDATE_ZONE="343.re"
# 申请证书
shell> acme.sh --issue --dns dns_nsupdate -d 343.re -d *.343.re
0 Comments