我的服务器搭建日志:在docker上使用nginx的反向代理环境中使用Let’s Encrypt
抚慰文字形103112
我个人的服务器建设日志:继上次重新开始后,关于建设家庭服务器的继续记录。
我们将按照标题所示的要求来完成任务。上次我们尝试在 Docker 上搭建了一个 Nginx 反向代理,现在我们将探索如何在这个环境中获取和维护 Let’s Encrypt 的证书。
我尝试了一下进行调查,但是关于类似的内容的文章并不多。特别是有关维护的步骤。我也考虑了一下步骤,但只能想到一些与Docker不太相关的方法。最终在不断尝试中,我选择了与主机机器的cron结合起来的方式。
要求给出中文句子的多个版本,这是一个指定标题的写作任务。请提供目标句子的多个版本。
-
- Dockerコンテナで立てたnginxリバースプロキシを前提とする
-
- リバースプロキシに証明書を持たせて、上流(upstream)にはHTTPで接続。
-
- 証明書を Let’s Encrypt で取得(certbotを利用)
- 証明書を定期的に自動更新する。
大纲
为了获取和维持证书,只需要在反向代理的Docker容器中安装certbot。之后按照标准步骤进行操作。
尽管知道这不是被赞赏的方法,我希望将cron放入Docker容器中。但实际尝试后,反向代理无法正常工作。这真是令人困扰。
因此,我们决定通过主机的cron设置来实现定期启动命令。
我本来是想避免做这种事情后会忘记,不过只使用反向代理将LXD容器化似乎有些夸张了。真遗憾。
文献引用
-
- nginxによるバーチャルホスト/リバースプロキシによる Let’s Encrypt 証明書の取得方法など – Qiita
-
- SSL証明書の自動更新。 – 無料のSSL証明書Let’s Encryptを設定・更新・自動更新する方法(CentOS7, Apache2.4対応) – プログラミング入門ナビ by Proglus(プログラス)
-
- 私的サーバー構築日誌:nginx on docker でリバースプロキシ – Qiita
私的サーバー構築日誌:LAN内DNSサーバー Unbound – Qiita … 我が家の家庭内DNSです。バーチャルホストを動かす為に、少し追記が必要になります。
【cron】改めてcronの設定方法について勉強し直してみた – とーますメモ … /etc/cron.d/に置く設定ファイルは、拡張子を付けてはいけないようです。
Docker Composeでログの設定をする – Qiita
这次我们决定不在Docker容器中使用cron。不过,我还是给出了参考文献。
-
- Docker コンテナで cron を使う – Docker コンテナ内でタスクを cron 起動する – Qiita
-
- Dockerコンテナ内でcronを実行し実行ログを出力する方法 – ゲンゾウ用ポストイット
- Dockerコンテナの中身のタイムゾーンを日本時刻にする方法 – My CMS
建立实验环境
我們將搭建與上次相同的實驗環境。由於反向代理有一些步驟變更,因此重新列出所有步驟。
网络设置
我会配置我们家的服务器,以便可以从外部互联网访问。首先设置DNS,然后进行家用路由器的端口转发。端口80和端口443。由于环境不同,设置步骤也会不同,请按照各自的步骤进行配置。
然后将设定内容设置为变量。
域名在这里假设为example.com,你需要购买并设置属于自己的域名,千万不要直接使用这个。
MY_DOMAIN=example.com
TEST_DOMAIN=test.$MY_DOMAIN
我家服务器在家庭局域网中的IP地址是172.16.1.2。
HOST_IPADDR=172.16.1.2
家庭内部域名系统
首先,我们会配置家庭内部的DNS。
cd /etc/unbound/unbound.conf.d/
cat | sudo tee -a machines.list >/dev/null <<___
local-data: "$TEST_DOMAIN. 3600000 IN A $HOST_IPADDR"
___
unbound-checkconf
sudo systemctl restart unbound
网络服务器
我将设置一个Web服务器。由于只涉及基本配置,所以我将直接进行,不做解释。
TEST_PORT=20080
cd
mkdir docker-nginx1
cd docker-nginx1
mkdir -p config/nginx
mkdir -p data/nginx
mkdir html
cat <<___ >docker-compose.yml
version: "3.9"
services:
nginx1:
image: nginx:latest
container_name: nginx1
restart: unless-stopped
ports:
- $TEST_PORT:80
volumes:
- ./config/nginx:/etc/nginx/conf.d
- ./data/nginx:/var/log/nginx
- ./html:/usr/share/nginx/html
___
cat <<___ >config/nginx/test.conf
server {
listen 80;
server_name _;
server_tokens off;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
___
cat <<___ >html/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>nginx test</title>
</head>
<body>
<h1>test</h1>
<p>hello,world</p>
</body>
</html>
___
docker compose up -d
确认动作。
curl http://$HOST_IPADDR:$TEST_PORT/
反向代理
反向代理是指,根据概述的内容,安装certbot。
cd
mkdir docker-proxy
cd docker-proxy
mkdir -p config/nginx
mkdir -p data/nginx
mkdir -p html/ssl-proof
mkdir letsencrypt
cat <<___ >docker-compose.yml
version: "3.9"
services:
proxy:
build: .
container_name: proxy
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./config/nginx:/etc/nginx/conf.d
- ./data/nginx:/var/log/nginx
- ./html:/usr/share/nginx/html
- ./letsencrypt:/etc/letsencrypt
logging:
driver: json-file
options:
max-size: 10m
max-file: '3'
___
cat <<___ >Dockerfile
FROM nginx:latest
RUN apt update \
&& apt install -y certbot \
&& apt -y clean
___
cat <<___ >config/nginx/default.conf
server {
listen 80 default_server;
server_name _;
server_tokens off;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
___
cat <<___ >config/nginx/test.conf
server {
listen 80;
server_name $TEST_DOMAIN;
server_tokens off;
location ^~ /.well-known/acme-challenge/ {
root /usr/share/nginx/html/ssl-proof;
}
location / {
proxy_pass http://$HOST_IPADDR:$TEST_PORT;
}
}
___
docker compose up -d
确认动作。
curl http://$TEST_DOMAIN/
使用Certbot获取证书。
从这里开始才是真正的实战吧。首先是获取证书的步骤。执行certbot命令。
docker compose exec proxy certbot certonly --register-unsafely-without-email --agree-tos --webroot -w /usr/share/nginx/html/ssl-proof -d $TEST_DOMAIN
证明文件等存储在以下位置。但权限已设置为root。
-
- 公開鍵: ~/docker-proxy/letsencrypt/live/$TEST_DOMAIN/fullchain.pem
秘密鍵: ~/docker-proxy/letsencrypt/live/$TEST_DOMAIN/privkey.pem
cd
cd docker-proxy
sudo ls -l letsencrypt/live/$TEST_DOMAIN
大致如此。
$ sudo ls -l letsencrypt/live/$TEST_DOMAIN
total 9
-rw-r--r-- 1 root root 692 Nov 28 13:50 README
lrwxrwxrwx 1 root root 42 Nov 28 13:50 cert.pem -> ../../archive/test.moon-night.jp/cert1.pem
lrwxrwxrwx 1 root root 43 Nov 28 13:50 chain.pem -> ../../archive/test.moon-night.jp/chain1.pem
lrwxrwxrwx 1 root root 47 Nov 28 13:50 fullchain.pem -> ../../archive/test.moon-night.jp/fullchain1.pem
lrwxrwxrwx 1 root root 45 Nov 28 13:50 privkey.pem -> ../../archive/test.moon-night.jp/privkey1.pem
让我们检查一下证书的内容。
sudo openssl x509 -text -in letsencrypt/live/$TEST_DOMAIN/fullchain.pem | grep -E "Issuer:|Subject:"
sudo openssl x509 -dates -noout -in letsencrypt/live/$TEST_DOMAIN/fullchain.pem
在反向代理服务器上设置证书。
在转发部分设置证书,并保留80号端口用于证书维护。
cat <<___ >config/nginx/test.conf
server {
listen 80;
server_name $TEST_DOMAIN;
server_tokens off;
location ^~ /.well-known/acme-challenge/ {
root /usr/share/nginx/html/ssl-proof;
}
location / {
return 301 http://$TEST_DOMAIN;
}
}
server {
listen 443 ssl;
server_name $TEST_DOMAIN;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/$TEST_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$TEST_DOMAIN/privkey.pem;
location / {
proxy_pass http://$HOST_IPADDR:$TEST_PORT;
}
}
___
我将重新启动 Nginx。
docker compose exec proxy nginx -s reload
确认动作。
curl https://$TEST_DOMAIN/
自动更新
这是关于证书更新的设定。
cd
cd docker-proxy
cat <<___ >certbot-renew.sh
#!/bin/bash
cd
cd docker-proxy
/usr/bin/date -Iseconds
/usr/bin/docker compose exec proxy certbot renew
/usr/bin/docker compose exec proxy nginx -s reload
echo "====="
___
chmod +x certbot-renew.sh
sudo ln -s $PWD/certbot-renew.sh /usr/local/bin/certbot-renew.sh
关于日志,我们停止使用logger命令,并改用将标准输出和标准错误输出重定向到本地。然后通过logrotate进行轮转。
sudo mkdir /var/log/letsencrypt
sudo chown $USER /var/log/letsencrypt
cat <<___ | sudo tee /etc/logrotate.d/certbot-renew >/dev/null
/var/log/letsencrypt/certbot-renew.log {
missingok
rotate 3
compress
monthly
minsize 1M
}
___
由于Let’s Encrypt证书的有效期为90天,因此我们需要每月两次在每月1日和15日凌晨3点运行更新检查。它会自动判断是否应该进行更新,需参考剩余天数是否超过30天。
另外,据说在/etc/cron.d设置文件时,文件的扩展名必须为空。
cat <<___ | sudo tee /etc/cron.d/certbot-renew >/dev/null
0 3 1,15 * * $USER /usr/local/bin/certbot-renew.sh >>/var/log/letsencrypt/certbot-renew.log 2>&1
___
接下来只需要确认实际操作了。这会是一个有点冗长的话题。
cd
cd docker-proxy
sudo ls -l letsencrypt/live/$TEST_DOMAIN/
cat /var/log/letsencrypt/certbot-renew.log
收场
这次的目的还是检查步骤。等确认动作完毕后,记得全部清除干净。
sudo rm /etc/cron.d/certbot-renew
sudo rm /etc/logrotate.d/certbot-renew
sudo rm /usr/local/bin/certbot-renew.sh
sudo rm -r /var/log/letsencrypt
cd
cd docker-proxy
docker compose down --rmi all --volumes
cd
cd docker-nginx1
docker compose down --rmi all --volumes
cd
sudo rm -r docker-proxy docker-nginx1
sudo sed -i -e"/$TEST_DOMAIN./d" /etc/unbound/unbound.conf.d/machines.list
unbound-checkconf
sudo systemctl restart unbound
这次我们确认了使用Let’s Encrypt获取证书并保持证书有效的步骤,在反向代理环境中进行设置。