Skip to main content

How do I use Let's Encrypt to get and automate SSL on ubuntu, nginx server

General • Asked by Thomas Bush

I was thinking maybe this could be a tutorial/guide request?

I always use the GoRails guides to setup my ubuntu, nginx, passenger servers(thanks!) I am having trouble figuring out how to use Lets Encrypt to get an ssl cert and automate renewal. I have seen quite a few tutorials and guides around the internet, but I must be missing something somewhere because they are not working for me.

Result

  • https: Safari server failed to respond error
  • http: still works.

Steps to install Lets Encrypt and create SSL

  • I install the agent via lets encrypt getting started guide.
  • I updated up my server block to included allow for /.well-known (included below)
  • ran certbot command to generate cert
    • ./certbot certonly -a webroot --webroot-path=/home/deploy/hexcom/current/public -d hexarmor.com -d www.hexarmor.com
  • I updated up my server block to listen on 443 and include cert keys (included below)
  • sudo service nginx reload

/etc/nginx/sites-available/default

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        listen 443 ssl;

        #ssl on;
        ssl_certificate /etc/letsencrypt/live/hexarmor.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/hexarmor.com/privkey.pem;

        server_name hexarmor.com;

        passenger_enabled on;
        rails_env    production;
        root         /home/deploy/hexcom/current/public;

        # redirect server error pages to the static page /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        location ~ /.well-known {
                allow all;
        }
}

Heck yes. Let's Encrypt seems awesome, but then when I started poking around it was like okay well this seems a little more complicated than I originally thought.

I'll try setting this up for my personal blog and try to make a tutorial on it.


Thanks Chris! I would love to be able to use this for all my projects, and just standardize on config.force_ssl = true in prod. Can't wait!


Anyone using this? I have certbot-auto installed, and have attempted to set up auto renewal, but it does not appear to be working. My cert expires in 2 days so I would REALLY appreciate any help anyone could provide.

error:

WARNING:certbot.renewal:Attempting to renew cert from /etc/letsencrypt/renewal/MY-SITE.com.conf produced an unexpected error: Failed authorization procedure. www.MY-SITE.com (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://www.MY-SITE.com/.well-known/acme-challenge/CHALLENGE-STRING: "<!DOCTYPE html>
<html>
<head>
  <title>The page you were looking for doesn't exist (404)</title>
  <meta name="viewport" content", MY-SITE.com (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://MY-SITE.com/.well-known/acme-challenge/DIFFERENT-STRING: "<!DOCTYPE html>
<html>
<head>
  <title>The page you were looking for doesn't exist (404)</title>
  <meta name="viewport" content". Skipping.
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/MY-SITE.com/fullchain.pem (failure)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
1 renew failure(s), 0 parse failure(s)

So I ended up figuring this out, it was an improper path issue -- whoops -- as well as an addition to my nginx server block. Lesson learned, don't use relative paths for this. Could we add this to the Deploy ROR Guides? I think this would probably benefit a lot of people to just be secure by default. SSL can be tricky in my opinion and certbot simplifies this.

I have included the addition to the server block below.

/etc/nginx/sites-available/default

location ~ /.well-known {
  allow all;
}  

Next ssh into your server and execute the dry-run first to ensure everything is set up properly.

/home/deploy/certbot-auto renew -w /home/deploy/your-app/current/public --dry-run

If successful run the one off command to renew your current ssl.

/home/deploy/certbot-auto renew -w /home/deploy/your-app/current/public --quiet --no-self-upgrade

Future renewal

The other thing I came across that I found useful, I scheduled this in crontab, using whenever gem. This way you don't have to worry about it again. I preferred this approach over writing to crontab myself in that its now part of git/github, therefore this requirement is documented for other devs, or for myself 6 months from now.

Just in case anyone has a similar setup or is interested in this setup, I have included an example whenever task that would live in your schedule file below.

config/schedule.rb

every 1.day, :at => '3:21 am' do
  command "/home/deploy/certbot-auto renew -w /home/deploy/your-app/current/public --quiet --no-self-upgrade"
end

I realize I'm about a month late on replying to this thread, but I'm definitely going to add this to the guides.

It looks like the renew goes into the public folder in your app. Does this mean that if you do a new deploy with Capistrano it loses access to that file if you ever rebooted nginx or are you symlinking the directory that Let's Encrypt creates on your deploys?


I've just set this up one two separate apps. Everything is symlinked, so deploys don't effect it at all.

This guide is pretty good:
https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04

You'll have to change the webroot path to point to the rails app rather than a the basic html folder. The one other gotcha to look out for is if you're using CloudFlare. You need to specify the authenticator method to use webroot, or it won't authenticate. I believe this one does, but older articles haven't. You can read more on it here:
https://support.cloudflare.com/hc/en-us/articles/214820528-How-to-Validate-a-Let-s-Encrypt-Certificate-on-a-Site-Already-Active-on-CloudFlare

The tutorial should result in an A+ rating from the Qualys SSL Labs Report.

I think a guide on setting this up for rails specifically would be great. Maybe add it into the security series you keep talking about? Once you wrap your head around it you can get it setup and auto renewing in about 15 minutes.


Awesome, I just ran into a thing that I need to have SSL for a side project last night so I'm going to try using Let's Encrypt to get that setup. Can't wait to try it out!


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.