olibato Documentation
Browse documentation

TCP edge

Protocol ports, implemented TLS routing, access grants, and the reconnect contract for private services.

Status
implemented
Audience
everyone
Updated

This page defines the implemented edge contract. Manifest additions, managed TLS delivery, Supervisor relays, protocol policy, private APIs, Envoy/xDS, and the MySQL gateway exist in source with component and local integration tests. The port map and client examples do not establish public deployment or verified connectivity. Check the returned endpoint and protocol readiness before attempting a connection.

Four external ports#

Ports identify protocols, never tenants. Every tenant shares the applicable protocol port; SNI hostnames or platform-minted credentials select the tenant. No additional external TCP port is permitted. Runtime ports and internal Unix sockets are independent of this map.

External port Protocol Tenant selection and TLS
443 HTTPS; Redis/Valkey TLS; MongoDB TLS; other client-first TLS protocols TLS ClientHello SNI selects the route. Private TCP TLS passes through to the runtime. HTTP continues through the HTTP routing and access layer.
5432 PostgreSQL SSLRequest-aware negotiation followed by SNI selection; the stream passes through byte for byte, so TLS exists only when the database itself has ssl enabled.
3306 MySQL and MariaDB A peer MySQL gateway handles the server-first handshake, requires TLS, authenticates platform-minted credentials, and routes by the site-unique username.
5671 AMQPS Client-first TLS and SNI selection; TLS passes through to the runtime.

External application traffic uses TLS only. Plaintext RESP, AMQP, and database sessions are never externally offered. A schema protocol value alone does not prove TLS capability: for example, a MongoDB service without server TLS remains internal-only. There is no external plaintext Redis listener or per-tenant port.

Routing mechanisms#

Client-first TLS through Envoy#

Envoy inspects the ClientHello on 443 and 5671, chooses an SNI filter chain, checks the source allowlist, and forwards the unmodified TLS stream to the selected Supervisor endpoint relay. xDS supplies endpoint and grant state. Missing or unknown SNI and unauthorized sources fail closed before wake. Use the assigned service hostname rather than an IP address; verify its certificate on the client.

PostgreSQL SSLRequest-aware negotiation#

PostgreSQL normally sends an eight-byte SSLRequest before a TLS ClientHello. The Envoy C module consumes that negotiation before SNI selection, then sends an independent SSLRequest on the backend leg; a generic TLS inspector alone is insufficient. The SSLRequest is negotiation, not permission to skip authentication. Database credentials are always required; TLS exists only when the database itself has ssl enabled, because the edge relays the stream byte for byte and never terminates it. A client without SNI cannot select a tenant on the shared listener.

MySQL gateway#

MySQL sends its server greeting before the client sends a TLS ClientHello. The gateway on 3306 therefore terminates client TLS, verifies platform-minted credentials, and selects the endpoint by the unique routing username. It is a peer of Envoy, not an Envoy listener. The private backend is plaintext by design; protocol: mysql rejects the platform backend tls: {} marker.

MySQL/MariaDB/WordPress template defaults render u_{{ site.token }} using the persisted site ID. Connect with that resolved username from the owner connection panel, not a shared app username or the literal placeholder. Credential generation, gateway snapshot consumption, and revocation enforcement are implemented and tested. Public listener activation still requires deployment verification. Custom usernames require a valid unique gateway binding before external access can be enabled.

Grants and allowlists#

The current owner API accepts POST /sites/{slug}/tcp-access with a non-public manifest service name and a duration of 1–1440 minutes. It derives the source IP from the request and returns hostname, port, connection, cidr, expires_at, operation_id, and grant_id, plus edge_state, protocol_state, protocol, and nullable routing_username. Connect only from the reported CIDR. A grant is network authorization; it does not replace database authentication or TLS verification.

Source responses use mysql://<routing_username>@<hostname>:3306 for MySQL and tcp://<hostname>:<port> for other protocols. They report configured_unverified / unverified; allocation or configuration is not a successful protocol probe. The source policy selects services.<name>.protocol, uses the fixed port map above, and retains the legacy private database@5432 inference for compatibility. tcp, redis, mongodb, and amqp require the tls: {} marker for an external grant. Runtime TLS capability must still be verified. Service names must also form a safe endpoint identity for provisioning.

Omitting protocol is intended to leave a new private service internal-only. Current validation normalizes omission to tcp; the policy can admit that normalized service if it has tls: {}. Omission alone therefore does not prove isolation. Declare the protocol explicitly and withhold grants for internal services. Strict omitted-protocol isolation remains a policy gap.

Envoy/gateway admission and Supervisor relay checks enforce grant CIDRs and expiry before wake. Revocation and credential rotation invalidate cached authorization. The relay bounds established connections by the grant deadline. HTTP public / authenticated access is a separate policy.

Private control-plane interfaces — implemented in source#

These routes are outside /v/api/v1, use dedicated internal bearer credentials, and are not customer or agent PAT interfaces:

Method and route Contract
GET /_internal/edge/state Full endpoint replacement snapshot: protocol, external port/mechanism, node, socket_path / internal_port, PROXY-v2 requirement, grant CIDRs/expiry, draining, and available.
POST /_internal/edge/authorize Accepts source_ip, sni, and listener_port; returns allowed, endpoint identity, and a bounded authorization lifetime. Denies stale, draining, missing, or unauthorized routes without waking them.
POST /_internal/edge/endpoints/{endpoint_id}/drain Marks draining and increments the revision. It does not itself withdraw an Envoy cluster, quiesce a relay, or checkpoint.
GET /_internal/gateway/credentials Full credential replacement snapshot: username, password verifier, endpoint/socket identity, revocation state, and active grant deadlines. The default response is verifier-only; an explicit HTTPS-only include_backend_password=1 pull supplies the password required for independent backend authentication.

Edge state/authz/drain require SITE_EDGE_API_TOKEN; credential sync requires SITE_MYSQL_GATEWAY_API_TOKEN. Empty or incorrect tokens fail closed. Snapshots include replace: true, a content revision, cache_ttl_seconds, and valid_until; consumers must evict absent entries and expired snapshots. The configured TTL is capped at five seconds and bounded by grant expiry. Rotation, expiry, drain, and purge affect the next snapshot. The gateway evicts stale/failed snapshots and revokes sessions. Envoy removes draining resources; controller ACK and connection grace-period checks must precede Supervisor quiescence in the lifecycle coordinator.

Connect with protocol clients#

These examples apply only after the relevant edge stage and endpoint have been verified. Set TCP_HOST to the returned service hostname and CA_FILE to a trusted CA bundle. Use the owner-revealed credentials; never send a control-plane PAT to an application endpoint. Keep passwords out of URLs and shell history.

Protocol Client configuration
HTTP Open https://<site>.<namespace>.serverl3ss.com on 443; follow the site's HTTP access policy.
PostgreSQL Use the service hostname, 5432, and SNI. The stream passes through byte for byte: enable ssl with the delivered service certificate on the database for TLS; the seeded PostgreSQL template currently serves plaintext, so sslmode=prefer negotiates down.
MySQL/MariaDB Use 3306, the resolved routing username, and VERIFY_IDENTITY.
Redis/Valkey Use 443, TLS, SNI, and ACL user app; the URI scheme is rediss.
AMQP Use amqps://<username>@<service-host>:5671 with hostname verification and application credentials.
MongoDB / generic TCP Use 443 only with client-first TLS, SNI, certificate verification, and an approved binding; otherwise keep the service internal.
psql "host=$TCP_HOST port=5432 dbname=app user=app"
# With ssl enabled on the database:
psql "host=$TCP_HOST port=5432 dbname=app user=app sslmode=verify-full sslrootcert=$CA_FILE"
mysql --host="$TCP_HOST" --port=3306 --user="$ROUTING_USERNAME" \
  --ssl-mode=VERIFY_IDENTITY --ssl-ca="$CA_FILE" --password app
redis-cli --tls --sni "$TCP_HOST" --cacert "$CA_FILE" \
  -h "$TCP_HOST" -p 443 --user app --askpass PING

MariaDB clients must use their equivalent CA and server-certificate verification options. A Redis/Valkey server must enable its TLS port, disable plaintext (--port 0), load its service certificate/key, and authenticate the app ACL user. The seeded ACL disables default and removes @dangerous commands.

Reconnect and awake time#

Client connections do not survive instance recycle. Checkpoint/restore, snapshots, restart, node moves, and idle scale-to-zero require clients to reconnect. Configured durable state persists, but a socket and an in-flight transaction are not durable state. Use connection-pool retries with bounded backoff and resolve ambiguous write outcomes before retrying.

Client keepalives hold an instance awake; that awake time is billable. Tune pool lifetime, idle connections, and keepalives to the workload's cost and latency needs. Supervisor relays own connection idle timeouts. Edge active health checks against wake-gated runtimes are forbidden because they would continually wake the workload.

Implementation and metering status#

Stage Repository status
Protocol/TLS manifest fields and template defaults Implemented in the validator and seed source; existing database rows need the normal seed rollout.
Internal per-endpoint Supervisor relays Implemented in source: trusted-peer PROXY v2 admission, wake, dial, relay, connection limits, and byte events.
Managed per-service TLS delivery Issuance and delivery implemented/tested for gVisor mounts, Firecracker disk material, and K3s Secrets; real Redis TLS integration coverage. Public deployment must be verified separately.
Protocol policy, internal endpoint persistence, edge state/authz/credential APIs Implemented in source with additive migration 0100_edge_endpoint_access_policy; edge/gateway consumers are implemented; public deployment must be verified separately.
Network byte ingestion Implemented in source; scoped to node/endpoint and deduplicated by node, Supervisor stream, and sequence. Public site usage exposes integer network_bytes totals.
Envoy/xDS and MySQL gateway Implemented and component-tested, including optional real Envoy/libpq and MySQL server/CLI oracles. Envoy is absent from the 3306 path.
Public four-port activation Deployment/drain source and repeatable protocol harnesses exist; this document does not establish an activated public rollout.

The Supervisor is the authoritative billing meter. Edge counters are for reconciliation only and must not independently charge usage. Relay source emits network_bytes with received/sent byte counts. Django ingestion records their sum as bytes with directional counters and duration in ledger metadata, once per node/stream/sequence. Its metered event set includes wake_minutes, requests, storage_gb_hours, and network_bytes. Ingestion is a recorded fact, not proof of deployment, complete coverage, or a new pricing rule. The public site usage response includes network_bytes as an integer.

This page supersedes the historical dedicated-port and TCP pool designs.