Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Background Jobs in Python
      • Working with Django
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Databases & Data Management
  • Heroku Postgres
  • Connecting to a Private or Shield Heroku Postgres Database from an External Resource

Connecting to a Private or Shield Heroku Postgres Database from an External Resource

English — 日本語に切り替える

Last updated March 13, 2023

Table of Contents

  • Overview
  • Heroku prerequisites
  • Configuring Mutual TLS and allowlisting your IP
  • Setting client-side certificates
  • Client certificate renewal
  • Connecting to your database from an external resource
  • Configuring external applications to connect via mTLS
  • mTLS CLI Plugin

Use Mutual TLS to create a secure and mutually authenticated channel between an external resource and a Heroku Postgres database running in a Private Space or a Shield Private Space. External resources can include any mTLS-enabled application or system running in private data centers or public clouds. To use this feature, you must also allowlist the external IP that will connect to your database.

Overview

This feature is only available for Private and Shield Postgres databases.

Heroku provisions Certificate Authorities (CAs) in the Private Space and Shield Private Space, and generates certificates for the Postgres database server and your client. The server certificate chain, client certificate chain, and client private key are then exposed for configuration of your Postgres client. You can provision additional client certificates if needed.

This process involves three high-level steps:

  • Configuring Mutual TLS and allowlisting your external IP
  • Setting client-side certificates
  • Connecting to your database from an external resource

Shield Postgres Access

Heroku prerequisites

The following Heroku resources are required to set up Mutual TLS:

  • A Private Space or Shield Private Space
  • A Heroku app running in the Space with an attached Private or Shield Heroku Postgres database

Configuring Mutual TLS and allowlisting your IP

Step 1: Install the Mutual TLS CLI plugin

$ heroku plugins:install mtls

Step 2: Enable Mutual TLS

Enable Mutual TLS on your database using:

$ heroku data:mtls:create DATABASE_NAME --app APP_NAME

where DATABASE_NAME is the name of your Postgres database, and APP_NAME is the name of your application.

Here’s an example command with accompanying output:

$ heroku data:mtls:create postgresql-sushi-12345 --app sushi

addon:  postgresql-sushi-12345
app:    sushi
status: Provisioning
Enabling MTLS on postgresql-sushi-12345... done

It typically takes 5–10 minutes to enable Mutual TLS. You can track your progress with heroku data:mtls DATABASE_NAME --app APP_NAME.

Step 3: Allowlist external IPs

A hard limit of 60 IP blocks can be allowlisted per Postgres database. After Mutual TLS has been enabled, allowlist your IP block to access your Postgres database using the following Heroku CLI command (note the values to substitute below):

$ heroku data:mtls:ip-rules:create DATABASE_NAME --app APP_NAME \
  --cidr CIDR_BLOCK \
  --description DESCRIPTION
  • Replace DATABASE_NAME with the name of your Postgres database (for example, postgresql-sushi-12345).
  • Replace APP_NAME with your app’s name (for example, sushi).
  • Replace CIDR_BLOCK with the CIDR block you would like to allowlist. An individual IP address is represented as x.x.x.x/32 where x can be any number between 0 and 255 (inclusive).
  • Replace DESCRIPTION with a readable description of this allowlisted CIDR block (for example, "Office IP").

Here’s an example command with accompanying output:

$ heroku data:mtls:ip-rules:create postgresql-sushi-12345 --app sushi \
  --cidr "1.2.3.4/32" \
  --description "My Office IP"

Creating IP Rule for database postgresql-sushi-12345... done
cidr:        1.2.3.4/32
created_at:  2019-07-17 00:05:52 +0000
description: My Office IP
id:          38c466b6-dcfb-4869-b5ac-40420b786fb4
status:      Authorizing
updated_at:  2019-07-17 00:05:52 +0000

It usually takes a few minutes to allowlist your external IPs. You can track your progress with the following command:

$ heroku data:mtls:ip-rules:get DATABASE_NAME --id IP_RULE_ID --app APP_NAME

where DATABASE_NAME and APP_NAME are as described above, and IP_RULE_ID is the id in the output of the create command (for example, the id is 38c466b6-dcfb-4869-b5ac-40420b786fb4 for the IP allowlisted above).

Here’s an example command with accompanying output:

$ heroku data:mtls:ip-rules:get postgresql-sushi-12345 --id "38c466b6-dcfb-4869-b5ac-40420b786fb4" --app sushi

cidr:        1.2.3.4/32
created_at:  2019-07-17 00:05:52 +0000
description: My Office IP
id:          38c466b6-dcfb-4869-b5ac-40420b786fb4
status:      Authorized
updated_at:  2019-07-17 00:05:52 +0000

You can view all the IP addresses allowlisted for this database with heroku data:mtls:ip-rules DATABASE_NAME --app APP_NAME .

Setting client-side certificates

Step 1: Download client-side certificates

View all client-side certificates for the Postgres database using

$ heroku data:mtls:certificates DATABASE_NAME --app APP_NAME

where DATABASE_NAME and APP_NAME are as defined above. Here’s an example command with accompanying output:

$ heroku data:mtls:certificates postgresql-sushi-12345 --app sushi
id                                   Created At                Status
61acf66f-e505-452c-a517-e727689fb54f 2019-07-16 23:39:26 +0000 ready

Download the certificates needed to configure your client to access your Postgres database using the following Heroku CLI command (note the values to substitute below):

$ heroku data:mtls:certificates:download DATABASE_NAME \
--id CERTIFICATE_ID \
--prefix PREFIX \
--dir DIRECTORY \
--app APP_NAME
  • Replace DATABASE_NAME with the name of your Postgres database (for example, postgresql-sushi-12345).
  • Replace APP_NAME with your app’s name (for example, sushi).
  • Replace CERTIFICATE_ID with the id of the certificate to download (for example, the id of the certificate in the example above is 61acf66f-e505-452c-a517-e727689fb54f).
  • Replace PREFIX with a prefix to put in front of the names of the downloaded files (for example, demo_).
  • Replace DIRECTORY with the directory to download files to (for example, ./folder). This defaults to $HOME/.postgresql.

Here’s an example command with accompanying output:

$ heroku data:mtls:certificates:download postgresql-sushi-12345 \
--id "61acf66f-e505-452c-a517-e727689fb54f" \
--prefix "demo_" \
--dir "./folder" \
--app sushi

Downloading certificates for database postgresql-sushi-12345... done
your certs are now located in ./folder

Open up the folder directory and you should see three files:

  • demo_postgresql.crt (client certificate with chain)
  • demo_postgresql.key (client private key)
  • demo_root.crt (server certificate chain)

Step 2: Configure environment variables

Set necessary environment variables using the following Heroku CLI command (note the values to substitute below):

$ export DATABASE_URL=`heroku config:get DATABASE_URL -a APP_NAME`
$ export PGSSLCERT=DIRECTORY/PREFIXpostgresql.crt
$ export PGSSLKEY=DIRECTORY/PREFIXpostgresql.key
$ export PGSSLROOTCERT=DIRECTORY/PREFIXroot.crt
  • Replace DATABASE_URL with the URL of your Postgres database (for example, postgresql-sushi-12345).
  • Replace APP_NAME with your app’s name (for example, sushi).
  • Replace DIRECTORY with the directory you downloaded files to in the previous step.
  • Replace PREFIX with the prefix you put in front of the names of the downloaded files in the previous step.

Set appropriate permissions for your private key. For the key downloaded in the previous step, permissions can be set using:

$ chmod 0600 ./folder/demo_postgresql.key

You don’t need to set the PGSSLCERT, PGSSLKEY, and PGSSLROOTCERT config variables if you downloaded your files to the default directory without setting any prefix.

 

It isn’t recommended to omit the prefix on your development environment as it causes the certificate to be sent to all databases, which can interfere with normal Heroku CLI operations.

Client certificate renewal

A client certificate has an expiration date of 13 months after its creation date. One month before the expiration date, the following occurs:

  1. A new client certificate is created for you
  2. An email is sent to you about the pending expiration of your current certificate. The contents of the email includes details about your new certificate and how to begin using it.

After a new certificate has been created, it’s recommended you begin using it before the current certificate expires and no longer works.

Connecting to your database from an external resource

You can now connect to your database using:

$ psql "${DATABASE_URL}?sslmode=verify-ca"
psql (11.1, server 11.4 (Ubuntu 11.4-1.pgdg16.04+1))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

abcdefghij1234=>

Configuring external applications to connect via mTLS

When configuring other applications to connect to your database via mTLS we recommend referring to the documentation for that application to see if there are any special requirements.

For example applications which use the JDBC PostgreSQL connector require a connection string containing the sslcert, sslkey, sslroot and sslmode parameters, and require that the key be provided in either the PKCS-12 or PKCS-8 DER format.

The key provided by the data:mtls:certificates:download command is in a PEM format, which can be converted to DER format using this openssl command (run from the directory containing the downloaded key file):

$ openssl pkcs8 -topk8 -inform PEM -in postgresql.key -outform DER -out postgresql.pk8 -nocrypt

As described above, you should set appropriate permissions on the new key file:

$ chmod 0600 postgresql.pk8

Further details on constructing the JDBC connection URL are available in the official PostgreSQL documentation.

For any issues or concerns with using this feature, open a support ticket.

mTLS CLI Plugin

See the full documentation of the mTLS CLI plugin.

Keep reading

  • Heroku Postgres

Feedback

Log in to submit feedback.

Postgres Write-Ahead Log Usage Connecting to a Private or Shield Heroku Postgres Database via PrivateLink

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences