Last updated June 28, 2021
Table of Contents
Heroku provides free Automated Certificate Management (ACM) for all applications running on paid dynos in the Common Runtime. With ACM, Heroku automatically provisions and renews SSL certificates for your application.
If you need to upload your own certificate manually, follow the steps in this article.
SSL is a cryptographic protocol that provides end-to-end encryption and integrity for all web requests. Apps that transmit sensitive data should enable SSL to ensure all information is transmitted securely.
The Heroku SSL feature is included for free on any app that uses paid dynos: Hobby, Standard-1X, Standard-2X, Performance-M and Performance-L. Apps using free dynos can use the
*.herokuapp.com certificate if they need SSL.
Heroku SSL uses Server Name Indication (SNI), an extension of the TLS protocol, which is widely supported in modern browsers.
Manually uploading certificates
Add your certificate and private key with the
certs:add command. You will be prompted to specify what custom domain you want to associate the new certificate with.
$ 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: 2012-10-31 21:53:18 GMT Issuer: C=US; ST=CA; L=SF; O=Heroku; CN=www.example.com Starts At: 2011-11-01 21:53:18 GMT ...
If you want to add intermediate certificates see this article on merging certificates to get a complete chain.
At this point, you can verify that your application is serving your certificate by grabbing the DNS target from the command output and running:
$ openssl s_client -connect <dns target>:443 -servername <your domain> # e.g. openssl s_client -connect exemplary-sushi-4gr7rb6h8djkvo9j5zf16mfp.herokudns.com:443 -servername www.example.com
Once you have verified that your app is serving your certificate, you must update your DNS settings for each domain on your app (if you haven’t already done so). The DNS entry assigned to your app’s domains will be listed after you add your certificate, using the pattern
<adjective>-<noun>-<random>.herokudns.com. In the above example, it would be
exemplary-sushi-4gr7rb6h8djkvo9j5zf16mfp.herokudns.com If you need to review the DNS targets again, simply run
heroku domains to see DNS targets for custom domains associated with your app.
Heroku does not allow private keys to be extracted out of its systems. Make sure to keep a copy safely for yourself in case it needs to be reused anywhere.
SSL certificate details
Multiple certificates can be added to a single app. Use the
certs command to list out certificates for an app:
$ heroku certs Name Common Name(s) Expires Trusted Type Domains ──────────────────── ─────────────────────── ──────────────────── ─────── ──── ─────── mamenchisaurus-65072 kapow.herokudev.frsm.us 2022-02-03 19:53 UTC False SNI 0 oviraptor-60827 bar.herokudev.frsm.us 2022-02-03 19:40 UTC False SNI 1
To get the detailed information about a certificate, use
$ heroku certs:info --name=mamenchisaurus-65072 Fetching SSL mamenchisaurus-65072 info for exampleapp... done Certificate details: Expires At: 2012-10-31 21:53:18 GMT Issuer: C=US; ST=CA; L=SF; O=Heroku; CN=www.example.com Starts At: 2011-11-01 21:53:18 GMT Subject: C=US; ST=CA; L=SF; O=Heroku; CN=www.example.com ...
Updating certificate and domain mappings
You can update the mapping between certificates and custom domains registered with an app using the
heroku domains:update command. You can use the
heroku certs:info --show-domains to see what domains are currently associated with a certificate. To associate a certificate with a domain run the
$ heroku domains:update www.example.com --cert mycert Updating www.example.com to use mycert certificate... done
Verify SSL is setup correctly
Use a command line utility like
curl to test that everything is configured correctly for your secure domain.
$ curl -vI https://www.example.com * About to connect() to www.example.com port 443 (#0) * Trying 184.108.40.206... connected * Connected to www.example.com (220.127.116.11) port 443 (#0) * SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS handshake, Server finished (14): * SSLv3, TLS handshake, Client key exchange (16): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSL connection using AES256-SHA * Server certificate: * subject: C=US; ST=CA; L=SF; O=SFDC; OU=Heroku; CN=www.example.com * start date: 2011-11-01 17:18:11 GMT * expire date: 2012-10-31 17:18:11 GMT * common name: www.example.com (matched) * issuer: C=US; ST=CA; L=SF; O=SFDC; OU=Heroku; CN=www.heroku.com * SSL certificate verify ok. > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3 > Host: www.example.com > Accept: */* ...
Pay attention to the output. It should print
SSL certificate verify ok. If it prints something like
common name: www.example.com (does not match 'www.somedomain.com') then something is not configured correctly.
If you use the
-k flag with the curl command, it will result in a connection error if are running curl on many versions of Mac OS X as SNI information is not passed with
You can update a certificate using the
certs:update command with the new certificate and the new or an existing private key:
$ heroku certs:update --name=mamenchisaurus-65072 server.crt server.key Updated certificate details: Common Name(s): www.example.com Expires At: 2017-03-21 21:35 UTC Issuer: /C=US/ST=California/L=San Francisco/O=Heroku/OU=Engineering/CN=www.example.com Starts At: 2016-03-21 21:35 UTC Subject: /C=US/ST=California/L=San Francisco/O=Heroku/OU=Engineering/CN=www.example.com
You can remove a certificate using the
$ heroku certs:remove --name=mamenchisaurus-65072 Removing SSL certificate mamenchisaurus-65072 (exemplary-sushi-4gr7rb6h8djkvo9j5zf16mfp.herokudns.com) from example... done
Removing a certificate will cease any HTTPS traffic to the certificate’s domain.
Migrate from SSL:Endpoint to Heroku SSL
You can migrate from the SSL:Endpoint add-on to Heroku SSL with zero downtime.
Add the SSL Certificate to your app
$ heroku certs:add example.crt example.key --type sni
You need to use the flag
--type sni if your app already has the SSL Endpoint add-on.
Verifying DNS for all domains on your app
Verify your DNS settings by running
dig www.yourdomainname.com cname +short. If it returns something like
<adjective>-<noun>-<random>.herokudns.com then it is likely you have set it up correctly. If you are using an ALIAS or ANAME record, you can verify that based on the DNS provider. For instance, DNSimple will return a TXT record showing how your domain’s ALIAS is set-up.
Please note that it may take up to 24 hours before your DNS is fully propagated globally.
Remove SSL:Endpoint Add-on after 24 hours
If it has been 24 hours since you updated your DNS settings, then you can remove the SSL:Endpoint add-on.
$ heroku addons:destroy ssl
Client IP address
When an end-client (often the browser) initiates an SSL request, the request must be decrypted before being sent to your app. This extra SSL termination step obfuscates the originating IP address of the request.
As a workaround, the IP address of the external client is added to the
X-Forwarded-For HTTP request header.
Supported SSL protocols
- TLS 1.0
- TLS 1.1
- TLS 1.2
We do not support SSLv3 for security reasons. The cipher suite in use is curated to strike a balance between security best practices and backwards compatibility.
Heroku SSL does not allow customization of TLS versions or ciphers for Common Runtime apps.
Internal server error
If you get an
Internal server error when adding your certificate, it may be that you have an outdated version of the Heroku CLI.
Verify your CLI installation and update it to the latest version with
heroku update, or reinstall it.
SSL file types
Many different file types are produced and consumed when creating an SSL certificate.
.csrfile is a certificate signing request, which initiates your certificate request with a certificate provider and contains administrative information about your organization.
.keyfile is the private key used for your site’s SSL-enabled requests.
.crtextensions are often used interchangeably and are both base64 ASCII encoded files. The technical difference is that
.pemfiles contain both the certificate and key whereas a
.crtfile only contains the certificate. In reality this distinction is often ignored.