Let’s Encrypt - certbot-auto
Let’s Encrypt is a free certificate authority that you can use to generate certificates to use SSL on all of your websites! These certificates are short-lived however (90 days), so a bit of automation is required for it to be useful. That’s where tools like certbot
(or certbot-auto
) come in handy!
You can use these tools to generate certificates and then auto-renew without any human intervention. Here is an easy getting-started guide for using the webroot
plugin with certbot-auto
.
Get certbot-auto
:
cd /usr/local/sbin
sudo wget https://dl.eff.org/certbot-auto
Make it executable:
chmod a+x /usr/local/sbin/certbot-auto
Make directory structure for the acme-challenge file:
mkdir -p <dir_you_are_serving_from>/.well-known/acme-challenge
Note: webroot-path
should be set to wherever your server is serving from. #
Note2: --debug
is required if running this on amazon-linux, as support there is limited. #
Note3: I also had to run pip install --upgrade pip
and pip install --upgrade virtualenv
to get things working on amazon-linux #
Run a command like this to perform the verification:
certbot-auto certonly --webroot --webroot-path=<dir_you_are_serving_from> -d <example.com>
It should output some stuff, then it will drop your certificate in /etc/letsencrypt/live/<example.com>
.
Now, to renew these automatically, you can add a cronjob that executes this command:
certbot-auto renew --quiet --no-self-upgrade
I recommend setting this to run twice a day, just to avoid potential expiration (or revocation) between runs.
I also recommend generating a strong Diffie-Hellman group, like this:
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
All you have to do after that is configure ssl in your webserver to use the new cert you generated. For nginx, that looks like this:
ssl_certificate /etc/letsencrypt/live/<example.com>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<example.com>/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
One last additional note - if you renew your certificate but don’t restart/reload your webserver, it won’t see the new cert. It just keeps using the one it loaded up on start. To avoid this, you can pass a post-hook
to certbot-auto that will execute an arbitrary command for you if it renews your cert - like this:
--post-hook "service nginx reload"