概要 †Let's Encrypt の SSL証明書を自動更新する手順のメモ。 [環境/要件など] Let's Encrypt の SSL証明書を取得/更新する場合、Certbot を使用する事になるが、上記の環境/要件を満たす為に以下の通り構成する。 ・更新には Certbot の webroot プラグインを使用する。(standaloneではなく) 尚、当記事の内容は Azure の VM を使用して行った為、何箇所か japaneast.cloudapp.azure.com 等の記述がある為、別環境で行う場合は適宜読み替える。 目次 †
作業ディレクトリ作成/移動 †sudo mkdir /containers sudo chmod 777 /containers cd /containers dockerインストール †setup_docker.sh #!/bin/bash apt-get update apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" apt-get update apt-get install -y docker-ce docker-ce-cli containerd.io curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose インストール実行 sudo bash setup_docker.sh docker周りの起動設定など # カレントユーザをdockerグループに所属させておく sudo usermod -aG docker azureuser # 起動設定 sudo update-rc.d docker defaults # 起動設定確認 ls -l /etc/rc?.d/*docker いったんログアウトして再ログインする。 SSL証明書取得 †ssl_cert_create.sh #!/bin/bash
domain=`hostname`.japaneast.cloudapp.azure.com
docker run -p 80:80 \
-v `pwd`/letsencrypt:/etc/letsencrypt \
-v `pwd`/letsencrypt/logs:/var/log/letsencrypt \
-v `pwd`/www:/var/www \
certbot/certbot certonly \
--standalone
--register-unsafely-without-email \
--non-interactive --agree-tos \
--force-renewal \
--renew-by-default \
-d ${domain}
aft=`sudo ls -l ./letsencrypt/live/${domain}/`
echo "## cert ##"
echo "$aft"
先にフォルダを作っておく mkdir letsencrypt mkdir www 実行 bash ssl_cert_create.sh : : ## cert ## total 20 -rw-r--r-- 1 root root 692 Feb 11 03:26 README lrwxrwxrwx 1 root root 63 Feb 11 03:26 cert.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/cert1.pem lrwxrwxrwx 1 root root 64 Feb 11 03:26 chain.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/chain1.pem lrwxrwxrwx 1 root root 68 Feb 11 03:26 fullchain.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/fullchain1.pem lrwxrwxrwx 1 root root 66 Feb 11 03:26 privkey.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/privkey1.pem docker コンテナ作成 †docker-compose.yml 作成 †docker-compose.yml version: "3"
services:
grafana:
image: grafana/grafana:7.3.7
hostname: grafana
container_name: grafana
ports:
- "3000:3000"
environment:
GF_SERVER_ROOT_URL: "https://{サーバ名}.japaneast.cloudapp.azure.com"
GF_SECURITY_ADMIN_PASSWORD: "admin"
volumes:
- ./grafana/lib:/var/lib/grafana
- ./grafana/log:/var/log/grafana
# - ./grafana.ini/etc/grafana/grafana.ini
# :
nginx:
image: nginx:latest
hostname: nginx
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx_default.conf:/etc/nginx/conf.d/default.conf
- ./letsencrypt:/etc/letsencrypt
- ./www:/var/www
nginx設定ファイル作成 †nginx_default.conf upstream backend {
server grafana:3000;
}
# http
server{
listen 80;
listen [::]:80;
server_name {サーバ名}.japaneast.cloudapp.azure.com;
# アクセストークン確認用リクエストの場合は、https にリダイレクトしない
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www;
}
location / {
return 301 https://$host$request_uri;
}
}
# https
server{
listen 443 ssl;
listen [::]:443 ssl;
server_name {サーバ名}.japaneast.cloudapp.azure.com;
ssl_certificate /etc/letsencrypt/live/{サーバ名}.japaneast.cloudapp.azure.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{サーバ名}.japaneast.cloudapp.azure.com/privkey.pem;
location / {
proxy_pass http://backend;
}
}
コンテナ起動 †コンテナ起動 docker-compose up -d 自動更新の設定 †証明書更新用の処理を作成 †ssl_cert_update.sh #!/bin/bash
cd /containers
domain=`hostname`.japaneast.cloudapp.azure.com
certbot_cmd=certonly
domain_arg="-d ${domain}"
if [ -e ./letsencrypt/live/${domain}/cert.pem ]; then
certbot_cmd=renew
domain_arg=
fi
bef=`sudo ls -l ./letsencrypt/live/${domain}/`
docker ps
docker run --rm \
-v `pwd`/letsencrypt:/etc/letsencrypt \
-v `pwd`/letsencrypt/logs:/var/log/letsencrypt \
-v `pwd`/www:/var/www \
certbot/certbot $certbot_cmd \
--webroot \
-w /var/www \
--register-unsafely-without-email \
--non-interactive --agree-tos \
--force-renewal \
--renew-by-default \
$domain_arg
aft=`sudo ls -l ./letsencrypt/live/${domain}/`
echo "## before ##"
echo "$bef"
echo "## after ##"
echo "$aft"
docker restart nginx
docker ps
権限付与 chmod 755 ssl_cert_update.sh cronの設定 †毎月1日の0時に実行する場合 sudo crontab -e 0 0 1 * * /containers/ssl_cert_update.sh 2>&1 >>/containers/ssl_cert_update.log 実行時のログサンプル CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fc95f0b03d9c grafana/grafana:7.3.7 "/run.sh" 15 minutes ago Up 15 minutes 0.0.0.0:3000->3000/tcp grafana 9fc2e7149baa nginx:latest "/docker-entrypoint.…" 26 minutes ago Up 15 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/xxxxxxxx.japaneast.cloudapp.azure.com.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Renewing an existing certificate for xxxxxxxx.japaneast.cloudapp.azure.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - new certificate deployed without reload, fullchain is /etc/letsencrypt/live/xxxxxxxx.japaneast.cloudapp.azure.com/fullchain.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations, all renewals succeeded: /etc/letsencrypt/live/xxxxxxxx.japaneast.cloudapp.azure.com/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## before ## total 20 -rw-r--r-- 1 root root 692 Feb 11 03:26 README lrwxrwxrwx 1 root root 63 Feb 11 03:26 cert.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/cert1.pem lrwxrwxrwx 1 root root 64 Feb 11 03:26 chain.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/chain1.pem lrwxrwxrwx 1 root root 68 Feb 11 03:26 fullchain.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/fullchain1.pem lrwxrwxrwx 1 root root 66 Feb 11 03:26 privkey.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/privkey1.pem ## after ## total 20 -rw-r--r-- 1 root root 692 Feb 11 03:26 README lrwxrwxrwx 1 root root 63 Feb 11 04:04 cert.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/cert2.pem lrwxrwxrwx 1 root root 64 Feb 11 04:04 chain.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/chain2.pem lrwxrwxrwx 1 root root 68 Feb 11 04:04 fullchain.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/fullchain2.pem lrwxrwxrwx 1 root root 66 Feb 11 04:04 privkey.pem -> ../../archive/xxxxxxxx.japaneast.cloudapp.azure.com/privkey2.pem nginx CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fc95f0b03d9c grafana/grafana:7.3.7 "/run.sh" 19 minutes ago Up 19 minutes 0.0.0.0:3000->3000/tcp grafana 9fc2e7149baa nginx:latest "/docker-entrypoint.…" 30 minutes ago Up Less than a second 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx |