Say where the string coercion has to happen
A ConfigMap's data values must be strings and this template cannot enforce it: kustomize re-serialises before Flux substitutes, stripping quotes and !!str alike, so a value that looks numeric or boolean parses as one and the apply fails on the type. The quotes have to be inside the substituted value. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,7 @@ The namespace must exist first, and so must the AppRole Secret the store reads.
|
|||||||
| `N8N_IMAGE`, `POSTGRES_IMAGE` | pinned images, tag included |
|
| `N8N_IMAGE`, `POSTGRES_IMAGE` | pinned images, tag included |
|
||||||
| `N8N_STORAGE`, `POSTGRES_STORAGE` | claim sizes, e.g. `2Gi`, `5Gi` |
|
| `N8N_STORAGE`, `POSTGRES_STORAGE` | claim sizes, e.g. `2Gi`, `5Gi` |
|
||||||
| `TIMEZONE` | e.g. `Europe/Paris`; drives cron triggers |
|
| `TIMEZONE` | e.g. `Europe/Paris`; drives cron triggers |
|
||||||
|
| `EXECUTIONS_MAX_AGE_HOURS`, `BLOCK_ENV_ACCESS` | **quote these inside the value**: `'"336"'`, `'"false"'`. They land in a ConfigMap, whose values must be strings, and the template cannot force it — kustomize strips quotes and `!!str` alike before substitution runs |
|
||||||
| `INGRESS_CLASS`, `INGRESS_BODY_SIZE` | e.g. `nginx`, `"50m"` |
|
| `INGRESS_CLASS`, `INGRESS_BODY_SIZE` | e.g. `nginx`, `"50m"` |
|
||||||
| `N8N_WEBHOOK_AUTH_URL` | an endpoint that answers 2xx for an authorised caller and 401/403 otherwise. **Required** — n8n's trigger endpoints carry no authentication of their own, so without this anyone who can reach the host can run any workflow. An OIDC provider's `userinfo` works as-is |
|
| `N8N_WEBHOOK_AUTH_URL` | an endpoint that answers 2xx for an authorised caller and 401/403 otherwise. **Required** — n8n's trigger endpoints carry no authentication of their own, so without this anyone who can reach the host can run any workflow. An OIDC provider's `userinfo` works as-is |
|
||||||
| `TLS_ISSUER_NAME`, `TLS_ISSUER_KIND` | a cert-manager issuer, e.g. `ClusterIssuer` |
|
| `TLS_ISSUER_NAME`, `TLS_ISSUER_KIND` | a cert-manager issuer, e.g. `ClusterIssuer` |
|
||||||
|
|||||||
+16
-9
@@ -1,7 +1,14 @@
|
|||||||
# Every substituted value is quoted. A ConfigMap's data values must be strings,
|
# A ConfigMap's data values must be **strings**, and this file cannot enforce
|
||||||
# and an unquoted ${VAR} that resolves to a number or a boolean becomes one in
|
# that: kustomize re-serialises before Flux substitutes, stripping both quotes
|
||||||
# YAML — the apply then fails on the type, naming a field the operator never
|
# and an `!!str` tag, so `${VAR}` is always bare by the time a value lands in it.
|
||||||
# wrote a type for.
|
# A value that then looks like a number or a boolean parses as one and the apply
|
||||||
|
# fails on the type.
|
||||||
|
#
|
||||||
|
# So any value substituted here that is not obviously text must carry its own
|
||||||
|
# quotes in the substitution map:
|
||||||
|
#
|
||||||
|
# EXECUTIONS_MAX_AGE_HOURS: '"336"'
|
||||||
|
# BLOCK_ENV_ACCESS: '"false"'
|
||||||
#
|
#
|
||||||
# Nothing here is sensitive. The two values that are — the database password and
|
# Nothing here is sensitive. The two values that are — the database password and
|
||||||
# the credential encryption key — arrive through n8n-secrets.
|
# the credential encryption key — arrive through n8n-secrets.
|
||||||
@@ -11,15 +18,15 @@ metadata:
|
|||||||
name: n8n-config
|
name: n8n-config
|
||||||
namespace: ${NAMESPACE}
|
namespace: ${NAMESPACE}
|
||||||
data:
|
data:
|
||||||
GENERIC_TIMEZONE: "${TIMEZONE}"
|
GENERIC_TIMEZONE: ${TIMEZONE}
|
||||||
TZ: "${TIMEZONE}"
|
TZ: ${TIMEZONE}
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
|
|
||||||
# What n8n believes it is reachable at. It goes into the webhook URLs it
|
# What n8n believes it is reachable at. It goes into the webhook URLs it
|
||||||
# generates and into the links it puts in its own UI, so it must be the
|
# generates and into the links it puts in its own UI, so it must be the
|
||||||
# ingress host and not the Service — a webhook advertised as `n8n` inside the
|
# ingress host and not the Service — a webhook advertised as `n8n` inside the
|
||||||
# cluster is a webhook nothing outside can call.
|
# cluster is a webhook nothing outside can call.
|
||||||
N8N_HOST: "${N8N_HOSTNAME}"
|
N8N_HOST: ${N8N_HOSTNAME}
|
||||||
N8N_PORT: "5678"
|
N8N_PORT: "5678"
|
||||||
N8N_PROTOCOL: https
|
N8N_PROTOCOL: https
|
||||||
WEBHOOK_URL: https://${N8N_HOSTNAME}/
|
WEBHOOK_URL: https://${N8N_HOSTNAME}/
|
||||||
@@ -33,7 +40,7 @@ data:
|
|||||||
# The default is to keep every execution for ever, which turns the database
|
# The default is to keep every execution for ever, which turns the database
|
||||||
# into a log. Two weeks is long enough to debug a failed run.
|
# into a log. Two weeks is long enough to debug a failed run.
|
||||||
EXECUTIONS_DATA_PRUNE: "true"
|
EXECUTIONS_DATA_PRUNE: "true"
|
||||||
EXECUTIONS_DATA_MAX_AGE: "${EXECUTIONS_MAX_AGE_HOURS}"
|
EXECUTIONS_DATA_MAX_AGE: ${EXECUTIONS_MAX_AGE_HOURS}
|
||||||
N8N_DIAGNOSTICS_ENABLED: "false"
|
N8N_DIAGNOSTICS_ENABLED: "false"
|
||||||
N8N_VERSION_NOTIFICATIONS_ENABLED: "false"
|
N8N_VERSION_NOTIFICATIONS_ENABLED: "false"
|
||||||
N8N_RUNNERS_ENABLED: "true"
|
N8N_RUNNERS_ENABLED: "true"
|
||||||
@@ -42,4 +49,4 @@ data:
|
|||||||
# workflow without being stored in the workflow JSON. n8n blocks it by
|
# workflow without being stored in the workflow JSON. n8n blocks it by
|
||||||
# default, and that default is right wherever more than one team can write a
|
# default, and that default is right wherever more than one team can write a
|
||||||
# workflow: any workflow can then read any variable in the pod.
|
# workflow: any workflow can then read any variable in the pod.
|
||||||
N8N_BLOCK_ENV_ACCESS_IN_NODE: "${BLOCK_ENV_ACCESS}"
|
N8N_BLOCK_ENV_ACCESS_IN_NODE: ${BLOCK_ENV_ACCESS}
|
||||||
Reference in New Issue
Block a user