Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: "traffic_shaping"
---

import { Callout } from "@hive/design-system/hive-components/callout";
import { Tabs } from "@hive/design-system/tabs";

The `traffic_shaping` configuration object provides control over how the Hive Router manages
Expand Down Expand Up @@ -130,10 +131,44 @@ new long-lived connection attempts are rejected with `503 Service Unavailable` a
This limit only activates when at least one of WebSocket or Subscriptions is enabled. Setting it
to `0` disables the limit entirely.

### `router.tls` (Client ↔ Router)

Use this configuration field to make the router serve HTTPS traffic (TLS) and optionally require client certificates (mTLS).
For a conceptual overview and step-by-step setup, see [TLS & mTLS](/docs/router/security/tls).

- `cert_file` (**required**): Router server certificate file path, or a list of certificate file
paths.
- `key_file` (**required**): Router server private key file path.
- `client_auth.cert_file` (optional): Trusted client CA certificate file path, or a list of
certificate file paths.
- `client_auth.required` (optional, default `true`): Whether client certificates are required when
`client_auth` is set.

```yaml title="router.config.yaml"
traffic_shaping:
router:
tls:
cert_file: /etc/router/tls/server.crt
key_file: /etc/router/tls/server.key
```

```yaml title="router.config.yaml"
traffic_shaping:
router:
tls:
cert_file:
- /etc/router/tls/server.crt
- /etc/router/tls/intermediate.crt
key_file: /etc/router/tls/server.key
client_auth:
cert_file: /etc/router/tls/client-ca.crt
required: true
```

## Outbound Options

The following options (`dedupe_enabled`, `pool_idle_timeout`, and `request_timeout`) can be set
globally for all subgraphs or overridden on a per-subgraph basis by nesting them under the
The following options (`dedupe_enabled`, `pool_idle_timeout`, `request_timeout`, and `tls`) can be
set globally for all subgraphs or overridden on a per-subgraph basis by nesting them under the
subgraph's name within the `traffic_shaping` map.

For example, the following example shows how to set global defaults and override them for a specific
Expand Down Expand Up @@ -238,3 +273,46 @@ traffic_shaping:

This example sets a shorter timeout for high-priority requests based on a custom header, and
configures the `product` subgraph to have a different timeout for requests originating from Europe.

### `tls` (Router ↔ Subgraphs)

Use these configuration fields to configure TLS for outbound requests from the router to subgraphs. For a
conceptual overview and step-by-step setup, see [TLS & mTLS](/docs/router/security/tls).

- `all.tls`: global default TLS config for all subgraphs.
- `subgraphs.<name>.tls`: per-subgraph override.

Supported fields:

- `cert_file` (optional): Trusted subgraph CA certificate file path, or a list of certificate file
paths.
- `client_auth.cert_file` + `client_auth.key_file` (optional): Router client certificate and key
for mTLS to subgraphs.
- `insecure_skip_ca_verification` (optional, default `false`): Disables server certificate
verification.

When both `all.tls` and `subgraphs.<name>.tls` are set, the subgraph config overrides the matching
global fields. Fields not set in the subgraph config fall back to `all.tls`.

```yaml title="router.config.yaml"
traffic_shaping:
all:
tls:
cert_file: /etc/router/tls/subgraph-ca.crt
subgraphs:
payments:
tls:
cert_file: /etc/router/tls/payments-ca.crt
accounts:
tls:
cert_file: /etc/router/tls/accounts-ca.crt
client_auth:
cert_file: /etc/router/tls/router-client.crt
key_file: /etc/router/tls/router-client.key
```

<Callout type="warning">
`insecure_skip_ca_verification: true` should only be used for local
development or controlled testing. It disables verification of subgraph server
certificates.
</Callout>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"csrf",
"introspection",
"jwt-authentication",
"operation-complexity",
"tls",
"operation-complexity"
"persisted-documents"
]
}
163 changes: 163 additions & 0 deletions packages/documentation/content/docs/router/security/tls.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
---
title: "TLS & mTLS"
---

import { Callout } from "@hive/design-system/hive-components/callout";

Transport Layer Security (TLS) encrypts traffic between every participant in your federated graph.
Mutual TLS (mTLS) goes a step further and authenticates both sides of a connection using
certificates, so each party can prove who it is, not just that the channel is encrypted.

Hive Router lets you configure TLS independently on two connection segments:

- **Client → Router (inbound):** the router terminates TLS toward API consumers.
- **Router → Subgraphs (outbound):** the router validates subgraph certificates and optionally
presents its own client certificate.

```
Client ──[TLS]──► Router ──[TLS]──► Subgraph(s)
inbound outbound
```

For the full configuration reference for every field described on this page, see
[`traffic_shaping` configuration](/docs/router/configuration/traffic_shaping).

## Inbound TLS (Client → Router)

By default the router listens on plain HTTP. Enable inbound TLS when the router is directly exposed
to clients and is **not** behind a TLS-terminating load balancer or reverse proxy (e.g. nginx,
Envoy, AWS ALB).

### Basic HTTPS

Provide a server certificate and its private key:

```yaml title="router.config.yaml"
traffic_shaping:
router:
tls:
cert_file: /etc/router/tls/server.crt
key_file: /etc/router/tls/server.key
```

When inbound TLS is enabled, WebSocket clients must connect using `wss://` instead of `ws://`. The router automatically accepts secure WebSocket upgrades on the same TLS port.

If your certificate is issued by an intermediate CA, supply the full chain by listing every file in
order (leaf certificate first):

```yaml title="router.config.yaml"
traffic_shaping:
router:
tls:
cert_file:
- /etc/router/tls/server.crt
- /etc/router/tls/intermediate.crt
key_file: /etc/router/tls/server.key
```

### Mutual TLS (mTLS) for Inbound Connections

mTLS requires clients to present a valid certificate signed by a trusted CA. This is useful in
zero-trust environments where you need to guarantee that only authorized clients can reach the
router.

Set `client_auth.cert_file` to the CA certificate that signed your clients' certificates. Set
`client_auth.required` to `true` (the default when `client_auth` is configured) to reject clients
that do not present a valid certificate.

```yaml title="router.config.yaml"
traffic_shaping:
router:
tls:
cert_file: /etc/router/tls/server.crt
key_file: /etc/router/tls/server.key
client_auth:
cert_file: /etc/router/tls/client-ca.crt
required: true
```

To make client certificates optional (for example, to accept both mTLS and plain TLS clients)
set `required: false`.

## Outbound TLS (Router → Subgraphs)

When subgraphs are served over HTTPS, the router validates their certificates using the operating
system's default CA bundle. No additional configuration is needed for subgraphs that use
publicly-trusted certificates.

### Custom or Self-Signed CA

If your subgraphs use a private CA or self-signed certificates, tell the router where to find the
trusted CA certificate:

```yaml title="router.config.yaml"
traffic_shaping:
all:
tls:
cert_file: /etc/router/tls/subgraph-ca.crt
```

This applies to all subgraphs. To use a different CA for a specific subgraph, override it under
`subgraphs.<name>`:

```yaml title="router.config.yaml"
traffic_shaping:
all:
tls:
cert_file: /etc/router/tls/subgraph-ca.crt
subgraphs:
payments:
tls:
cert_file: /etc/router/tls/payments-ca.crt
```

Fields not set in a per-subgraph override fall back to the `all.tls` value.

### Mutual TLS (mTLS) to Subgraphs

Some subgraphs require the router to authenticate itself with a client certificate. Provide the
router's client certificate and key under `client_auth`:

```yaml title="router.config.yaml"
traffic_shaping:
all:
tls:
cert_file: /etc/router/tls/subgraph-ca.crt
subgraphs:
accounts:
tls:
cert_file: /etc/router/tls/accounts-ca.crt
client_auth:
cert_file: /etc/router/tls/router-client.crt
key_file: /etc/router/tls/router-client.key
```

### Skipping Certificate Verification

<Callout type="warning">
`insecure_skip_ca_verification: true` disables verification of subgraph server
certificates. Only use this for local development or controlled testing, never
in production.
</Callout>

```yaml title="router.config.yaml"
traffic_shaping:
all:
tls:
insecure_skip_ca_verification: true
```

## Certificate Management Tips

- **Store certificate files outside the config file.** Reference them by path so you can rotate
them without editing `router.config.yaml`.
- **Use a secrets manager or mounted secrets.** In Kubernetes, mount TLS secrets as volumes and
reference the resulting file paths in the config.
- **Rotate certificates by restarting the router.** The router reads certificate files at startup.
After replacing a certificate file, perform a rolling restart to pick up the new certificate with
zero downtime.
- **Keep private keys restricted.** Ensure key files are readable only by the user the router
process runs as (e.g. `chmod 600`).
- **Automate renewal.** Tools such as [cert-manager](https://cert-manager.io) (Kubernetes) or
[Certbot](https://certbot.eff.org) can renew certificates automatically and trigger a restart when
they do.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ websocket:
persist: false
```

#### TLS and `wss://`

When the router has [inbound TLS enabled](/docs/router/security/tls), WebSocket clients must use `wss://` instead of `ws://`. The router accepts secure WebSocket upgrades on the same port as HTTPS.

```ts
import { createClient } from "graphql-ws";

const client = createClient({
url: "wss://your-router.example.com/ws",
// ...
});
```

#### `enabled`

Enables or disables WebSocket support for clients. Defaults to `false`. Can also be set via the `WEBSOCKET_ENABLED` environment variable.
Expand Down
Loading