Secure your Heroku Apps with SSL
Tags: heroku, ssl
Published: 2024-03-16 18:55:39

## How to secure your apps with SSL certificates for custom domains

If you’re building an application that needs to go toward production, you’ll undoubtedly need to serve it up securely with SSL. What that entails varies from provider to provider, and you’ll encounter differing levels of complexity (and cost) in getting it all set up.

Fortunately, if you’re using Heroku to run your application, this is pretty straightforward. Because I’ve been giving Heroku another spin recently, I’m going to spend this article looking at what you’ll need to get going with SSL on the platform and why you might choose some features over others.

## What does Heroku provide for SSL right out of the box?

Heroku focuses on ease of use, and I love that. Whether it’s the one-click deploy straight from my GitHub repo or the plugin ecosystem that lets me drop all kinds of great things into my app from the command line, I always appreciate the out-of-the-box options I have at my fingertips. Likewise, SSL on Heroku provides some great default options.

Heroku offers two main ways of [working with SSL certificates on their platform](https://devcenter.heroku.com/articles/understanding-ssl-on-heroku):

1. [Automated Certificate Management (ACM)](https://devcenter.heroku.com/articles/automated-certificate-management)
2. [Heroku SSL](https://devcenter.heroku.com/articles/ssl)

For most apps, ACM will give you a really simple, automated certificate management experience—that is the name, after all. But there may be times when you’ll need the more robust Heroku SSL option. We’ll take a look at ACM first. Then, we’ll investigate why you might need Heroku SSL and how you’d use it.

## Automated Certificate Management and how it works

ACM is built on top of [Let’s Encrypt](https://letsencrypt.org)—a free, automated certificate authority, run by a nonprofit organization committed to enhancing the security of the web in general. While organizations can [sponsor the Let’s Encrypt project](https://www.abetterinternet.org/sponsor/), there is no cost for using Let’s Encrypt-issued SSL certificates. Because the certificates are free, Heroku provides Automated Certificate Management with any of their basic plans at no additional charge.

While Let’s Encrypt automates the process of requesting and issuing certificates, ACM automates the process of installing those certificates on the relevant apps for the domains they’re issued for. Other methods exist for automated management of certificates, but they’re paid add-ons, so I won’t be looking at them here. Instead, let’s show you how to add ACM to a demo app I’ve already deployed to Heroku.

To be clear, there isn’t a whole lot you need to configure for ACM. In fact, if you haven’t added a custom domain to your app, the Heroku-generated URL (on the herokuapp.com domain) for your app already has SSL.

### Step 1: Enable ACM

Your first step is to turn on ACM. The easiest way to do this for any deployed app is with [the Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). Assuming you’re logged into Heroku via the CLI, all you need to do is run a single command to turn on ACM:

```
$ heroku certs:auto:enable
Enabling Automatic Certificate Management... starting.
See status with heroku certs:auto or wait until active with
heroku certs:auto --wait
=== Your certificate will now be managed by Heroku.
Check the status by running heroku certs:auto.
```

If you enable ACM before setting up a custom domain on your app, you’ll get a message like this:

```
$ heroku certs:auto
=== Automatic Certificate Management is enabled on pure-brushlands-82324

=== Add a custom domain to your app by running: heroku domains:add <yourdomain.com>

```

### Step 2: Add custom domain

At this point, you simply need to do what the Heroku CLI says and add a domain to your app. You can do this in the CLI too.

```
$ heroku domains:add really-cool-stuff.app
Configure your app's DNS provider to point to the DNS Target lively-basin-0v9xkh99iaz1yc0xldmakla5.herokudns.com.
    For help, see https://devcenter.heroku.com/articles/custom-domains

The domain really-cool-stuff.app has been enqueued for addition
Run heroku domains:wait 'really-cool-stuff.app' to wait for completion
Adding really-cool-stuff.app to ⬢ pure-brushlands-82324... done
```

### Step 3: Configure DNS

At this point, you need to update your DNS records on your domain to point to the DNS target provided by Heroku. The [instructions in the help documentation it links to](https://devcenter.heroku.com/articles/custom-domains) are detailed and clear. Typically, this means adding a CNAME record that directs to the new location provided by Heroku.

Once you have your DNS configured properly, you can check on the status of your certificates. You should see output like this:

```
$ heroku certs:auto
=== Automatic Certificate Management is enabled on pure-brushlands-82324

Certificate details:
Common Name(s): really-cool-stuff.app
Domain(s):      fe6ab605-91f9-4261-974c-ee85c043dbf7
Expires At:     2024-05-27 17:08 UTC
Issuer:         /CN=R3/O=Let's Encrypt/C=US
Starts At:      2024-02-27 17:09 UTC
Subject:        /CN=really-cool-stuff.app
SSL certificate is verified by a root authority.

Domain                       Status       Last Updated
───────────────────────────  ───────────  ────────────
really-cool-stuff.app        Cert issued  4 minutes

```

If you’re like me and you made a mistake when setting up the DNS records 🤦🏻, then you might see some warnings on the app dashboard in the web interface like this:

![ACM Failing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5fsfwut7mh68aiodxxko.png)


Or this one:

![Domain failed validation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vxjrhk9g0n9a4sl1jxpp.png)

Fortunately, ACM repeats its validation attempts regularly for an entire hour. So, I was able to fix my issues quickly. I got to a green status pretty easily.

![Certificate automatically managed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcguk57yqogn31ysdvmi.png)

If you’ve ever had to set up SSL on another platform before, you’re probably painfully aware that it usually isn’t this simple (and that’s putting it mildly). That said, Let’s Encrypt has some limitations that may require you to use the more robust offering: Heroku SSL.

## Heroku SSL and why you might want it

While ACM gives you a really simple experience, with that simplicity also comes somewhat limited functionality. Let’s consider two examples where ACM might not meet your unique needs.

### Example 1: When you need wildcard certificates

Let’s Encrypt is restricted to providing [common name](https://letsencrypt.org/docs/glossary/#def-CN) certificates on only one single domain name zone at a time. Sometimes, you might actually want to have a wildcard certificate; this is the type of functionality you might need if you have a multi-tenant application that switches between tenants at the subdomain level. ACM doesn’t support this. But Heroku SSL does.

### Example 2: When you need Organizational or Extended Validation (OV/EV)

Let’s Encrypt also doesn’t _really_ guarantee that you are who you say you are. What I mean is that the type of certificate issued by Let’s Encrypt only attests that the entity requesting the certificate also controls the domain name that it’s securing. There are some scenarios when you need to ensure more than just that your domain traffic is encrypted in transit. You might need to verify that your application is actually associated with your company. In this case, you’d want to purchase an SSL certificate with either Organizational Validation (OV) or Extended Validation (EV). Those usually require checks that can’t be simply automated by a product like Let’s Encrypt.

### Using Heroku SSL

In the above cases, you’ll need to manually upload your own certificate. As usual, this process has been beautifully simplified by Heroku (but it’s still more work than just telling the platform to start issuing certificates with ACM).

To add or update the certificate for your Heroku app, and to use a certificate you provide, you need to run a single command:

```
$ heroku certs:add server.crt server.key
Adding SSL to example... done
exampleapp now served by exemplary-sushi-4gr7rb6h8djkvo9j5zf16mfp.herokudns.com.
Certificate details:
Expires At: 2022-08-18 21:53:18 GMT
Issuer: C=US; ST=CA; L=SF; O=Heroku; CN=www.example.com
Starts At: 2021-08-18 21:53:18 GMT
...

```

Ok, so it’s not _that_ much more work than using ACM.

Note that you can’t add multiple intermediate certificates to make a valid chain toward whatever root certificate has signed your new certificate. However, you can [merge your intermediate certificates](https://help.salesforce.com/s/articleView?id=000386535&type=1) into one file so they can be uploaded as a single file.

After uploading your certificate through Heroku SSL, you’ll be able to see your application protected by the SSL certificate you provided on your own. While Heroku SSL still keeps things pretty simple, keep in mind that **you’re responsible for keeping your certificates up to date**. You’ll also need knowledge of how to work with certificates. While these might not be deal-breakers for you, they’re important points to remember—especially when you consider that ACM takes care of automatic renewals of SSL certificates. With ACM, the simple commands to set it up really are “set it and forget it.” That said, Heroku designed their entire certificate management system in such a way that even if you need the most advanced options, it’s still quite simple and manageable, even if you don’t have extensive certificate experience.

## Conclusion

While there is more you can do with SSL on Heroku, both the ACM and Heroku SSL options can provide the functionality to fit most use cases. Heroku’s [documentation in this space](https://help.heroku.com/n/11/domains-routing/ssl-sni) also provides enough detail to point you in the right direction. If you haven’t secured your app with SSL (shame on you!), then the simplicity of ACM should remove any excuse you have to secure your site properly. If your use case is more complicated, then Heroku SSL should give you what you need.