2026免费SSL证书申请部署与自动续签全攻略

最近这一两年,只要手上有网站、有服务器,就绕不开 SSL 证书这件事。不管是个人博客、企业官网还是内部系统,地址栏前面那个小锁图标,直接决定了访客和平台对你的信任度。我自己从最早手动买付费证书,到后来摸索免费方案、折腾自动续签、踩遍各种部署坑,算是把这条路上的弯弯绕绕基本走完了。这篇就按 2026 年的实际情况,把免费 SSL 证书的申请、续期、部署和排错从头到尾捋一遍,给正在折腾或者准备折腾的朋友一份可以直接照做的参考。

1. 免费SSL证书到底能省多少事?

1.1 为什么所有站长都在折腾SSL证书

先说个大实话:现在的浏览器和搜索引擎对 HTTPS 的强制已经到了“没有证书就活不下去”的程度。Chrome 对 HTTP 站点直接标记为“不安全”,微信内置浏览器也经常拦截未加密链接,小程序接口更是强制要求 HTTPS。至于搜索引擎,HTTPS 已经是基础加分项,虽然不至于因为你没上证书就彻底不收录,但在同等内容质量下,有证书的站点排名更有优势是行业共识。

所以这早就不是“要不要装”的问题,而是“怎么又快又稳地装上”。免费证书和付费证书在这件事上,能解决的底层问题是一样的:在访客浏览器和你的服务器之间建立一条加密通道。差别主要在服务等级协议、保险赔付额度、兼容范围和有效期管理上。对绝大多数个人站长、中小企业官网、内部工具系统来说,免费证书完全够用,真正需要付费证书的场景其实是电商平台、金融业务、大型政企门户这类对信任背书要求极高的场景。

1.2 免费证书和付费证书的核心差异

我直接给一个对比表,方便你判断自己到底需要哪种:

对比维度免费证书(Let's Encrypt / ZeroSSL / 云厂商DV)付费证书(企业级 OV / EV)
申请成本0 元每年几百到几千不等
签发速度几分钟到几小时OV 需要 1-3 个工作日,EV 更久
有效期90 天(Let's Encrypt)或 90 天(ZeroSSL)通常 1 年,也有 2 年但逐年缩短
信任等级DV(仅验证域名所有权)企业身份验证/扩展验证
浏览器兼容性主流现代浏览器全部支持,老旧设备有差异兼容性最好
适合场景个人博客、中小网站、API接口、NAS、内网穿透电商、金融、政企官网

什么叫 DV 证书?就是只验证“这个域名是不是你的”,不验证你是哪家公司、什么身份。验证方式主要有三种:在域名解析里加一条 DNS TXT 记录、在网站根目录放一个验证文件、或者通过 HTTP 访问特定路径。只要你能证明自己能控制这个域名,CA 就给你签发证书。这个验证过程通常是全自动的,所以免费证书才能做到 90 天有效期还能自动续期。

再说白一点:免费证书省下的不只是钱,主要是省去了填申请资料、传真营业执照、等人工审核这些繁琐流程。我见过很多朋友第一次申请付费证书时被 OV 验证折腾得够呛,反观免费证书,只要域名解析权限在自己手里,十分钟之内就能搞定。

2. 2026年还在用的4种免费方案

2.1 方案一:Let's Encrypt + Certbot(全能型)

Let's Encrypt 是目前市场占有率最高的免费 CA,它背后的核心逻辑是把证书签发完全自动化。Certbot 是 EFF(电子前沿基金会)出品的官方客户端,在 Ubuntu、Debian、CentOS 这些主流 Linux 发行版的软件源里都能直接安装。

安装方式很简单:

sudo apt update sudo apt install certbot python3-certbot-nginx

如果你用的是 Nginx,装好之后一条命令就可以完成申请和自动配置:

sudo certbot --nginx -d example.com -d www.example.com

Certbot 会自动检测 Nginx 配置、修改配置文件、把证书路径指过去,然后重载服务。整个过程非常丝滑,基本不需要你手动改任何配置文件。

如果你是 Apache 用户,把命令里的nginx换成apache即可:

sudo apt install certbot python3-certbot-apache sudo certbot --apache -d example.com

如果你不想让 Certbot 帮你改 Web 服务器配置,也可以用 webroot 模式,它只负责申请证书,把验证文件放到指定目录下,然后你自己手动配置 Web 服务器引用证书文件:

sudo certbot certonly --webroot -w /var/www/example -d example.com

申请成功后会生成四个文件:

/etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem /etc/letsencrypt/live/example.com/cert.pem /etc/letsencrypt/live/example.com/chain.pem

实际部署时只需关注fullchain.pem(证书链)和privkey.pem(私钥)。这两个文件后面配置 Nginx、Apache、Tomcat、群晖、FTP 服务都会用到。

2.2 方案二:acme.sh + ZeroSSL(脚本党首选)

acme.sh 是一个纯 Shell 写的 ACME 客户端,最大的优势是脚本化、无依赖、安装完就常住用户目录,通过定时任务完成续签。它默认使用 ZeroSSL 作为 CA,也可以切回 Let's Encrypt。

安装就一条命令:

curl https://get.acme.sh | sh

安装完成后会把环境变量写入用户配置文件(通常是~/.bashrc或~/.profile),然后你可以通过 DNS API 方式签发证书。这种方式适合不方便暴露 80 端口、或者域名在 Cloudflare、阿里云、腾讯云等平台管理的场景。

比如你的域名 DNS 托管在阿里云,先在阿里云控制台创建 AccessKey,然后:

export Ali_Key="你的AccessKey ID" export Ali_Secret="你的AccessKey Secret" acme.sh --issue --dns dns_ali -d example.com -d *.example.com

看到没有,这是我最喜欢它的原因之一:支持通配符证书。Let's Encrypt 通过 Certbot 也能申请通配符证书,但需要用 DNS 验证,配置上稍微麻烦一些。acme.sh 通过各家 DNS 服务商的 API 自动添加 TXT 记录,然后自动验证、自动删除,全程不需要手动操作。

如果你域名在 Cloudflare:

export CF_Token="你的Cloudflare API Token" acme.sh --issue --dns dns_cf -d example.com -d *.example.com

安装证书到指定目录:

acme.sh --install-cert -d example.com \ --key-file /etc/ssl/example.com/privkey.pem \ --fullchain-file /etc/ssl/example.com/fullchain.pem \ --reloadcmd "systemctl reload nginx"

这个--reloadcmd参数非常实用,证书更新后自动重载 Web 服务,无缝衔接。

2.3 方案三:阿里云/腾讯云免费DV证书(国内访问友好型)

如果你人在国内、服务器也部署在国内,那么国内云厂商提供的免费 DV 证书值得特别关注。原因还是那句话:云厂商的证书做了一些针对国内网络环境和旧设备的兼容性优化,尤其是老版本 Android、Windows 7 等场景,某些国外 CA 的证书链在国内设备上偶尔会展示不完全。当然这不是绝对,但实际遇到的概率确实存在。

以阿里云为例,进入数字证书管理服务(Certificate Management Service),在 SSL 证书管理中找到免费证书申请入口。每年可以申请一定数量的免费 DV 证书,单张有效期一般是 3 个月,到期前可以在控制台申请新证书替换。

整个流程是:

  1. 在控制台选择“申请免费证书”,输入域名
  2. 选择验证方式:DNS 验证(推荐)或文件验证
  3. 如果域名解析也在阿里云,DNS 验证可以一键自动添加,几分钟内签发
  4. 签发后点击“下载”,根据你的服务器类型选择 Nginx、Apache、Tomcat、IIS 或其他格式

下载下来的压缩包里就是证书文件和私钥。Nginx 部署时把.pem和.key文件上传到服务器,在 Nginx 配置里指向即可。

腾讯云的流程基本一致,控制台路径是“SSL 证书”->“我的证书”->“申请免费证书”。值得留意的是,腾讯云针对部分场景也提供了更长时间或更大数量的免费额度,申请页面会有明确说明。

这种方案最大的优点:对国内用户极其友好,中文控制台、文档齐全、客服响应快,遇到问题可以提工单解决。缺点就是有效期短、需要定期去控制台操作,除非你用 API 方式做自动化,否则没法像 acme.sh 那样全自动续签。

2.4 方案四:宝塔面板/1Panel一键申请(小白救星)

如果你用的是宝塔面板或 1Panel 这类可视化运维面板,申请证书这件事已经简单到“点几下鼠标”的程度了。以宝塔为例,在网站设置 -> SSL 证书栏目里,选择 Let's Encrypt,勾选你要的域名,点申请。一分钟内证书就自动装好并配置到网站配置里,勾上“自动续签”后就再也不用管了。

1Panel 也是类似逻辑,在网站页面选择域名,然后在证书管理里申请 Let's Encrypt 证书,支持 DNS 验证和 HTTP 验证。1Panel 的证书管理界面做得比宝塔更清晰一些,能看到证书的到期时间、签发机构、域名列表,续签状态也有明确记录。

为什么把面板方案单独列为一种?因为我实操下来发现,面板不仅帮你完成证书申请和安装,还会自动处理续签、自动重载服务、自动检查证书剩余天数,这一套组合拳对不熟悉命令行操作的朋友来说简直就是救命稻草。哪怕你以后不想用面板了,也可以把面板生成的证书文件路径记下来,手动迁移到其他环境。

我个人的建议是:如果你只有一个站点、两三台服务器,面板方案是最省心的选择。如果你服务器数量多、域名多、还涉及通配符证书,建议好好学习 acme.sh,它能帮你省下大量重复劳动。

3. 自动续签的三种姿势

3.1 定时任务续签(Certbot 与 acme.sh 的 cron 玩法)

免费证书有效期短,所以自动续签不是“可选项”,而是“必需品”。Let's Encrypt 和 ZeroSSL 的证书有效期都是 90 天。要是你哪天忘了续期,浏览器直接报错,访客一进站点就看到一个红色的“不安全”警告,那种体验真的是灾难。我自己就吃过这个亏,凌晨三点被监控报警吵醒,原因是证书过期导致接口大面积报错。后来老老实实把自动续签流程规范化。

Certbot 安装的时候会在/etc/cron.d/下生成一个定时任务文件,默认每天检查两次,如果证书距离过期不到 30 天就自动续期。你可以用下面这个命令手动验证续签流程是否正常:

sudo certbot renew --dry-run

这个--dry-run参数很重要,它会真实走一遍 ACME 协议的交互流程,但不会真的替换证书。我建议每次改完配置都先跑一遍这个命令确认没毛病。

acme.sh 安装时会自动注册一个 crontab 任务:

crontab -l # 你会看到类似这样的输出: # 24 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

默认是每天凌晨 0 点 24 分检查一次,如果距离过期不足 60 天就会自动续签。这个频率是合理的,因为 ACME 协议允许在证书过期前 30 天内续签(实际上 Let's Encrypt 在过期前 60 天也接受续签请求,acme.sh 采用 60 天阈值就更为稳妥了)。你也可以手动执行:

acme.sh --cron

如果续签成功,acme.sh 会自动执行你在安装证书时指定的--reloadcmd命令,比如systemctl reload nginx。这意味着证书更新后服务立即生效,不需要你半夜爬起来手动重启。

3.2 容器化部署自动续签(Nginx Proxy Manager 与 Docker 场景)

Docker 环境下的证书自动续签是另一个高频场景。如果你用 Docker 部署网站、内部工具或者 NAS 应用,推荐看一下 Nginx Proxy Manager(NPM)。这个项目把 Nginx 的配置、SSL 证书申请和自动续签全部封装成一个 Web 管理界面,非常友好。

NPM 的做法是,在配置代理主机时直接选择“Let's Encrypt”证书,填写域名和邮箱,点保存后自动完成签发。它内部内置了一个定时任务,默认每隔一段时间检查所有证书,如果发现即将过期就自动续签。整个过程中不需要进入容器,不需要执行命令,几乎所有操作都在浏览器里完成。

使用 Docker 部署 NPM 的参考 docker-compose.yml:

version: '3.8' services: npm: image: jc21/nginx-proxy-manager:latest container_name: nginx-proxy-manager restart: always ports: - '80:80' - '443:443' - '81:81' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt

部署完通过http://服务器IP:81访问管理后台,默认用户名密码是admin@example.com/changeme,登录后记得第一时间改掉。添加 SSL 证书就在 “SSL Certificates” 页面操作。

如果你是自己用 Docker Compose 部署了一堆服务,不希望额外引入一个反向代理层,也可以在容器内使用命令行版 acme.sh。比如在 Alpine 镜像里:

apk add --no-cache curl openssl curl https://get.acme.sh | sh \ && export Ali_Key="xxx" \ && export Ali_Secret="xxx" \ && /root/.acme.sh/acme.sh --issue --dns dns_ali -d example.com --standalone

这种方式适合把证书放到共享卷中,多个容器引用同一份证书文件。

3.3 云证书到期提醒与手动续期(阿里云和腾讯云控制台操作实录)

云厂商的免费证书目前没法做到全自动续签,因为它们的证书签发流程需要在你登录控制台后手动确认、重新申请。但好消息是,阿里云和腾讯云都提供了比较完善的到期提醒机制,一般会提前 30 天、15 天、7 天给你发短信、邮件和站内信。

在阿里云控制台的“SSL 证书管理”页面,可以看到每个证书的状态和到期时间。到期前重新申请一张,然后在“证书列表”里找到新证书,点击“部署”,按提示选择你要部署的云产品(Nginx 服务器、负载均衡 SLB、CDN 等)。如果你的域名和 Web 服务器不在同一台云服务器上,下载证书文件到服务器上替换即可。

腾讯云的操作路径类似:SSL 证书 -> 证书列表 -> 申请免费证书 -> 填写域名信息 -> DNS 验证 -> 签发下载。需要注意的是,免费证书一般不支持同一主体在同一时间重复申请同域名证书,要等上一张过期或主动撤销后才重新申请。

这里我给一个实操建议:把云厂商证书和 acme.sh 做一个“双保险”。也就是说,你用 acme.sh 管理主要证书并自动续签,同时再申请一张云厂商证书作为备用。万一 acme.sh 因为域名解析问题或 API 变更导致续签失败,你还有一张云厂商证书能临时代替,不至于直接裸奔。

4. 部署避坑指南(含配置模板)

4.1 Nginx 部署:最容易踩的坑是证书链不完整

Nginx 部署 SSL 证书的配置文件本身不复杂,核心就三行:

server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/ssl/cert.pem; ssl_certificate_key /etc/ssl/key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; }

我最常看到的坑有两个。第一个是证书链不完整,很多人只填了cert.pem,没有填 CA 证书链,导致 Android 手机和某些桌面浏览器报“证书链不完整”。解决方案是使用fullchain.pem而不是cert.pem,因为前者包含了完整的证书链。第二个坑是私钥和证书不匹配,这种情况通常是因为同时申请了多个域名的证书,不小心把 A 域名的私钥用到了 B 域名的证书上。检查方法很简单:

openssl x509 -in fullchain.pem -noout -modulus | md5sum openssl rsa -in privkey.pem -noout -modulus | md5sum

两个命令输出的哈希值一致,说明证书和私钥配对。不一致就去服务商重新下载或者重新申请。

4.2 群晖换证书后提示“抱歉,您所指定的页面不存在”

群晖 NAS 换证书是个高频操作,但也是最容易出奇怪问题的地方。很多用户从阿里云或 Let's Encrypt 申请了 Nginx 格式的证书,在群晖控制面板 -> 安全性 -> 证书里导入之后,套件正常打开了,但点击“存储空间管理员”或某个应用图标时提示“抱歉,您所指定的页面不存在”。

我查了很多资料,也自己复现过,核心原因是群晖在导入新证书后,没有自动把相关服务的端口和证书关联起来,或者证书导入过程中出现了权限问题。尤其是在群晖 DSM 7.x 版本中,如果你使用非管理员账号或者通过 WebDAV 方式导入证书,容易出现名称冲突或服务变量未更新的问题。

解决办法按顺序尝试:

  1. 在控制面板 -> 登录门户 -> 高级 -> 反向代理中,确认各服务的反向代理规则仍然指向正确端口
  2. 在控制面板 -> 安全性 -> 证书中,选中刚导入的证书,点击“配置”,把需要用到 HTTPS 的套件和服务都勾选上去
  3. 如果还是提示页面不存在,在 SSH 登录群晖后执行:
sudo synosystemctl restart nginx sudo synosystemctl restart httpd
  1. 如果还不行,把证书改为默认证书,重启群晖,通常能解决

我遇到过一个更隐蔽的情况:群晖内置的 Apache 服务依赖一个根证书文件,导入新证书后这个文件却被替换成了新的 CA 链,导致反向代理服务无法启动。这种情况只能用 SSH 去/usr/syno/etc/www/certificate/目录下检查各服务的证书状态。如果搞不定就直接把证书删除,重新导入,注意一定要选择“替换现有证书”而不是新增证书。

4.3 Tomcat 和 .NET 部署:cer 转 PFX 的正确姿势

Tomcat 的坑在于格式转换。很多服务商默认给的是 Nginx 格式的.pem/.crt/.key,但 Tomcat 需要的是 JKS 或 PKCS12 格式。JKS 是老一代 Java KeyStore 格式,配置起来相对繁琐,而 PKCS12 是公开标准,用起来更方便、兼容性也更好,所以这里推荐转成 PKCS12(即.pfx/.p12文件)。

我以“cer 转 tomcat ssl 证书 pfx”这个最常见的问题为例。假设你从阿里云下载的压缩包里包含了xxx.pem和xxx.key两个文件,转换命令如下:

openssl pkcs12 -export \ -in xxx.pem \ -inkey xxx.key \ -out server.pfx \ -name tomcat \ -passout pass:你的密码

转换完成后,在 Tomcat 的conf/server.xml里增加或修改一个 Connector:

注意:这里的certificateKeystoreFile路径是相对于 Tomcat 安装目录的,如果你放在 Tomcat 的conf/目录下就写conf/server.pfx。如果你的服务商直接给的是.cer文件,没有私钥,那没法直接转 pfx。.cer通常只是公钥证书,缺少私钥信息,需要联系服务商要完整的证书和私钥文件。这一点我见过太多人踩坑了,以为拿到.cer就能用,结果在 Tomcat 里怎么配都启动不了。

.NET 环境(IIS)下的操作也类似,但 IIS 的导入过程更傻瓜一点:打开 IIS 管理器,选择服务器节点,双击“服务器证书”,点“导入”,选择.pfx文件,填入密码即可。IIS 本身只支持 pfx 格式,所以如果你手头只有 pem 文件,也先要用上面的 OpenSSL 命令转换成 pfx 再导入。

4.4 vsftpd 和 FTP 服务的证书配置

FTP 服务走的是 20/21 端口,默认不加密,但如果你在公网环境下跑 FTP,强烈建议开启 FTPS(FTP over SSL/TLS)。vsftpd 是 Linux 上最常见的 FTP 服务端,它的证书配置其实很简单,但绝大多数人根本没配过。

在vsftpd.conf中添加:

ssl_enable=YES allow_anon_ssl=NO force_local_data_ssl=YES force_local_logins_ssl=YES ssl_tlsv1=YES ssl_sslv2=NO ssl_sslv3=NO rsa_cert_file=/etc/ssl/certs/example.com/fullchain.pem rsa_private_key_file=/etc/ssl/private/example.com/privkey.pem

配置完成后重启服务:

systemctl restart vsftpd

这里有个常见问题:如果客户端连接时报“服务器使用了一个安全证书,该证书无法被验证”或类似 TLS 警告,通常是因为客户端把 FTPS 的证书链加载不完整。解决方案是在客户端中把 CA 证书导入信任库,或者使用主动模式(Active Mode)连接。vsftpd 的rsa_cert_file最好用fullchain.pem而不是cert.pem,否则部分 FTP 客户端在验证服务器身份时会报错。

另外提醒一句,如果你的 vsftpd 同时开启了虚拟用户和被动模式,记得检查pasv_min_port和pasv_max_port配置,确保防火墙放行了这些端口,否则会出现能连上但列不出目录的诡异问题。这些坑和证书本身无关,但排查过程会让人误以为是证书的问题。

4.5 Docker 容器、反向代理和证书热更新

Docker 部署场景里,最常见的证书更新问题是“容器已经挂载了证书文件,但更新证书后容器内的服务没有生效”。原因很简单:如果你用的是 bind mount 方式挂载证书文件,比如-v /etc/ssl/example.com:/etc/nginx/ssl:ro,那么证书文件更新后,Nginx 进程不会自动感知,必须重启容器或执行nginx -s reload。

解决方案有三种:

  1. 每次续签后,重启容器或执行docker exec <容器名> nginx -s reload
  2. 使用支持热加载的镜像,比如nginx:latest配合acme.sh --reloadcmd "docker restart nginx"的 reload 命令来做自动更新
  3. 使用专门的代理容器(如 Nginx Proxy Manager、Traefik),它们内部已经实现了证书监控和自动重载

如果你是 Traefik 用户,直接通过 Let's Encrypt 配置证书存储,证书的申请、更新、加载全部由 Traefik 自动管理,不需要你手工干预。这种方案在微服务和容器化场景中是最省心的。

5. 常见问题速查表与排错思路

这一节我把实战中遇到的典型问题整理成速查表,出了问题先对着表格排查,大概率能解决一半以上的问题。

症状常见原因解决方法
浏览器提示证书无效证书过期执行certbot renew或acme.sh --cron
浏览器提示证书链不完整只配置了cert.pem,未使用fullchain.pem替换为 fullchain 文件
私钥与证书不匹配申请了多张证书,用错私钥用 md5sum 检查 modulus 配对
Android 手机访问失败证书链缺少中间证书使用 fullchain,并在 HTTP 层补齐证书链
群晖页面提示“页面不存在”证书关联服务未配置在安全性 -> 证书 -> 配置中勾选所有服务
续签命令成功但服务未生效未重载 Web 服务执行systemctl reload nginx或docker restart
DNS 验证一直不通过解析记录有缓存等待 TTL 过期或用dig命令确认记录存在
Tomcat 启动报 Keystore 错误格式不是 PKCS12 或密码错误确认使用 pfx 格式和正确密码
vsftpd 连接报证书警告证书链不完整或客户端不信任使用 fullchain.pem 并导入 CA 证书
acme.sh 申请时提示 400 错误DNS API 权限不足或域名不在该账号下检查 AccessKey 权限和政策

我再补充几个排错时必用的命令。证书过期时间排查:

openssl x509 -enddate -noout -in fullchain.pem

查看证书内容和 SAN 域名列表:

openssl x509 -text -noout -in fullchain.pem | grep -A 1 "Subject Alternative Name"

测试 TLS 握手和证书链:

openssl s_client -connect example.com:443 -servername example.com

6. 最后再分享两个实用小技巧

6.1 多个域名统一管理:先规划再用工具

如果你有多个域名、多台服务器,强烈建议在一开始就规划好证书管理方案。我自己现在的方式是:所有域名统一用 acme.sh 管理,DNS 解析放在 Cloudflare 或阿里云,通过 API 自动验证。每台服务器的证书都存放到固定的目录结构里,比如/etc/ssl/<域名>/fullchain.pem,方便后续脚本统一处理。这种方式配合监控工具(比如 UptimeRobot 或自建的 Prometheus 黑盒探针)能确保任何一张证书过期前都被及时发现。

6.2 免费证书有效期只有90天,其实不是坏事

很多人觉得 90 天有效期太麻烦,说实话我一开始也这么觉得。但后来想明白了一件事:短有效期强制你完成自动化,反而是好事。证书是安全链路里最需要自动化管理的环节之一,一旦自动化跑通,你就再也不用担心证书过期。现代 CA 和 ACME 协议把续签做成了一件非常顺滑的事,反而比那种“申请一次用一年”的模式更安全——每年一次的人工操作基本无法避免遗忘或疏漏,而每天自动检查一次几乎不可能出问题。

如果你还在犹豫要不要上免费证书,我的建议是:直接上。选一种适合你场景的方案,花半小时把自动续签配好,然后把这个话题忘掉。之后你会发现,访问地址栏里那把锁,已经是你最不用担心的事情了。