概要 †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 |