Skip to content
This is BOSH release for cloud foundry routers
Shell Ruby HTML Dockerfile HCL
Branch: develop
Clone or download
tcdowney and KauzClay fix: add default for unbound variable

Co-authored-by: Clay Kauzlaric <>
Latest commit 23725ac Sep 4, 2019

Cloud Foundry Routing [BOSH release]

This repo is a BOSH release that delivers HTTP and TCP routing for Cloud Foundry.


Job Status
unit tests
performance tests
smoke tests

Getting Help

For help or questions with this release or any of its submodules, you can reach the maintainers on Slack at in the #networking channel.

Developer Workflow

When working on individual components of the Routing Release, work out of the submodules under src/.

Run the appropriate unit tests (see Testing).

Commits to this repo (including Pull Requests) should be made on the Develop branch.

Get the code

  1. Fetch release repo.
mkdir -p ~/workspace
cd ~/workspace
git clone
cd routing-release/
  1. Automate $GOPATH and $PATH setup.

This BOSH release doubles as a $GOPATH. It will automatically be set up for you if you have direnv installed.

direnv allow

If you do not wish to use direnv, you can simply source the .envrc file in the root of the release repo. You may manually need to update your $GOPATH and $PATH variables as you switch in and out of the directory.

  1. Initialize and sync submodules.

Running Unit Tests

In a Docker container

  • Run unit tests using the script provided. This script pulls a docker image and runs the unit tests in there, as some tests in Gorouter check things like file descriptors and need to be run on a Linux machine.

  • If you'd like to run a specific component's unit tests in a Docker container, the run-unit-tests script also takes a package name as an argument:

    ./scripts/run-unit-tests-in-docker gorouter


  • If you'd like to run the unit tests for an individual component locally, we recommend you run bin/test in that component's directory. Please make sure it's a component that doesn't require a Linux operating system.

Deploying Routing for Cloud Foundry

  1. For high availability, configure a load balancer in front of the routers; for more information see High Availability. If high-availability is not required allocate a public IP to a single instance of each router. See Port Requirements for TCP Routing.

  2. If you are using a load balancer see Configuring Load Balancer Healthcheck.

  3. Choose domain names from which developers will configure HTTP and TCP routes for their applications. Separate domain names will be required for HTTP and TCP routing. Configure DNS to resolve these domain names to the load balancer in front of the routers. You may use the same or separate load balancers for the HTTP and TCP domains. If high-availability is not required configure DNS to resolve the domains directly to a single instance of the routers.

  4. If your manifest is configured with self-signed certificates for UAA, configure routing components to skip validation of the TLS certificate; see Validation of TLS Certificates from Route Services and UAA.

  5. Deploy Cloud Foundry using the instructions for cf-deployment.

Port Requirements for TCP Routing

Choose how many TCP routes you'd like to offer. For each TCP route, a port must be opened on your load balancer. Configure your load balancer to forward the range of ports you choose to the IPs of the TCP Router instances.

Routing API must be configured with the same range of ports. By default cf-deployment will enable 100 ports in the range 1024-1123. If you choose a range other than 1024-1123, you must configure this using the deployment manifest property routing-api.router_groups.reservable_ports. This is a seeded value only; after deploy, changes to this property will be ignored. To modify the reservable port range after deployment, use the Routing API; (see "To update a Router Group's reservable_ports field with a new port range").

- name: routing_api
    - name: default-tcp
      reservable_ports: 1024-1123
      type: tcp
    - name: test1
        - 1066
        - 1266
      type: tcp
    - name: test2
      reservable_ports: 1111-2222,4444
      type: tcp

Validation of TLS Certificates from Route Services and UAA

The following components communicate with UAA via TLS:

  • Routing API
  • Gorouter
  • TCP Router

Additionally, gorouter communicates with Route Services via TLS.

In all cases, these components will validate that certs are signed by a known CA and that the cert is for the requested domain. To disable this validation, as when deploying the routing subsystem to an environment with self-signed certs, configure the following property for Gorouter, routing-api and tcp-router.

- name: routing-api
    skip_ssl_validation: true
- name: tcp_router
    skip_ssl_validation: true
- name: gorouter
      ssl_skip_validation: true

Post Deploy Steps

Create a Shared Domain in CF

After deploying this release you must add the domain you chose (see Domain Names) to CF as a Shared Domain (admin only), associating it with the Router Group.

The CLI commands below require version 6.17+ of the cf CLI, and must be run as admin.

List available router-groups

$ cf router-groups
Getting router groups as admin ...

name          type
default-tcp   tcp

Note: If you receive this error: FAILED This command requires the Routing API. Your targeted endpoint reports it is not enabled. This is due to the CF CLI's ~/.cf/config.json having an old cached RoutingEndpoint value. To fix this, just do a cf login again and this error should go away.

Create a shared-domain for the TCP router group

$ cf create-shared-domain --router-group default-tcp
Creating shared domain as admin...

See Router Groups for details on that concept.

Enable Quotas for TCP Routing

As ports can be a limited resource in some environments, the default quotas in Cloud Foundry for IaaS other than BOSH Lite do not allow reservation of route ports; required for creation of TCP routes. The final step to enabling TCP routing is to modify quotas to set the maximum number of TCP routes that may be created by each organization or space.

Determine whether your default org quota allows TCP Routes:

$ cf quota default
Getting quota default info as admin...

Total Memory           10G
Instance Memory        unlimited
Routes                 -1
Services               100
Paid service plans     allowed
App instance limit     unlimited
Reserved Route Ports   0

If Reserved Route Ports is greater than zero, you can skip the following step, as this attribute determines how many TCP routes can be created within each organization assigned this quota.

If Reserved Route Ports is zero, you can update the quota with the following command:

$ cf update-quota default --reserved-route-ports 2
Updating quota default as admin...

  $ cf quota default
Getting quota default info as admin...

Total Memory           10G
Instance Memory        unlimited
Routes                 -1
Services               100
Paid service plans     allowed
App instance limit     unlimited
Reserved Route Ports   2

Configuring Reserved Route Ports to -1 sets the quota attribute to unlimited. For more information on configuring quotas for TCP Routing, see Enabling TCP Routing.

Running Acceptance tests

Using a BOSH errand on BOSH-Lite

Before running the acceptance tests errand, make sure to have the following setup.

  1. bosh is targeted to your local bosh-lite
  2. routing-release deployed on bosh-lite
  3. Endpoints for http routes are not tested by the errand by default. To enable them, set the property properties.acceptance_tests.include_http_routes in your manifest for the errand job.

Run the following commands to execute the acceptance tests as an errand on bosh-lite

bosh run errand routing_acceptance_tests


See the README for Routing Acceptance Tests

Manual Testing of TCP Routing

  1. The simplest way to test TCP Routing is by pushing your app. By specifying the TCP domain and including the --random-route option, a TCP route will be created with a reserved port and the route mapped to your app.

    $ cf p myapp -d --random-route

  2. Send a request to your app using the TCP shared domain and the port reserved for your route.

    $ curl

Testing TCP Routing with BOSH Lite

On a BOSH deployed environment, you would configure DNS to resolve the TCP shared domain to a load balancer in front of the TCP Routers. However BOSH Lite does not expose ports used by TCP Router. To test TCP Routing against a local BOSH Lite, you can use its curl its IP directly using the route port (assumes route port is 60073):

$ curl

Or you could add an entry to /etc/hosts and curl the domain and port:

To test this against a remote BOSH Lite, you must ssh into a job (like the TCP Router itself) and curl the IP of the router and the route port.

TCP Router demo

For step by step instructions on TCP router demo done at Cloud Foundry Summit 2016, refer to TCP Router demo

Manual Configuration of BOSH Deployment Manifest

If you use the canonical manifest provided with cf-deployment the following prerequisites will be configured for you automatically.


  1. UAA must be configured to terminate TLS for internal requests. Set the following properties in your environment stub for cf-release when using the manifest generation scripts, or set it directly in your manifest. The routing-release's manifest generation scripts will set uaa.tls_port to the value of uaa.ssl.port from the cf-release manifest.

    - name: uaa
            port: <choose a port for UAA to listen to SSL on; e.g. 8443>
          sslCertificate: |
            <insert certificate>
          sslPrivateKey: |
            <insert private key>
  2. You must add the and routing.router_groups.write scopes to your admin user.

    - name: uaa
            - name: admin
              password: PASSWORD
              - scim.write
              - openid
              - cloud_controller.admin
              - clients.write
              - doppler.firehose
              - routing.router_groups.write
  3. The following OAuth clients must be configured for UAA. All but the cf client are new; the important change to the cf client is adding the and routing.router_groups.write scopes. If you're using the manifest generation scripts for cf-release, you can skip this step as the necessary clients are in the Spiff templates. If you're handrolling your manifest for cf-release, you'll need to add them.

    - name: uaa
              authorized-grant-types: client_credentials
              secret: <your-secret>
              override: true
              authorized-grant-types: password,refresh_token
              authorities: uaa.none
              access-token-validity: 600
              refresh-token-validity: 2592000
              authorized-grant-types: client_credentials,refresh_token
              secret: <your-secret>
              authorities: routing.routes.write,
              authorized-grant-types: client_credentials,refresh_token
              secret: <your-secret>
              authorized-grant-types: client_credentials,refresh_token
              secret: <your-secret>
  4. UAA must be configured to accept requests using an internal hostname. The manifest generation scripts for cf-release will do this for you (both BOSH Lite and non). However, if you override the uaa.zones.internal.hostnames property yourself, be sure to include in your stub.

    - name: uaa
           ca_cert: "((uaa_ca.certificate))"

Routing API Database

  1. Routing API requires a relational database as a data store; MySQL and PostgreSQL are supported. Routing API does not create the database; one must exist on startup. cf-deployment uses CF MySQL Release by default. For any deployment you can use this or provide your own MySQL or PostgreSQL database. Configure the credentials for the database with the following properties.
- name: routing-api
      type: <mysql || postgres>
      host: <IP of SQL Host>
      port: <Port for SQL Host>
      schema: <Schema name>
      username: <Username for SQL DB>
      password: <Password for SQL DB>

If you are using cf-mysql-release, then the values for these properties can be obtained from the following properties in the manifest for that release. - type should be mysql - host corresponds to the IP address of the proxy_z1 job - port is 3306 - schema corresponds to cf_mysql.mysql.seeded_databases[].name - username corresponds to cf_mysql.mysql.seeded_databases[].username - password corresponds to cf_mysql.mysql.seeded_databases[].password

  1. If you use the CF MySQL Release, you can seed the required database on deploy using the manifest property cf_mysql.mysql.seeded_databases. Do not use the same deployment of cf-mysql-release that is exposed as a CF marketplace service. Instead, use a deployment intended for internal platform use; for these deployments you should set broker instances to zero. Update the following manifest properties before deploying.
- name: database
        - name: routing-api
          username: <your-username>
          password: <your-password>

Enable Support for TCP Routing in Route Emitter

The Diego Route Emitter component must be configured to emit TCP routes in order to support TCP routing.

- name: route_emitter
     enabled: true

Router Groups

A Router Group represents a horizontally scalable cluster of identically configured routers. Only one router group is currently supported. Shared domains in Cloud Foundry are associated with one router group; see Post Deploy Configuration. To create a TCP route for their application, a developer creates it from a TCP domain; see Create a TCP Route. For each TCP route, Cloud Foundry reserves a port on the CF router. Each port is dedicated to that route; route ports may not be shared by multiple routes. The number of ports available for reservation dictates how many TCP routes can be created.

A router group is limited to maximum port range 1024-65535; defaulting to 1024-1123. As one router group is supported, the maximum number of TCP routes than can be created in CF is 64512 (65535-1024). Though multiple Shared Domains can be assigned to the router group, they share a common pool of ports. E.g. given Shared Domains and are assigned to the default-tcprouter group, and a route for port 1024 is created from, the same port could not be reserved for a route from domain`. Eventually we may support multiple router groups and/or TCP routes that share a port.

The same reservable port range must be configured both on the load balancer, and in this release using the manifest property routing-api.router_groups.reservable_ports. The port range can be modified after deploying using the Routing API.

Note: when modifying the port range using the Routing API, consider that the new port range must include those ports that have already been reserved.

High Availability

The TCP Router and Routing API are stateless and horizontally scalable. The TCP Routers must be fronted by a load balancer for high-availability. The Routing API depends on a database, that can be clustered for high-availability. For high availability, deploy multiple instances of each job, distributed across regions of your infrastructure.

Routing API

For details refer to Routing API.

Metrics Documentation

For documentation on metrics available for streaming from Routing components through the Loggregator Firehose, visit the CloudFoundry Documentation. You can use the NOAA Firehose sample app to quickly consume metrics from the Firehose.

Gorouter Support for PROXY Protocol

Steps for enabling PROXY Protocol on the GoRouter can be found here.

You can’t perform that action at this time.