قالب تحقق DNS من Let's Encrypt باستخدام Cloudflare

مرحباً يا رفاق

لقد احتجت إلى استخدام طريقة DNS للمصادقة على ملكية شهادة SSL الخاصة بي مع Let’s Encrypt.

لقد أخذت نسخة من ملف web.letsencrypt.ssl.template.yml الموجود في /var/discourse/templates/ وقمت بتعديله لاستخدام طريقة التكامل التلقائي لواجهة برمجة تطبيقات DNS. أدناه نموذجي للقالب، وسأكون سعيدًا إذا كانت هناك أي اقتراحات حول كيفية تحسينه.

لقد أسميت هذا الملف 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 الخاص بك. جميع إعدادات واجهة برمجة التطبيقات لمختلف المزودين موجودة هنا

هذا ما أضفته إلى app.yml الخاص بي تحت قسم templates

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  ## Uncomment the next line to enable the IPv6 listener
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  ## Uncomment these two lines if you wish to add Lets Encrypt (https)
  - "templates/web.ssl.template.yml"
  - "templates/web.letsencrypt.ssl.dns.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

وفي أسفل قسم env.

## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
  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" ## i.e. dns_cf

بعد تحديث تلك الملفات، قمت ببساطة بتشغيل الأمر لإعادة بناء تطبيق docker

cd /var/discourse
./launcher rebuild app 

بمجرد إعادة البناء، يجب أن يكون لديك التطبيق الخاص بك يعمل على https:// ويجب أن تكون هناك مهمة cron تتحقق يوميًا مما إذا كانت شهادتك بحاجة إلى تحديث. إذا كانت بحاجة إلى تحديث، فستحصل على شهادة جديدة وتثبيتها تلقائيًا.

آمل أن يساعد هذا شخصًا ما.

إعجابَين (2)

تعديل: لقد وصلت للتو إلى الحد الأقصى لشهادات letsencrypt البالغ 5 (لكل نطاق بالضبط) في الأسبوع.

هل واجهت مشكلة في إنشاء شهادة _ecc؟

باستخدام منشورك، يتم إنشاء الملف الرئيسي website.com.cer بنجاح، ومع ذلك، فإن ملف website.com_ecc.cer يظهر بحجم 0 بايت (الملف _ecc.key جيد).

ولكن يتم إصدار كلتا الشهادتين بواسطة نفس الدالة issue_cert، لذا لسبب ما تعمل الشهادة الرئيسية وتفشل شهادة _ecc.