Skip to content

Commit 29b5c66

Browse files
author
deepshekhardas
committed
feat(webapp): add RUNTIME_API_ORIGIN to decouple runner traffic from external origin
1 parent debfa2b commit 29b5c66

8 files changed

Lines changed: 48 additions & 1 deletion

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: feature
4+
---
5+
6+
Add `RUNTIME_API_ORIGIN` env var to route managed runner traffic through an in-cluster URL, bypassing tracing gateways that rewrite the W3C `traceparent` header and break parent→child run links.

apps/webapp/app/env.server.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,21 @@ const EnvironmentSchema = z
239239
// Global default for internalApiOriginEnabled when an org hasn't set it.
240240
INTERNAL_API_ORIGIN_ENABLED: z.string().default("0"),
241241
STREAM_ORIGIN: z.string().optional(),
242+
// Origin that the webapp publishes to MANAGED (deployed) runner pods as
243+
// both `TRIGGER_API_URL` and (as the first fallback) `TRIGGER_STREAM_URL`.
244+
// When self-hosting behind a tracing-enabled gateway (Envoy/Istio/etc.)
245+
// that rewrites the W3C `traceparent` on egress, point this at an
246+
// in-cluster service URL so runner-to-webapp traffic stays inside the
247+
// cluster and the parent->child run link in the trace tree is preserved.
248+
// Intentionally NOT used for dev (CLI) task runs, which usually run on a
249+
// developer's machine outside the cluster and would lose connectivity if
250+
// forced onto an in-cluster URL. Empty string is normalized to unset so
251+
// blank `${RUNTIME_API_ORIGIN:-}` passthroughs from caller environments
252+
// don't short-circuit the `??` fallback chain.
253+
RUNTIME_API_ORIGIN: z
254+
.string()
255+
.optional()
256+
.transform((v) => v || undefined),
242257
ELECTRIC_ORIGIN: z.string().default("http://localhost:3060"),
243258
// A comma separated list of electric origins to shard into different electric instances by environmentId
244259
// example: "http://localhost:3060,http://localhost:3061,http://localhost:3062"

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,10 @@ async function resolveOverridableOtelDevVariables(
11571157
function resolveProdApiOrigin(runtimeEnvironment: RuntimeEnvironmentForEnvRepo): string {
11581158
const publicOrigin = env.API_ORIGIN ?? env.APP_ORIGIN;
11591159

1160+
if (env.RUNTIME_API_ORIGIN) {
1161+
return env.RUNTIME_API_ORIGIN;
1162+
}
1163+
11601164
if (!env.INTERNAL_API_ORIGIN) {
11611165
return publicOrigin;
11621166
}
@@ -1190,7 +1194,7 @@ async function resolveBuiltInProdVariables(
11901194
// Deliberately not switched by internalApiOriginEnabled: streams are
11911195
// long-lived connections served on their own path.
11921196
key: "TRIGGER_STREAM_URL",
1193-
value: env.STREAM_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
1197+
value: env.RUNTIME_API_ORIGIN ?? env.STREAM_ORIGIN ?? env.API_ORIGIN ?? env.APP_ORIGIN,
11941198
},
11951199
{
11961200
key: "TRIGGER_RUNTIME_WAIT_THRESHOLD_IN_MS",

docs/self-hosting/env/webapp.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mode: "wide"
1919
| `LOGIN_ORIGIN` | Yes | http://localhost:3030 | Login origin URL. Most likely the same as `APP_ORIGIN`. |
2020
| `API_ORIGIN` | No | `APP_ORIGIN` | API origin URL. |
2121
| `STREAM_ORIGIN` | No | `APP_ORIGIN` | Realtime stream origin URL. |
22+
| `RUNTIME_API_ORIGIN` | No || In-cluster origin used by managed (deployed) runners for `TRIGGER_API_URL`/`TRIGGER_STREAM_URL`. Set this to keep runner-to-webapp traffic on an internal hop that bypasses tracing-enabled gateways (which rewrite the W3C `traceparent` header and break the run-detail tree). Leave unset to keep using `API_ORIGIN`/`STREAM_ORIGIN`. |
2223
| `ELECTRIC_ORIGIN` | No | http://localhost:3060 | Electric origin URL. |
2324
| **Postgres** | | | |
2425
| `DATABASE_URL` | Yes || PostgreSQL connection string. |

hosting/docker/.env.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ API_ORIGIN=http://localhost:8030
5050
DEV_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:8030/otel
5151
# You may need to set this when testing locally or when using the combined setup
5252
# API_ORIGIN=http://webapp:3000
53+
# Optional: origin advertised to MANAGED (deployed) runner pods as both
54+
# TRIGGER_API_URL and TRIGGER_STREAM_URL (intentional: keeps all managed
55+
# runner traffic on the same bypass hop). Dev (CLI) task runs are NOT
56+
# affected -- they keep using API_ORIGIN/APP_ORIGIN so a developer running
57+
# `trigger.dev dev` from outside the cluster doesn't lose connectivity.
58+
# Set this to an in-cluster service URL when running behind a tracing-enabled
59+
# gateway that rewrites the W3C `traceparent` header on egress (e.g. Envoy/
60+
# Istio with tracing on). If you need streams on a dedicated endpoint (CDN,
61+
# etc.), keep RUNTIME_API_ORIGIN unset and use STREAM_ORIGIN instead.
62+
# RUNTIME_API_ORIGIN=http://webapp:3000
5363

5464
# Webapp - memory management
5565
# - 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
@@ -44,6 +44,7 @@ services:
4444
APP_ORIGIN: ${APP_ORIGIN:-http://localhost:8030}
4545
LOGIN_ORIGIN: ${LOGIN_ORIGIN:-http://localhost:8030}
4646
API_ORIGIN: ${API_ORIGIN:-http://localhost:8030}
47+
RUNTIME_API_ORIGIN: ${RUNTIME_API_ORIGIN:-}
4748
ELECTRIC_ORIGIN: http://electric:3000
4849
# Realtime streams v2, backed by the bundled s2-lite service. This powers
4950
# AI-agent token streaming and run streams. Point the endpoint at a hosted

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.s2.enabled" . }}

hosting/k8s/helm/values.yaml

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

7783
replicaCount: 1
7884

0 commit comments

Comments
 (0)