Skip to content
Talk to our solutions team

Gateway Operations

Local HTTP-only loop:

Terminal window
gateway.svc config generate quickstart > .gateway.yaml
gateway.svc config generate spa-http -d config/
mkdir -p public && echo '<h1>hello</h1>' > public/index.html
gateway.svc -f .gateway.yaml -L debug
curl http://localhost:8443/

Production: start from the bootstrap profile (port 443, zerotrust: true, cert flags), keep routing in config.router.dir or on config.svc.

Run flags: -f/--config, -p/--port, -l/--log, -L/--loglevel, --sid, --datacenter, --cluster, --zerotrust, --svccert/--svckey/--rootca, --jwt_public_key, --config_url/--config_apikey, --servicediscovery_url/--servicediscovery_apikey.

The platform supervisor manages it as service gateway with default state up.

Routing config reloads without restart, from either source:

  • Local dir: recursive filesystem watch; any write/create/remove/rename triggers a debounced reload.
  • Remote: config.svc pushes over SSE.

Reload semantics:

  • The update is overlaid onto the last-known-good config, so a routing-only push can never wipe listener/boot keys.
  • On reload failure the previous config is re-applied; if that fails too, the process exits: the supervisor restarts it clean.
  • In-flight requests finish on the old configuration.
  • Static router config cannot change at runtime: entrypoints, ACME resolvers, and provider settings apply at boot only: changing them requires a restart. Everything in the routing plane (domainmaps, backends, endpoints, routes, staticpaths, LB profiles, passthrough dynamic config) is hot.

Backend server lists additionally update live via the service-discovery watcher (default 5s poll) without any config push.

  • Metrics listener (kisaimetrics, default 127.0.0.1:8088): Prometheus /metrics and Go pprof /debug/pprof/*. There is no health endpoint on the data plane: probe a route or the metrics listener.
  • Logs: log: stdout or fluentd host:port. loglevel controls the gateway; router.loglevel independently dials the embedded router’s verbosity.
  • Access logs / tracking: an anonymous-tracker cookie and access-log events publish asynchronously (fire-and-forget) to configured endpoints; disabled on internal traffic; non-fatal when unset.
  • Dashboard: expose the router dashboard only through a normal, kisai-auth-gated route (dashboard example), the insecure API mode is a protected key and rejected at boot.
Terminal window
gateway.svc version
gateway 2.0.0 …
traefik (vendored fork): v3.7.13 (fc92cc118a05)

The second line is the upstream release the embedded router was built from, with its pinned commit. Check it when triaging anything that looks like proxy behaviour rather than routing behaviour, and when an upstream advisory names a version range.

The expensive failure in a gateway is the quiet one: the config parses, the process starts, and a route is simply not there. An advisory pass at boot and on every reload names the shapes that load without routing anything.

WarningWhat it means
A domainmap, endpoint or staticpath is bound by no routeIt was declared and nothing references it
One local staticpath is bound by two routesThe file server starts once per route, so the two contend for the same port
Two routes claim the same entrypoint, host and pathThe router picks by priority, and the loser never sees a request

These are warnings rather than errors. Each shape is legal and some are deliberate, so the reload carries on; read them as a list of things to confirm you meant.

Observability does not gate the data plane

Section titled “Observability does not gate the data plane”

A metrics listener that fails to start, or that is slow to stop during a reload, is logged and the gateway keeps routing. A taken metrics port or a bad kisaimetrics: block does not stop the boot, and a slow shutdown of that listener does not fail a reload.

SymptomCause / action
Every request on a domain → 400Domain missing from all domainmaps: or domains: written as a scalar instead of a list (caught with a targeted error at load)
Nothing matches behind another proxyThe fronting proxy sends its own Host (e.g. localhost); add its IP to the entrypoint’s trustedips so X-Forwarded-Host is honored
Boot fails parsing routing filesThey’re in config.path instead of config.router.dir
Reload rejectedDuplicate names / unresolved references / protected passthrough paths / unknown certresolver. The error names the offender; last-known-good stays live
Browser shows a self-signed certACME issuance failed: check the certresolver is referenced by the route, ACME logs, :80 reachability for HTTP-01, and that acme.json is writable
Boot error “internal.port required”Legacy listener mode needs internal.port, or switch to an explicit entrypoints: list
TCP/UDP routes skip tenant headersL4 routes bypass the HTTP middleware chain by design. No CEPT attribution
Every request on a route answers 503 with rate_limit_unavailableThe rate-limit store is unreachable and that profile is set to on_store_failure: deny. See Rate limiting