This is the second of four pages that expand
Deploy to production: with
credentials in place, this page covers the ingress and TLS
requirements, then how images and config.yaml reach a running
deployment.
Ingress routing
Terminate TLS at your ingress and expose one origin for the web application and API. Reproduce the routing the reference nginx configuration implements:
| Path | Upstream | Requirements |
|---|---|---|
|
Static bundle built from |
Single-page application fallback to |
|
Core, port 8000 |
Prefix match. The core is mounted with |
|
Core, port 8000 |
Server-sent events: response buffering off, HTTP/1.1, no compression, read timeout long enough for a run (600 seconds in the reference; the stream itself lives up to three hours). |
|
Phoenix, port 6006, with |
Restrict access (identity-aware proxy, VPN, or network policy). The
admin panel links to |
Object-storage public endpoint |
The bucket’s endpoint ( |
Reachable by browsers; the reference forwards port 9000 to RustFS and
adds an unconditional The endpoint must also expose two artifact metadata headers. The client does not guess between those two spellings. The core derives
the prefix from |
Other settings that follow from the origin:
-
http.cors_originsmust list the origin; the API setsallow_credentialsand reflects it. -
The identity provider must have
<origin>/auth/callbackand<origin>registered. -
The core’s OpenAPI document (
/api/openapi.json), Swagger UI (/api/docs), and ReDoc (/api/redoc) are public by design; block them at the ingress if your policy requires it. -
No component enforces rate limiting; add it at the ingress.
-
The reference nginx config caps request bodies at
client_max_body_size 4mon port 80. Keep an explicit limit at your own ingress; Kumoss’s requests (repository descriptions, not file uploads) are small, but an unbounded body size is an easy denial-of-service vector. -
Sidecars, databases, Redis, object storage’s internal endpoint, and Phoenix’s OTLP port must not be exposed through the ingress. Use network policies so that only the core reaches the sidecars.
Outbound connections you must allow: the core to the LLM provider, the
Git host, the identity provider, object storage, and Phoenix; the IaC
sidecar to the provider registry (registry.opentofu.org or
registry.terraform.io) and to the cloud APIs; the notifications
sidecar to hooks.slack.com (or your channel).
Images and configuration delivery
-
Build the images from the repository with your registry’s tags. The core image copies
config.yamlfrom the repository root at build time; to keep one image per version and vary configuration per environment, mount the file instead and setKUMOSS_CONFIGto its path inside the container. The path must be a regular file, or the core silently falls back to built-in defaults, which disable every optional sidecar (notifications, mapping, authz). The IaC sidecar has noenabledflag and is always called: if the fallback also leaves its bearer token unresolved, the core fails to boot; but if the token is set and only the endpoint falls back to the built-in default (http://iac:8082, unreachable from most environments), the core boots successfully and the failure only surfaces on the first IaC call (init/validate/plan/apply), not at boot. -
Build the core and IaC images with the same
KUMOSS_UIDandKUMOSS_GIDbuild arguments (default10001) and run both with that identity. -
Build the images from a release tag (
vX.Y.Z). The core reports the version of the source it was built from in its OpenAPI document; setAPP_VERSIONonly to override it, for example on a patched build. -
docker compose watchand bind-mounted source directories are development conveniences; do not use them in production.