Internal Routing
Last updated October 16, 2024
Table of Contents
On creation, apps in Private Spaces can enable Internal Routing. Unlike other apps, apps with Internal Routing cannot receive external web traffic to their web
process type. Instead, their web
process type can receive traffic from:
- Your other apps running in the Private Space network
- Software running in VPC-peered or VPN-connected networks
In all other ways, apps with Internal Routing behave exactly like other Private Space apps.
Internal Routing is useful for:
- APIs and other secure microservice components that are consumed solely by your other Private Space apps and software running in a peered AWS VPC.
- Apps that are accessible only to users on a VPN-connected, on-prem network. Requests to apps can originate only from hosts on the private network, and requests and responses can only transit the IPSEC connection.
Internal Routing complements other Heroku features for intra-space networking and locking down app access:
- Private Space DNS Service Discovery enables direct network connections between dynos and process types, but it provides no routing stack and therefore no request logging or SSL termination.
- Trusted IP ranges limit external access to all apps in a space to a set of CIDR ranges, but they provide no per-app granularity, and IP ranges must be kept up to date.
Creating internally routed apps
Internal Routing can only be configured on app creation. It is not possible to enable Internal Routing for an existing app.
Include the --internal-routing
option when creating a new app:
$ heroku apps:create --internal-routing --space test-space
Creating app... done, ⬢ frozen-oasis-70544
http://frozen-oasis-70544.herokuapp.com/ | https://git.heroku.com/frozen-oasis-70544.git
Working with internally routed apps
Deploying internally routed apps is no different from deploying other Heroku apps. Like other apps, they get a https://<appname>.herokuapp.com
URL and additional DNS targets when adding custom domains.
Unlike with other apps, these URLs and targets resolve to internal, private IP addresses in the Private Space RFC 1918 CIDR range. Consequently, apps with Internal Routing only accept connections opened from:
- Your other apps running in the Private Space network
- Software running in VPC-peered or VPN-connected networks
The default domain must have at least one web dyno running to resolve private IPs correctly.
Internal Routing is compatible with most other Heroku features, including add-ons, logging, application metrics, custom domains, and SSL termination.
Automated Certificate Management is not compatible with Internal Routing, because Heroku’s certificate partner cannot perform the required validation. You can either use the default SSL mechanism on the .herokuapp.com domain or Heroku SSL with a custom domain.
Troubleshooting internally routed apps
The quickest way to troubleshoot apps with Internal Routing is to check your logs with heroku logs
, or to execute a curl
command from a heroku run bash
session (you can use the app itself or any other app in the same Private Space):
$ heroku run bash -a frozen-oasis-70544
...
$ curl -I http://frozen-oasis-70544.herokuapp.com/
HTTP/1.1 200 OK
Troubleshooting and debugging internally routed apps can be hard. Consider first developing and testing code with a non-internal app. Use standard access controls like username and password and Trusted IP ranges, and ensure you don’t include any sensitive data.
Accessing from a peered VPC
To access internally routed apps from a peered VPC, the VPC must have a route for the entire Private Space /16
CIDR. This is because the endpoint used to reach internally routed apps is not within dyno CIDR ranges. (Previously, Heroku documentation recommended only adding routes for the two Private Space /20
subnets that contain dynos.)
First, obtain your VPC’s routing table ID with the following AWS CLI command:
$ aws ec2 describe-route-tables
Look for the route table with the same VPC ID as your VPC and obtain its route table ID. Provide this ID to the create-route
AWS CLI command:
$ aws ec2 create-route --route-table-id rtb-your-route-table-id --destination-cidr-block 10.0.0.0/16 --vpc-peering-connection-id pcx-111aaa111
Optionally remove the two existing routes for the /20
dyno CIDRs, because these are covered by the new route.