I visited https://letsencrypt.org/ where it said Let’s Encrypt is a free, automated, and open SSL Certificate Authority. That sounds great, time to check them out. This may not take 1 minute on your server but it did on mine (a self-managed Ubuntu 16.04/NGINX server). If you are not sure why you need an SSL cert read Life Is About to Get a Whole Lot Harder for Websites Without Https from Troy hunt.
Advertisement:
FYI you can set up an Ubuntu Vutur VM here (my guide here) for as low as $2.5 a month or a Digital Ocean VM server here (my guide here) for $5 a month, billing is charged to the hour and is cheap as chips.
I clicked Get Started and read the Getting started guide. I was redirected to https://certbot.eff.org/ where it said: “Automatically enable HTTPS on your website with EFF’s Certbot, deploying Let’s Encrypt certificates.“. I was asked what web server and OS I use..
I confirmed my Linux version
1 |
lsb_release -a |
Ensure your NGINX is setup (read my Vultr guide here) and you have a”server_name” specified in the “/etc/nginx/sites-available/default” file.
e.g
1 |
server_name yourdomain.com www.yourdomain.com; |
I also like to set “root” to “/www” in the NGINX configuration.
e.g
1 |
root /www; |
Tip: Ensure the www folder is set up first and has ownership.
1 2 |
mkdir /www sudo chown -R www-data:www-data /www |
Also, make and verify the contents of a /www /index.html file.
1 |
echo "Hello World..." > /www/index.html && cat /www/index.html |
I then selected my environment on the site (NGINX and Ubuntu 16.04) and was redirected to the setup instructions.
FYI: I will remove mention of my real domain and substitute with thesubdomain.thedomain.com for security in the output below.
I was asked to run these commands
1 2 3 4 5 |
sudo apt-get update sudo apt-get install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install python-certbot-nginx |
Detailed instructions here.
Obtaining an SSL Certificate
I then ran the following command to automatically obtain and install (configure NGINX) an SSL certificate.
1 |
sudo certbot --nginx |
Output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
sudo certbot --nginx Saving debug log to /var/log/letsencrypt/letsencrypt.log Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):Invalid email address: . Enter email address (used for urgent renewal and security notices) If you really want to skip this, you can run the client with --register-unsafely-without-email but make sure you then backup your account key from /etc/letsencrypt/accounts (Enter 'c' to cancel): removed@removed.com ------------------------------------------------------------------------------- Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree in order to register with the ACME server at https://acme-v01.api.letsencrypt.org/directory ------------------------------------------------------------------------------- (A)gree/(C)ancel: A ------------------------------------------------------------------------------- Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about EFF and our work to encrypt the web, protect its users and defend digital rights. ------------------------------------------------------------------------------- (Y)es/(N)o: Y Which names would you like to activate HTTPS for? ------------------------------------------------------------------------------- 1: thesubdomain.thedomain.com ------------------------------------------------------------------------------- Select the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shown (Enter 'c' to cancel):1 Obtaining a new certificate Performing the following challenges: tls-sni-01 challenge for thesubdomain.thedomain.com Waiting for verification... Cleaning up challenges Deployed Certificate to VirtualHost /etc/nginx/sites-enabled/default for set(['thesubdomain.thedomain.com', 'localhost']) Please choose whether HTTPS access is required or optional. ------------------------------------------------------------------------------- 1: Easy - Allow both HTTP and HTTPS access to these sites 2: Secure - Make all requests redirect to secure HTTPS access ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2 Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/default ------------------------------------------------------------------------------- Congratulations! You have successfully enabled https://thesubdomain.thedomain.com You should test your configuration at: https://www.ssllabs.com/ssltest/analyze.html?d=thesubdomain.thedomain.com ------------------------------------------------------------------------------- IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/thesubdomain.thedomain.com/fullchain.pem. Your cert will expire on 2017-10-27. To obtain a new or tweaked version of this certificate in the future, simply run certbot again with the "certonly" option. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le |
That was the easiest SSL cert generation in history.
SSL Certificate Renewal (dry run)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
sudo certbot renew --dry-run Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Processing /etc/letsencrypt/renewal/thesubdomain.thedomain.com.conf ------------------------------------------------------------------------------- Cert not due for renewal, but simulating renewal for dry run Renewing an existing certificate Performing the following challenges: tls-sni-01 challenge for thesubdomain.thedomain.com Waiting for verification... Cleaning up challenges ------------------------------------------------------------------------------- new certificate deployed with reload of nginx server; fullchain is /etc/letsencrypt/live/thesubdomain.thedomain.com/fullchain.pem ------------------------------------------------------------------------------- ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates below have not been saved.) Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/thesubdomain.thedomain.com/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry ** (The test certificates above have not been saved.) IMPORTANT NOTES: - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. |
SSL Certificate Renewal (Live)
1 |
certbot renew |
The Lets Encrypt SSL certificate is only a 90-day certificate.
Again: The Lets Encrypt SSL certificate is only a 90-day certificate.
I’ll run “certbot renew” again 2 months time to manually renew the certificate (and configure my higher security configuration (see below)).
Certbot NGINX Config renew (what did it do)
It’s nice to see forces HTTPS added to the configuration
1 2 3 |
if ($scheme != "https") { return 301 https://$host$request_uri; } # managed by Certbot |
Cert stuff added
1 2 3 4 |
listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/thesubdomain.thedomain.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/thesubdomain.thedomain.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot |
Contents of /etc/letsencrypt/options-ssl-nginx.conf
1 2 3 4 5 6 7 |
ssl_session_cache shared:le_nginx_SSL:1m; ssl_session_timeout 1440m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"; |
This contains too many legacy cyphers for my liking.
I changed /etc/letsencrypt/options-ssl-nginx.conf to tighten ciphers and add TLS 1.3 (as my NGINX Supports it).
1 2 3 4 5 6 7 |
ssl_session_cache shared:le_nginx_SSL:1m; ssl_session_timeout 1440m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; |
Enabling OCSP Stapling and Strict Transport Security in NGINX
I add the following to /etc/nginx/sites/available/default
1 2 3 4 |
# OCSP (Online Certificate Status Protocol) is a protocol for checking if a SSL certificate has been revoked ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; |
Restart NGINX.
1 2 3 |
sudo nginx -t sudo nginx -s reload sudo /etc/init.d/nginx restart |
SSL Labs SSL Score
I am happy with this.
Read my guide on Beyond SSL with Content Security Policy, Public Key Pinning etc
Automatic SSL Certificate Renewal
There are ways to auto renew the SSL certs floating around YouTube but I’ll stick to manual issue and renewals of SSL certificates.
SSL Checker Reports
‘I checked the certificate with other SSL checking sites.
NameCheap SSL Checker – https://decoder.link/sslchecker/ (Passed). I did notice that the certificate will expire in 89 days (I was not aware of that). I guess a free 90-day certificate for a noncritical server is OK (as long as I renew it in time).
CertLogik – https://certlogik.com/ssl-checker/ (OK)
Comodo – https://sslanalyzer.comodoca.com (OK)
Lets Encrypt SSL Certificate Pros
- Free.
- Secure.
- Easy to install.
- Easy to renew.
- Good for local, test or development environments.
- It auto-detected my domain name (even a subdomain)
Lets Encrypt SSL Certificate Cons
- The auto install process does not setup OCSP Stapling (I configured NGINX but the certificate does not support it may be to limit the Certificate Authority resources handing the certificate revocation checks).
- The auto install process does not setup HSTS. (I enabled it in NGINX manually).
- The auto install process does not setup HPKP. More on enabling Public Key Pinning in NGINX here.
- Too many cyphers installed by default.
- No TLS 1.3 installed by default by the install process in my NGINX config in the default certbot secure auto install (even though my NGINX supports it). More on enabling TLS 1.3 in NGINX here.
Read my guide on Beyond SSL with Content Security Policy, Public Key Pinning etc
I’d recommend you follow these Twitter security users
http://twitter.com/GibsonResearch
Troubleshooting
I had one server were certbot failed to verify the SSL and said I needed a public routable IP (it was) and that the firewall needed to be disabled (it was). I checked the contents of “/etc/nginx/sites-available/default” and it appeared no additional SSL values were added (not even listening on port 443?????).
I am viewing: /var/log/letsencrypt/letsencrypt.log
Conclusion
Free is free but I’d still use paid certs from Namecheap for important stuff/sites, not having OCSP stapling on the CA and 90-day certs is a deal breaker for me. The Lets Encrypt certificate is only a 90-day certificate (I’d prefer a 3-year certificate).
A big thank you to Electronic Frontier Foundation for making this possible and providing a free service (please donate to them)..
Lets Encrypt does recommend you renew certs every 60 days or use auto-renew tools but rate limits are in force and Lets Encrypt admit their service is young (will they stick around)? Even Symantec SSL certs are at risk.
Happy SSL’ing.
Check out the extensive Hardening a Linux Server guide at thecloud.org.uk: https://thecloud.org.uk/wiki/index.php?title=Hardening_a_Linux_Server
Read my guide on Setting up a Vultr VM and configuring it
Donate and make this blog better
Ask a question or recommend an article
V1.62 added hardening Linux server link