## Routing

A **Route** defines how to access a service running behind Pomerium. This includes authentication (both for Pomerium and passed through to the service), rewrites, header management, load balancing, etc.

When first installing Pomerium Enterprise, users may want to import existing routes from the open-source Pomerium core. The **Migrate Routes** button accepts the open-source `config.yaml` file and imports routes from it to Pomerium Enterprise.

\[Migrate routes in Console]

From the main Routes page you can view and manage existing routes. From the table of routes you can:

- Filter visible routes
- Delete one or more routes
- Move routes between Namespaces
- Export one or more route definitions to a CSV file
- Create a JSON-formatted policy report on one or more selected routes

The sections below cover the options available when creating or editing a route.

### General

The **General** tab defines the route path, both from the internet and to the internal service, and the policies attached. Note that policies enforced on a [Namespace](https://www.pomerium.com/docs/internals/namespacing.md#hierarchical-policy-enforcement) the route resides in will also be applied.

#### Name

This value is only visible in the Console UI.

#### From

`From` is the externally accessible URL for the proxied request.

Specifying `tcp+https` or `udp+https` for the scheme enables [TCP proxying](https://www.pomerium.com/docs/capabilities/non-http.md) or [UDP proxying](https://www.pomerium.com/docs/capabilities/non-http/udp.md) support for the route. You may map more than one port through the same hostname by specifying a different `:port` in the URL.

Only secure schemes (`https`, `tcp+https` and `udp+https`) are supported.

#### Metrics Name

Once a Route is created, the Metric Name field will populate. You can use this name to scrape the Prometheus service for metrics on this Route when making custom dashboards.

#### To

`To` is the destination(s) of a proxied request. It can be an internal resource, or an external resource. Multiple upstream resources can be targeted by using a list instead of a single URL:

```yaml
- from: https://example.com
  to:
    - https://a.example.com
    - https://b.example.com
```

Both `http://` and `https://` URLs are supported, as well as `http+unix:///var/run/example.sock` and `https+unix:///var/run/example.sock` for local unix addresses. If the `from` address starts with `tcp+https://`, use `tcp://` for the upstream. If the `from` address starts with `udp+https://`, use `udp://` for the upstream.

A load balancing weight may be associated with a particular upstream by appending `,[weight]` to the URL. The exact behavior depends on your [`lb_policy`](#load-balancing-method) setting.

With rule:

```yaml
- from: https://verify.corp.example.com
  to: https://verify.pomerium.com/anything
```

Requests to `https://verify.corp.example.com` will be forwarded to `https://verify.pomerium.com/anything`, while requests to `https://verify.corp.example.com/foo` will be forwarded to `https://verify.pomerium.com/anythingfoo`.\
To make the request forwarded to `https://httbin.org/anything/foo`, you can use double slashes in your request `https://httbin.corp.example.com//foo`.

While the rule:

```yaml
- from: https://verify.corp.example.com
  to: https://verify.pomerium.com/anything/
```

All requests to `https://verify.corp.example.com/*` will be forwarded to `https://verify.pomerium.com/anything/*`. That means accessing `https://verify.corp.example.com` will be forwarded to `https://verify.pomerium.com/anything/`. That said, if your application does not handle trailing slash, the request will end up with 404 not found.

Either `redirect` or `to` must be set.

#### Redirect

`Redirect` is used to redirect incoming requests to a new URL. The `redirect` field is an object with several possible options:

- `https_redirect` (boolean): the incoming scheme will be swapped with "https".
- `scheme_redirect` (string): the incoming scheme will be swapped with the given value.
- `host_redirect` (string): the incoming host will be swapped with the given value.
- `port_redirect` (integer): the incoming port will be swapped with the given value.
- `path_redirect` (string): the incoming path portion of the URL will be swapped with the given value.
- `prefix_rewrite` (string): the incoming matched prefix will be swapped with the given value.
- `response_code` (integer): the response code to use for the redirect. Defaults to 301.
- `strip_query` (boolean): indicates that during redirection, the query portion of the URL will be removed. Defaults to false.

Either `redirect` or `to` must be set.

#### Pass Identity Headers

When enabled, this option will pass identity headers to upstream applications. These headers include:

- X-Pomerium-Jwt-Assertion
- X-Pomerium-Claim-\*

#### Policies

Add or remove Policies to be applied to the Route. Note that Policies enforced in the Route's Namespace will be applied automatically.

For information and examples related to PPL, see [**Policy Language**](https://www.pomerium.com/docs/internals/ppl.md). :::

#### Enable Google Cloud Serverless Authentication

Enable sending a signed [Authorization Header](https://cloud.google.com/run/docs/authenticating/service-to-service) to upstream GCP services.

Requires setting [Google Cloud Serverless Authentication Service Account](https://www.pomerium.com/docs/reference/google-cloud-serverless-authentication-service-account.md) or running Pomerium in an environment with a GCP service account present in default locations.

### Matchers

#### Path

If set, the route will only match incoming requests with a path that is an exact match for the specified path.

#### Regex

If set, the route will only match incoming requests with a path that matches the specified regular expression. The supported syntax is the same as the Go [regexp package](https://golang.org/pkg/regexp/) which is based on [re2](https://github.com/google/re2/wiki/Syntax).

#### Regex Rewrite Pattern

The pattern to match before rewriting, ex: `^/service/([^/]+)(/.*)$`.

#### Regex Rewrite Substitution

The substitution for your regex pattern, ex: `\\2/instance/\\1`.

#### Prefix

If set, the route will only match incoming requests with a path that begins with the specified prefix.

#### Prefix Rewrite

If set, indicates that during forwarding, the matched prefix (or path) should be swapped with this value. For example, given this policy:

```yaml
from: https://from.example.com
to: https://to.example.com
prefix: /admin
prefix_rewrite: /
```

A request to `https://from.example.com/admin` would be forwarded to `https://to.example.com/`.

### Timeouts

#### Allow Websockets

If set, enables proxying of websocket connections.

**Use with caution:** websockets are long-lived connections, so [global timeouts](https://www.pomerium.com/docs/reference/global-timeouts.md) are not enforced (though the policy-specific `timeout` is enforced). Allowing websocket connections to the proxy could result in abuse via [DOS attacks](https://www.cloudflare.com/learning/ddos/ddos-attack-tools/slowloris/).

#### Allow SPDY

If set, enables proxying of SPDY protocol upgrades.

#### Timeout

Policy timeout establishes the per-route timeout value. Cannot exceed global timeout values.

#### Idle Timeout

If you are proxying long-lived requests that employ streaming calls such as websockets or gRPC, set this to either a maximum value there may be no data exchange over a connection (recommended), or set it to unlimited (`0s`). If `idle_timeout` is specified, and `timeout` is not explicitly set, then `timeout` would be unlimited (`0s`). You still may specify maximum lifetime of the connection using `timeout` value (i.e. to 1 day).

### Headers

#### Host Headers

The `host` header can be preserved via the `preserve_host_header` setting or customized via three mutually exclusive options:

1. `preserve_host_header` will, when enabled, this option will pass the host header from the incoming request to the proxied host, instead of the destination hostname. It's an optional parameter of type `bool` that defaults to `false`.

   See [ProxyPreserveHost](http://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypreservehost).

2. `host_rewrite`, which will rewrite the host to a new literal value.

3. `host_rewrite_header`, which will rewrite the host to match an incoming header value.

4. `host_path_regex_rewrite_pattern` & `host_path_regex_rewrite_substitution`, which will rewrite the host according to a regex matching the path. For example with the following config:

   ```yaml
   host_path_regex_rewrite_pattern: '^/(.+)/.+$'
   host_path_regex_rewrite_substitution: \1
   ```

   Would rewrite the host header to `example.com` given the path `/example.com/some/path`.

The 2nd, 3rd and 4th options correspond to the Envoy route action host related options, which can be found [here](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto.html#config-route-v3-routeaction).

#### Set Request Headers

Set Request Headers allows you to set static values for given request headers. This can be useful if you want to pass along additional information to upstream applications as headers, or set authentication header to the request. For example:

```yaml
- from: https://verify.corp.example.com
  to: https://verify.pomerium.com
  policy:
    - allow:
        or:
          - email:
              is: user@example.com
  set_request_headers:
    # works auto-magically!
    # https://verify.corp.example.com/basic-auth/root/hunter42
    Authorization: Basic cm9vdDpodW50ZXI0Mg==
    X-Your-favorite-authenticating-Proxy: 'Pomerium'
```

Neither `:-prefixed` pseudo-headers nor the `Host:` header may be modified via this mechanism. Those headers may instead be modified via mechanisms such as `prefix_rewrite`, `regex_rewrite`, and `host_rewrite`.

#### Remove Request Headers

Remove Request Headers allows you to remove given request headers. This can be useful if you want to prevent privacy information from being passed to upstream applications. For example:

```yaml
- from: https://verify.corp.example.com
  to: https://verify.pomerium.com
  policy:
    - allow:
        or:
          - email:
              is: user@example.com
  remove_request_headers:
    - X-Email
    - X-Username
```

#### Rewrite Response Headers

Rewrite Response Headers allows you to modify response headers before they are returned to the client. The `header` field will match the HTTP header name, and `prefix` will be replaced with `value`. For example, if the upstream server returns a header:

```text
Location: http://localhost:8000/two/some/path/
```

And the policy has this config:

```yaml
rewrite_response_headers:
  - header: Location
    prefix: http://localhost:8000/two/
    value: http://frontend/one/
```

The browser would be redirected to: `http://frontend/one/some/path/`. This is similar to nginx's [`proxy_redirect` option](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect), but can be used for any header.

### Load Balancer

#### Multiple Upstream Servers

You may specify multiple servers for your upstream application, and Pomerium would load balance user requests between them.

```yaml
routes:
  - from: https://myapp.localhost.pomerium.io
    to:
      - http://myapp-srv-1:8080
      - http://myapp-srv-2:8080
```

In the presence of multiple upstream servers, make sure to specify either an **active** or **passive** health check, or both, to avoid requests being served to an unhealthy backend.

#### Active Health Checks

Active health checks issue periodic requests to each upstream to determine its health. See [Envoy Health Checking](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/health_checking) for more details.

#### Passive Health Checks

Passive health check tries to deduce upstream server health based on recent observed responses. See [Outlier Detection](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/outlier) for a comprehensive overview.

```yaml
routes:
  - from: https://myapp.localhost.pomerium.io
    to:
      - http://myapp-srv-1:8080
      - http://myapp-srv-2:8080
    outlier_detection: {}
```

#### Load Balancing Method

`lb_policy` should be set to [one of the values](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers):

- [`ROUND_ROBIN`](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#weighted-round-robin) (default)
- [`LEAST_REQUEST`](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#weighted-least-request)\
  *May be further configured via [`least_request_lb_config`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-msg-config-cluster-v3-cluster-leastrequestlbconfig).*
- [`RING_HASH`](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#ring-hash)\
  *May be further configured via [`ring_hash_lb_config`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-ringhashlbconfig).*
- [`RANDOM`](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#random)
- [`MAGLEV`](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#maglev)\
  *May be further configured via [`maglev_lb_config`](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-msg-config-cluster-v3-cluster-maglevlbconfig).*

> **Some policy types support additional advanced configuration**, such as [least request randomization](https://www.pomerium.com/docs/reference/routes/load-balancing-policy-config.md). See [Load Balancing Policy Config](https://www.pomerium.com/docs/reference/routes/load-balancing-policy-config.md) for details.

##### Example

```yaml
routes:
  - from: https://myapp.localhost.pomerium.io
    to:
      - http://myapp-srv-1:8080
      - http://myapp-srv-2:8080
      - http://myapp-srv-3:8080
      - http://myapp-srv-4:8080
      - http://myapp-srv-5:8080
    lb_policy: LEAST_REQUEST
    least_request_lb_config:
      choice_count: 2 # current envoy default
```

#### Load Balancing Weight

When a list of upstream URLs is specified in the `to` field, you may append an optional load balancing weight parameter. The individual [`lb_policy`](#load-balancing-method) settings will take this weighting into account when making routing decisions.

##### Example

```yaml
routes:
  - from: https://myapp.localhost.pomerium.io
    to:
      - http://myapp-srv-1:8080,10
      - http://myapp-srv-2:8080,20
      - http://myapp-srv-3:8080,30
      - http://myapp-srv-4:8080,20
      - http://myapp-srv-5:8080,10
```

### Route Matching Order

Pomerium matches routes in a specific order; an incoming request will be sent to the first route that matches.

Pomerium considers routes defined in a configuration file first, in the order in which they appear in the configuration file, followed by any routes defined in the Enterprise Console or by the Ingress Controller.

Routes from the Enterprise Console or Ingress Controller are sorted in the following order:

1. Ascending by `host`
2. Descending by `path`
3. Descending by `regex`
4. Descending by `prefix`

The example below defines two routes in a configuration file that both point to the same domain. The first route contains a prefix (`api`).

If Pomerium receives a request to access `https://a.example.com:8080`, Pomerium will first check `https://a.example.com:8080/api` before matching the request with `https://a.example.com:8080`.

```yaml title="config.yaml"
- from: https://a.example.com:8080
  to: http://example:8080
  prefix: /api
  allow_any_authenticated_user: true

- from: https://a.example.com:8080
  to: http://example:8080
  allow_any_authenticated_user: true
```

### Advanced

#### Allow Upgrades

If set, enable proxying of an HTTP upgrade request and its payload. This option takes a list of strings and can be set both at the global level for all routes and for a specific route (in which case it overrides the global option).

```yaml
allow_upgrades:
  - custom-upgrade-type
  - websocket
  - spdy/3.1
```

Using `websocket` is equivalent to enabling the `allow_websockets` option and `spdy/3.1` is equivalent to enabling the `allow_spdy` option.

## Certificates

Certificates are the x509 *public-key* and *private-key* used to establish secure HTTP and gRPC connections. Any combination of the above can be used together, and are additive. You can also use any of these settings in conjunction with `Autocert` to get OCSP stapling.

Certificates loaded into Pomerium from these config values are used to attempt secure connections between end users and services, between Pomerium services, and to upstream endpoints.

For example, if specifying multiple certificates at once:

```yaml
certificates:
  - cert: '$HOME/.acme.sh/authenticate.example.com_ecc/fullchain.cer'
    key: '$HOME/.acme.sh/authenticate.example.com_ecc/authenticate.example.com.key'
  - cert: '$HOME/.acme.sh/verify.example.com_ecc/fullchain.cer'
    key: '$HOME/.acme.sh/verify.example.com_ecc/verify.example.com.key'
  - cert: '$HOME/.acme.sh/prometheus.example.com_ecc/fullchain.cer'
    key: '$HOME/.acme.sh/prometheus.example.com_ecc/prometheus.example.com.key'
```

Or to set a single certificate and key covering multiple domains and/or a wildcard subdomain:

```yaml
certificate_file: '$HOME/.acme.sh/*.example.com/fullchain.crt'
certificate_key: '$HOME/.acme.sh/*.example.com/*.example.com.key'
```

**Note:** Pomerium will check your system's trust/key store for valid certificates first. If your certificate solution imports into the system store, you don't need to also specify them with these configuration keys.
