diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 501e9c488..f9e32a38a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1270,9 +1270,24 @@ jobs: --set 'extraVolumeMounts[0].readOnly=true' \ --set probes.liveness=null \ > "$out/variants.yaml" + helm template trek charts/trek \ + --set httpRoute.enabled=true \ + --set 'httpRoute.parentRefs[0].name=gateway' \ + > "$out/http-route.yaml" + helm template trek charts/trek \ + --set ingress.enabled=true \ + --set fullnameOverride=custom-trek \ + --set service.port=8080 \ + --set-json 'httpRoute={"enabled":true,"parentRefs":[{"name":"gateway","namespace":"gateway-system","sectionName":"https"}],"hostnames":["trek.example.com"],"paths":["/","/api"],"annotations":{"example.com/note":"custom route"},"timeouts":{"request":"0s","backendRequest":"0s"}}' \ + > "$out/http-route-variants.yaml" - name: Check the manifests against the Kubernetes schemas - run: kubeconform -strict -summary "$RUNNER_TEMP"/rendered/*.yaml + # The pinned Gateway API schema adds HTTPRoute validation without skipping unknown resources. + run: >- + kubeconform -strict -summary + -schema-location default + -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/041baf4c1d3740ca21461cab765e7432ecd073ef/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' + "$RUNNER_TEMP"/rendered/*.yaml - name: Check every compose file run: | diff --git a/charts/README.md b/charts/README.md index 7f9c11540..a31fa2cdf 100644 --- a/charts/README.md +++ b/charts/README.md @@ -8,6 +8,7 @@ This is a minimal Helm chart for deploying the TREK app. - Optional persistent storage for `/app/data` and `/app/uploads`, plus extra volumes and mounts - Configurable environment variables and secrets - Optional generic Ingress support +- Optional Gateway API HTTPRoute support - Configurable health checks (liveness/readiness probes) on `/api/health` ## Helm Repository @@ -27,13 +28,38 @@ helm install trek trek/trek Or install directly from the local chart: ```sh -helm install trek ./chart \ +helm install trek ./charts/trek \ --set ingress.enabled=true \ --set ingress.hosts[0].host=yourdomain.com ``` See `values.yaml` for more options. +### HTTPRoute + +HTTPRoute support is off by default. Enable it to attach TREK to an existing Gateway: + +```yaml +httpRoute: + enabled: true + annotations: {} + parentRefs: + - name: gateway + namespace: gateway-system + sectionName: https + hostnames: + - trek.example.com + paths: + - / + timeouts: + request: "0s" + backendRequest: "0s" +``` + +The cluster must have the Gateway API `HTTPRoute` v1 CRD and a Gateway API controller. The chart creates only the HTTPRoute, targeting TREK's existing Service and `service.port`; the Gateway, GatewayClass, listener, TLS certificate, and `allowedRoutes` configuration remain the operator's responsibility. When enabled, `parentRefs` and `paths` must be non-empty. Each path is a string prefix. Ingress and HTTPRoute can both be enabled. + +Timeout fields became Standard Channel in Gateway API v1.2, but controller support is implementation-specific. Omitting them leaves timeout behavior to the controller. `0s` disables the corresponding request timeout; controller idle and buffering settings can still interrupt `/ws` connections or streamed assistant responses. Set `env.ALLOWED_ORIGINS` and `env.APP_URL` to the public URL; when the Gateway terminates TLS, configure `env.FORCE_HTTPS: "true"` and `env.TRUST_PROXY: "1"`. + ## Files - `Chart.yaml` — chart metadata - `values.yaml` — configuration values @@ -47,7 +73,7 @@ See `values.yaml` for more options. - `JWT_SECRET` is managed entirely by the server — auto-generated into the data PVC on first start and rotatable via the admin panel (Settings → Danger Zone). No Helm configuration needed. - `ENCRYPTION_KEY` encrypts stored secrets (API keys, MFA, SMTP, OIDC) at rest. Recommended: set via `secretEnv.ENCRYPTION_KEY` or `existingSecret`. If left empty, the server falls back automatically: existing installs use `data/.jwt_secret` (no action needed on upgrade); fresh installs auto-generate a key persisted to the data PVC. - Liveness and readiness probes are configurable under `probes`. Overrides are merged over the defaults, so `--set probes.liveness.initialDelaySeconds=60` keeps the `httpGet` handler. When switching to `exec` or `tcpSocket`, clear `httpGet` in the same override. Set `probes.liveness: null` to remove a probe. -- If using ingress, you must manually keep `env.ALLOWED_ORIGINS` and `ingress.hosts` in sync to ensure CORS works correctly. The chart does not sync these automatically. +- If exposing TREK through an Ingress or HTTPRoute, set `env.ALLOWED_ORIGINS` and `env.APP_URL` to the public URL. The chart does not sync these automatically. - Set `env.ALLOW_INTERNAL_NETWORK: "true"` if Immich or other integrated services are hosted on a private/RFC-1918 address (e.g. a pod on the same cluster or a NAS on your LAN). Loopback (`127.x`) and link-local/metadata addresses (`169.254.x`) remain blocked regardless. - Set `env.ALLOW_LINK_LOCAL_IPS` to a single link-local address (e.g. `"169.254.1.2"`) only when a service TREK needs sits behind one, such as a host gateway. Cloud metadata addresses (`169.254.169.x`, `169.254.170.x`) cannot be listed. - `FORCE_HTTPS` is optional. Set `env.FORCE_HTTPS: "true"` only when ingress (or another proxy) terminates TLS. It enables HTTPS redirects, HSTS, CSP `upgrade-insecure-requests`, and forces the session cookie `secure` flag. Requires `TRUST_PROXY` to be set. diff --git a/charts/trek/templates/NOTES.txt b/charts/trek/templates/NOTES.txt index 7845bc00d..6562dd60d 100644 --- a/charts/trek/templates/NOTES.txt +++ b/charts/trek/templates/NOTES.txt @@ -31,3 +31,12 @@ The other values for that volume (size, storageClassName, annotations) are then ignored. - With `persistence.enabled=false` the volumes use an emptyDir — storage is ephemeral and is lost when the pod restarts. Use only for testing. + +{{- if .Values.httpRoute.enabled }} +6. HTTPRoute: + - The chart creates an HTTPRoute v1 to the existing TREK Service. The Gateway, GatewayClass, + listeners, TLS certificates and allowedRoutes are managed by your cluster operator. + - Ingress and HTTPRoute may be enabled together. + - Timeout fields are Standard Channel in Gateway API v1.2, but controller support varies. Omit + them to use controller defaults; `0s` disables the corresponding timeout where supported. +{{- end }} diff --git a/charts/trek/templates/httproute.yaml b/charts/trek/templates/httproute.yaml new file mode 100644 index 000000000..30c49cae0 --- /dev/null +++ b/charts/trek/templates/httproute.yaml @@ -0,0 +1,39 @@ +{{- if .Values.httpRoute.enabled -}} +{{- if not .Values.httpRoute.parentRefs }} +{{- fail "httpRoute.parentRefs must include at least one parent" }} +{{- end }} +{{- if not .Values.httpRoute.paths }} +{{- fail "httpRoute.paths must include at least one path" }} +{{- end }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ include "trek.fullname" . }} + labels: + app: {{ include "trek.name" . }} + {{- with .Values.httpRoute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- toYaml .Values.httpRoute.parentRefs | nindent 4 }} + {{- with .Values.httpRoute.hostnames }} + hostnames: + {{- toYaml . | nindent 4 }} + {{- end }} + rules: + {{- range $path := .Values.httpRoute.paths }} + - matches: + - path: + type: PathPrefix + value: {{ $path | quote }} + backendRefs: + - name: {{ include "trek.fullname" $ }} + port: {{ $.Values.service.port }} + {{- with $.Values.httpRoute.timeouts }} + timeouts: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/trek/values.yaml b/charts/trek/values.yaml index 35e9f751f..deaeb8e13 100644 --- a/charts/trek/values.yaml +++ b/charts/trek/values.yaml @@ -36,7 +36,7 @@ env: # Browser/OS language is auto-detected first; this is the fallback when no match is found. # Supported: ar, az, br, ca, cs, de, en, es, et, fr, gr, hu, id, it, ja, ko, nl, pl, ru, sk, sv, th, tr, uk, vi, zh, zh-TW # ALLOWED_ORIGINS: "" - # NOTE: If using ingress, ensure env.ALLOWED_ORIGINS matches the domains in ingress.hosts for proper CORS configuration. + # NOTE: If using ingress or HTTPRoute, ensure env.ALLOWED_ORIGINS matches the public domains for proper CORS configuration. # APP_URL: "https://trek.example.com" # Public base URL of this instance. Required when OIDC is enabled — must match the redirect URI registered with your IdP. # Also used as the base URL for links in email notifications and other external links. @@ -294,3 +294,20 @@ ingress: # - secretName: chart-example-tls # hosts: # - chart-example.local + +httpRoute: + enabled: false + annotations: {} + parentRefs: [] + # - name: gateway + # namespace: gateway-system + # sectionName: https + hostnames: [] + # - trek.example.com + paths: + - / + # Timeout fields are Standard Channel in Gateway API v1.2; controller support varies. + # Leave empty for controller defaults. Use "0s" to disable the corresponding timeout. + timeouts: {} + # request: "0s" + # backendRequest: "0s" diff --git a/wiki/Install-Helm.md b/wiki/Install-Helm.md index b1a1cab76..6dfd290a2 100644 --- a/wiki/Install-Helm.md +++ b/wiki/Install-Helm.md @@ -271,6 +271,31 @@ ingress: > **Note:** When using ingress with TLS termination, set `env.FORCE_HTTPS: "true"` and `env.TRUST_PROXY: "1"` to enable HTTPS redirects, HSTS, and secure cookies. +### HTTPRoute + +HTTPRoute support is off by default. To attach TREK to an existing Gateway, enable it in your values file: + +```yaml +httpRoute: + enabled: true + annotations: {} + parentRefs: + - name: gateway + namespace: gateway-system + sectionName: https + hostnames: + - trek.example.com + paths: + - / + timeouts: + request: "0s" + backendRequest: "0s" +``` + +The cluster needs the Gateway API `HTTPRoute` v1 CRD and a compatible controller. The chart creates only an HTTPRoute to TREK's existing Service on `service.port`; your operator must provide the Gateway and GatewayClass, configure its listener and TLS certificate, and allow routes from the chart's namespace. When enabled, `parentRefs` and `paths` must be non-empty. Paths are string prefixes. Ingress and HTTPRoute may be enabled together. + +Timeout fields are Standard Channel in Gateway API v1.2, though controller support varies. If omitted, the controller's timeout defaults apply. `0s` disables that request timeout; controller idle and buffering limits can still affect `/ws` and streamed assistant responses. Set `env.ALLOWED_ORIGINS` and `env.APP_URL` to the public URL. If the Gateway terminates TLS, also set `env.FORCE_HTTPS: "true"` and `env.TRUST_PROXY: "1"`. + ## Upgrade The Deployment uses the `Recreate` update strategy (`updateStrategy: Recreate`): the old pod stops before the new one starts. TREK is a single-writer SQLite application, and during a rolling update the new pod would migrate the database while the old one still writes to it. A ReadWriteMany volume does not make that safe, so leave the strategy as it is and keep one replica.