最近这一两年,只要手上有网站、有服务器,就绕不开 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.comCertbot 会自动检测 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 个月,到期前可以在控制台申请新证书替换。
整个流程是:
- 在控制台选择“申请免费证书”,输入域名
- 选择验证方式:DNS 验证(推荐)或文件验证
- 如果域名解析也在阿里云,DNS 验证可以一键自动添加,几分钟内签发
- 签发后点击“下载”,根据你的服务器类型选择 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 方式导入证书,容易出现名称冲突或服务变量未更新的问题。
解决办法按顺序尝试:
- 在控制面板 -> 登录门户 -> 高级 -> 反向代理中,确认各服务的反向代理规则仍然指向正确端口
- 在控制面板 -> 安全性 -> 证书中,选中刚导入的证书,点击“配置”,把需要用到 HTTPS 的套件和服务都勾选上去
- 如果还是提示页面不存在,在 SSH 登录群晖后执行:
sudo synosystemctl restart nginx sudo synosystemctl restart httpd- 如果还不行,把证书改为默认证书,重启群晖,通常能解决
我遇到过一个更隐蔽的情况:群晖内置的 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。
解决方案有三种:
- 每次续签后,重启容器或执行
docker exec <容器名> nginx -s reload - 使用支持热加载的镜像,比如
nginx:latest配合acme.sh --reloadcmd "docker restart nginx"的 reload 命令来做自动更新 - 使用专门的代理容器(如 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.com6. 最后再分享两个实用小技巧
6.1 多个域名统一管理:先规划再用工具
如果你有多个域名、多台服务器,强烈建议在一开始就规划好证书管理方案。我自己现在的方式是:所有域名统一用 acme.sh 管理,DNS 解析放在 Cloudflare 或阿里云,通过 API 自动验证。每台服务器的证书都存放到固定的目录结构里,比如/etc/ssl/<域名>/fullchain.pem,方便后续脚本统一处理。这种方式配合监控工具(比如 UptimeRobot 或自建的 Prometheus 黑盒探针)能确保任何一张证书过期前都被及时发现。
6.2 免费证书有效期只有90天,其实不是坏事
很多人觉得 90 天有效期太麻烦,说实话我一开始也这么觉得。但后来想明白了一件事:短有效期强制你完成自动化,反而是好事。证书是安全链路里最需要自动化管理的环节之一,一旦自动化跑通,你就再也不用担心证书过期。现代 CA 和 ACME 协议把续签做成了一件非常顺滑的事,反而比那种“申请一次用一年”的模式更安全——每年一次的人工操作基本无法避免遗忘或疏漏,而每天自动检查一次几乎不可能出问题。
如果你还在犹豫要不要上免费证书,我的建议是:直接上。选一种适合你场景的方案,花半小时把自动续签配好,然后把这个话题忘掉。之后你会发现,访问地址栏里那把锁,已经是你最不用担心的事情了。