Kibotos

Install the Exposure gateway

This page shows how to install the Exposure gateway so that HTTP services in Workspaces can be reached through public URLs.

Exposure lets developers turn one HTTP port inside a Workspace into an https:// address. This page installs the two deployment-level components it needs: kibotos-gw, and the tunnel that brings in public traffic. Without both, ctrl does not advertise the Exposure capability, and create requests are rejected.

Prerequisites

  • You have ctrl, nodes, and at least one usable Template in place, in the order given in Installation overview.
  • A registrable domain dedicated to this purpose. It cannot share a registrable domain with ctrl's identity.host or the nodes' data_plane.host_suffix: Workspaces run code written by developers, and the pages it produces are untrusted content. A shared domain would drag cookie scope, same-origin assumptions, and phishing exposure into the control plane.
  • An account with a tunnel provider for that domain. The first release supports cloudflared.
  • A dedicated Operator identity for the gateway: an enrollment key, or an identity directory enrolled as described in Identity and enrollment.
  • The gateway uses the same release set as ctrl and the nodes.

1. Declare the zone on ctrl

Fill in [exposure] zone in /etc/kibotos/ctrl/config.toml and restart ctrl. Leaving it empty means this deployment does not offer Exposure.

[exposure]
zone = "preview.example.com"

A zone in the same registrable domain as identity.host or data_plane.host_suffix is rejected by ctrl.

2. Install the package and write the configuration

set -eu
sudo apt-get install ./kibotos-gw_1.2.3_amd64.deb
sudo test ! -e /etc/kibotos/gw/config.env
sudo install -o root -g root -m 0600 \
  /usr/share/doc/kibotos-gw/gw.example.env /etc/kibotos/gw/config.env
sudoedit /etc/kibotos/gw/config.env

The package creates the kibotos-gw account and the service unit; it neither starts nor enables the service. All of the gateway's configuration goes in this environment file. For a full example, see gw.example.env.

VariableDescription
KIBOTOS_GW_ZONEA domain exactly the same as ctrl's [exposure] zone. If they differ, none of the hostnames ctrl mints match on the gateway, and the failure looks like a mistyped URL
KIBOTOS_GW_IDENTITY_DIRThe absolute path of the Operator identity directory. The service can write only to /var/lib/kibotos/gw/, so put it there. Required; the examples use /var/lib/kibotos/gw/identity
KIBOTOS_GW_ENROLLMENT_KEY_FILEOptional. When the identity directory is empty, the gateway enrolls with this one-time enrollment key. See the next step
KIBOTOS_GW_CTRL_ENDPOINTThe HTTPS address of ctrl
KIBOTOS_GW_LISTENThe listen address that the tunnel connects to. The example uses 127.0.0.1:18097
KIBOTOS_GW_DATA_PLANE_TRANSPORTbidi_stream (default) or websocket. Use the former when the gateway connects directly to the node data plane. Switch to the latter when the node data plane is behind an L7 front layer, because the front layer does not forward Connect bidirectional streams
KIBOTOS_GW_TELEMETRY_LISTENOptional. The metrics listen address, for example 127.0.0.1:18197. When it is not set, nothing listens. See Cluster and service metrics

3. Prepare the identity and start

Each gateway calls ctrl with a dedicated Operator identity, and each running instance needs an identity of its own. This step applies to both gateways. The commands use the Exposure gateway's names. For the E2B gateway, use the names in its column:

ItemExposure gatewayE2B gateway
Service and accountkibotos-gwkibotos-e2b
Configuration file/etc/kibotos/gw/config.env/etc/kibotos/e2b/config.env
Enrollment key variableKIBOTOS_GW_ENROLLMENT_KEY_FILEKIBOTOS_E2B_ENROLLMENT_KEY_FILE
Enrollment key file/var/lib/kibotos/gw/enrollment.key/var/lib/kibotos/e2b/enrollment.key
Identity directory in the examples/var/lib/kibotos/gw/identity/var/lib/kibotos/e2b/identity

Enroll with a key

The simplest approach is to let the gateway enroll itself. The Operator issues a key with kibo enrollment create --operator kibotos-gw-a --output kibotos-gw-a.key and hands it to the gateway host over a secure channel. Put it where the service account can read it, add it to the configuration, then start:

set -eu
sudo install -o kibotos-gw -g kibotos-gw -m 0600 kibotos-gw-a.key /var/lib/kibotos/gw/enrollment.key
echo 'KIBOTOS_GW_ENROLLMENT_KEY_FILE=/var/lib/kibotos/gw/enrollment.key' | sudo tee -a /etc/kibotos/gw/config.env >/dev/null
sudo systemctl enable --now kibotos-gw.service
sudo journalctl -u kibotos-gw.service -n 50 --no-pager
  • When the identity directory is empty, the gateway first enrolls and publishes the identity, and only then starts serving. The log has an enrolled Operator identity line. After that, the file is no longer read, and you can delete it.
  • A key is valid for 1 hour by default. If it has expired, has been used, or has been revoked, the gateway fails to start. Replace it with a new key.

Copy an enrolled identity directory

Instead of a key, you can copy an already enrolled, gateway-specific Operator identity directory in full to the location given in the configuration. Replace gateway_identity_source with the actual path. Run this only when preparing the identity for the first time:

set -eu
gateway_identity_source=/absolute/path/to/enrolled-gateway-context
sudo test ! -e /var/lib/kibotos/gw/identity
sudo cp -a "$gateway_identity_source" /var/lib/kibotos/gw/identity
sudo chown -R kibotos-gw:kibotos-gw /var/lib/kibotos/gw/identity
sudo chmod -R u=rwX,go= /var/lib/kibotos/gw/identity
sudo systemctl enable --now kibotos-gw.service
sudo systemctl status kibotos-gw.service

Identity rules

  • The service runs as its own non-root account and can write only to /var/lib/kibotos/gw (/var/lib/kibotos/e2b for the E2B gateway). The identity directory must be writable, because the gateway renews its certificate there.
  • Each instance needs its own identity. Do not copy one identity directory to several instances, and do not copy a context directory that kibo is using: each user renews on its own, and ctrl accepts only the current and previous certificates, so with more than two users, one is always rejected.
  • To run several instances of a gateway, enroll each one with its own key, for example kibotos-gw-a and kibotos-gw-b.
  • The Exposure gateway holds no long-lived data-plane credential: for each request, it resolves the hostname with ctrl, and ctrl at the same time issues a credential for that exact port that serves only this one request.

4. Configure the tunnel

The tunnel configuration is static: the whole zone points to the gateway. Configure it once; creating and revoking Exposures afterward never touches it. With cloudflared as an example, the ingress has only two rules, and DNS has only one wildcard record pointing to this tunnel:

tunnel: kibotos-exposure
credentials-file: /etc/cloudflared/kibotos-exposure.json
ingress:
  - hostname: "*.preview.example.com"
    service: http://127.0.0.1:18097
  - service: http_status:404

Notes:

  • The provider supplies the wildcard certificate, so the deployer does not need to request a certificate for each hostname.
  • The provider account and tunnel credentials exist only on the host running the tunnel. They never enter the node's Workspace execution path or the guest.
  • The tunnel forwards traffic for the whole zone and can see requests to all Workspaces. It is not a security boundary: hostname resolution, binding to the execution generation, and all access decisions happen on the gateway.
  • For redundancy, run several replicas of the same tunnel, and the provider distributes traffic across the connections.

5. Verify

Create an Exposure with kibo and open the returned url. For usage, see Public URLs. When ctrl has no zone configured, kibo exposure create fails with failed_precondition (CAPABILITY_UNAVAILABLE).

On this page