This is very similar to Collective Idea's blog post, "Let's Encrypt with a Rails app on Heroku". I ran through the process a couple of times to try to understand how the various parts fit together.
NOTE. I'm skipping Active Record to make the deployment to Heroku slightly easier.
$ rails new rails-app-with-lets-encrypt --skip-active-record
$ cd rails-app-with-lets-encrypt
$ git init .
$ git add .
$ git commit -m 'Add empty Rails app'
To make it easier to confirm that we're connecting to our Rails app on Heroku.
$ echo "<h1>Rails app with Let's Encrypt</h1>" > public/index.html
$ git add .
$ git commit -m 'Add public index page'
NOTE. Use your own application name here.
$ heroku apps:create rails-app-with-lets-encrypt
Creating ⬢ rails-app-with-lets-encrypt... done
https://rails-app-with-lets-encrypt.herokuapp.com/ | https://git.heroku.com/rails-app-with-lets-encrypt.git
$ git push heroku master
Observe that we see the output of the index page added earlier.
$ curl https://rails-app-with-lets-encrypt.herokuapp.com
<h1>Rails app with Let's Encrypt</h1>
$ heroku domains:add testing-lets-encrypt.seagul.co.uk
Adding testing-lets-encrypt.seagul.co.uk to ⬢ rails-app-with-lets-encrypt... done
▸ Configure your app's DNS provider to point to the DNS Target rails-app-with-lets-encrypt.herokuapp.com.
▸ For help, see https://devcenter.heroku.com/articles/custom-domains
I'm using AWS Route 53 and manually configured my DNS records using the web console.
$ curl http://testing-lets-encrypt.seagul.co.uk
<h1>Rails app with Let's Encrypt</h1>
I've set the various *-dir options to the tmp directory in the Rails app. This was so that I could destroy the dummy Rails app and be confident that nothing's hanging around. You almost certainly won't want to do this if you were generating a certificate for real.
$ certbot certonly --manual \
--domain testing-lets-encrypt.seagul.co.uk \
--logs-dir tmp/letsencrypt/log/ \
--config-dir tmp/letsencrypt/config/ \
--work-dir tmp/letsencrypt/work/
Observe the output similar to:
Make sure your web server displays the following content at
http://testing-lets-encrypt.seagul.co.uk/.well-known/acme-challenge/<token> before continuing:
Create the required file:
NOTE. I'm using token
and JWS
as that's what I believe these things are according to the acme-spec.
$ mkdir -p ./public/.well-known/acme-challenge
$ echo "<JWS>" > \
./public/.well-known/acme-challenge/<token>
$ git add .
$ git commit -m "Add file required by Let's Encrypt"
$ git push heroku master
$ curl http://testing-lets-encrypt.seagul.co.uk/.well-known/acme-challenge/<token>
JWS
Observe the notice that says the certificate and chain have been saved.
See Heroku SSL (Beta) for more information.
$ heroku labs:enable http-sni
Enabling http-sni for rails-app-with-lets-encrypt... done
$ heroku plugins:install heroku-certs
Installing plugin heroku-certs... done
NOTE. Your Heroku app needs to be on a paid plan (at least "Hobby") for you to be allowed to use Heroku SSL. If you run the following command on a Free plan then you'll see the following error:
You need to be running on either Hobby or Professional dynos to be able to use SNI SSL.
NOTE. This command needs to be run as root as the certificate and key aren't publicly accessible.
$ sudo heroku _certs:add \
tmp/letsencrypt/config/live/testing-lets-encrypt.seagul.co.uk/fullchain.pem \
tmp/letsencrypt/config/live/testing-lets-encrypt.seagul.co.uk/privkey.pem
Resolving trust chain... done
Adding SSL certificate to ⬢ rails-app-with-lets-encrypt... done
Certificate details:
Common Name(s): testing-lets-encrypt.seagul.co.uk
Expires At: 2016-11-10 16:06 UTC
Issuer: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Starts At: 2016-08-12 16:06 UTC
Subject: /CN=testing-lets-encrypt.seagul.co.uk
SSL certificate is verified by a root authority.
=== The following common names already have domain entries
testing-lets-encrypt.seagul.co.uk
=== Your certificate has been added successfully. Update your application's DNS settings as follows
Domain Record Type DNS Target
───────────────────────────────── ─────────── ───────────────────────────────────────────────
testing-lets-encrypt.seagul.co.uk CNAME testing-lets-encrypt.seagul.co.uk.herokudns.com
I updated AWS Route 53 to point testing-lets-encrypt.seagul.co.uk at testing-lets-encrypt.seagul.co.uk.herokudns.com.
$ curl https://testing-lets-encrypt.seagul.co.uk
<h1>Rails app with Let's Encrypt</h1>
$ curl -v -I https://testing-lets-encrypt.seagul.co.uk 2>&1 | grep certificate
* Server certificate: testing-lets-encrypt.seagul.co.uk
* Server certificate: Let's Encrypt Authority X3
* Server certificate: DST Root CA X3