Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

https://dehydrated.de/  is a great tool for automating the renewal workflow, particularly if you want to use the DNS challenge method, rather than web access. 

  • An example configuration file is:

    Code Block
    CA="https://acme-v01.api.letsencrypt.org/directory"
    #CA="https://acme-staging.api.letsencrypt.org/directory"
    LICENSE="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
    CERTDIR=/usr/local/etc/dehydrated/certs
    CHALLENGETYPE="dns-01"
    HOOK=/usr/local/etc/dehydrated/dnshook.sh
    PRIVATE_KEY_RENEW="no"
    PRIVATE_KEY_ROLLOVER="no"
    CONTACT_EMAIL=alice@example.com

     

  • Private keys are then stored in

    Code Block
    /usr/local/etc/dehydrated/certs/<domain>/privkey.pem
  • The SubjectAltNames are then enumerated in the file

    Code Block
    /usr/local/etc/dehydrated/domains.txt


    Add one line in this for each 'group' of names that should share a certificate e.g

    Code Block
    example.com www.example.com example.org
    example1.com www.example1.com example1.net
  • Then the challenge record needs to be provisioned in the corresponding zone in a record of the form

    Code Block
    _acme-challenge.<domain name>



  • If you have many zones it can be helpful to use CNAMES to redirect to a single zone that can hold the acme_challenge records e.g. <domain>.acme.example.com

    Info

    The domain acme.example.com is then hosted only on the server that also runs dehydrated. 

  • A script can then be used to deploy and clean the challenge in this domain. An example script is included below

    Code Block
    #!/bin/sh
    
    zonefile=/usr/local/etc/dehydrated/acmezone
    
    deploy_challenge() {
       local DOMAIN="${1}" RDATA="${3}"
       echo "$DOMAIN 10 TXT \"$RDATA\"" >> $zonefile
       echo "$DOMAIN 10 TXT \"$RDATA\""
       ldns-read-zone $zonefile > /dev/null
       if [ $? -eq 0 ]; then
           cp $zonefile ~/unsigned/acme.example.com
           ods-signer sign acme.example.com
           sleep .5
       fi
    }
    
    clean_challenge() {
       local DOMAIN="${1}" RDATA="${3}"
       sed -i ".old" "/$DOMAIN 10 TXT \"$RDATA\"/d" $zonefile
       ldns-read-zone $zonefile > /dev/null
       if [ $? -eq 0 ]; then
           cp $zonefile ~/unsigned/acme.example.com
           ods-signer sign acme.example.com
       fi
    }
    
    deploy_cert() {
       local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}"
    FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"
       # nothing yet..
    }
    
    unchanged_cert() {
       local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}"
    FULLCHAINFILE="${4}" CHAINFILE="${5}"
       # nothing yet..
    }
    
    HANDLER="$1"; shift
    "$HANDLER" "$@"