Skip to content
6 changes: 5 additions & 1 deletion apps/supervisor/src/workloadManager/kubernetes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,11 @@ export class KubernetesWorkloadManager implements WorkloadManager {
"app.kubernetes.io/component": "create",
},
...(Object.keys(env.KUBERNETES_WORKER_POD_ANNOTATIONS).length > 0
? { annotations: { ...env.KUBERNETES_WORKER_POD_ANNOTATIONS } }
? {
annotations: {
...env.KUBERNETES_WORKER_POD_ANNOTATIONS,
} as Record<string, string>,
}
: {}),
},
spec: {
Expand Down
10 changes: 10 additions & 0 deletions docker/scripts/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#!/bin/sh
set -xe

if [ "$1" = "migrate" ]; then
echo "Running migrations only (entrypoint.sh migrate mode)"
SKIP_POSTGRES_MIGRATIONS=0
fi

if [ -n "$DATABASE_HOST" ]; then
scripts/wait-for-it.sh ${DATABASE_HOST} -- echo "database is up"
fi
Expand Down Expand Up @@ -39,6 +44,11 @@ else
echo "CLICKHOUSE_URL not set, skipping ClickHouse migrations."
fi

if [ "$1" = "migrate" ]; then
echo "Migrations complete, exiting."
exit 0
fi

# Copy over required prisma files
cp internal-packages/database/prisma/schema.prisma apps/webapp/prisma/
cp node_modules/@prisma/engines/*.node apps/webapp/prisma/
Expand Down
2 changes: 1 addition & 1 deletion hosting/k8s/helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: trigger
description: The official Trigger.dev Helm chart
type: application
version: 4.4.6
version: 4.4.6-plt663.1
appVersion: v4.4.6
home: https://trigger.dev
sources:
Expand Down
11 changes: 7 additions & 4 deletions hosting/k8s/helm/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -401,11 +401,14 @@ ClickHouse hostname
{{/*
ClickHouse URL for application (with secure parameter)

Note on the external+existingSecret branch: the password is expanded via
Note on `$(CLICKHOUSE_PASSWORD)`: the password is expanded via
Kubernetes' `$(VAR)` syntax, not shell `${VAR}`. Kubelet substitutes
`$(CLICKHOUSE_PASSWORD)` at container-creation time from the
CLICKHOUSE_PASSWORD env var declared just before CLICKHOUSE_URL in
webapp.yaml. Shell-style `${...}` does not work here because
webapp.yaml. Both the `deploy: true` and external+existingSecret
branches use this placeholder so that the chart never bakes the
password literal into a rendered URL string. Shell-style `${...}`
does not work here because
`docker/scripts/entrypoint.sh` assigns CLICKHOUSE_URL to GOOSE_DBSTRING
with a single-pass expansion (`export GOOSE_DBSTRING="$CLICKHOUSE_URL"`),
so any inner `${...}` reaches goose verbatim and fails URL parsing.
Expand All @@ -418,7 +421,7 @@ hex-encoded password or percent-encode before storing in the Secret.
{{- if .Values.clickhouse.deploy -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.secure -}}
{{- $secure := ternary "true" "false" .Values.clickhouse.secure -}}
{{ $protocol }}://{{ .Values.clickhouse.auth.username }}:{{ .Values.clickhouse.auth.password }}@{{ include "trigger-v4.clickhouse.hostname" . }}:8123?secure={{ $secure }}
{{ $protocol }}://{{ .Values.clickhouse.auth.username }}:$(CLICKHOUSE_PASSWORD)@{{ include "trigger-v4.clickhouse.hostname" . }}:8123?secure={{ $secure }}
{{- else if .Values.clickhouse.external.host -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.external.secure -}}
{{- $secure := ternary "true" "false" .Values.clickhouse.external.secure -}}
Expand All @@ -439,7 +442,7 @@ applies to the replication URL.
{{- define "trigger-v4.clickhouse.replication.url" -}}
{{- if .Values.clickhouse.deploy -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.secure -}}
{{ $protocol }}://{{ .Values.clickhouse.auth.username }}:{{ .Values.clickhouse.auth.password }}@{{ include "trigger-v4.clickhouse.hostname" . }}:8123
{{ $protocol }}://{{ .Values.clickhouse.auth.username }}:$(CLICKHOUSE_PASSWORD)@{{ include "trigger-v4.clickhouse.hostname" . }}:8123
{{- else if .Values.clickhouse.external.host -}}
{{- $protocol := ternary "https" "http" .Values.clickhouse.external.secure -}}
{{- if .Values.clickhouse.external.existingSecret -}}
Expand Down
12 changes: 12 additions & 0 deletions hosting/k8s/helm/templates/electric.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ spec:
{{- end }}
resources:
{{- toYaml .Values.electric.resources | nindent 12 }}
volumeMounts:
- name: electric-persistent
mountPath: /app/persistent
{{- with .Values.electric.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
volumes:
- name: electric-persistent
emptyDir: {}
{{- with .Values.electric.extraVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
---
apiVersion: v1
kind: Service
Expand Down
12 changes: 12 additions & 0 deletions hosting/k8s/helm/templates/supervisor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ spec:
value: {{ .Values.supervisor.config.kubernetes.workerServiceAccount | quote }}
- name: KUBERNETES_WORKER_AUTOMOUNT_SERVICE_ACCOUNT_TOKEN
value: {{ .Values.supervisor.config.kubernetes.workerAutomountServiceAccountToken | quote }}
{{- if .Values.supervisor.config.kubernetes.workerPodSecurityContext }}
- name: KUBERNETES_WORKER_POD_SECURITY_CONTEXT
value: {{ .Values.supervisor.config.kubernetes.workerPodSecurityContext | toJson | quote }}
{{- end }}
{{- if .Values.supervisor.config.kubernetes.workerContainerSecurityContext }}
- name: KUBERNETES_WORKER_CONTAINER_SECURITY_CONTEXT
value: {{ .Values.supervisor.config.kubernetes.workerContainerSecurityContext | toJson | quote }}
{{- end }}
{{- if .Values.supervisor.config.kubernetes.workerPodAnnotations }}
- name: KUBERNETES_WORKER_POD_ANNOTATIONS
value: {{ .Values.supervisor.config.kubernetes.workerPodAnnotations | toJson | quote }}
{{- end }}
{{- $registryAuthEnabled := false }}
{{- if .Values.registry.deploy }}
{{- $registryAuthEnabled = .Values.registry.auth.enabled }}
Expand Down
35 changes: 31 additions & 4 deletions hosting/k8s/helm/templates/webapp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ spec:
secretKeyRef:
name: {{ include "trigger-v4.secretsName" . }}
key: MANAGED_WORKER_SECRET
{{- end }}
{{- /*
Object-store credentials are scoped independently of the four
session secrets above. Three branches:
1. s3.deploy → mount from the chart's internal MinIO
creds (s3.auth.existingSecret or the
chart-managed s3-auth-* keys).
2. s3.external.useIam → skip entirely. IRSA / Workload
Identity provides credentials to the
SDK; mounting OBJECT_STORE_* would
force static-key mode.
3. external static keys → s3.external.existingSecret, OR
s3.external.accessKeyId when the
chart is provisioning its own
secret (requires secrets.enabled
so secrets.yaml actually writes
s3-access-key-id).
*/}}
{{- if .Values.s3.deploy }}
{{- if .Values.s3.auth.existingSecret }}
- name: OBJECT_STORE_ACCESS_KEY_ID
Expand All @@ -327,7 +345,7 @@ spec:
name: {{ include "trigger-v4.secretsName" . }}
key: s3-auth-secret-access-key
{{- end }}
{{- else }}
{{- else if not .Values.s3.external.useIam }}
{{- if .Values.s3.external.existingSecret }}
- name: OBJECT_STORE_ACCESS_KEY_ID
valueFrom:
Expand All @@ -339,7 +357,7 @@ spec:
secretKeyRef:
name: {{ include "trigger-v4.s3.external.secretName" . }}
key: {{ include "trigger-v4.s3.external.secretAccessKeyKey" . }}
{{- else if .Values.s3.external.accessKeyId }}
{{- else if and .Values.secrets.enabled .Values.s3.external.accessKeyId }}
- name: OBJECT_STORE_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
Expand All @@ -352,7 +370,6 @@ spec:
key: s3-secret-access-key
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.webapp.observability }}
{{- if .Values.webapp.observability.tracing.exporterUrl }}
- name: INTERNAL_OTEL_TRACE_EXPORTER_URL
Expand Down Expand Up @@ -387,7 +404,17 @@ spec:
- name: INTERNAL_OTEL_METRIC_EXPORTER_INTERVAL_MS
value: {{ .Values.webapp.observability.metrics.exporterIntervalMs | quote }}
{{- end }}
{{- if and .Values.clickhouse.external.host .Values.clickhouse.external.existingSecret }}
{{- if .Values.clickhouse.deploy }}
- name: CLICKHOUSE_PASSWORD
{{- if .Values.clickhouse.auth.existingSecret }}
valueFrom:
secretKeyRef:
name: {{ .Values.clickhouse.auth.existingSecret }}
key: {{ .Values.clickhouse.auth.existingSecretKey | default "admin-password" }}
{{- else }}
value: {{ .Values.clickhouse.auth.password | quote }}
{{- end }}
{{- else if and .Values.clickhouse.external.host .Values.clickhouse.external.existingSecret }}
- name: CLICKHOUSE_PASSWORD
valueFrom:
secretKeyRef:
Expand Down
25 changes: 25 additions & 0 deletions hosting/k8s/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,23 @@ electric:
# - name: CUSTOM_VAR
# value: "custom-value"

# Extra volumes added to the Electric pod. The Electric container always
# has an emptyDir at /app/persistent regardless of this list — that's
# required by the Electric runtime. Use `extraVolumes` for things like
# an enterprise CA bundle ConfigMap.
extraVolumes:
[]
# - name: ca-bundle
# configMap:
# name: enterprise-ca-bundle

# Extra volume mounts added to the Electric container.
extraVolumeMounts:
[]
# - name: ca-bundle
# mountPath: /etc/ssl/enterprise-ca
# readOnly: true

# ClickHouse configuration
# Subchart: https://github.com/bitnami/charts/tree/main/bitnami/clickhouse
clickhouse:
Expand Down Expand Up @@ -756,6 +773,14 @@ s3:
accessKeyId: "admin" # Default for internal MinIO - change for production
secretAccessKey: "very-safe-password" # Default for internal MinIO - change for production
#
# IAM-based authentication (for AWS S3 with IRSA / GCP Workload Identity).
# When true, the webapp pod skips the OBJECT_STORE_ACCESS_KEY_ID /
# OBJECT_STORE_SECRET_ACCESS_KEY env vars entirely so the AWS SDK can
# fall back to its credential-provider chain (instance metadata,
# web-identity-token file, etc.). Pair with a ServiceAccount
# `eks.amazonaws.com/role-arn` annotation on `webapp.serviceAccount`.
useIam: false
#
# Secure credential management
existingSecret: "" # Name of existing secret containing S3 credentials
existingSecretAccessKeyIdKey: "access-key-id" # Key in existing secret containing access key ID
Expand Down
Loading