前言介绍
在互联网环境中,网站的安全性是用户信任的基石。当你的网站没有部署SSL证书时,浏览器会显示“不安全”的警告,这不仅影响用户体验,还会导致搜索引擎降低排名。SSL证书的核心作用是对网站与访客之间的数据传输进行加密,防止信息被窃取或篡改。对于个人站长或中小企业来说,购买商业SSL证书往往需要数百甚至上千元,而免费的SSL证书(如Let's Encrypt、ZeroSSL、阿里云/腾讯云免费版)完全能够满足日常需求,它们同样提供A级加密强度,有效期为90天(可自动续期)。本教程将手把手教你从零开始申请并配置免费SSL证书,覆盖服务器端和CDN场景,无论你是使用Nginx、Apache还是宝塔面板,都能找到对应的操作方案。
前置准备
- 一台已部署网站的服务器(Linux或Windows均可),并已绑定域名(例如 example.com)。
- 域名已正确解析到服务器IP(A记录生效)。
- 服务器开放80端口(用于HTTP验证)和443端口(用于HTTPS服务)。
- 拥有服务器的管理员权限(root或sudo)。
- 可选:安装宝塔面板或LNMP一键包等管理工具(非必需,但能简化操作)。
- 注册一个邮箱地址(用于证书申请时的紧急联系)。
分步操作步骤
1. 选择并安装ACME客户端(以acme.sh为例)
ACME协议是自动化证书管理的标准,acme.sh是目前最流行的开源客户端,支持Let's Encrypt和ZeroSSL。首先通过SSH登录服务器,执行以下命令安装:
```
curl https://get.acme.sh | sh -s email=your_email@example.com
```
安装完成后,会显示“Installed to /root/.acme.sh/”等提示。接着运行以下命令使环境变量生效:
```
source ~/.bashrc
```
验证安装是否成功:
```
acme.sh --version
```
如果返回版本号(例如 3.0.7),则说明安装成功。注意:安装过程会自动添加定时任务(cron),用于证书到期前自动续签,无需手动干预。
2. 申请免费SSL证书(DNS手动模式或HTTP模式)
这里提供两种最常用的申请方式,根据你的网络环境选择其一。
方式A:HTTP验证(推荐,需80端口可访问)
这种方式要求你的网站已正常运行且80端口可被外网访问。执行命令:
```
acme.sh --issue -d example.com -d www.example.com --webroot /var/www/html
```
其中 /var/www/html 是你的网站根目录路径(例如宝塔默认路径为 /www/wwwroot/example.com)。命令执行后,acme.sh会在该目录下创建一个隐藏文件夹 .well-known/acme-challenge,Let's Encrypt服务器会通过HTTP请求验证你对域名的控制权。等待约30秒,如果出现“Cert success”字样,说明证书申请成功。
方式B:DNS手动模式(适用于80端口无法访问或泛域名)
如果你无法通过HTTP验证(例如网站未上线或80端口被屏蔽),可以使用DNS手动模式。执行:
```
acme.sh --issue -d example.com -d *.example.com --dns dns_manual
```
命令会返回一条TXT记录值,你需要登录域名管理后台(如阿里云、腾讯云、Cloudflare),添加一条TXT解析记录,主机记录为 _acme-challenge,记录值填入返回的字符串。等待DNS生效(通常1-5分钟),然后按回车继续。这种方式可以申请泛域名证书(*.example.com),适合多子域名场景。
3. 安装证书到服务器(以Nginx为例)
证书申请成功后,需要将证书文件复制到指定目录并配置Web服务器。首先查看证书文件列表:
```
acme.sh --list
```
会显示证书路径,例如 /root/.acme.sh/example.com_ecc/。然后执行安装命令:
```
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/example.com.crt \
--reloadcmd "systemctl reload nginx"
```
如果 /etc/nginx/ssl 目录不存在,先创建:
```
mkdir -p /etc/nginx/ssl
```
接着修改Nginx配置文件(通常位于 /etc/nginx/nginx.conf 或 /etc/nginx/sites-available/default),添加或修改server块:
```
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/html;
index index.html index.php;
}
```
同时添加HTTP自动跳转HTTPS的规则:
```
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
```
保存文件后,测试配置是否正确:
```
nginx -t
```
如果输出“syntax is ok”,则重新加载Nginx:
```
systemctl reload nginx
```
此时访问 https://example.com 应该能看到绿色小锁图标。
4. 配置自动续签与验证
acme.sh默认已添加每日自动续签任务(每天检查一次,距离过期30天内才续签)。你可以通过以下命令查看定时任务:
```
crontab -l
```
应该能看到类似“0 0 * * * /root/.acme.sh/acme.sh --cron --home /root/.acme.sh > /dev/null”的条目。为了验证续签是否正常工作,可以手动模拟一次:
```
acme.sh --cron --force
```
如果证书未到期,会提示“Skip, Next renewal time is ...”。建议在证书到期前一个月手动执行一次检查,确保自动续签环境正常。另外,注意服务器时间必须准确(使用`date`命令查看),否则可能导致续签失败。
常见问题
- 问题1:申请证书时提示“Invalid response from http://example.com/.well-known/acme-challenge/...”
原因:HTTP验证路径无法被外网访问。请检查网站根目录是否正确,以及是否有防火墙或CDN屏蔽了该路径。如果使用了CDN,需要临时关闭CDN(或使用DNS验证模式)。
- 问题2:安装证书后浏览器提示“NET::ERR_CERT_COMMON_NAME_INVALID”
原因:证书域名与访问域名不匹配。例如你只申请了example.com,却用www.example.com访问。建议在申请时同时添加 -d example.com -d www.example.com。
- 问题3:自动续签失败,日志显示“Error renew”
常见原因:服务器80端口不可用(被防火墙或CDN拦截),或者DNS验证的TXT记录被删除。解决方法是确保HTTP验证路径始终可访问,或者改用DNS API模式(acme.sh支持阿里云、腾讯云等API自动添加TXT记录,无需手动操作)。
- 问题4:宝塔面板用户如何操作?
宝塔面板内置了Let's Encrypt免费证书申请功能,直接在面板“网站”设置中点击“SSL”->“Let's Encrypt”即可一键申请。如果你希望使用acme.sh,也可以在宝塔的“文件”管理中将证书路径指向acme.sh生成的证书,但建议优先使用面板自带功能,更省心。
- 问题5:证书到期后网站无法访问怎么办?
如果自动续签失败,手动执行一次 `acme.sh --cron --force` 重新申请。如果仍然失败,检查服务器时间和网络连接,必要时删除旧证书目录(/root/.acme.sh/example.com/)重新申请。
收尾总结
通过本教程,你已经掌握了从零申请免费SSL证书并部署到Nginx服务器的完整流程。核心要点包括:使用acme.sh客户端自动化申请;通过HTTP或DNS验证域名所有权;正确配置Nginx的SSL参数并强制HTTPS跳转;确保自动续签定时任务正常运行。部署完成后,建议使用SSL Labs(https://www.ssllabs.com/ssltest/)测试你的网站安全等级,通常能获得A级评分。免费证书虽然有效期短,但通过自动续签机制完全可以做到“一次配置,长期无忧”。如果你使用的是Apache、Caddy或其他Web服务器,acme.sh同样支持对应的安装命令(如--reloadcmd "apachectl graceful"),原理完全一致。现在就去为你的网站加一把“安全锁”吧。