相信一些同学注意到了, 本站启用了https, 域名改成了xhl.me, 服务也早就全都改用docker了.
顺带介绍下之前搞的两个个docker项目: alpine-tengine, docker-backup.
*本文主要介绍letsencrypt证书的创建和通配符HTTPS证书生成, 还有基于letsencrypt docker镜像实现证书自动续期.
Let's Encrypt 是一个自动签发免费HTTPS证书的非营利机构, 生成的证书有3个月有效期, 到期可以免费续期.
Certbot 是 Let's Encrypt 官方推荐的生成证书的客户端工具, 文档.
使用dnsrobocert生成证书(支持通配符域名证书), 并自动续期
这个项目, 集成了certbot(证书生成命令行工具), Lexicon(DNS记录修改工具, 主流DNS服务商都支持).
另外还自带了crontab 定时任务, 只要服务启动, 就会自动续期域名了.
1. 创建, /etc/dnsrobocert/config.yml, 内容类似这样:
# https://git.io/JL1cD
draft: false
acme:
email_account: <youremail>
staging: false
profiles:
- name: cloudflare
provider: cloudflare
provider_options:
auth_username: <cloudflare_email>
auth_token: <cloudflare_token>
- name: dnspod
provider: dnspod
provider_options:
auth_username: <dnspod_id>
auth_token: <dnspod_token>
certificates:
- domains:
- "*.xhl.me"
- xhl.me
profile: cloudflare
# autorestart:
# - containers:
# - nginx
autocmd: # 自动重启
- cmd: nginx -s reload
containers:
- nginx
# - domains:
# - "*.test.com"
# profile: dnspod
# ...
2. 根据DNS PROVIDER信息验证, 并自动创建和续期证书
docker run -it --rm --name letsencrypt2 \
-v /etc/dnsrobocert:/etc/dnsrobocert \
-v /etc/letsencrypt:/etc/letsencrypt \
-v /var/run/docker.sock:/var/run/docker.sock \
adferrand/dnsrobocert
LEXICON_PROVIDER 主流的DNS服务都支持, 比如:
3. 进阶: 使用docker-compose
创建 /compose/letsencrypt/docker-compose.yml
:
version: '3'
services:
letsencrypt:
container_name: letsencrypt
image: adferrand/dnsrobocert
# network_mode: "host"
volumes:
- /etc/dnsrobocert/:/etc/dnsrobocert
- /etc/letsencrypt/:/etc/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock
启动服务执行: cd /compose/letsencrypt; docker-compose up -d --force-recreate -V;
5. 进阶: 开机自启服务
创建 /etc/systemd/system/letsencrypt.service
, 内容:
[Unit]
Description=Letsencrypt Container
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
TimeoutStartSec=0
ExecStart=/usr/local/bin/docker-compose up -d --force-recreate
ExecReload=/usr/local/bin/docker-compose up -d --force-recreate
ExecStop=/usr/local/bin/docker-compose stop
WorkingDirectory=/composes/letsencrypt
[Install]
WantedBy=multi-user.target
执行下, 下面的命令就可以成为自启的服务了:
systemctl daemon-reload;
systemctl enable letsencrypt; systemctl restart letsencrypt;
同理, 也可以把其他docker服务做成自启, 比如Nginx.
证书生成后 nginx 的配置
server {
listen 80;
listen 443 ssl;
server_name xhl.me www.xhl.me;
ssl_certificate /etc/letsencrypt/live/xhl.me/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xhl.me/privkey.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_stapling on;
ssl_stapling_verify on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
...
}
可能用到的debug命令
telnet xhl.me 443
openssl s_client -connect xhl.me:443
curl -vv -k https://xhl.me # 测试https
docker exec -it letsencrypt sh # 进入容器执行shell命令
docker logs letsencrypt -f # 查看letsencrypt输出的日志信息
tools
- Mozilla SSL Configuration Generator SSL配置生成器.
- SSL Server Test 测试站点HTTPS, SSL评分.
- HTTP/2 Test 测试站点是否支持HTTP2.
另外, 也可以使用certbot 生成证书, 但是没有dnsrobocert方便, 就不介绍了.
如果letsencrypt提示了lexicon执行错误, 看不到具体的错误, 比如: 422 Client Error: Unprocessable Entity for url: xxx
, 这时可以看域名对应DNS服务商的API文档, 用curl直接调用接口来debug, 比如:
// godaddy 获取域名的所有记录
curl -X GET -H"Authorization: sso-key KEY:SECRET" https://api.godaddy.com/v1/domains/yourdomain.com/records
// godaddy 批量修改域名记录
curl -X PUT https://api.godaddy.com/v1/domains/yourdomain.com/records -H "Authorization: sso-key KEY:SECRET" \
-H "Content-Type: application/json" -d '[....., {"data": "test", "type": "TXT", "name": "_acme-challenge", "ttl": 3600}]'