I have a Node Express app running on Heroku that I want to encrypt with a free-of-charge SSL cert from LetsEncrypt. However, the methods I've seen require opening up ports 443 and 80 to allow the ACME process to work.
Heroku only gives you one port, and doesn't let you choose which port. So how can I use LetsEncrypt?
I spent a bunch of time figuring this out yesterday. First time in a long time there were no answers on StackOverflow for something I was trying to do!
Heroku now supports LetsEncrypt natively! So this workaround is no longer needed.
Instructions here:
https://devcenter.heroku.com/articles/automated-certificate-management
For new apps, you don't have to do anything, it's turned on by default.
For apps created before March 21 2017, you can turn it on with this Heroku cli command:
heroku certs:auto:enable
Thanks @Spain Train
Ideally, LetsEncrypt allows for an automated certificate renewal process. That's harder to do on Heroku, so this answer describes how to use a manual process. Using a Heroku environment var, you'll be able to update your certs manually fairly easily going forward - no code changes.
Credit for this answer goes largely to two nice blog posts:
https://medium.com/@franxyzxyz/setting-up-free-https-with-heroku-ssl-and-lets-encrypt-80cf6eac108e#.67pjxutaw
and
https://medium.com/should-designers-code/how-to-set-up-ssl-with-lets-encrypt-on-heroku-for-free-266c185630db#.ldr9wrg2j
There's a GitHub project which apparently supports automated certs updates on Heroku. I'll update this answer when I've tried it out:
https://github.com/dmathieu/sabayon
Add this middleware to your Express app. Be sure to add it BEFORE any middleware that redirects http to https, because this endpoint must be http.
// Read the Certbot response from an environment variable; we'll set this later:
const letsEncryptReponse = process.env.CERTBOT_RESPONSE;
// Return the Let's Encrypt certbot response:
app.get('/.well-known/acme-challenge/:content', function(req, res) {
res.send(letsEncryptReponse);
});
sudo certbot certonly --manual
sudo ls /etc/letsencrypt/live/www.example.com
to see if the files exist.Run heroku certs:add
if your site doesn't have a cert. If updating, run heroku certs:update
.sudo heroku certs:update --app your-heroku-app-name /etc/letsencrypt/live/www.example.com/fullchain.pem /etc/letsencrypt/live/www.example.com/privkey.pem
You can also validate your domain ownership to Let's Encrypt with DNS instead of HTTP.
With certbot
, specify DNS as your preferred challenge:
sudo certbot certonly --manual --preferred-challenges dns
After a couple of prompts, certbot will tell you to deply a DNS TXT record to validate your domain:
Please deploy a DNS TXT record under the name
_acme-challenge.www.codesy.io with the following value:
CxYdvM...5WvXR0
Once this is deployed,
Press ENTER to continue
Your domain registrar probably has its own docs for deploying a TXT record. Do that, and go back to certbot
and press ENTER - Let's Encrypt will check the TXT record, sign the cert, and certbot
will save it for you to upload to heroku.
See my detailed blog post for more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With