最近给自己服务器上的两个网站换了 SSL 证书,顺便把整个过程记录一下。
以前用的是阿里云申请的免费证书,每隔一段时间就要手动续期、替换证书文件,太麻烦了。其实如果只是个人网站,直接用 Let’s Encrypt 就挺方便,免费、有效期短一些,但可以通过 Certbot 自动续期,基本配置好以后就不用管了。
这次我给两个 Nginx 网站配置了 HTTPS,并且顺便把自动续期也一起弄好了。
一、先安装 Certbot
如果服务器还没有 Certbot,可以先安装它。
以 Linux 服务器为例,我这里采用 Python 虚拟环境安装,这样不会影响系统自带的 Python,后面升级 Certbot 也比较方便。
先确认 Python 版本:
python3 --version
如果服务器已经安装了 Python 3.11,可以直接创建一个专门给 Certbot 使用的虚拟环境:
python3.11 -m venv /opt/certbot311
激活虚拟环境:
source /opt/certbot311/bin/activate
然后升级 pip:
pip install -U pip
安装 Certbot:
pip install certbot
安装完成后检查:
certbot --version
如果能正常显示 Certbot 版本号,就说明安装成功。
为了以后直接输入 certbot 就能使用,而不用每次手动进入虚拟环境,可以创建一个软链接:
ln -sf /opt/certbot311/bin/certbot /usr/local/bin/certbot
再检查:
which certbot
certbot --version
正常情况下会看到:
/usr/local/bin/certbot
certbot x.x.x
这样 Certbot 就安装好了。
为什么我更喜欢这种安装方式?
主要是为了不折腾系统自带的 Python。
很多 Linux 系统自己的管理工具依赖系统 Python,如果为了装一个 Certbot 直接升级或替换 /usr/bin/python3,反而容易把系统环境搞乱。
单独给 Certbot 建一个 Python 虚拟环境,相当于把它“关”在自己的小环境里,和系统其他程序互不影响。我个人觉得这种方式更适合自己维护 VPS。
二、申请 Let’s Encrypt 证书
我的网站使用 Nginx,比较喜欢 webroot 这种方式,因为它不会直接修改 Nginx 配置。
例如:
certbot certonly --webroot \
-w /home/wwwroot/heqianwei \
-d heqianwei.com \
-d www.heqianwei.com
另一个网站同样操作:
certbot certonly --webroot \
-w /home/wwwroot/ihacksoft \
-d ihacksoft.com \
-d www.ihacksoft.com
这里的 -w 后面填写的是网站实际的 Web 根目录。
申请成功后,证书一般会放在:
/etc/letsencrypt/live/
例如:
/etc/letsencrypt/live/heqianwei.com/
├── cert.pem
├── chain.pem
├── fullchain.pem
└── privkey.pem
Nginx 通常使用:
fullchain.pem
privkey.pem
三、让 Nginx 使用新证书
我原来的 Nginx 配置是使用 /etc/nginx/cert/ 下面的证书文件,所以没有直接修改 Nginx 配置结构,而是把 Let’s Encrypt 生成的证书复制过去。
例如:
cp -L /etc/letsencrypt/live/heqianwei.com/fullchain.pem \
/etc/nginx/cert/heqianwei.com.pem
cp -L /etc/letsencrypt/live/heqianwei.com/privkey.pem \
/etc/nginx/cert/heqianwei.com.key
另一个网站:
cp -L /etc/letsencrypt/live/ihacksoft.com/fullchain.pem \
/etc/nginx/cert/ihacksoft.com.pem
cp -L /etc/letsencrypt/live/ihacksoft.com/privkey.pem \
/etc/nginx/cert/ihacksoft.com.key
然后检查 Nginx:
nginx -t
如果看到:
syntax is ok
test is successful
就可以重新加载:
systemctl reload nginx
到这里,网站的 HTTPS 基本就已经正常了。
四、关键来了:设置自动续期
Let’s Encrypt 的证书有效期比较短,所以不能申请完就不管了。
Certbot 本身提供了:
certbot renew
这个命令的作用不是每次都重新申请证书,而是检查现有证书是否已经接近过期,需要续期时才自动续期。
我这里直接用 Linux 的 cron 定时任务,每天凌晨 3 点执行一次:
crontab -e
加入:
0 3 * * * /usr/local/bin/certbot renew -q
然后检查:
crontab -l
看到:
0 3 * * * /usr/local/bin/certbot renew -q
就说明定时任务已经配置好了。
每天执行一次其实没什么问题,因为 Certbot 会自己判断证书是否需要续期。
五、还有一个容易忽略的问题
这里我一开始也觉得,配置好:
certbot renew
就万事大吉了。
但实际上还差一步。
因为我的 Nginx 使用的是:
/etc/nginx/cert/
下面的证书,而 Certbot 续期成功后,新证书是在:
/etc/letsencrypt/live/
下面。
也就是说:
Certbot 虽然把证书更新了,但 Nginx 还在使用旧的证书文件。
所以还需要一个 Deploy Hook。
先创建目录:
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
然后创建脚本:
cat > /etc/letsencrypt/renewal-hooks/deploy/update-nginx-certs.sh <<'EOF'
#!/bin/bash
set -e
cp -L /etc/letsencrypt/live/heqianwei.com/fullchain.pem /etc/nginx/cert/heqianwei.com.pem
cp -L /etc/letsencrypt/live/heqianwei.com/privkey.pem /etc/nginx/cert/heqianwei.com.key
cp -L /etc/letsencrypt/live/ihacksoft.com/fullchain.pem /etc/nginx/cert/ihacksoft.com.pem
cp -L /etc/letsencrypt/live/ihacksoft.com/privkey.pem /etc/nginx/cert/ihacksoft.com.key
chmod 600 /etc/nginx/cert/heqianwei.com.key
chmod 600 /etc/nginx/cert/ihacksoft.com.key
nginx -t
systemctl reload nginx
EOF
然后给脚本执行权限:
chmod +x /etc/letsencrypt/renewal-hooks/deploy/update-nginx-certs.sh
以后 Certbot 只要真正续期成功,就会自动执行这个脚本。
整个过程就变成:
Certbot 自动续期
↓
复制新证书
↓
修改证书权限
↓
检查 Nginx 配置
↓
重新加载 Nginx
↓
网站自动使用新证书
这样就不用每隔几个月再登录服务器手动换证书了。
六、最后一定要测试一下
实际证书还没到续期时间,不可能现在真的给你换一张新证书。
所以可以用:
certbot renew --dry-run
模拟一次续期。
如果最后看到:
Congratulations, all simulated renewals succeeded
基本就说明自动续期流程没有问题。
如果还想连刚才配置的 Deploy Hook 一起测试,可以:
certbot renew --dry-run --run-deploy-hooks
我这次实际测试两个网站都成功了。
最后简单总结一下
其实整个方案并不复杂:
① Certbot 申请证书
certbot certonly --webroot ...
② Nginx 使用证书
/etc/letsencrypt/live/
或者根据自己的 Nginx 配置复制到指定目录。
③ 设置每天自动检查
0 3 * * * /usr/local/bin/certbot renew -q
④ 配置 Deploy Hook
续期成功后自动复制新证书,并:
nginx -t
systemctl reload nginx
⑤ 用 dry-run 测试
certbot renew --dry-run
我个人感觉这种方式还是挺省心的,尤其是自己维护好几个小网站的时候。证书申请一次,后面让服务器自己续期就行,平时基本不用再操心 SSL 证书过期的问题。
比较适合自己折腾 VPS、Nginx、Typecho、WordPress 这类网站的人。