latest is published as a convenience and should not be the only
tag you rely on. Images are built for linux/amd64 and linux/arm64.
Run it
The browser only ever calls same-origin paths —/api/* for the control-plane API and /collect
for Faro telemetry — and nginx forwards them to upstreams chosen when the container is created. Both
upstream variables are required:
When the control plane and Alloy run on the Docker host:
http://localhost:3000; the health endpoint is /healthz. host.docker.internal already
exists on Docker Desktop, and the explicit --add-host makes the example work on Docker Engine for
Linux too.
If the other processes are containers, put them on the same user-defined network and use their
container names. No Compose file is needed:
Runtime settings
The container writes/config.js at startup rather than baking installation-specific values into
the JavaScript bundle. So the same image works for every installation.
CUSTOS_SERVER_TRANSPORT_PUBLIC_KEY is the value custoscp gen-keys prints — see
Configuration. It must match the control plane’s
CUSTOS_SERVER_TRANSPORT_PRIVATE_KEY, and CUSTOS_ENCRYPTION must agree on both sides.
Request flow
nginx strips/api before forwarding, so a browser request to /api/credentials arrives at the
control plane as /credentials. /collect is forwarded unchanged to Alloy. traceparent and other
headers pass through normally, so frontend-to-backend trace correlation survives.
Neither upstream has to be publicly reachable. TLS terminates at the load balancer or ingress in
front of port 8080.
Because the browser calls same-origin paths through this proxy, a container deployment normally does
not need
CUSTOS_CORS_ORIGINS set on the control plane. That setting matters when a browser calls
the control plane directly on another origin.Build it yourself
APP_VERSION identifies the exact build; it is reported to Faro and shown in the account menu.
Publishing a release
Releases are tag-driven, matching the control-plane and daemon repositories:custos-web/v* tag; the workflow then creates the GitHub Release and publishes
the three image tags above. Set the GHCR package visibility to public if installations should pull
without GitHub credentials.