Template di validazione DNS di LetsEncrypt utilizzando Cloudflare

Ciao ragazzi

Ho dovuto utilizzare il metodo DNS per autenticare la proprietà del mio certificato SSL con Let’s Encrypt.

Ho preso una copia del file web.letsencrypt.ssl.template.yml esistente, che si trova in /var/discourse/templates/, e l’ho modificato per utilizzare il metodo di integrazione automatica dell’API DNS. Di seguito è riportato il mio modello di esempio, sarei felice se ci fossero suggerimenti su come migliorarlo.

Ho chiamato questo file 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"

    - 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';

Ci sono alcune variabili d’ambiente aggiuntive che devi aggiungere ad app.yml e possibilmente modificare se non utilizzi Cloudflare come provider DNS. Tutte le impostazioni API dei diversi provider sono qui

Questo è ciò che ho aggiunto al mio app.yml nella sezione 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"

E più in basso nella sezione 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

Dopo aver aggiornato quei file, ho semplicemente eseguito il comando per ricostruire l’app docker

cd /var/discourse
./launcher rebuild app 

Una volta ricostruito, dovresti avere la tua app in esecuzione su https:// e dovrebbe esserci un cron job che controlla quotidianamente se il tuo certificato necessita di aggiornamenti. Se necessita di aggiornamenti, otterrà un nuovo certificato e lo installerà automaticamente.

Spero che questo aiuti qualcuno.

2 Mi Piace

MODIFICA: Ho appena raggiunto il limite di 5 certificati Let’s Encrypt (per dominio esatto) a settimana.

Hai avuto un problema con la generazione del certificato _ecc?

Usando il tuo post, il file principale website.com.cer viene generato con successo, tuttavia website.com_ecc.cer mostra 0 byte (la _ecc.key va bene).

Ma entrambi i certificati sono emessi dallo stesso metodo issue_cert, quindi per qualche motivo quello principale funziona e l’_ecc fallisce.