Skip to content

Commit c1ee97e

Browse files
committed
feat(webapp): add RUNTIME_API_ORIGIN to decouple runner traffic from external origin
The webapp publishes `API_ORIGIN` to runner pods as `TRIGGER_API_URL`, so runner-to-webapp traffic flows back through whatever URL is configured for external clients. Self-hosting behind a tracing-enabled gateway (Envoy, Istio, kgateway, ...) breaks the parent->child run link in trigger.dev's run-detail tree because the gateway's W3C `traceparent` rewrite on egress overwrites the SDK's `triggerAndWait()` span id. The webapp then writes that gateway-generated span id as the child run's `parentSpanId`, which never reaches the trigger event store, so the child renders as an orphan in the UI. Operators can split the two concerns without sacrificing external auth/ callbacks/UI flows that rely on the public `API_ORIGIN`: - Set `RUNTIME_API_ORIGIN=http://<service>.<namespace>:<port>` (k8s) or `http://webapp:3000` (docker) to keep runner->webapp traffic on a cluster-internal hop that bypasses the gateway. - Leave `API_ORIGIN` on the public URL so the dashboard, magic-link emails, waitpoint callbacks, and API `apiUrl` responses keep working for external clients. The new env is optional and falls back to `API_ORIGIN`/`APP_ORIGIN`, so existing deployments are unaffected. Refs: #2821
1 parent 12d2125 commit c1ee97e

6 files changed

Lines changed: 28 additions & 4 deletions

File tree

apps/webapp/app/env.server.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,14 @@ const EnvironmentSchema = z
127127
LOGIN_RATE_LIMITS_ENABLED: BoolEnv.default(true),
128128
APP_ORIGIN: z.string().default("http://localhost:3030"),
129129
API_ORIGIN: z.string().optional(),
130+
// Origin that the webapp publishes to runner pods as `TRIGGER_API_URL`.
131+
// When self-hosting behind a tracing-enabled gateway (Envoy/Istio/etc.)
132+
// that rewrites the W3C `traceparent` on egress, point this at an
133+
// in-cluster service URL so runner-to-webapp traffic stays inside the
134+
// cluster and the parent->child run link in the trace tree is preserved.
135+
// Falls back to API_ORIGIN/APP_ORIGIN, so the existing behavior is
136+
// unchanged when this is unset.
137+
RUNTIME_API_ORIGIN: z.string().optional(),
130138
STREAM_ORIGIN: z.string().optional(),
131139
ELECTRIC_ORIGIN: z.string().default("http://localhost:3060"),
132140
// A comma separated list of electric origins to shard into different electric instances by environmentId

apps/webapp/app/v3/environmentVariables/environmentVariablesRepository.server.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -962,11 +962,11 @@ async function resolveBuiltInDevVariables(runtimeEnvironment: RuntimeEnvironment
962962
},
963963
{
964964
key: "TRIGGER_API_URL",
965-
value: env.API_ORIGIN ?? env.APP_ORIGIN,
965+
value: env.RUNTIME_API_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
966966
},
967967
{
968968
key: "TRIGGER_STREAM_URL",
969-
value: env.STREAM_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
969+
value: env.STREAM_ORIGIN ?? env.RUNTIME_API_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
970970
},
971971
];
972972

@@ -1104,11 +1104,11 @@ async function resolveBuiltInProdVariables(
11041104
},
11051105
{
11061106
key: "TRIGGER_API_URL",
1107-
value: env.API_ORIGIN ?? env.APP_ORIGIN,
1107+
value: env.RUNTIME_API_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
11081108
},
11091109
{
11101110
key: "TRIGGER_STREAM_URL",
1111-
value: env.STREAM_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
1111+
value: env.STREAM_ORIGIN ?? env.RUNTIME_API_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
11121112
},
11131113
{
11141114
key: "TRIGGER_RUNTIME_WAIT_THRESHOLD_IN_MS",

hosting/docker/.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ API_ORIGIN=http://localhost:8030
4646
DEV_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8030/otel
4747
# You may need to set this when testing locally or when using the combined setup
4848
# API_ORIGIN=http://webapp:3000
49+
# Optional: origin advertised to runner pods as TRIGGER_API_URL. When unset,
50+
# runners fall back to API_ORIGIN/APP_ORIGIN. Set this to an in-cluster
51+
# service URL when running behind a tracing-enabled gateway that rewrites
52+
# the W3C `traceparent` header on egress (e.g. Envoy/Istio with tracing on).
53+
# RUNTIME_API_ORIGIN=http://webapp:3000
4954

5055
# Webapp - memory management
5156
# - This sets the maximum memory allocation for Node.js heap in MiB (e.g. "4096" for 4GB)

hosting/docker/webapp/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ services:
4343
APP_ORIGIN: ${APP_ORIGIN:-http://localhost:8030}
4444
LOGIN_ORIGIN: ${LOGIN_ORIGIN:-http://localhost:8030}
4545
API_ORIGIN: ${API_ORIGIN:-http://localhost:8030}
46+
RUNTIME_API_ORIGIN: ${RUNTIME_API_ORIGIN:-}
4647
ELECTRIC_ORIGIN: http://electric:3000
4748
DATABASE_URL: ${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/main?schema=public&sslmode=disable}
4849
DIRECT_URL: ${DIRECT_URL:-postgresql://postgres:postgres@postgres:5432/main?schema=public&sslmode=disable}

hosting/k8s/helm/templates/webapp.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ spec:
186186
value: {{ .Values.webapp.loginOrigin | quote }}
187187
- name: API_ORIGIN
188188
value: {{ .Values.webapp.apiOrigin | quote }}
189+
{{- with .Values.webapp.runtimeApiOrigin }}
190+
- name: RUNTIME_API_ORIGIN
191+
value: {{ . | quote }}
192+
{{- end }}
189193
- name: ELECTRIC_ORIGIN
190194
value: {{ include "trigger-v4.electric.url" . | quote }}
191195
{{- if include "trigger-v4.postgres.useSecretUrl" . }}

hosting/k8s/helm/values.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ webapp:
6868
appOrigin: "http://localhost:3040"
6969
loginOrigin: "http://localhost:3040"
7070
apiOrigin: "http://localhost:3040"
71+
# Origin advertised to runner pods as TRIGGER_API_URL.
72+
# When unset (default), runners use apiOrigin/appOrigin. Set this to an
73+
# in-cluster service URL to keep runner->webapp traffic inside the cluster,
74+
# bypassing gateways/proxies (e.g. Envoy with tracing enabled) that rewrite
75+
# the W3C `traceparent` header on egress and break the parent->child run link.
76+
runtimeApiOrigin: ""
7177

7278
replicaCount: 1
7379

0 commit comments

Comments
 (0)