背景
原先服务器中,blog的ssl证书也是由acme.sh申请的,不过为了新服务器贯彻docker化的策略,acme.sh也实行docker化,并且官方这边也有docker容器
概况
根据这篇的说明deploy to docker containers就可以把证书部署到另一个容器中,但里面与配置没有说明多域名的情况下该如何实现。
所以我采取的是把输出的ssl证书文件路径,同时映射给nginx与acme.sh,这样的做法可能在证书更替期间,nginx没有重启,导致依旧使用旧ssl证书的情况,这个问题之后再说吧
然后是ssl证书签发的验证,则是采取http验证,为nginx和acme.sh创建个数据卷作为网站的根目录
大概流程如下:
1. acme.sh和nginx容器的启动
2. nginx中网站htpp配置编写
3. 申请ssl证书
4. https添加
acme.sh和nginx容器启动
使用docker-compose.yml部署这两个容器
services:
web:
image: nginx:alpine
volumes:
- ./config/conf.d:/etc/nginx/conf.d
- ./config/nginx.conf:/etc/nginx/nginx.conf
- html_file:/etc/nginx/html
- ./ssl:/etc/nginx/ssl
ports:
- "80:80"
- "443:443"
acme-sh:
image: neilpang/acme.sh
container_name: acme.sh
volumes:
- ./ssl:/acme.sh
- html_file:/html
command: daemon
stdin_open: true
tty: true
restart: no
volumes:
html_file:
网站的访问统一由nginx来管理,所以只有nginx映射了宿主机的端口。
这里我同时映射了nginx中的nginx.conf文件和conf.d文件夹到宿主机,这里面的nginx.conf文件和conf.d内的default.conf文件我们可以简单启动一个临时nginx容器复制出来
在docker-compose.yml目录下使用这个指令
docker run --rm -v $PWD/config:/config nginx cp -r /etc/nginx/nginx.conf /etc/nginx/conf.d /config
目录下的config文件夹内就是我们所需文件,这些文件路径在docker-compose.yml也是正确对应的,这就是为什么在docker-compose.yml文件目录下使用这个指令的原因
docker compose up -d
http文件编写
由于是使用http验证,需要写好域名的配置才能正常验证。
acme.sh使用http验证时,会是往网站根目录放一个存有key的文件来给ssl证书签发机构验证的,这个文件位置我们可以通过acme.sh的源码中查看到或者log文件(需要先执行申请ssl证书)中查看到
这位置是.well-known/acme-challenge
我们简单写一个http的nginx配置来让我们通过http验证
server {
listen 80;
listen [::]:80;
server_name your.example.com;
location /.well-known/acme-challenge {
# 这里的路径对应好数据卷挂载的路径
root /etc/nginx/html;
}
}
保存这内容到文件,文件最好以域名命名your.example.com.conf
因为nginx内的conf.d文件夹也映射到宿主机,所以,直接放到对应目录即可,这里是./config/conf.d,放好后直接重启nginx容器即可
docker restart nginx容器ID
ssl证书申请
万事具备,使用以下指令申请,记得添加域名DNS记录指向服务器IP
docker exec acme.sh --issue -d your.example.com -w /html
使用后可能会要求添加邮箱地址,按要求添加即可
指令最后的/html是与acme.sh容器挂载html_file数据卷对应的路径,别写错,写错验证过不了
如无意外,ssl证书就能正常签发下来,证书存在容器内的/acme.sh文件夹内,并且以域名文件夹区分,我们这里直接映射这个目录
https添加
acme.sh容器申请的证书文件夹我们直接映射到宿主机,这些文件也映射到了nginx容器内的/etc/nginx/ssl,所以我们直接读取这些文件即可
以下是修改后的配置文件
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/nginx/ssl/your.example.com_ecc/your.example.com.cer;
ssl_certificate_key /etc/nginx/ssl/your.example.com_ecc/your.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519:P-256:P-384:P-521;
server_name your.example.com;
index index.html index.htm;
root /etc/nginx/html;
error_page 400 = /400.html;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000" always;
# disable nginx version info
server_tokens off;
# disable response resource type guessing
add_header X-Content-Type-Options nosniff;
location /
{
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_redirect off;
proxy_pass http://wordpress:80;
proxy_set_header X-Real-IP remote_addr;
proxy_set_header X-Forwarded-Forproxy_add_x_forwarded_for;
proxy_set_header Host blog.qiuzhizhe.top;
proxy_set_header X-Forwarded-Proto scheme;
client_max_body_size 10m;
}
# 记得加上这个,后续自动续签验证需要的
location /.well-known/ {
root /etc/nginx/html;
index index.html index.htm;
}
}
server {
listen 80;
listen [::]:80;
server_name your.example.com;
location /.well-known/acme-challenge {
root /etc/nginx/html;
}
location / {
return 301 https://http_host$request_uri;
}
}
保存成your.example.com.conf然后覆盖掉原来的即可,然后重启nginx容器
至此,完成

Comments NOTHING