bg-tutorials

How to Install an SSL Certificate on Heroku

This guide shows you how to install an SSL certificate on Heroku. It covers both ways Heroku terminates TLS today: Automated Certificate Management (ACM), which provisions and renews free Let’s Encrypt certificates for you, and manual upload of a third-party certificate via the dashboard or the Heroku CLI.

A few things to know before you start. Heroku’s legacy SSL Endpoint add-on (the paid $20/month product) was deprecated in 2021 and can no longer be provisioned on new apps. Every new HTTPS deployment uses Heroku SSL, which relies on the SNI (Server Name Indication) extension and is included at no extra cost on every paid dyno tier. Free dynos were retired on November 28, 2022, so you need an Eco, Basic, Standard, or Performance plan to attach a custom domain and serve HTTPS.

Generate the CSR (for manually uploaded certificates)

If you have already generated your CSR and received the issued certificate from your Certificate Authority, skip ahead to Install an SSL certificate on Heroku.

You only need a CSR if you are buying a third-party certificate to upload manually. If you plan to use ACM, you can skip this section entirely: ACM issues the certificate for you and there is no CSR to submit.

A CSR (Certificate Signing Request) is a text block you submit to the Certificate Authority during the order. It carries your domain and organization details and the public key the certificate will be issued against. Heroku does not generate CSRs on the platform itself, so you generate the request off-platform. You have two options:

Open the resulting .csr file in any text editor and copy the entire block, including the —–BEGIN CERTIFICATE REQUEST—– and —–END CERTIFICATE REQUEST—– markers, then paste it during your SSL Dragon order. Wait for the CA to validate and issue the certificate (anywhere from a few minutes for DV to several business days for OV/EV) and continue with installation below.

Install an SSL certificate on Heroku

Heroku gives you two paths to HTTPS. Pick the one that matches how you obtained the certificate:

  • ACM (recommended for most apps). Heroku issues, installs, and auto-renews a free Let’s Encrypt certificate for every custom domain on the app. No files to upload, no renewal calendar. Available on Eco, Basic, Standard, and Performance dynos.
  • Manual upload. Use this when you need a specific third-party certificate (for example, an Organization Validated or Extended Validation product, or a wildcard from a CA other than Let’s Encrypt). You upload the certificate and private key yourself through the dashboard or the CLI.

Step 1. Add your custom domain to the app

Heroku will not provision any certificate (ACM or manual) until your custom domain is registered with the app. From an elevated terminal, run:

heroku domains:add www.example.com -a your-app-name

Replace www.example.com with your domain and your-app-name with your Heroku app. Repeat the command for any additional hostnames (for example a bare root domain or a second subdomain). You can also add the domain from the dashboard under Settings > Domains and certificates > Add domain.

Each domain you add is returned along with a unique DNS target, for example quiet-fire-1234.herokudns.com. You will need this value when you update DNS in Step 3.

Step 2. Provision the certificate

Option A: ACM (free, auto-renewing Let’s Encrypt)

Enable ACM for the app from the CLI:

heroku certs:auto:enable -a your-app-name

Heroku starts issuing a Let’s Encrypt certificate for every custom domain on the app. To watch progress and confirm the status, run:

heroku certs:auto -a your-app-name

You can also enable ACM from the dashboard: open the app, go to Settings > Domains and certificates, click Configure SSL, choose Automated Certificate Management, then Continue. Once DNS is in place (Step 3), ACM completes domain validation and the certificate goes live. Renewals happen automatically about one month before expiry.

Option B: manual upload of a third-party certificate

The CA delivers three files in your inbox:

  • The end-entity certificate, usually with a .crt extension (PEM format).
  • The CA bundle (intermediate certificates), often with a .ca-bundle extension.
  • The private key generated alongside the CSR (a .key file).

Heroku expects a single PEM file that contains the end-entity certificate followed by the intermediates (a fullchain). On Linux or macOS, concatenate them with cat:

cat yourcertificate.crt bundle.ca-bundle > server.crt

On Windows, open both files in a plain text editor (Notepad++ or VS Code, not Word) and paste the contents of the .ca-bundle below the contents of the .crt, in that order, with no blank line between blocks. Save the combined file as server.crt.

Upload the fullchain and the private key with the Heroku CLI:

heroku certs:add server.crt server.key -a your-app-name

If you are replacing an existing certificate on the app (for example, during renewal), use certs:update instead so Heroku keeps the same DNS target:

heroku certs:update server.crt server.key -a your-app-name

Prefer the dashboard? Open the app, go to Settings > Domains and certificates, click Configure SSL, choose Manually, then drag the combined server.crt into the certificate slot and the .key file into the private-key slot. Click Next and confirm.

If you see an Internal server error while uploading, your local Heroku CLI is most likely out of date. Update it with heroku update and try again. Heroku also requires RSA keys; ECDSA keys are not supported for manual uploads at this time.

Step 3. Point DNS at the Heroku DNS target

Regardless of the provisioning method, the certificate only goes live once DNS for the custom domain resolves to Heroku. List your domains and copy the DNS target Heroku returned:

heroku domains -a your-app-name

You will see a value such as quiet-fire-1234.herokudns.com next to each domain. At your DNS provider, create one record per domain:

  • Subdomain (for example www.example.com): create a CNAME record pointing to the Heroku DNS target.
  • Apex / root domain (for example example.com): CNAME is not allowed on the apex per the DNS spec, so use an ALIAS, ANAME, or flattened-CNAME record (the exact name depends on your DNS provider) pointing to the same Heroku DNS target. If your DNS provider does not support any of these, host DNS on one that does (Cloudflare, DNSimple, Route 53, NS1, easyDNS, etc.).

Do not point DNS at your-app-name.herokuapp.com or at any *.herokussl.com hostname: ACM cannot validate the certificate through those, and a manual binding will not route correctly either. Always use the per-domain DNS target Heroku assigned.

DNS changes can take a few minutes to a few hours to propagate. Once Heroku sees the updated record, ACM completes validation automatically (or your manual cert begins serving traffic).

Step 4. Verify the certificate is live

Confirm the installation from the CLI:

heroku certs:info -a your-app-name

The output lists the certificate, the issuing CA, the expiration date, and the domains it covers. Then open your site over https:// in a browser and check that the padlock is present, and run a deeper external scan with our SSL Checker to confirm that the certificate chain is complete and the protocols are configured correctly.

Frequently Asked Questions

Do I still need the SSL Endpoint add-on on Heroku?

No. The legacy SSL Endpoint add-on was deprecated in 2021 (new provisioning stopped on May 14, 2021) and reached end of life later that year. Every new app uses Heroku SSL with SNI, which is included free on every paid dyno tier. Existing SSL Endpoints on long-running apps continue to work, but Heroku recommends migrating them to Heroku SSL.

ACM or manual upload: which one should I use?

Use ACM unless you have a specific reason not to. It is free, auto-renews every certificate about a month before expiry, and removes the renewal calendar from your team’s plate. Pick manual upload when you need a Domain Validated, Organization Validated, or Extended Validation certificate from a specific CA, a wildcard certificate, or a multi-domain (SAN) certificate covering hostnames that are not all on this Heroku app.

Can I install SSL on a free Heroku dyno?

No. Free dynos were retired on November 28, 2022. Custom domains and SSL (both ACM and manual) require a paid plan: Eco, Basic, Standard, or Performance. As of November 2025, ACM and manual certificates are both supported on Eco dynos, which is the lowest-cost path to HTTPS on a custom domain.

Why does my custom domain still show the default Heroku certificate?

Two common causes. First, DNS is still pointed at *.herokuapp.com instead of the per-domain DNS target Heroku assigned (something like quiet-fire-1234.herokudns.com). Re-check the record at your DNS provider and update it. Second, DNS has changed but propagation is not complete yet; allow a few minutes to a few hours, then run heroku certs:info -a your-app-name to confirm.

How do I renew an SSL certificate on Heroku?

With ACM, you do not: Heroku reissues the certificate from Let’s Encrypt automatically, roughly one month before expiry. With a manual certificate, order the renewal (generating a fresh CSR), build a new fullchain file, and run heroku certs:update server.crt server.key -a your-app-name. Using certs:update instead of certs:add preserves the existing DNS target so you do not have to touch DNS again. Public SSL/TLS certificates are currently capped at about one year, so plan to repeat this annually if you stay on manual upload, or switch to ACM and let Heroku handle it.

Why am I getting an “Internal server error” when running heroku certs:add?

Almost always an outdated Heroku CLI. Run heroku update to upgrade to the latest version, then retry the command. If the error persists, confirm the certificate file is a fullchain in PEM format (end-entity first, intermediates after) and that the private key is an RSA key matching the CSR you submitted to the CA.

Save 10% on SSL Certificates when ordering from SSL Dragon today!

Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

A detailed image of a dragon in flight
Written by

I've been writing for SSL Dragon for over 10 years, focusing entirely on SSL certificates and digital security. My job is to take complex cybersecurity topics and strip away the jargon, making sure you get the clear, practical information you need to keep your website safe.