首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >牛逼!一个脚本就把系统升级到 https 了,且永久免费

牛逼!一个脚本就把系统升级到 https 了,且永久免费

作者头像
民工哥
发布2026-07-11 12:37:20
发布2026-07-11 12:37:20
2280
举报

👉体系化学习:运维工程师打怪升级进阶之路 4.0

特色专栏

MySQL/PostgreSQL/MongoDB

ElasticSearch/Hadoop/Redis

Kubernetes/Docker/DevOps

Kafka/RabbitMQ/Zookeeper

监控平台/应用与服务/集群管理

Nginx/Git/Tools/OpenStack

大家好,我是民工哥!

一个脚本就把系统升级到 https 了,且永久免费!

这到底是怎么个事呢?

接下来慢慢看。

摘要

HTTPS 早已不再是大型网站的专利,个人站长、中小企业乃至开发者测试环境,都有足够理由将全站升级到加密传输。

然而长期以来,SSL/TLS 证书的高昂费用和繁琐申请流程让许多人望而却步。

2016年 Let's Encrypt 的横空出世,以及 自动化 证书管理协议(ACME)的普及,彻底改变了这一局面。

本文将用整整 2 万字的篇幅,手把手带你从零开始,仅使用一个开源脚本 acme.sh一键将系统升级至 HTTPS,并且全程 永久免费。无论你是初次接触 SSL 的小白,还是寻求大规模部署方案的运维专家,都能从中获得完整、实用的指导。

HTTPS与免费证书的崛起

为什么需要HTTPS?

在 HTTP 明文传输的世界里,任何中间节点(路由器、代理、ISP)都可以窃听、篡改传输内容。HTTPS通过SSL/TLS协议加密通信,提供三大保障:

  • 加密性:数据密文传输,防止窃听。
  • 完整性:数据一旦被篡改,接收方能够立即发现。
  • 身份认证:客户端可通过证书验证服务器的真实身份。

如今,浏览器对HTTP站点标记“不安全”,搜索引擎降低HTTP站点的排名,甚至苹果强制要求App所有网络请求必须为HTTPS。升级HTTPS早已不是可选项,而是必选项。

SSL/TLS证书的工作原理

SSL/TLS证书是由受信任的证书颁发机构(CA)签发的电子文件,包含网站的公钥、组织信息、颁发者、有效期等。浏览器内置了CA根证书列表,当服务器出示证书时,浏览器可验证签名链,确保证书合法且未被篡改。

证书的核心生命周期分为:生成私钥 → 生成证书签名请求(CSR)→ CA验证域名所有权 → 签发证书 → 部署 → 续期

传统证书的昂贵与繁琐

在Let's Encrypt诞生之前,购买一张受信任的SSL证书每年需数百甚至数千元,而且申请流程通常需要人工审核邮件或电话,周期长达数天。对于个人开发者或中小企业,这是不小的负担。

Let's Encrypt与自动化证书管理( ACME 协议)

Let's Encrypt成立于2016年,由Mozilla、思科、Google等机构赞助,旨在为全球网站提供免费、自动化的SSL证书。其核心技术是ACME(自动证书管理环境)协议,客户端通过该 协议 与CA服务器交互,自动完成域名验证、证书申请、下载与续期。

ACME协议彻底解放了运维人员,将证书有效期缩短为90天,但通过自动化脚本实现无感续期,反而比传统一年期证书更安全(密钥轮换更频繁)。

永久免费的可能性

很多人会疑惑:“免费证书真的能永久免费吗?”答案是:是的,而且有成熟、可持续的商业模式支持。

  • Let's Encrypt作为非营利机构,依赖捐赠和企业赞助,其成本已经极低。
  • 其他免费CA如ZeroSSL、Buypass也提供类似服务,部分通过销售高级服务补贴免费证书。
  • acme.sh本身是开源软件,遵循GPLv3协议,永不开源收费

因此,“永久免费”不是营销口号,而是由开放生态和技术进步共同支撑的现实。

初识ACME脚本——acme.sh

什么是acme.sh?

acme.sh 是一个纯Shell脚本编写的ACME客户端,无需任何依赖(仅需Unix-like系统下的curl和openssl),可运行在Linux、macOS、Windows(WSL/Cygwin)上。作者是Neil Pang,项目托管于GitHub,是目前全球最受欢迎的ACME客户端之一。

acme.sh与其他ACME客户端对比

客户端

语言

特性优势

不足

acme.sh

Shell

极轻量,零依赖,DNS API最全,安装即续期

仅限类Unix

Certbot

Python

官方客户端,模块化,社区庞大

依赖复杂,重

Lego

Go

单二进制,跨平台

功能相对精简

Win-ACME

C#/.NET

Windows原生

仅Windows

acme.sh最大的优势是对DNS服务商的API支持极其丰富(超过100家),可以一键完成泛域名证书申请与自动续期。

核心特性与优势
  • 纯Shell实现:安装简单,无需编译、无需依赖数据库。
  • 零配置自动续期:一旦安装,cron任务自动执行续期。
  • 支持RSA/ECC双证书:可同时签发RSA和ECDSA密钥。
  • 内建Web服务器:支持Standalone模式验证。
  • 灵活的证书安装钩子:可自定义部署脚本。
  • 零停机更新:配合Nginx/Apache优雅重载。
安装前的准备

操作系统:建议CentOS 7+、Ubuntu 16+、Debian 8+、macOS。

工具curlopensslcrontab

域名:需要有一个已经解析到当前服务器的域名。

防火墙:若使用HTTP验证,需开放80端口;若使用DNS验证,无端口要求。

一键安装acme.sh

最简单的安装方式
代码语言:javascript
复制
curl https://get.acme.sh | sh -s email=my@example.com

或者

代码语言:javascript
复制
wget -O -  https://get.acme.sh | sh -s email=my@example.com

这一条命令,即可完成下载脚本、安装、配置别名、设置定时任务全过程。安装脚本会自动:

  1. 克隆acme.sh仓库到~/.acme.sh/
  2. 在用户家目录下创建.acme.sh目录,并设置环境变量。
  3. ~/.bashrc中添加别名acme.sh
  4. 添加每日自动续期的cron任务。
3.2 安装过程详解

执行上述命令后,终端输出大致如下:

代码语言:javascript
复制
Installing to /home/ubuntu/.acme.sh
Installed to /home/ubuntu/.acme.sh/acme.sh
Installing alias to '/home/ubuntu/.bashrc'
OK, Close and reopen your terminal to start using acme.sh, or just run 'source ~/.bashrc'
Installing cron job
no crontab for ubuntu
no crontab for ubuntu
Cron job installed. Good!

source ~/.bashrc 或重新登录后即可直接使用acme.sh命令。

升级与卸载

升级acme.sh自身

代码语言:javascript
复制
acme.sh --upgrade

自动升级(推荐):

代码语言:javascript
复制
acme.sh --upgrade --auto-upgrade

卸载acme.sh

代码语言:javascript
复制
acme.sh --uninstall
rm -rf ~/.acme.sh
配置默认CA(Let's Encrypt、ZeroSSL、Buypass等)

acme.sh 1.0以后默认CA为ZeroSSL(也完全免费),但我们可以手动切换回Let's Encrypt,或使用其他CA:

代码语言:javascript
复制
acme.sh --set-default-ca --server letsencrypt

目前支持的CA:

  • letsencrypt
  • zerossl
  • buypass
  • ssl.com
  • google(公测中)

不同CA证书有效期不同:Let's Encrypt/ZeroSSL 90天,Buypass 180天,Google 90天。

账户注册与密钥

首次签发证书时,acme.sh会自动与CA注册账户。也可提前注册:

代码语言:javascript
复制
acme.sh --register-account -m my@example.com --server letsencrypt

账户私钥保存在~/.acme.sh/ca/letsencrypt/account.key

使用acme.sh申请第一个SSL证书

单域名证书申请

假设我们有一个域名example.com,且已经解析到服务器IP,HTTP服务运行于80端口(用于验证)。执行:

代码语言:javascript
复制
acme.sh --issue -d example.com -w /var/www/html

-w指定网站根目录,acme.sh会将验证文件写入该目录下的.well-known/acme-challenge/,Let's Encrypt会通过HTTP访问该文件来验证域名所有权。

成功后,证书和私钥会保存在~/.acme.sh/example.com/目录下。

多域名(SAN)证书申请

将多个域名放在同一张证书中:

代码语言:javascript
复制
acme.sh --issue -d example.com -d www.example.com -d blog.example.com -w /var/www/html

只要第一个域名是主域名,证书的Subject Alternative Name将包含所有列出的域名。

泛域名(Wildcard)证书申请

泛域名证书(如*.example.com)可以保护所有二级子域名。必须使用DNS-01验证,因为HTTP验证无法对泛域名生效(验证域名本身不存在)。

代码语言:javascript
复制
acme.sh --issue --dns dns_cf -d example.com -d '\*.example.com'

这里的dns_cf是Cloudflare的DNS API标识,我们将在第6章详细讲解。

指定密钥长度(RSA/ECC)

默认签发RSA 2048位证书。若需ECC证书(更高效),添加--keylength参数:

代码语言:javascript
复制
acme.sh --issue -d example.com -w /var/www/html --keylength ec-256

也可同时申请RSA+ECC双证书:

代码语言:javascript
复制
acme.sh --issue -d example.com -w /var/www/html --keylength ec-256
acme.sh --issue -d example.com -w /var/www/html --keylength 2048

证书分别保存在example.com_eccexample.com目录。

证书文件说明

申请成功后,~/.acme.sh/example.com/目录下包含:

  • example.com.key:私钥
  • example.com.cer:证书
  • fullchain.cer:证书链(含中间证书)
  • ca.cer:仅CA证书

注意:永远不要手动拷贝这些文件用于部署!应使用acme.sh --install-cert命令安装证书,该命令会将证书复制到目标位置并执行重载脚本(见第7章)。

证书验证方式详解

HTTP-01 验证

原理:CA服务器访问http://<域名>/.well-known/acme-challenge/<token>,验证指定文件内容。

优点:无需DNS操作,即时生效。

缺点:需要80端口可访问;无法签发泛域名;无法用于仅限内网的服务器。

acme.sh命令:

代码语言:javascript
复制
acme.sh --issue -d example.com -w /var/www/html
DNS-01 验证

原理:在域名的_acme-challenge.<域名>下添加TXT记录,CA通过查询DNS验证所有权。

优点:可签发泛域名;无需开放HTTP端口;适合非Web服务。

缺点:需DNS服务商支持API自动化,否则手动添加记录较繁琐。

acme.sh支持通过API自动添加/删除TXT记录(需配置凭据)。如Cloudflare:

代码语言:javascript
复制
export CF_Token="你的API Token"
export CF_Account_ID="你的账户ID"
acme.sh --issue --dns dns_cf -d example.com -d '\*.example.com'
静态文件验证

与HTTP-01类似,但acme.sh不写入文件,而是要求用户提前自行放置验证文件。适合无法执行命令写入的环境。通过--webroot参数指定根目录即可。

Standalone 模式

原理:acme.sh自身启动一个临时Web服务器(监听80或443端口)来响应验证请求。无需已有Web服务器

用法

代码语言:javascript
复制
acme.sh --issue -d example.com --standalone

需确保80端口未被占用。若仅443端口可用,可用--httpport 443

其他验证方式

TLS-ALPN-01:基于TLS扩展,需443端口支持ALPN协议(Nginx等支持)。

阿里云DNSDNSPod等数十种DNS API均被acme.sh原生支持。

自动化DNS API集成

DNS-01验证自动化是acme.sh的核心优势。我们以最常用的Cloudflare和 阿里云 为例讲解。

支持哪些DNS服务商

acme.sh通过--dns指定提供商标识,目前支持超过100家,包括:

  • Cloudflare (dns_cf)
  • 阿里云 (dns_ali)
  • DNSPod (dns_dp)
  • 华为云 (dns_huaweicloud)
  • AWS Route53 (dns_aws)
  • GoDaddy (dns_gd)
  • Namecheap (dns_namecheap)
  • 以及几乎所有国内外主流服务商。

完整列表:acme.sh dnsapi目录(https://github.com/acmesh-official/acme.sh/tree/master/dnsapi "acme.sh dnsapi目录")

以Cloudflare为例配置DNS API

步骤1:在Cloudflare获取API Token (推荐)或Global API Key。

步骤2:设置环境变量。

代码语言:javascript
复制
export CF_Token="your_api_token"
export CF_Account_ID="your_account_id"

步骤3:执行签发。

代码语言:javascript
复制
acme.sh --issue --dns dns_cf -d example.com -d '\*.example.com'

acme.sh会自动创建_acme-challenge.example.com TXT记录,验证后自动删除。

步骤4:持久化凭据。可将export语句写入~/.bashrc,或使用acme.sh的--set-dns命令保存(1.5+版本):

代码语言:javascript
复制
acme.sh --set-dns dns_cf --dnssleep 30
以阿里云为例配置DNS API

阿里云用户需在控制台获取AccessKey ID和Secret(建议使用子账号,仅授权DNS管理)。

代码语言:javascript
复制
export Ali_Key="your_ak_id"
export Ali_Secret="your_ak_secret"
acme.sh --issue --dns dns_ali -d example.com -d '\*.example.com'

注意:阿里云API修改解析记录后,生效时间一般为1-10分钟,acme.sh默认等待120秒,可通过--dnssleep调整。

其他服务商配置

配置方式均类似:设置特定环境变量,然后--dns指定标识。详见acme.sh Wiki。

安全存储API凭据

永远不要将API密钥明文写在脚本中! acme.sh将凭据保存在~/.acme.sh/account.conf,此文件权限默认600,相对安全。也可通过密码管理器注入环境变量。

证书安装与部署

申请到的证书只有被Web服务器加载并对外提供HTTPS服务,才算真正“升级系统”。

安装到 Nginx

假设Nginx配置文件路径为/etc/nginx/nginx.conf,证书计划放在/etc/nginx/ssl/example.com/

代码语言:javascript
复制
acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com/fullchain.cer \
  --reloadcmd      "systemctl force-reload nginx"
————————————————
版权声明:本文为CSDN博主「油墨香^_^」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41581588/article/details/157993141

说明

  • --key-file 私钥目标路径
  • --fullchain-file 证书链完整路径(证书+中间证书)
  • --reloadcmd 安装或续期后执行的命令,通常用于重载Web服务器

Nginx配置示例:

代码语言:javascript
复制
nginx

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate     /etc/nginx/ssl/example.com/fullchain.cer;
    ssl_certificate_key /etc/nginx/ssl/example.com/example.com.key;
    # ... 其他配置
}
安装到Apache

类似地,指定--key-file--fullchain-file--reloadcmd

代码语言:javascript
复制
acme.sh --install-cert -d example.com \
  --key-file       /etc/ssl/private/example.com.key \
  --fullchain-file /etc/ssl/certs/example.com.crt \
  --reloadcmd      "systemctl force-reload apache2"

Apache配置:

代码语言:javascript
复制
apache

<VirtualHost *:443>
    ServerName example.com
    SSLEngine on
    SSLCertificateFile      /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile   /etc/ssl/private/example.com.key
</VirtualHost>
安装到Tomcat、IIS等其他服务器

acme.sh不直接支持每种服务器的配置格式,但我们可以导出证书再手动转换。

Tomcat需要PKCS12或JKS格式

代码语言:javascript
复制
acme.sh --install-cert -d example.com \
  --cert-file /tmp/example.com.pem \
  --key-file  /tmp/example.com.key \
  --fullchain-file /tmp/example.com.chain.pem

然后使用openssl转换:

代码语言:javascript
复制
openssl pkcs12 -export -in /tmp/example.com.pem -inkey /tmp/example.com.key \
               -out /tmp/example.com.p12 -name tomcat -CAfile /tmp/example.com.chain.pem -caname root

之后导入Java密钥库。

IIS需要PFX格式,类似方法转换。

复制证书到其他服务

若有多台服务器需要同一张证书,可通过scp或rsync将证书文件分发,并在远程执行重载命令。acme.sh内置了--deploy钩子,支持sftp、scp、ssh等,也可自定义脚本。

重载Web服务器

确保--reloadcmd正确执行。acme.sh会捕获命令的退出码,失败时会提示。常见重载命令:

Nginx: nginx -s reloadsystemctl reload nginx

Apache: apachectl -k gracefulsystemctl reload apache2

仅验证配置:nginx -t 后再重载。

自动续期——永不过期

续期原理

Let's Encrypt证书有效期90天,acme.sh会在证书剩余不足30天时自动续期。续期过程完全复用首次申请的参数(域名、验证方式、密钥长度等),无需重新指定。

acme.sh的自动续期机制

安装acme.sh时自动添加cron任务:

代码语言:javascript
复制
0 0 * * * "/home/ubuntu/.acme.sh"/acme.sh --cron --home "/home/ubuntu/.acme.sh" > /dev/null

每天零点执行--cron,检查所有已签发证书,自动续期并执行部署命令。

手动触发续期

立即执行续期:

代码语言:javascript
复制
acme.sh --cron

强制续期(即使未到期):

代码语言:javascript
复制
acme.sh --renew -d example.com --force
强制续期与更新

--renew仅续期指定域名,--cron处理所有。若修改了证书参数(如增加域名、更换CA),需先更新域名信息再强制续期。

检查续期状态
代码语言:javascript
复制
acme.sh --list

显示所有已签发证书的主域名、签发CA、到期时间等。

从HTTP到HTTPS的全站升级

仅仅配置好证书还不足够,我们需要确保所有流量默认走HTTPS,同时避免混合内容。

修改站点配置文件

以Nginx为例,新建HTTPS server块,并复制原有location配置。

配置301重定向

将所有HTTP请求永久重定向到HTTPS:

代码语言:javascript
复制
nginx

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

注意:若已经配置HSTS,且includeSubDomains开启,浏览器会强制HTTPS,无需HTTP跳转。但首次启用时仍需保留跳转。

混合内容问题

HTTPS页面加载HTTP资源(图片、CSS、JS)时,浏览器会阻止或标记不安全。通过Content Security Policy或直接修改资源链接解决。

代码语言:javascript
复制
# 简单粗暴:全站替换http://为https://
sed -i 's|http://|https://|g' /var/www/html/\*.html

更稳妥的方法是升级CMS插件,或使用相对协议//example.com/xxx.js

更新资源链接
  • WordPress:在后台“常规设置”中修改WordPress地址和站点地址为HTTPS,并安装SSL插件(如Really Simple SSL)。
  • 静态站点:全局搜索替换。
  • CDN:确保CDN回源使用HTTPS,并开启SSL。
测试HTTPS

使用浏览器访问https://example.com/ 查看小锁标志。

使用SSL Labs测试获取详细评分。

使用curl -I https://example.com验证重定向链。

进阶安全配置

现代SSL/TLS最佳实践
  • 禁用SSLv3、TLSv1.0/1.1,仅启用TLSv1.2/1.3。
  • 优先使用ECDHE密钥交换
  • 强加密套件:ECDHE+AES-GCM+HMAC-SHA256等。

Nginx配置示例:

代码语言:javascript
复制
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';
ssl_prefer_server_ciphers off;
10.2 配置HSTS

HTTP Strict Transport Security 告诉浏览器:未来指定时间内,此域名强制使用HTTPS,禁止任何HTTP连接。

Nginx添加响应头:

代码语言:javascript
复制
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  • max-age:秒,建议至少31536000(一年)。
  • includeSubDomains:可选,影响所有子域。
  • preload:申请加入浏览器预加载列表,无法轻易撤销。

启用HSTS前,请确保HTTPS永久可用!

OCSP Stapling

OCSP Stapling可提升TLS握手性能,由服务器主动缓存OCSP响应并发送给客户端。

Nginx配置:

代码语言:javascript
复制
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/example.com/chain.cer;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
证书透明度(Certificate Transparency)

现代CA必须将证书签发记录提交到公开日志,浏览器也要求提供SCT(签名证书时间戳)。Let's Encrypt证书已自动包含,通常无需额外配置。若需自签名嵌入,可使用acme.sh--embedded-scts(实验性)。

密钥管理与安全
  • 私钥权限:文件权限设为600,属主为运行Web服务器的用户(或root)。
  • 定期轮换密钥:acme.sh续期时默认生成新私钥,无需手动干预。
  • 备份:定期备份~/.acme.sh/目录,包含所有证书、私钥及配置文件。

监控与告警

证书过期监控

虽然acme.sh自动续期,但仍有极少数情况会失败(如DNS API过期、服务器宕机)。建议部署外部监控,例如:

  • crontab + curl 访问自己的HTTPS页面,检查证书有效期。
  • 使用商业监控服务(如StatusCake、UptimeRobot)配置SSL证书检查。
acme.sh的部署钩子

acme.sh在续期成功后会执行--reloadcmd,你可以将通知命令加入其中:

代码语言:javascript
复制
--reloadcmd "systemctl reload nginx && curl -fsS -m 10 --retry 3 -o /dev/null https://hchk.io/your-uuid"
集成通知(邮件、钉钉、微信)

acme.sh本身不支持内置邮件通知,但我们可以自定义脚本:

邮件通知示例(需安装mail命令):

代码语言:javascript
复制
--reloadcmd "systemctl reload nginx && echo '证书已续期' | mail -s 'SSL Renewal Success' admin@example.com"

钉钉机器人

代码语言:javascript
复制
--reloadcmd "systemctl reload nginx && curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' -H 'Content-Type: application/json' -d '{\"msgtype\":\"text\",\"text\":{\"content\":\"SSL证书续期成功\"}}'"
定期安全扫描

推荐使用 testssl.sh定期扫描,检查SSL配置漏洞,并可将报告发送到日志系统。

大规模部署与自动化

多服务器证书同步

单张证书部署在多台服务器上,可以使用以下策略:

  • 共享存储:将证书保存到NFS/S3,各服务器挂载。
  • 同步脚本:在证书续期服务器执行rsync到其他节点。
  • acme.sh的远程部署功能
代码语言:javascript
复制
acme.sh --deploy -d example.com --deploy-hook ssh \
  --deploy-ssh-user root \
  --deploy-ssh-server 192.168.1.10 \
  --deploy-cert /etc/nginx/ssl/example.com/fullchain.cer \
  --deploy-key  /etc/nginx/ssl/example.com/example.com.key \
  --deploy-reloadcmd "systemctl reload nginx"
集中式证书管理

对于几十个域名,可编写循环脚本批量签发。对于成百上千个域名,建议搭建ACME自动化平台,如Step CA + acme.sh,实现私有CA与公网CA结合。

使用acme.sh的远程部署功能

acme.sh支持多种部署钩子(deploy hook),详见Wiki(https://github.com/acmesh-official/acme.sh/wiki/deployhooks "Wiki")。

结合Ansible、Salt等配置管理工具

将acme.sh安装和证书申请写成Ansible playbook,实现基础设施即代码。示例任务:

代码语言:javascript
复制
- name:Installacme.sh
shell:curlhttps://get.acme.sh|sh-semail={{acme_email}}
args:
    creates:/root/.acme.sh/acme.sh

-name:Issuecertificate
shell:/root/.acme.sh/acme.sh--issue--dnsdns_ali-d{{domain}}-d'*.{{ domain }}'
environment:
    Ali_Key:"{{ aliyun_ak }}"
    Ali_Secret:"{{ aliyun_sk }}"
when:ssl_certisnotexists

故障排除与常见问题

申请失败原因
  • 域名解析未生效:检查A记录。
  • 验证超时:防火墙阻止80端口(HTTP-01)或DNS更新延迟(DNS-01)。
  • 重复申请过多:Let's Encrypt有速率限制(每域名每小时5次失败)。
  • CSR信息错误:无需手动生成CSR,acme.sh自动完成。
验证失败排查

HTTP-01:手动访问http://example.com/.well-known/acme-challenge/xxx,确认返回正确token。

DNS-01:使用dig _acme-challenge.example.com txt查看记录是否已生效。增加--dnssleep 300以等待更长时间。

续期失败处理
  • 检查cron是否运行:crontab -l
  • 手动执行acme.sh --cron --debug查看详细日志。
  • 验证API凭据是否过期(DNS-01)。
  • 若某域名已停用,使用acme.sh --remove -d example.com移除。
兼容性问题
  • 旧版OpenSSL:某些系统(CentOS 6)openssl版本过低,不支持ECC证书。可降级至RSA或升级openssl。
  • Windows WSL:acme.sh可运行,但需处理路径问题。
日志查看

acme.sh默认日志输出到终端,可通过--debug参数输出更详细信息。持久化日志:

代码语言:javascript
复制
acme.sh --cron --debug >> /var/log/acme.sh.log 2>&1

案例实战——零成本将个人博客升级HTTPS

环境介绍
  • 操作系统:Ubuntu 20.04 LTS
  • Web服务器:Nginx 1.18
  • 域名example.com(托管在阿里云)
  • 博客程序:WordPress
从零开始安装acme.sh
代码语言:javascript
复制
curl https://get.acme.sh | sh -s email=admin@example.com
source ~/.bashrc
acme.sh --set-default-ca --server letsencrypt
申请泛域名证书

使用阿里云DNS API:

代码语言:javascript
复制
export Ali_Key="LTAI5t...xxxx"
export Ali_Secret="LTAI5t...xxxx"
acme.sh --issue --dns dns_ali -d example.com -d '*.example.com'

等待约2分钟,看到Cert success.即成功。

配置Nginx启用HTTPS

创建目录/etc/nginx/ssl/example.com/,安装证书:

代码语言:javascript
复制
acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com/fullchain.cer \
  --reloadcmd      "systemctl reload nginx"

编辑Nginx配置文件,添加443监听,复制原有根目录配置。然后重载Nginx。

设置自动续期

acme.sh的cron已存在,无需额外设置。测试续期:

代码语言:javascript
复制
acme.sh --renew -d example.com --force
验证结果
  • 浏览器访问https://example.com,显示安全锁。
  • 使用SSL Labs测试,得到A+(需额外配置HSTS、OCSP Stapling)。
  • 设置301重定向HTTP→HTTPS,并启用HSTS。

永久免费的商业模式探讨

Let's Encrypt的运营与赞助

Let's Encrypt由Linux基金会托管,2021年时年度预算约360万美元,主要来自Google、Mozilla、Facebook、Cisco、AWS等企业赞助以及个人捐赠。其成本包括工程师薪酬、服务器、带宽等。证书签发完全免费,将来也会坚持免费。

acme.sh的开源与捐赠

acme.sh项目作者Neil Pang为独立开发者,通过GitHub Sponsors、PayPal捐赠等方式获得支持。项目遵循GPLv3协议,任何人可以免费使用、修改,甚至商用。因此acme.sh本身也是永久免费的。

其他免费CA的介绍
  • ZeroSSL:提供类似服务,Web界面友好,免费版限制3个证书,但ACME方式无限制。
  • Buypass:有效期180天,需挪威CA,DNS验证支持较少。
  • Google Trust Services:全球信任,目前公测中,完全免费。

来源:https://youmoxiang.blog.csdn.net/arti cle/details/157993141

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 摘要
  • HTTPS与免费证书的崛起
    • 为什么需要HTTPS?
    • SSL/TLS证书的工作原理
    • 传统证书的昂贵与繁琐
    • Let's Encrypt与自动化证书管理( ACME 协议)
    • 永久免费的可能性
  • 初识ACME脚本——acme.sh
    • 什么是acme.sh?
    • acme.sh与其他ACME客户端对比
    • 核心特性与优势
    • 安装前的准备
  • 一键安装acme.sh
    • 最简单的安装方式
    • 3.2 安装过程详解
    • 升级与卸载
    • 配置默认CA(Let's Encrypt、ZeroSSL、Buypass等)
    • 账户注册与密钥
  • 使用acme.sh申请第一个SSL证书
    • 单域名证书申请
    • 多域名(SAN)证书申请
    • 泛域名(Wildcard)证书申请
    • 指定密钥长度(RSA/ECC)
    • 证书文件说明
  • 证书验证方式详解
    • HTTP-01 验证
    • DNS-01 验证
    • 静态文件验证
    • Standalone 模式
    • 其他验证方式
  • 自动化DNS API集成
    • 支持哪些DNS服务商
    • 以Cloudflare为例配置DNS API
    • 以阿里云为例配置DNS API
    • 其他服务商配置
    • 安全存储API凭据
  • 证书安装与部署
    • 安装到 Nginx
    • 安装到Apache
    • 安装到Tomcat、IIS等其他服务器
    • 复制证书到其他服务
    • 重载Web服务器
  • 自动续期——永不过期
    • 续期原理
    • acme.sh的自动续期机制
    • 手动触发续期
    • 强制续期与更新
    • 检查续期状态
  • 从HTTP到HTTPS的全站升级
    • 修改站点配置文件
    • 配置301重定向
    • 混合内容问题
    • 更新资源链接
    • 测试HTTPS
  • 进阶安全配置
    • 现代SSL/TLS最佳实践
    • 10.2 配置HSTS
    • OCSP Stapling
    • 证书透明度(Certificate Transparency)
    • 密钥管理与安全
  • 监控与告警
    • 证书过期监控
    • acme.sh的部署钩子
    • 集成通知(邮件、钉钉、微信)
    • 定期安全扫描
  • 大规模部署与自动化
    • 多服务器证书同步
    • 集中式证书管理
    • 使用acme.sh的远程部署功能
    • 结合Ansible、Salt等配置管理工具
  • 故障排除与常见问题
    • 申请失败原因
    • 验证失败排查
    • 续期失败处理
    • 兼容性问题
    • 日志查看
  • 案例实战——零成本将个人博客升级HTTPS
    • 环境介绍
    • 从零开始安装acme.sh
    • 申请泛域名证书
    • 配置Nginx启用HTTPS
    • 设置自动续期
    • 验证结果
  • 永久免费的商业模式探讨
    • Let's Encrypt的运营与赞助
    • acme.sh的开源与捐赠
    • 其他免费CA的介绍
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档