• Let’s Encrypt is a new Certificate Authority that is automated and free to use. This makes it possible to obtain domain validated (DV) certificates for your domain names as no cost!

    I registered for the closed beta, and got a few of my domain names authorised. This meant that I could now obtain certificates for them. The process was fairly simple. I chose to use the webroot authentication method, which means that the Let’s Encrypt client should be able to place files under my webroot to prove that I control the domain.

    Since my webroot is /var/www I created the /var/www/acme/.well-known/acme-challenge folders for the webroot plugin to use. My web server is Nginx so I placed the following code in the server blocks for the domains I want to obtain certificates for and reloaded the Nginx configuration.

    location ~ ^/\.well-known/acme-challenge {
      root /var/www/acme;
      default_type application/jose+json;
    }
    

    Now it was time to install and run the Let’s Encrypt client to obtain the certificates. When prompted I used /var/www/acme as the webroot path.

    git clone https://github.com/letsencrypt/letsencrypt
    cd letsencrypt
    ./letsencrypt-auto --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory certonly
    

    So far so good. I now had my certificates under /etc/letsencrypt/live and could configure Nginx to use them. Great! For those who are curious this is my SSL configuration for Nginx:

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA";
    ssl_ecdh_curve secp384r1;
    ssl_dhparam /etc/ssl/dhparams.pem;
    add_header Strict-Transport-Security max-age=31536000;
    

    The certificates are valid for 90 days, so they need to be renewed fairly often. I wanted to automate this process, so I wrote the following script. Basically it checks all certificates under /etc/letsencrypt/live and if one is about to expire in less than 4 weeks it is automatically renewed. I named this script certrenew.

    #!/bin/bash
    
    if [ ! -d /etc/letsencrypt/live ]; then
      exit 1
    fi
    
    function issueCert {
      /root/.local/share/letsencrypt/bin/letsencrypt certonly --renew-by-default --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory --authenticator webroot --webroot-path /var/www/acme $1
    }
    
    exitcode=1
    while IFS= read -r -d '' cert; do
      if ! openssl x509 -noout -checkend $((4*7*86400)) -in "${cert}"; then
        subject="$(openssl x509 -noout -subject -in "${cert}" | grep -o -E 'CN=[^ ,]+' | tr -d 'CN=')"
        subjectaltnames="$(openssl x509 -noout -text -in "${cert}" | sed -n '/X509v3 Subject Alternative Name/{n;p}' | sed 's/\s//g' | tr -d 'DNS:' | sed 's/,/ /g')"
        domains="-d ${subject}"
        for name in ${subjectaltnames}; do
          if [ "${name}" != "${subject}" ]; then
            domains="${domains} -d ${name}"
          fi
        done
        issueCert "${domains}"
        exitcode=0
      fi
    done < <(find /etc/letsencrypt/live -name cert.pem -print0)
    
    exit ${exitcode}
    

    The script can be downloaded here.

    To automate everything I run the following script via cron every day. It calls the certrenew script and if certificates are renewed it reloads the Nginx configuration after the renewal process. This will produce output so you will get an e-mail from the cron daemon when certificates are renewed. If you don't what that then just send the output of certrenew to /dev/null.

    #!/bin/bash
    
    if /usr/local/bin/certrenew; then
      /usr/sbin/nginx -t && systemctl reload nginx
    fi
    
    exit 0
    

    That's it. Fully automated renewal of Let's Encrypt certificates 🙂

    Posted by Michael @ 11:00

6 kommentarer til Automatic renewal of Let’s Encrypt issued certificates

  • Conrad siger:

    Hello,

    could you please post your script in Plaintext or as a download? It looks realy helpful, but unfortunately your blog software scrambled some characters so i can’t copy&paste it.

    Thank!

  • Michael siger:

    Thanks for the comment. I have added a download link for the script.

  • For Apache, the webroot challenge folder in Apache could be defined like this:

    <Alias /.well-known/acme-challenge/ /www/acme-challenge/>

    <Directory “/www/acme-challenge/”>
    Order Deny,Allow
    Allow from all
    </Directory>

    The config lines should/could be defined outside of the vhosts so they don’t have to be defined for every single vhost.

  • El Severo siger:

    Michael, thanks for this great article! I have a question though, how did you've runned this part:

    “`
    #!/bin/bash

    if /usr/local/bin/certrenew; then
    /usr/sbin/nginx -t && systemctl reload nginx
    fi

    exit 0
    “`
    Thanks!

  • Hamada siger:

    This script can work for cpanel based on Apache? If yes , how can i Automate and edit this script ?
    Thanks you !

  • Michael siger:

    This script is obsolete. Use the renew feature of certbot instead.