> For the complete documentation index, see [llms.txt](https://docs.kangal.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kangal.dev/gateway/gateways-data-planes.md).

# Gateways and data planes

A gateway is Kangal's tenant-scoped configuration boundary. A data-plane node is a runtime instance registered to one gateway. Keep the two concepts separate: creating a gateway records desired hosting and plan metadata; it does not prove that a runtime node or public listener exists.

## Choose a deployment profile

The Console pairs each profile with a plan code:

| Deployment profile    | Console plan code      | Intended ownership                                                   |
| --------------------- | ---------------------- | -------------------------------------------------------------------- |
| `serverless`          | `serverless_starter`   | Shared or managed runtime.                                           |
| `dedicated_cloud`     | `dedicated_enterprise` | Dedicated managed capacity.                                          |
| `self_managed_hybrid` | `hybrid_scale`         | Customer-operated data planes connected to the Kangal control plane. |
| `kubernetes_ingress`  | `kic_readonly`         | Kubernetes-oriented configuration view.                              |

The Console keeps the pair synchronized. API automation must submit one of the listed `deployment_profile` values with its approved `plan_code`. The profile is desired hosting metadata; provisioning the runtime capacity, Kubernetes controller, and data-plane registration is a separate deployment workflow.

## Create a gateway in the Console

1. Open **API Gateway** and select **New**.
2. Choose the deployment profile.
3. Enter a name and optional description.
4. Expand the advanced section only when labels are needed for ownership, environment, search, or automation.
5. Create the gateway, then open its detail page.
6. Record the gateway ID and inspect the generated proxy and workspace metadata.
7. Open **Data plane nodes** before declaring the gateway ready.

Console name validation requires at least three characters. The first character must be lowercase alphanumeric; subsequent characters may also contain `-`, `_`, and `.`. The description is limited to 512 characters in the Console.

## Gateway fields

| Field                            | Meaning                          | Notes                                                                                                        |
| -------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `tenant_id`                      | Owner tenant.                    | Required on create and checked against the administrator scope. It cannot be changed through gateway update. |
| `name`                           | Human and automation identifier. | Use a stable, DNS-safe value. Changing it does not regenerate the stored proxy metadata.                     |
| `description`                    | Operator context.                | Do not place secrets here.                                                                                   |
| `deployment_profile`             | Desired hosting model.           | One of the four values above.                                                                                |
| `plan_code`                      | Entitlement/billing association. | Keep it aligned with the profile selected by the Console.                                                    |
| `labels`                         | Free-form metadata.              | The Console enters values as strings and reserves profile-related labels for its own display logic.          |
| `proxy_host`, `proxy_url`        | Generated proxy identity.        | A logical address until DNS, edge routing, and TLS have been verified. Read-only in the gateway update API.  |
| `workspace_id`, `workspace_name` | Generated workspace metadata.    | Read-only in the gateway update API.                                                                         |

Gateway creation consumes the `gateway.manage` entitlement. A plan or entitlement failure can reject creation even when the JSON is otherwise valid.

## Manage gateways with `kangalctl`

```bash
kangalctl get gateways --tenant-id tenant-acme
```

Create from a JSON or YAML payload:

```bash
kangalctl create gateways -f gateway.yaml
```

Update only supported mutable fields:

```yaml
description: Production orders traffic
labels:
  environment: production
  owner: platform
```

```bash
kangalctl update gateways "$GATEWAY_ID" -f gateway-update.yaml
```

Deleting a gateway removes the gateway record and entitlement usage, but it is not a full cascade. Delete or repoint routes, services, upstreams, targets, certificates, and other scoped resources first.

## Register a data-plane node

Registration is an administrator operation. Use a stable `node_id`; posting the same tenant, gateway, and node ID updates the registration rather than creating a second node.

```bash
curl -sS -X POST \
  "$KANGAL_API_URL/api/v1/admin/gateways/$GATEWAY_ID/data-planes" \
  -H "Authorization: Bearer $KANGAL_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "tenant-acme",
    "node_id": "dp-eu-1",
    "name": "EU production 1",
    "hostname": "kangal-dp-01.internal",
    "version": "1.0.0",
    "labels": {"region": "eu-central", "environment": "production"},
    "capabilities": ["http", "plugins"],
    "issue_token": true
  }'
```

The response includes `node_token` only when a token is issued. Store it in the node's secret store immediately; later list and get responses do not reveal it. Kangal stores a SHA-256 hash of the token.

To rotate a token, register the same `node_id` again with `issue_token: true` and replace the node secret before its next control-plane call. The old token stops authenticating after rotation.

Where the deployment requires certificate pinning, also provide:

* `client_cert_sha256`: the verified client certificate's SHA-256 fingerprint;
* `client_cert_subject`: informational certificate subject metadata.

The fingerprint is normalized before storage. For a pinned node, Kangal requires the matching fingerprint injected by the trusted TLS terminator in addition to the node token.

Certificate verification must occur at a trusted TLS terminator. Configure that terminator to remove any client-supplied `X-Kangal-DP-Client-Cert-SHA256` header (or the configured equivalent), verify the client certificate, and inject its SHA-256 fingerprint. Block direct access to the application endpoints so requests cannot bypass the terminator. Kangal then compares the trusted injected value with the registered pin alongside the node token.

## Connect the runtime

Configure the node with the control-plane URL, `tenant_id`, `gateway_id`, stable `node_id`, and the issued token. Use the deployment's supported secret injection mechanism; never commit the token to a manifest or image.

The independent runtime exposes only:

* `GET /health` for process health and current mode;
* `GET /ready` for configuration readiness;
* `GET /status` for detailed last-known-good and connectivity state;
* `/proxy/{path}`, `/api/proxy/{path}`, and the transparent `/{path}` request paths.

The runtime communicates with the control plane through the scoped `X-Kangal-DP-Token` channel and keeps administrative and database access in the control-plane tier. When the deployment enables mTLS, the trusted TLS terminator supplies the verified certificate fingerprint as described above.

## Understand node state

| Field or status                  | Meaning                                                                       | Operator action                                                                       |
| -------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `registered`                     | The node record exists but has not reported a live heartbeat.                 | Check runtime start, scope IDs, token, and network access.                            |
| `online`                         | The last heartbeat reported normal operation.                                 | Still compare current and desired versions.                                           |
| `degraded`                       | The node is serving a last-known-good bundle with an error or pending report. | Inspect `last_telemetry.mode`, pending reports, and NACK details.                     |
| `offline`                        | The control plane marked the heartbeat stale.                                 | Determine whether the node is down or serving offline from its local status endpoint. |
| `draining`                       | The node reports that it should leave normal traffic service.                 | Confirm the external load balancer is also draining it.                               |
| `current_config_version`         | Active bundle version reported by the node.                                   | Must match the intended rollout target after completion.                              |
| `desired_config_version`         | Bundle version the control plane wants the node to run.                       | A mismatch indicates pending delivery, deferral, or failure.                          |
| `config_sync_status`             | `pending`, `success`, `failed`, or `partial`.                                 | Investigate anything other than `success` for required production nodes.              |
| `last_config_ack_status`         | Latest `ACK` or `NACK`.                                                       | A NACK means the bundle was not activated.                                            |
| `last_known_good_config_version` | Last acknowledged rollback candidate.                                         | Confirm it exists before relying on automatic rollback.                               |
| `last_seen_at`                   | Last authenticated node activity.                                             | Use with heartbeat age; a stored `online` value can become stale.                     |

The node's own runtime modes are more specific:

* `online`: control plane reachable and no pending local error;
* `degraded-lkg`: valid last-known-good configuration with an activation or reporting problem;
* `offline-lkg`: control plane unavailable while the signed cache is still in use;
* `stale-lkg`: cached bundle exceeds the configured maximum age;
* `not-ready`: no valid configuration is available, so proxy requests return `503`.

## Roll out configuration

The **Data plane nodes** page shows the active rollout, node ACK/NACK state, current and desired versions, wave, last-known-good version, and last-seen time.

For a production change:

1. Confirm every intended node is registered and recently seen.
2. Start **canary** for a high-risk change or **staged** for a routine change.
3. Set the canary or batch size and keep offline nodes excluded unless their participation is intentional.
4. Configure automatic rollback thresholds.
5. Wait for the active wave to finish. Do not promote while nodes are in progress.
6. Resolve every NACK before promotion.
7. Promote the next wave until the rollout completes.
8. Confirm current and desired versions match on all required nodes.

The Console starts canary with one node and staged waves with a batch size of five. Both defaults use automatic rollback after one failed node or a 50% failed rate in the active wave. Adjust API payloads when those defaults do not match the size and risk of your fleet.

API strategies are `immediate`, `staged`, and `canary`. `batch_size` and `canary_size` accept 1 through 100. Offline nodes are excluded by default.

```bash
curl -sS -X POST \
  "$KANGAL_API_URL/api/v1/admin/gateways/$GATEWAY_ID/data-planes/config-rollout?tenant_id=$KANGAL_TENANT_ID" \
  -H "Authorization: Bearer $KANGAL_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "strategy": "canary",
    "canary_size": 1,
    "batch_size": 5,
    "reason": "orders-route-change",
    "include_offline": false,
    "policy": {
      "automatic_rollback": true,
      "failure_count_threshold": 1,
      "failure_rate_threshold_percent": 50
    }
  }'
```

Use the corresponding endpoints to inspect status, pause, resume, promote, or roll back:

```
GET  /api/v1/admin/gateways/{gateway_id}/data-planes/config-rollout/status
POST /api/v1/admin/gateways/{gateway_id}/data-planes/config-rollout/pause
POST /api/v1/admin/gateways/{gateway_id}/data-planes/config-rollout/resume
POST /api/v1/admin/gateways/{gateway_id}/data-planes/config-rollout/promote
POST /api/v1/admin/gateways/{gateway_id}/data-planes/config-rollout/rollback
```

Each request requires the tenant query parameter and an authorized administrator. Transitions that do not fit the current rollout state return `409`.

## Operational checks

* Registration upserts by `(tenant_id, gateway_id, node_id)`. Reusing a node ID unintentionally can rotate its token and reset its visible state to `registered`.
* A heartbeat is not an ACK. It can report `online` while the desired bundle is still pending.
* When the control plane marks a stale record offline, drain or remove the node from the external load balancer through its own control system.
* Rollback requires a captured and usable snapshot. The UI reports when an automatic rollback is unavailable or fails.
* Offline service requires a valid signed cache and anti-rollback state; verify `/ready` and the runtime mode in addition to process health.
* Configuration synchronization covers gateway runtime resources. External DNS, ingress, cloud load balancers, and public certificate activation remain deployment responsibilities.

## Troubleshooting

### Node remains `registered`

Verify exact tenant, gateway, and node IDs; the control-plane base URL; token rotation; TLS trust; and that the node can call heartbeat and config endpoints.

### `401` from node endpoints

The token is missing, stale, or associated with another node. If certificate pinning is configured, also verify that the trusted TLS terminator injected the expected SHA-256 fingerprint after validating the client certificate.

### Current and desired versions differ

Check rollout deferral, node wave, `config_available`, last pull time, and NACK details. A staged node in `waiting`, `paused`, or `blocked` is intentionally not offered the target generation yet.

### Node reports `NACK`

Use `last_config_nack_message` and `last_config_nack_errors`. Scope, checksum, signature, malformed collection, or anti-rollback failures must be fixed before promotion. The rejected bundle never replaces the active snapshot.

### Rollout cannot be promoted

Kangal rejects promotion when the wave is paused, still in progress, has failed nodes, or has no waiting nodes. Refresh status rather than retrying blindly.

### Rollback is unavailable

No required node has acknowledged a usable last-known-good generation, or the pinned snapshot is unavailable. Stabilize the current rollout manually and capture a known-good state before the next change.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kangal.dev/gateway/gateways-data-planes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
