Running a docker-target deployment with the built-in sign-in broker fails at qm up: the portal container exits before becoming ready.
Repro
qm up pulls everything, core/web-ui/admin/auth start, then portal dies:
[portal] FATAL: OIDC endpoint must be https unless it is the built-in broker on the private network: http://auth:8080/token
[portal] FATAL: OIDC endpoint must be https unless it is the built-in broker on the private network: http://auth:8080/userinfo
[portal] FATAL: OIDC endpoint must be https unless it is the built-in broker on the private network: http://auth:8080/.well-known/jwks.json
[portal] FATAL: AUTH_BROKER_UPSTREAM must address a private-network host — the broker is never exposed directly
Error: portal refusing to start: 4 misconfiguration(s)
Cause
The docker backend wires the broker as a bare Docker alias — cli/src/backends/docker.ts uses authBaseUrl: "http://auth:8080" — but isPrivateNetworkUrl in plugins/portal/src/index.ts only accepts localhost, *.localhost, *.internal, *.flycast, *.local, private IPs, and private IPv6. A single-label hostname like auth matches none of those, so every broker endpoint fails the boot check.
The fly wiring (<app>-auth.flycast) and aws wiring (...internal) pass because their hostnames carry a recognized suffix, so docker is the odd one out. It also bites the published package itself: @yc-software/qm@0.1.5 pins a portal image digest whose boot check rejects 0.1.5's own generated env.
Workaround we shipped locally
Patch the installed CLI to wire http://auth.qm.internal:8080 and add a matching --network-alias auth.qm.internal to the auth container's docker run. That makes the URL pass the existing check without weakening it.
Two possible directions in-repo:
- keep the check strict and change the docker wiring + network alias to something like
auth.qm.internal (matches how fly/aws embed a suffix), or
- teach
isPrivateNetworkUrl to accept single-label hostnames — they can only resolve through the Docker network's embedded DNS, so they cannot be public either way.
Happy to test whichever fix lands. Environment: @yc-software/qm 0.1.5, Node v24, Ubuntu 24.04, Docker 28.
Running a docker-target deployment with the built-in sign-in broker fails at
qm up: the portal container exits before becoming ready.Repro
{ "orgId": "example", "publicUrl": "https://qm.example.com", "target": "docker", "services": ["core", "web-ui", "admin", "portal", "auth"], "env": { "core": { "HARNESS": "pi" }, "auth": { "AUTH_EMAIL_TRANSPORT": "smtp" } } }qm uppulls everything, core/web-ui/admin/auth start, then portal dies:Cause
The docker backend wires the broker as a bare Docker alias —
cli/src/backends/docker.tsusesauthBaseUrl: "http://auth:8080"— butisPrivateNetworkUrlinplugins/portal/src/index.tsonly accepts localhost,*.localhost,*.internal,*.flycast,*.local, private IPs, and private IPv6. A single-label hostname likeauthmatches none of those, so every broker endpoint fails the boot check.The fly wiring (
<app>-auth.flycast) and aws wiring (...internal) pass because their hostnames carry a recognized suffix, so docker is the odd one out. It also bites the published package itself:@yc-software/qm@0.1.5pins a portal image digest whose boot check rejects 0.1.5's own generated env.Workaround we shipped locally
Patch the installed CLI to wire
http://auth.qm.internal:8080and add a matching--network-alias auth.qm.internalto the auth container'sdocker run. That makes the URL pass the existing check without weakening it.Two possible directions in-repo:
auth.qm.internal(matches how fly/aws embed a suffix), orisPrivateNetworkUrlto accept single-label hostnames — they can only resolve through the Docker network's embedded DNS, so they cannot be public either way.Happy to test whichever fix lands. Environment: @yc-software/qm 0.1.5, Node v24, Ubuntu 24.04, Docker 28.