## 什么是 Let's Encrypt
Let's Encrypt 是一个免费、自动化和开放的证书颁发机构(Certificate Authority, CA),其目的是使获得和安装 SSL/TLS 证书的过程自动化,以便网站能够通过 HTTPS 提供加密的通信。
## 生成证书
下面演示 Ubunut 系统操作步骤
```Shell
# 工具安装
$ sudo apt update
$ sudo apt install snapd
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
# 生成证书
$ sudo certbot certonly --standalone -d domain.com
# Successfully received certificate.
# Certificate is saved at: /etc/letsencrypt/live/domain.com/fullchain.pem
# Key is saved at: /etc/letsencrypt/live/domain.com/privkey.pem
# 验证续签
$ sudo certbot renew
# 查看证书
$ sudo certbot certificates
# 删除证书
$ sudo certbot delete --cert-name ${域名}
```
## 使用 Nginx 配置 HTTPS 证书
由于 Let's Encrypt 在验证域名时需要占用 80 端口,这可能与现有 Web 服务器产生端口冲突。为了解决该问题,可以使用 `webroot` 参数的方式进行验证。以下是一个通过 Docker 运行 Nginx 并申请证书的完整示例。
1. 生成证书
```shell
$ mkdir certbot-webroot
$ sudo certbot certonly --key-type rsa --webroot -w ./certbot-webroot -d domain.com
$ sudo certbot certonly --key-type rsa --webroot -w ./certbot-webroot -d www.domain.com
```
2. nginx 配置文件
```conf
server {
listen 80;
listen [::]:80;
server_name domain.com www.domain.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot-webroot/;
}
location / {
return 301 https://domain.com$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name www.domain.com;
ssl_certificate /etc/letsencrypt/live/www.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.domain.com/privkey.pem;
return 301 https://domain.com$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name domain.com;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
index index.html index.htm;
root /var/www/html;
server_tokens off;
}
```
3. docker-compose 配置文件
```yaml
services:
ngx:
image: nginx:latest
container_name: ngx
ports:
- "80:80"
- "443:443"
restart: always
volumes:
- /etc/letsencrypt:/etc/letsencrypt
- ./certbot-webroot:/var/www/certbot-webroot
- # 这里忽略其他 nginx 配置文件映射
```
4. 验证是否生效
```shell
$ sudo certbot certonly --key-type rsa --webroot -w ./certbot-webroot -d domain.com --dry-run
# 提示 The dry run was successful. 字样说明成功了
```
5. 测试续签
```
$ sudo certbot renew --dry-run --webroot -w ./certbot-webroot
```
## 自动续签
使用 `crontab` 工具定时续签
```shell
# 编辑 crontab
crontab -e
# 添加每天凌晨2点执行续签命令,如果证书有更新时重启 Nginx
0 2 * * * /usr/bin/certbot renew --quiet --deploy-hook "docker restart ngx" >> /var/log/letsencrypt/renewal_log.txt 2>&1
```
## 参考
- https://letsencrypt.org/zh-cn/docs/
- https://certbot.eff.org/instructions?ws=other&os=ubuntufocal