概要

Let's Encrypt の SSL証明書を自動更新する手順のメモ。

[環境/要件など]
・nginx は docker で動作させている。
・nginx を止めずに自動更新を行いたい。

Let's Encrypt の SSL証明書を取得/更新する場合、Certbot を使用する事になるが、上記の環境/要件を満たす為に以下の通り構成する。

・更新には Certbot の webroot プラグインを使用する。(standaloneではなく)
・アクセストークンの確認用リクエストも nginx で受け付ける。(リダイレクト等の対象にしない)
・トークンの確認用リクエスト時には webroot ディレクトリ配下に出力されるトークンを参照できるように nginx を設定しておく。

尚、当記事の内容は 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

いったんログアウトして再ログインする。
※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

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-02-11 (木) 13:19:19 (128d)