Operations
Bootstrap from zero
Section titled “Bootstrap from zero”Local HTTP-only loop:
gateway.svc config generate quickstart > .gateway.yamlgateway.svc config generate spa-http -d config/mkdir -p public && echo '<h1>hello</h1>' > public/index.htmlgateway.svc -f .gateway.yaml -L debugcurl 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.
Hot reload
Section titled “Hot reload”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.
Observability
Section titled “Observability”- Metrics listener (
kisaimetrics, default127.0.0.1:8088): Prometheus/metricsand Go pprof/debug/pprof/*. There is no health endpoint on the data plane — probe a route or the metrics listener. - Logs —
log: stdoutor fluentdhost:port.loglevelcontrols the gateway;router.loglevelindependently 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 (dashboardexample). The insecure API mode is a protected key and rejected at boot.
Failure modes
Section titled “Failure modes”| Symptom | Cause / action |
|---|---|
| Every request on a domain → 400 | Domain 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 proxy | The 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 files | They’re in config.path instead of config.router.dir |
| Reload rejected | Duplicate names / unresolved references / protected passthrough paths / unknown certresolver — the error names the offender; last-known-good stays live |
| Browser shows a self-signed cert | ACME 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 headers | L4 routes bypass the HTTP middleware chain by design — no CPET attribution |