Difference between revisions of "Letsencrypt"

From Jon's Wiki
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
__NOTOC__
 
__NOTOC__
It's easy!
+
It's easy in Ubuntu 20.04 using [https://github.com/lukas2511/dehydrated dehydrated].
  
 
== Install the things ==
 
== Install the things ==
  
First install the nifty checker and make some directories:
+
First install the nifty dehydrated utility<ref>If you don't have Ubuntu 20.04, use <pre>git clone <nowiki>https://github.com/lukas2511/dehydrated.git</nowiki> /opt/dehydrated
 +
ln -s /opt/dehydrated/dehydrated /usr/local/bin/</pre></ref>:
  
  git clone <nowiki>https://github.com/lukas2511/dehydrated.git</nowiki> /opt/letsencrypt
+
  apt install dehydrated
mkdir -p /etc/ssl/letsencrypt
 
mkdir -p /var/www/dehydrated
 
  
 
== Set up the site's handshake ==
 
== Set up the site's handshake ==
  
This script talks to the Letsencrypt CA and temporarily drops tokens in <tt>/var/www/dehydrated</tt> for your site to host for the handshake, deleting them afterwards. So make sure the HTTP side of your site can facilitate the handshake by using a known URL alias. In Apache, you need something like:
+
You can use the dehydrated script to use the ACME HTTP challenge method. It talks to the Letsencrypt CA and temporarily drops tokens in <tt>/var/lib/dehydrated/acme-challenges</tt> for your site to host for the handshake, deleting them afterwards. So make sure the HTTP side of your site can facilitate the handshake by using a known URL alias without redirecting it to HTTPS. In Apache, you need something like:
  
 
  <VirtualHost *:80>
 
  <VirtualHost *:80>
 
   ServerName '''www.myniftysite.com'''
 
   ServerName '''www.myniftysite.com'''
   Alias "/.well-known/acme-challenge/" "/var/www/dehydrated/"
+
   Alias "/.well-known/acme-challenge/" "/var/lib/dehydrated/acme-challenges/"
 
   RewriteEngine On
 
   RewriteEngine On
   RedirectMatch 302 ^(?!/\.well-known/acme-challenge/).* <nowiki>https://</nowiki>'''www.myniftysite.com'''$0
+
   RedirectMatch 301 ^(?!/\.well-known/acme-challenge/).* <nowiki>https://</nowiki>'''www.myniftysite.com'''$0
 
  </VirtualHost>
 
  </VirtualHost>
 
   
 
   
Line 27: Line 26:
 
   server_name '''www.myniftysite.com''';
 
   server_name '''www.myniftysite.com''';
 
   location /.well-known/acme-challenge/ {
 
   location /.well-known/acme-challenge/ {
     alias /var/www/dehydrated/;
+
     alias /var/lib/dehydrated/acme-challenges/;
 
   }
 
   }
 
   location / {
 
   location / {
     return 302 <nowiki>https://$host$request_uri; </nowiki>
+
     return 301 <nowiki>https://$host$request_uri; </nowiki>
 
   }
 
   }
 
  }
 
  }
Line 38: Line 37:
 
Then run the following command. Once you've proven it works, bung it in <tt>/etc/cron.d/letsencrypt-renew</tt> to run every so often (Letsencrypt certificates expire in 3 months).
 
Then run the following command. Once you've proven it works, bung it in <tt>/etc/cron.d/letsencrypt-renew</tt> to run every so often (Letsencrypt certificates expire in 3 months).
  
  /opt/letsencrypt/dehydrated -c --domain '''www.myniftysite.com''' --challenge http-01 --out /etc/ssl/letsencrypt
+
  /usr/bin/dehydrated -c --domain '''www.myniftysite.com''' --challenge http-01
  
 
== Set up your HTTPS site ==
 
== Set up your HTTPS site ==
  
Now you can enable the HTTPS side of your site with the shiny new certificates the Letsencrypt CA generated for you (best to refer to the [https://mozilla.github.io/server-side-tls/ssl-config-generator/ Mozilla SSL config generator] for the most up-to-date configuration).
+
Now you can enable the HTTPS side of your site with the shiny new certificates the Letsencrypt CA generated for you.
  
 
  <VirtualHost *:443>
 
  <VirtualHost *:443>
 +
  ServerName '''www.myniftysite.com'''
 
   SSLEngine On
 
   SSLEngine On
   SSLCertificateFile /etc/ssl/letsencrypt/'''www.myniftysite.com'''/fullchain.pem
+
   SSLCertificateFile /var/lib/dehydrated/certs/'''www.myniftysite.com'''/fullchain.pem
   SSLCertificateKeyFile /etc/ssl/letsencrypt/'''www.myniftysite.com'''/privkey.pem
+
   SSLCertificateKeyFile /var/lib/dehydrated/certs/'''www.myniftysite.com'''/privkey.pem
   Header always set Strict-Transport-Security "max-age=15768000"
+
   Header always set Strict-Transport-Security "max-age=63072000"
  SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
 
  SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:
 
                  ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:
 
                  ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES1
 
  SSLHonorCipherOrder on
 
  SSLCompression off
 
 
  # Ticket option and OCSP Stapling supported in Apache 2.4
 
  SSLSessionTickets off
 
  SSLUseStapling on
 
  SSLStaplingResponderTimeout 5
 
  SSLStaplingReturnResponderErrors off
 
  SSLStaplingCache shmcb:/var/run/ocsp(128000)
 
 
   ...  
 
   ...  
  
Line 68: Line 55:
 
  server {
 
  server {
 
   listen        *:443 ssl;
 
   listen        *:443 ssl;
   server_name  cloud.jon.geek.nz;
+
   server_name  '''www.myniftysite.com;'''
 
 
   ssl  on;
 
   ssl  on;
   ssl_certificate    /etc/ssl/letsencrypt/'''www.myniftysite.com'''/fullchain.pem;
+
   ssl_certificate    /var/lib/dehydrated/certs/'''www.myniftysite.com'''/fullchain.pem;
   ssl_certificate_key /etc/ssl/letsencrypt/'''www.myniftysite.com'''/privkey.pem;
+
   ssl_certificate_key /var/lib/dehydrated/certs/'''www.myniftysite.com'''/privkey.pem;
   ssl_trusted_certificate /etc/ssl/letsencrypt/'''www.myniftysite.com'''/chain.pem;
+
   ssl_trusted_certificate /var/lib/dehydrated/certs/'''www.myniftysite.com'''/chain.pem;
  ssl_session_timeout  5m;
 
  ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
 
  ssl_ciphers EECDH+aRSA+AES256:EDH+aRSA+AES256:EECDH+aRSA+AES128:EDH+aRSA+AES128;
 
  ssl_session_cache shared:SSL:50m;
 
  ssl_prefer_server_ciphers on;
 
  ssl_stapling on;
 
  ssl_stapling_verify on;
 
 
   add_header Strict-Transport-Security max-age=63072000;
 
   add_header Strict-Transport-Security max-age=63072000;
 
  # For this, run this command:
 
  #    openssl dhparam -out /etc/ssl/letsencrypt/dhparam.pem 2048
 
  ssl_dhparam /etc/ssl/letsencrypt/dhparam.pem;
 
 
   ...
 
   ...
 +
 +
In addition, you probably want to lock down the SSL nicely. Best to refer to the [https://mozilla.github.io/server-side-tls/ssl-config-generator/ Mozilla SSL config generator] for the most up-to-date configuration, and put this in a separate common config file that you can include where needed.
  
 
== Run a script from cron ==
 
== Run a script from cron ==
  
Set up a config file:
+
Edit the config file:
  
  # Stick this in /etc/dehydrated/config
+
  ''# Contents of /etc/dehydrated/config''
  CERTDIR='/etc/ssl/letsencrypt'
+
  CERTDIR='/var/lib/dehydrated/certs'
 
  CHALLENGETYPE='http-01'
 
  CHALLENGETYPE='http-01'
  
Then a script somewhere in /usr/local/bin to run from a cron job:
+
Then make a script to run from a cron job:
 
 
<pre>
 
#!/bin/bash
 
# Renew SSL certificates with LetsEncrypt using dehydrated.
 
# See: https://github.com/lukas2511/dehydrated
 
  
DEHYDRATED='/opt/letsencrypt/dehydrated'
+
''#!/bin/bash''
 +
''# Script: /usr/local/bin/letsencrypt-renew''
 +
''# Renew site SSL certificates with LetsEncrypt using dehydrated.''
 +
''# See: https://github.com/lukas2511/dehydrated''
 +
for domain in                  \
 +
        my-domain-1.com        \
 +
        my-other-domain.com    \
 +
        foo-bar-baz.com        \
 +
; do
 +
    dehydrated -c --domain $domain
 +
    sleep 2
 +
done
  
# Save etckeeper state just in case.
+
And a cron job like this:
if /usr/bin/etckeeper unclean; then
 
    /usr/bin/etckeeper pre-install
 
fi
 
  
for domain in                  \
+
''# Contents of /etc/cron.d/letsencrypt-renew''
        my-domain-1.com        \
+
''# Attempt SSL certificate renewals with dehydrated weekly''
        my-other-domain.com    \
+
22 22 * * 2 root /usr/local/bin/letsencrypt-renew > /var/log/letsencrypt-renew.log 2> /var/log/letsencrypt-renew.err
        foo-bar-baz.com        \
 
; do
 
    $DEHYDRATED -c --domain $domain
 
    sleep 2
 
done
 
  
# If SSL certs renewed, update etckeeper and restart services
+
== Notes ==
if /usr/bin/etckeeper unclean; then
+
<references/>
    /usr/bin/etckeeper commit "LetsEncrypt certificates updated."
 
    /usr/sbin/service nginx restart
 
fi</pre>
 

Latest revision as of 11:14, 1 September 2021

It's easy in Ubuntu 20.04 using dehydrated.

Install the things

First install the nifty dehydrated utility[1]:

apt install dehydrated

Set up the site's handshake

You can use the dehydrated script to use the ACME HTTP challenge method. It talks to the Letsencrypt CA and temporarily drops tokens in /var/lib/dehydrated/acme-challenges for your site to host for the handshake, deleting them afterwards. So make sure the HTTP side of your site can facilitate the handshake by using a known URL alias without redirecting it to HTTPS. In Apache, you need something like:

<VirtualHost *:80>
  ServerName www.myniftysite.com
  Alias "/.well-known/acme-challenge/" "/var/lib/dehydrated/acme-challenges/"
  RewriteEngine On
  RedirectMatch 301 ^(?!/\.well-known/acme-challenge/).* https://www.myniftysite.com$0
</VirtualHost>

Or the same thing in nginx:

server {
  listen 80;
  server_name www.myniftysite.com;
  location /.well-known/acme-challenge/ {
    alias /var/lib/dehydrated/acme-challenges/;
  }
  location / {
    return 301 https://$host$request_uri; 
  }
}

Fetch your certificates

Then run the following command. Once you've proven it works, bung it in /etc/cron.d/letsencrypt-renew to run every so often (Letsencrypt certificates expire in 3 months).

/usr/bin/dehydrated -c --domain www.myniftysite.com --challenge http-01

Set up your HTTPS site

Now you can enable the HTTPS side of your site with the shiny new certificates the Letsencrypt CA generated for you.

<VirtualHost *:443>
  ServerName www.myniftysite.com
  SSLEngine On
  SSLCertificateFile /var/lib/dehydrated/certs/www.myniftysite.com/fullchain.pem
  SSLCertificateKeyFile /var/lib/dehydrated/certs/www.myniftysite.com/privkey.pem
  Header always set Strict-Transport-Security "max-age=63072000"
  ... 

More or less the same thing in nginx:

server {
  listen        *:443 ssl;
  server_name   www.myniftysite.com; 
  ssl  on;
  ssl_certificate     /var/lib/dehydrated/certs/www.myniftysite.com/fullchain.pem;
  ssl_certificate_key /var/lib/dehydrated/certs/www.myniftysite.com/privkey.pem;
  ssl_trusted_certificate /var/lib/dehydrated/certs/www.myniftysite.com/chain.pem;
  add_header Strict-Transport-Security max-age=63072000;
  ...

In addition, you probably want to lock down the SSL nicely. Best to refer to the Mozilla SSL config generator for the most up-to-date configuration, and put this in a separate common config file that you can include where needed.

Run a script from cron

Edit the config file:

# Contents of /etc/dehydrated/config
CERTDIR='/var/lib/dehydrated/certs'
CHALLENGETYPE='http-01'

Then make a script to run from a cron job:

#!/bin/bash
# Script: /usr/local/bin/letsencrypt-renew
# Renew site SSL certificates with LetsEncrypt using dehydrated.
# See: https://github.com/lukas2511/dehydrated 
for domain in                   \
        my-domain-1.com         \
        my-other-domain.com     \
        foo-bar-baz.com         \
; do
    dehydrated -c --domain $domain
    sleep 2
done

And a cron job like this:

# Contents of /etc/cron.d/letsencrypt-renew
# Attempt SSL certificate renewals with dehydrated weekly
22 22 * * 2 root /usr/local/bin/letsencrypt-renew > /var/log/letsencrypt-renew.log 2> /var/log/letsencrypt-renew.err

Notes

  1. If you don't have Ubuntu 20.04, use
    git clone https://github.com/lukas2511/dehydrated.git /opt/dehydrated
    ln -s /opt/dehydrated/dehydrated /usr/local/bin/