Cloudflare を使用した LetsEncrypt DNS検証 テンプレート

こんにちは皆さん

SSL証明書の所有権を Let’s Encrypt で認証するために DNS メソッドを使用する必要がありました。
/var/discourse/templates/ にある既存の web.letsencrypt.ssl.template.yml ファイルをコピーし、自動 DNS API 統合メソッドを使用するように変更しました。以下は私のサンプルテンプレートです。改善点があれば教えていただけると幸いです。

このファイルを web.letsencrypt.ssl.dns.template.yml と名付けました。

env:
  LETSENCRYPT_DIR: "/shared/letsencrypt"
  DISCOURSE_FORCE_HTTPS: true

hooks:
  after_ssl:
    - exec:
       cmd:
         - if [ -z "$LETSENCRYPT_ACCOUNT_EMAIL" ]; then echo "LETSENCRYPT_ACCOUNT_EMAIL ENV variable is required and has not been set."; exit 1; fi
         - /bin/bash -c "if [[ ! \"$LETSENCRYPT_ACCOUNT_EMAIL\" =~ ([^@]+)@([^\\.]+) ]]; then echo \"LETSENCRYPT_ACCOUNT_EMAIL is not a valid email address\"; exit 1; fi"

    - exec:
       cmd:
         - cd /root && git clone --branch 3.0.7 --depth 1 https://github.com/acmesh-official/acme.sh.git && cd /root/acme.sh
         - touch /var/spool/cron/crontabs/root
         - install -d -m 0755 -g root -o root $LETSENCRYPT_DIR
         - cd /root/acme.sh && LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --install --log "${LETSENCRYPT_DIR}/acme.sh.log"
         - cd /root/acme.sh && LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --upgrade --auto-upgrade
         - cd /root/acme.sh && LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --set-default-ca  --server  letsencrypt

    - file:
       path: /etc/runit/1.d/letsencrypt
       chmod: "+x"
       contents: |
        #!/bin/bash

        issue_cert() {
          export CF_Token="$ENV_LETSENCRYPT_CF_TOKEN"
          export CF_Account_ID="$ENV_LETSENCRYPT_CF_ACCOUNT_ID"
          export CF_Zone_ID="$ENV_LETSENCRYPT_CF_ZONE_ID"
          LE_WORKING_DIR="${LETSENCRYPT_DIR}" $ENV_LETSENCRYPT_DIR/acme.sh --issue --dns $ENV_LETSENCRYPT_DNS_PROVIDER $2 -d $ENV_DISCOURSE_HOSTNAME --keylength $1 -w /var/www/discourse/public
        }

        cert_exists() {
          [[ "$(cd ${ENV_LETSENCRYPT_DIR}/${ENV_DISCOURSE_HOSTNAME}$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")"]]
        }

        ########################################################
        # RSA cert
        ########################################################
        issue_cert "4096"

        if ! cert_exists ""; then
          # Try to issue the cert again if something goes wrong
          issue_cert "4096" "--force"
        fi

        LE_WORKING_DIR="${LETSENCRYPT_DIR}" $ENV_LETSENCRYPT_DIR/acme.sh \
          --installcert \
          -d $ENV_DISCOURSE_HOSTNAME \
          --fullchainpath /shared/ssl/$ENV_DISCOURSE_HOSTNAME.cer \
          --keypath /shared/ssl/$ENV_DISCOURSE_HOSTNAME.key \
          --reloadcmd "sv reload nginx"

        ########################################################
        # ECDSA cert
        ########################################################
        issue_cert "ec-256"

        if ! cert_exists "_ecc"; then
          # Try to issue the cert again if something goes wrong
          issue_cert "ec-256" "--force"
        fi

        LE_WORKING_DIR="${LETSENCRYPT_DIR}" $ENV_LETSENCRYPT_DIR/acme.sh \
          --installcert --ecc \
          -d $ENV_DISCOURSE_HOSTNAME \
          --fullchainpath /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.cer \
          --keypath /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.key \
          --reloadcmd "sv reload nginx"

        if cert_exists "" || cert_exists "_ecc"; then
          grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
        fi

    - replace:
       filename: "/etc/nginx/conf.d/discourse.conf"
       from: /ssl_certificate.+/
       to: |
         ssl_certificate /shared/ssl/$ENV_DISCOURSE_HOSTNAME.cer;
         ssl_certificate /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.cer;

    - replace:
       filename: /shared/letsencrypt/account.conf
       from: /#?ACCOUNT_EMAIL=.+/
       to: |
         ACCOUNT_EMAIL=$ENV_LETSENCRYPT_ACCOUNT_EMAIL

    - replace:
       filename: "/etc/nginx/conf.d/discourse.conf"
       from: /ssl_certificate_key.+/
       to: |
         ssl_certificate_key /shared/ssl/$ENV_DISCOURSE_HOSTNAME.key;
         ssl_certificate_key /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.key;

    - replace:
       filename: "/etc/nginx/conf.d/discourse.conf"
       from: /add_header.+/
       to: |
         add_header Strict-Transport-Security 'max-age=63072000';

app.yml に追加する必要がある追加の環境変数があります。また、Cloudflare 以外の DNS プロバイダーを使用している場合は、変更が必要になる場合があります。すべての異なるプロバイダーの API 設定はこちらにあります。

app.ymltemplates セクションに次を追加しました。

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  ## IPv6 リスナーを有効にするには、次の行のコメントを解除します
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  ## Let's Encrypt (https) を追加したい場合は、次の 2 行のコメントを解除します
  - "templates/web.ssl.template.yml"
  - "templates/web.letsencrypt.ssl.dns.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

さらに下に env セクションがあります。

## Let's Encrypt テンプレートを追加した場合、以下のコメントを解除して無料の SSL 証明書を取得します
  LETSENCRYPT_ACCOUNT_EMAIL: me@mydomain.com
  LETSENCRYPT_CF_TOKEN: "YOUR_TOKEN"
  LETSENCRYPT_CF_ACCOUNT_ID: "YOUR_ACCOUNT_ID"
  LETSENCRYPT_CF_ZONE_ID: "YOUR_ZONE_ID"
  LETSENCRYPT_DNS_PROVIDER: "YOUR_DNS_PROVIDER" ## 例: dns_cf

これらのファイルを更新した後、docker アプリケーションを再構築するためのコマンドを実行しました。

cd /var/discourse
./launcher rebuild app

再構築が完了すると、https:// でアプリが実行され、証明書の更新が必要かどうかを毎日チェックする cron ジョブが作成されているはずです。更新が必要な場合は、新しい証明書を取得して自動的にインストールします。

誰かの役に立つことを願っています。

「いいね!」 2

編集: 週5枚のLet’s Encrypt証明書(正確にはドメインごと)の上限に達しました。

_ecc証明書の生成で問題がありましたか?

あなたの投稿によると、メインのwebsite.com.cerファイルは正常に生成されていますが、website.com_ecc.cerは0バイトになっています(_ecc.keyは問題ありません)。

しかし、両方の証明書は同じissue_certメソッドによって発行されているため、メインの証明書は機能し、_ecc証明書が失敗する理由は不明です。