Skip to main content

NodeRED GKE Module — Configuration Guide

Node-RED is a leading open-source flow-based programming tool designed for wiring together IoT devices, APIs, and online services through a browser-based visual editor. This module deploys Node-RED on GKE Autopilot with NFS-backed persistent flow storage, optional Redis context storage, and full Kubernetes reliability controls.

NodeRED GKE is a wrapper module built on top of App GKE. It delegates all GCP infrastructure provisioning to App GKE (GKE Autopilot cluster, networking, Cloud Storage, NFS, Secret Manager, CI/CD) and uses a NodeRED Common sub-module to supply Node-RED-specific application configuration. The NodeRED Common outputs feed into App GKE's application_config, module_storage_buckets, and scripts_dir inputs.

This guide documents variables that are unique to NodeRED GKE or that have Node-RED-specific defaults differing from the App GKE base module. For full documentation of variables with identical semantics, refer to the App_GKE Configuration Guide.


§1 · Module Overview

What NodeRED GKE provides

  • A Node-RED container (prebuilt nodered/node-red image from Docker Hub, enable_image_mirroring = true) deployed as a Kubernetes Deployment or StatefulSet, listening on port 1880.
  • NFS (Cloud Filestore) enabled by default (enable_nfs = true) and mounted at /data. Node-RED stores all persistent data in /data — flows, credentials, installed nodes, and settings.
  • Network tag nfsserver applied by default via network_tags to ensure GKE nodes have connectivity to the NFS server.
  • Session affinity set to "ClientIP" by default, ensuring the Node-RED editor UI is served consistently from the same pod during a browser session.
  • NODE_RED_CREDENTIAL_SECRET auto-generated by the Foundation Module and stored in Secret Manager. This secret encrypts Node-RED's stored credentials. Its length is controlled by database_password_length.
  • NODE_RED_ENABLE_SAFE_MODE = "false" always injected by NodeRED Common, ensuring flows execute on startup.
  • Optional Redis for Node-RED context storage (enable_redis = false by default).
  • No Cloud SQL is required or used. database_type defaults to "NONE".
  • A kubernetes_ready output gate controls all Kubernetes resource deployment; on first apply of a new inline cluster, resources are skipped and a second apply is required.

Key differences from App GKE defaults

FeatureApp GKE defaultNodeRED GKE default
container_port80801880
container_resources.cpu_limit"1000m""500m"
container_resources.memory_limit"512Mi""512Mi"
min_instance_count11
max_instance_count11
enable_nfsfalsetrue
nfs_mount_path"/mnt/nfs""/data"
enable_cloudsql_volumevariesfalse (unused)
enable_redisfalsefalse
session_affinity"None""ClientIP"
network_tags[]["nfsserver"]
Health probe path/healthz/
database_typevaries"NONE"
workload_type"Deployment""Deployment"

§2 · IAM & Project Identity

VariableDefaultDescription
project_id(required)GCP project into which all resources are deployed.
tenant_deployment_id"demo"Short suffix appended to resource names.
resource_creator_identity"rad-module-creator@tec-rad-ui-2b65.iam.gserviceaccount.com"Service account used by Terraform.
support_users[]Email addresses granted IAM access and added to monitoring alert channels.
resource_labels{}Labels applied to all module-managed resources.
module_description(Node-RED GKE description)Platform UI description.
module_documentation"https://docs.radmodules.dev/docs/modules/NodeRED_GKE"External documentation URL.
module_dependency["Services GCP"]Platform modules that must be deployed first.
module_services(GKE Autopilot, Filestore, GCS, etc.)GCP services used by this module.
credit_cost150Platform credits consumed on deployment.
require_credit_purchasesfalseEnforces credit balance check.
enable_purgetruePermits full resource deletion on destroy.
public_accesstrueVisibility to all platform users.
deployment_id""Optional fixed deployment ID. Auto-generated when blank.
region"us-central1"GCP region fallback when network auto-discovery cannot determine the region.

§3 · Core Service Configuration

§3.A · Application Identity

VariableDefaultDescription
application_name"nodered"Internal identifier. Used as the base name for GKE workloads, GCS buckets, Kubernetes namespace, and Artifact Registry. Do not change after initial deployment.
application_display_name"Node-RED"Human-readable name in the platform UI and monitoring dashboards.
application_description"Node-RED - Flow-based programming for IoT and event automation"Brief description populated into Kubernetes deployment annotations.
application_version"latest"Container image tag for nodered/node-red.
deploy_applicationtrueSet false to provision infrastructure without deploying the Kubernetes workload.

§3.B · Container & Scaling

NodeRED GKE uses the full container_resources object (as documented in App GKE). The top-level cpu_limit and memory_limit shorthand variables used by NodeRED CloudRun are not present — pass resource sizing via container_resources.

VariableDefaultDescription
container_image_source"prebuilt"Determines how the image is sourced. Use "prebuilt" to deploy nodered/node-red directly. "custom" activates container_build_config.
container_image"nodered/node-red:latest"Full image URI. Used when container_image_source = "prebuilt".
container_port1880TCP port Node-RED binds to inside the container.
container_resources{ cpu_limit = "500m", memory_limit = "512Mi" }CPU and memory resource limits. Node-RED is lightweight. Also accepts optional cpu_request, mem_request, ephemeral_storage_limit, ephemeral_storage_request.
container_build_config{ enabled = false }Cloud Build configuration when container_image_source = "custom".
min_instance_count1Minimum pod replicas. Must be ≥ 1 for GKE (no scale-to-zero).
max_instance_count1Maximum pod replicas. Keep at 1 unless using Redis-backed external context storage.
enable_image_mirroringtrueMirrors nodered/node-red from Docker Hub into Artifact Registry.
enable_pod_disruption_budgettrueCreates a PodDisruptionBudget to limit simultaneous pod unavailability during voluntary disruptions.
pdb_min_available"1"Minimum pods available during disruptions. Accepts an integer or percentage string (e.g. "50%").
termination_grace_period_seconds30Seconds Kubernetes waits after SIGTERM before forcibly terminating.
workload_type"Deployment"Kubernetes workload controller. Use "StatefulSet" for per-pod persistent storage — see §3.F.
enable_vertical_pod_autoscalingfalseEnables VPA to automatically adjust CPU and memory requests. Recommended for GKE Autopilot.
timeout_seconds300Maximum seconds the load balancer waits for a backend pod response.
container_protocol"http1"HTTP protocol version. Valid: "http1", "h2c".
enable_cloudsql_volumefalseNot used by Node-RED. Kept for API compatibility.
cloudsql_volume_mount_path"/cloudsql"Not used by Node-RED. Kept for API compatibility.
service_annotations{}Custom annotations applied to the Kubernetes Service resource.
service_labels{}Custom labels applied to the Kubernetes Service resource.

§3.C · Environment Variables & Secrets

The following variable is always injected automatically and must not be set manually:

  • NODE_RED_CREDENTIAL_SECRET — auto-generated by App GKE using database_password_length.

Do not set in environment_variables: NODE_RED_CREDENTIAL_SECRET.

VariableDefaultDescription
environment_variables{}Plain-text environment variables injected into the GKE pod. Use for Node-RED configuration such as NODE_RED_ENABLE_PROJECTS = "true".
secret_environment_variables{}Map of env var name → Secret Manager secret name.
secret_propagation_delay30Seconds to wait after secret creation before dependent operations proceed.
secret_rotation_period"2592000s"Secret Manager rotation notification period. Set null to disable.
enable_auto_password_rotationfalseAutomates credential secret rotation.
rotation_propagation_delay_sec90Seconds to wait after rotation before the application restarts.

§3.D · GKE Backend Configuration

VariableDefaultDescription
service_type"LoadBalancer"Kubernetes Service type. Use "LoadBalancer" for external access, "ClusterIP" for internal.
session_affinity"ClientIP"Defaults to "ClientIP" — ensures the Node-RED editor is consistently served from the same pod, which is required for the visual editor UI to function correctly.
namespace_name""Kubernetes namespace. Leave empty to auto-generate from application_name and tenant_deployment_id.
gke_cluster_name""Name of the GKE cluster. Leave empty to auto-discover.
gke_cluster_selection_mode"primary"Cluster selection strategy. Options: "explicit", "round-robin", "primary".
network_tags["nfsserver"]Network tags applied to GKE nodes. The "nfsserver" tag is required for NFS connectivity — do not remove it when enable_nfs = true.
enable_network_segmentationfalseCreates Kubernetes NetworkPolicy resources to restrict pod ingress and egress.
configure_service_meshfalseEnables Istio service mesh injection for the application namespace.
enable_multi_cluster_servicefalseEnables Multi-Cluster Services by creating a ServiceExport.
deployment_timeout1800Seconds Terraform waits for the Kubernetes rollout to complete.
prereq_gke_subnet_cidr"10.201.0.0/24"CIDR for inline GKE subnet. Must not overlap with existing subnets.

§3.E · Kubernetes Cluster Networking

VariableDefaultDescription
enable_custom_domainfalseProvisions a Kubernetes Ingress for custom domain routing and SSL termination.
application_domains[]Custom domain names for the Ingress. Only used when enable_custom_domain = true.
reserve_static_iptrueProvisions a global static external IP for the load balancer. Recommended for production.
static_ip_name""Name for the static IP. Auto-generated when empty.
network_name""VPC network name. Auto-discovered when empty.

§3.F · StatefulSet Configuration

When workload_type = "StatefulSet", the following variables configure per-pod persistent volumes. For most Node-RED deployments, the default Deployment with NFS-backed /data is sufficient.

VariableDefaultDescription
stateful_pvc_enabledfalseProvisions a PVC per pod. Only effective when workload_type = "StatefulSet".
stateful_pvc_size"10Gi"Storage size for each PVC.
stateful_pvc_mount_path"/data"Mount path for the per-pod PVC. Set to "/data" to back Node-RED's data directory with a PVC.
stateful_pvc_storage_class"standard-rwo"Kubernetes StorageClass. Use "premium-rwo" for higher IOPS.
stateful_headless_servicetrueCreates a headless Service for stable pod DNS names.
stateful_pod_management_policy"OrderedReady"Pod startup/shutdown order. "OrderedReady" starts pods sequentially.
stateful_update_strategy"RollingUpdate"Update strategy. "RollingUpdate" or "OnDelete".

§4 · Advanced Security

§4.A · Credential Secret Management

VariableDefaultDescription
database_password_length32Length of the auto-generated NODE_RED_CREDENTIAL_SECRET. Valid range: 16–64.
enable_auto_password_rotationfalseAutomates credential secret rotation.
rotation_propagation_delay_sec90Seconds to wait after rotation before restarting the application.
secret_rotation_period"2592000s"Secret Manager rotation notification period (30 days).
secret_propagation_delay30Seconds to wait after secret creation before proceeding.

§4.B · Identity-Aware Proxy (IAP)

GKE IAP requires OAuth client credentials, unlike Cloud Run IAP. All four IAP variables must be set when enabling IAP.

VariableDefaultDescription
enable_iapfalseEnables IAP authentication. Recommended for production deployments.
iap_authorized_users[]Individual users granted access. Format: "user:email@example.com".
iap_authorized_groups[]Google Groups granted access. Format: "group:name@example.com".
iap_oauth_client_id""OAuth 2.0 Client ID. Required when enable_iap = true. Sensitive.
iap_oauth_client_secret""OAuth 2.0 Client Secret. Required when enable_iap = true. Sensitive.
iap_support_email""Support email for the OAuth consent screen. Required when enable_iap = true.

Validation guard: When enable_iap = true, both iap_oauth_client_id and iap_oauth_client_secret must be provided. Without them, Terraform rejects the configuration.

§4.C · Cloud Armor

VariableDefaultDescription
enable_cloud_armorfalseEnables Cloud Armor WAF security policy.
admin_ip_ranges[]IP CIDR ranges for administrative access.
cloud_armor_policy_name"default-waf-policy"Cloud Armor security policy name. Only used when enable_cloud_armor = true.

§4.D · VPC Service Controls

VariableDefaultDescription
enable_vpc_scfalseEnables VPC-SC perimeter enforcement.
vpc_cidr_ranges[]VPC subnet CIDRs for the network access level. Auto-discovered when empty.
vpc_sc_dry_runtrueWhen true, violations are logged but not blocked. Set false to enforce.
organization_id""GCP Organization ID for Access Context Manager. Auto-discovered when empty.
enable_audit_loggingfalseEnables detailed Cloud Audit Logs.

§4.E · Binary Authorization

VariableDefaultDescription
enable_binary_authorizationfalseEnforces Binary Authorization on the GKE cluster.
binauthz_evaluation_mode"ALWAYS_ALLOW"Enforcement mode. Options: "ALWAYS_ALLOW", "REQUIRE_ATTESTATION", "ALWAYS_DENY".

§5 · Reliability

§5.A · Pod Disruption Budget

VariableDefaultDescription
enable_pod_disruption_budgettrueCreates a PodDisruptionBudget.
pdb_min_available"1"Minimum pods that must remain available during voluntary disruptions.

§5.B · Topology Spread Constraints

VariableDefaultDescription
enable_topology_spreadfalseAdds TopologySpreadConstraints to distribute pods across zones.
topology_spread_strictfalseWhen true, pods are rejected (DoNotSchedule) if spread constraints cannot be satisfied. When false, pods are placed anyway (ScheduleAnyway).

§5.C · Resource Quotas

VariableDefaultDescription
enable_resource_quotafalseCreates a Kubernetes ResourceQuota in the namespace.
quota_cpu_requests""Total CPU requests limit across all pods.
quota_cpu_limits""Total CPU limits across all pods.
quota_memory_requests""Total memory requests across all pods.
quota_memory_limits""Total memory limits across all pods.
quota_max_pods""Maximum pods in the namespace.
quota_max_services""Maximum Kubernetes Services in the namespace.
quota_max_pvcs""Maximum PVCs in the namespace.

§6 · CI/CD Integration

§6.A · GitHub & Cloud Build

VariableDefaultDescription
enable_cicd_triggerfalseCreates a Cloud Build trigger for automatic builds on code push.
github_repository_url""Full HTTPS URL of the GitHub repository. Required when enable_cicd_trigger = true.
github_token""GitHub PAT for repository authentication. Sensitive.
github_app_installation_id""Cloud Build GitHub App installation ID. Alternative to PAT.
cicd_trigger_config{ branch_pattern = "^main$" }Branch filter, included/ignored paths, trigger name, and substitutions.

§6.B · Cloud Deploy Pipelines

VariableDefaultDescription
enable_cloud_deployfalseSwitches to a Cloud Deploy pipeline with promotion stages. Requires enable_cicd_trigger = true.
cloud_deploy_stages[dev, staging, prod(approval)]Ordered promotion stages. Each stage supports name, target_name, namespace, cluster, project_id, region, require_approval, auto_promote.

§7 · Storage

VariableDefaultDescription
enable_nfstrueProvisions Cloud Filestore NFS and mounts it at nfs_mount_path. Node-RED stores all persistent data in /data — NFS is the recommended backend.
nfs_mount_path"/data"Container path for the NFS volume.
nfs_instance_name""Name of an existing NFS GCE VM. Auto-discovers or creates when empty.
nfs_instance_base_name"app-nfs"Base name for a newly created NFS GCE VM.

§7.B · Cloud Storage (GCS)

VariableDefaultDescription
create_cloud_storagetrueControls whether GCS buckets in storage_buckets are provisioned.
storage_buckets[{ name_suffix = "data" }]GCS buckets to provision. NodeRED Common adds a "nodered-storage" bucket via module_storage_buckets.
gcs_volumes[]GCS buckets mounted as filesystem volumes using the GCS Fuse CSI driver.
manage_storage_kms_iamfalseCreates a CMEK KMS keyring and enables CMEK on all storage buckets.
enable_artifact_registry_cmekfalseEnables CMEK for the Artifact Registry repository.
enable_cdnfalseEnables Cloud CDN on the GKE Ingress backend. Only applies when enable_custom_domain = true.

§7.C · Backup & Recovery

VariableDefaultDescription
backup_schedule"0 2 * * *"Cron expression (UTC) for the automated NFS backup job. Leave empty to disable.
backup_retention_days7Days to retain backup files.
enable_backup_importfalseTriggers a one-time restore job during deployment.
backup_source"gcs"Source: "gcs" or "gdrive".
backup_file"backup.tar"Filename of the backup to import. Must exist in the GCS backup bucket.
backup_format"tar"Format of the backup file. Options: sql, tar, gz, tgz, tar.gz, zip, auto.

§8 · Database (Compatibility Stubs)

Node-RED does not use a relational database. The following variables are present for API compatibility with App GKE and have no operational effect:

VariableDefaultDescription
database_type"NONE"No database. Do not change.
application_database_name"nodered"No-op. Kept for API compatibility.
application_database_user"nodered"No-op. Kept for API compatibility.
enable_cloudsql_volumefalseNo Cloud SQL Auth Proxy.
cloudsql_volume_mount_path"/cloudsql"No-op. Kept for API compatibility.
enable_postgres_extensionsfalseNo-op.
postgres_extensions[]No-op.
enable_mysql_pluginsfalseNo-op.
mysql_plugins[]No-op.
enable_custom_sql_scriptsfalseNo-op.
custom_sql_scripts_bucket""No-op.
custom_sql_scripts_path""No-op.
custom_sql_scripts_use_rootfalseNo-op.
sql_instance_name""No-op.
sql_instance_base_name"app-sql"No-op.

§9 · Redis (Context Storage)

VariableDefaultDescription
enable_redisfalseEnables Redis for Node-RED context storage. Injects REDIS_HOST and REDIS_PORT into the pod.
redis_host""Redis hostname or IP. Required when enable_redis = true (unless enable_nfs = true).
redis_port"6379"Redis TCP port (string).
redis_auth""Redis authentication password. Sensitive.

Validation guard: When enable_redis = true, either redis_host must be set or enable_nfs must be true (the NFS server IP is usable as a fallback Redis host). Otherwise Terraform rejects the configuration.


§10 · Observability & Health

§10.A · Health Probes

Node-RED responds to HTTP GET on / with the editor UI. Both probe types use this path. A 30-second initial delay is sufficient as Node-RED starts quickly.

VariableDefaultDescription
startup_probe_config{ enabled=true, type="HTTP", path="/", initial_delay_seconds=30, timeout_seconds=5, period_seconds=10, failure_threshold=3 }Kubernetes startup probe (passed directly to App GKE).
health_check_config{ enabled=true, type="HTTP", path="/", initial_delay_seconds=30, timeout_seconds=5, period_seconds=30, failure_threshold=3 }Kubernetes liveness probe (passed directly to App GKE).
uptime_check_config{ enabled=true, path="/", check_interval="60s", timeout="10s" }Cloud Monitoring uptime check.
alert_policies[]List of metric-threshold alert policies. Each entry requires name, metric_type, comparison, threshold_value, duration_seconds.

§10.B · Additional Services

VariableDefaultDescription
additional_services[]Supplementary Kubernetes Deployments deployed alongside Node-RED. Each entry defines its own image, port, resources, and probes.

§11 · Workload Automation

§11.A · Initialization Jobs

VariableDefaultDescription
initialization_jobs[]Kubernetes Jobs executed once during deployment. Node-RED requires no initialization jobs — use for custom flow imports or palette installations.

§11.B · CronJobs

VariableDefaultDescription
cron_jobs[]Recurring Kubernetes CronJobs. Supports name, schedule, image, command, args, env_vars, cpu_limit, memory_limit, restart_policy, concurrency_policy, suspend, mount_nfs, mount_gcs_volumes, script_path.

§12 · Platform-Managed Behaviours

The following are set automatically and cannot be overridden via input variables.

Environment Variables (always injected)

VariableValue / SourceNotes
NODE_RED_ENABLE_SAFE_MODE"false"Injected by NodeRED Common; ensures flows execute on startup.
NODE_RED_CREDENTIAL_SECRETSecret Manager ref (auto-generated)Generated by App GKE using database_password_length. Encrypts stored credentials.

Structural Wiring

BehaviourDetail
application_config{ nodered = module.nodered_app.config } — NodeRED Common config keyed as "nodered".
module_env_varsAlways {} — no additional Foundation-level env vars.
module_secret_env_varsAlways {} — no auto-generated secrets from NodeRED Common.
module_storage_bucketsmodule.nodered_app.storage_buckets — the "nodered-storage" GCS bucket.
scripts_dirabspath("${module.nodered_app.path}/scripts") — NodeRED Common's scripts/ directory.
Region resolutionRegion is auto-discovered via module.network_discovery before being passed to NodeRED Common as region.
Resource prefix"app${application_name}${tenant_deployment_id}${random_id}" — computed in main.tf locals.
container_image_sourceFrom var.container_image_source (default "prebuilt"); user-configurable.
database_type"NONE" in the NodeRED Common config output — always hardcoded.
Two-apply patternThe kubernetes_ready output is false on first apply of a new inline cluster. All Kubernetes resources are gated on this value. A second tofu apply is required to complete deployment.

Cross-Variable Validation Guards (validation.tf)

GuardConditionError
Instance countmin_instance_count <= max_instance_countConflicting HPA configuration.
Redis without host!enable_redis || redis_host != "" || enable_nfsREDIS_HOST would be empty and Node-RED would fail to connect.
IAP without credentials!enable_iap || (iap_oauth_client_id != "" && iap_oauth_client_secret != "")IAP silently disabled without credentials, leaving the application exposed.

§13 · Outputs

OutputDescription
service_urlThe Kubernetes Service URL or external load balancer IP for the deployed Node-RED instance.
kubernetes_readytrue when the GKE cluster endpoint is available and all Kubernetes resources are deployed. false on first apply of a new inline cluster — a second apply is required.

§14 · Variable Reference

Complete list of all input variables, grouped by UI section.

GroupVariableTypeDefaultUpdatable
0module_descriptionstring(long description)
0module_documentationstring"https://docs.radmodules.dev/docs/modules/NodeRED_GKE"
0module_dependencylist(string)["Services GCP"]
0module_serviceslist(string)(service list)
0credit_costnumber150
0require_credit_purchasesboolfalse
0enable_purgebooltrue
0public_accessbooltrue
0deployment_idstring""yes
0resource_creator_identitystring"rad-module-creator@…"yes
1project_idstring
1tenant_deployment_idstring"demo"yes
1support_userslist(string)[]yes
1resource_labelsmap(string){}yes
1regionstring"us-central1"yes
2application_namestring"nodered"yes
2application_display_namestring"Node-RED"yes
2application_descriptionstring"Node-RED - Flow-based programming…"yes
2application_versionstring"latest"yes
3deploy_applicationbooltrueyes
3container_image_sourcestring"prebuilt"yes
3container_imagestring"nodered/node-red:latest"yes
3container_portnumber1880yes
3container_resourcesobject{ cpu_limit = "500m", memory_limit = "512Mi" }yes
3container_build_configobject{ enabled = false }yes
3min_instance_countnumber1yes
3max_instance_countnumber1yes
3enable_image_mirroringbooltrueyes
3enable_cloudsql_volumeboolfalseyes
3cloudsql_volume_mount_pathstring"/cloudsql"yes
3service_annotationsmap(string){}yes
3service_labelsmap(string){}yes
3enable_vertical_pod_autoscalingboolfalseyes
3timeout_secondsnumber300yes
3container_protocolstring"http1"yes
4environment_variablesmap(string){}yes
4secret_environment_variablesmap(string){}yes
4secret_rotation_periodstring"2592000s"yes
4secret_propagation_delaynumber30yes
5service_typestring"LoadBalancer"yes
5workload_typestring"Deployment"yes
5session_affinitystring"ClientIP"yes
5namespace_namestring""yes
5gke_cluster_namestring""yes
5gke_cluster_selection_modestring"primary"yes
5enable_network_segmentationboolfalseyes
5configure_service_meshboolfalseyes
5enable_multi_cluster_serviceboolfalseyes
5termination_grace_period_secondsnumber30yes
5deployment_timeoutnumber1800yes
5prereq_gke_subnet_cidrstring"10.201.0.0/24"
6stateful_pvc_enabledboolfalseyes
6stateful_pvc_sizestring"10Gi"yes
6stateful_pvc_mount_pathstring"/data"yes
6stateful_pvc_storage_classstring"standard-rwo"yes
6stateful_headless_servicebooltrueyes
6stateful_pod_management_policystring"OrderedReady"yes
6stateful_update_strategystring"RollingUpdate"yes
7enable_resource_quotaboolfalseyes
7quota_cpu_requestsstring""yes
7quota_cpu_limitsstring""yes
7quota_memory_requestsstring""yes
7quota_memory_limitsstring""yes
7quota_max_podsstring""yes
7quota_max_servicesstring""yes
7quota_max_pvcsstring""yes
8enable_pod_disruption_budgetbooltrueyes
8pdb_min_availablestring"1"yes
8enable_topology_spreadboolfalseyes
8topology_spread_strictboolfalseyes
9startup_probe_configobject(HTTP /, 30s delay)yes
9health_check_configobject(HTTP /, 30s delay)yes
9uptime_check_configobject{ enabled = true, path = "/" }yes
9alert_policieslist(object)[]yes
10initialization_jobslist(object)[]yes
10cron_jobslist(object)[]yes
10additional_serviceslist(object)[]yes
11enable_cicd_triggerboolfalseyes
11github_repository_urlstring""yes
11github_tokenstring""yes
11github_app_installation_idstring""yes
11cicd_trigger_configobject{ branch_pattern = "^main$" }yes
11enable_cloud_deployboolfalseyes
11cloud_deploy_stageslist(object)[dev, staging, prod(approval)]yes
11enable_binary_authorizationboolfalseyes
11binauthz_evaluation_modestring"ALWAYS_ALLOW"yes
12enable_nfsbooltrueyes
12nfs_mount_pathstring"/data"yes
12nfs_instance_namestring""yes
12nfs_instance_base_namestring"app-nfs"yes
13create_cloud_storagebooltrueyes
13storage_bucketslist(object)[{ name_suffix = "data" }]yes
13gcs_volumeslist(object)[]yes
13manage_storage_kms_iamboolfalseyes
13enable_artifact_registry_cmekboolfalseyes
14enable_redisboolfalseyes
14redis_hoststring""yes
14redis_portstring"6379"yes
14redis_authstring""yes
15database_typestring"NONE"
15application_database_namestring"nodered"yes
15application_database_userstring"nodered"yes
15database_password_lengthnumber32yes
15enable_auto_password_rotationboolfalseyes
15rotation_propagation_delay_secnumber90yes
15enable_postgres_extensionsboolfalseyes
15postgres_extensionslist(string)[]yes
15enable_mysql_pluginsboolfalseyes
15mysql_pluginslist(string)[]yes
16backup_schedulestring"0 2 * * *"yes
16backup_retention_daysnumber7yes
16enable_backup_importboolfalseyes
16backup_sourcestring"gcs"yes
16backup_filestring"backup.tar"yes
16backup_formatstring"tar"yes
17enable_custom_sql_scriptsboolfalseyes
17custom_sql_scripts_bucketstring""yes
17custom_sql_scripts_pathstring""yes
17custom_sql_scripts_use_rootboolfalseyes
18enable_custom_domainboolfalseyes
18application_domainslist(string)[]yes
18reserve_static_ipbooltrueyes
18static_ip_namestring""yes
18network_tagslist(string)["nfsserver"]yes
18network_namestring""yes
19enable_iapboolfalseyes
19iap_authorized_userslist(string)[]yes
19iap_authorized_groupslist(string)[]yes
19iap_oauth_client_idstring""yes
19iap_oauth_client_secretstring""yes
19iap_support_emailstring""yes
20enable_cloud_armorboolfalseyes
20admin_ip_rangeslist(string)[]yes
20cloud_armor_policy_namestring"default-waf-policy"yes
20enable_cdnboolfalseyes
21enable_vpc_scboolfalseyes
21vpc_cidr_rangeslist(string)[]yes
21vpc_sc_dry_runbooltrueyes
21organization_idstring""yes
21enable_audit_loggingboolfalseyes

§15 · Configuration Examples

Basic Deployment

Deploys Node-RED on GKE using default settings. Suitable for evaluation and development.

# config/basic.tfvars
resource_creator_identity = ""
project_id = "my-project-123"
tenant_deployment_id = "basic"

Advanced Deployment

Production-grade deployment with Redis context storage, CI/CD, GKE reliability policies, and full observability.

# config/advanced.tfvars
resource_creator_identity = ""
project_id = "my-project-123"
tenant_deployment_id = "prod"

application_name = "nodered"
application_display_name = "Node-RED"
application_version = "4.0.9"

# Scaling & Performance
container_resources = {
cpu_limit = "1000m"
memory_limit = "1Gi"
cpu_request = "500m"
mem_request = "512Mi"
}
min_instance_count = 1
max_instance_count = 1

# Redis context storage
enable_redis = true
redis_host = "10.0.0.5"
redis_port = "6379"

# GKE specific
enable_resource_quota = true
enable_pod_disruption_budget = true
enable_network_segmentation = true
enable_vertical_pod_autoscaling = true

# CI/CD & Cloud Deploy
enable_cicd_trigger = true
enable_cloud_deploy = true
cloud_deploy_stages = [
{ name = "dev", require_approval = false, auto_promote = false },
{ name = "staging", require_approval = false, auto_promote = false },
{ name = "prod", require_approval = true, auto_promote = false },
]

# Security
enable_iap = true
iap_oauth_client_id = "123456789-abc.apps.googleusercontent.com"
iap_oauth_client_secret = "GOCSPX-…"
iap_support_email = "admin@example.com"
enable_binary_authorization = true
enable_cloud_armor = true

# Backup
backup_schedule = "0 2 * * *"
backup_retention_days = 14

# Observability
uptime_check_config = {
enabled = true
path = "/"
check_interval = "60s"
timeout = "10s"
}

alert_policies = [
{
name = "high-cpu"
metric_type = "kubernetes.io/container/cpu/usage_time"
comparison = "COMPARISON_GT"
threshold_value = 800
duration_seconds = 300
aggregation_period = "60s"
}
]

StatefulSet Deployment

Deploys Node-RED as a StatefulSet with a PVC for per-pod local data storage.

# config/custom.tfvars
resource_creator_identity = ""
project_id = "my-project-123"
tenant_deployment_id = "stateful"

application_name = "nodered"

# StatefulSet
workload_type = "StatefulSet"
min_instance_count = 1
max_instance_count = 1

# StatefulSet PVC (backs /data with a persistent disk)
stateful_pvc_enabled = true
stateful_pvc_size = "20Gi"
stateful_pvc_mount_path = "/data"
stateful_pvc_storage_class = "standard-rwo"

# StatefulSet behaviour
stateful_headless_service = true
stateful_pod_management_policy = "OrderedReady"
stateful_update_strategy = "RollingUpdate"

# Custom environment configuration
environment_variables = {
NODE_RED_ENABLE_PROJECTS = "true"
NODE_OPTIONS = "--max-old-space-size=512"
}

Configuration Pitfalls & Sensible Defaults

Risk levels: Critical (data loss, full outage, security breach) — High (service unavailable or significant degradation) — Medium (degraded function or increased cost) — Low (minor impact).

VariableSensible DefaultRiskConsequence of Incorrect Value
NODE_RED_CREDENTIAL_SECRET (auto-generated, length from database_password_length)Auto-generated random string stored in Secret ManagerCriticalEncrypts all flow credentials at rest. Changing or rotating this key after flows are deployed renders all stored credentials unreadable — every API key, password, and token in every flow must be manually re-entered.
enable_auto_password_rotation (if supported)falseCriticalAutomatic rotation of NODE_RED_CREDENTIAL_SECRET changes the encryption key, making all existing flow credentials permanently inaccessible. Only enable with a credential re-encryption procedure in place.
database_password_length32MediumControls the length of NODE_RED_CREDENTIAL_SECRET. Valid range: 16–64. The GKE validation guard blocks values outside this range.
enable_nfstrueCriticalNode-RED stores all flow definitions, credentials (flows_cred.json), and installed nodes in /data. Without NFS persistent storage, every pod restart, rescheduling, or Kubernetes node upgrade erases all flows and credentials.
nfs_mount_path"/mnt/nfs"HighThe /data directory must point to the NFS mount. Changing this path without updating Node-RED's settings file causes flows to be written to ephemeral pod storage.
application_name"nodered"CriticalImmutable after first deploy. Changing it renames all GCP and Kubernetes resources, causing full recreation. The NFS instance is disconnected from the new deployment.
min_instance_count1 (GKE default)HighGKE does not support true scale-to-zero without KEDA. The HPA validation guard rejects min > max. Unlike Cloud Run, scale-to-zero in GKE leaves the pod in a pending/terminated state rather than cleanly scaling.
max_instance_count1HighNode-RED is not designed for active-active horizontal scaling — flow context and state are per-instance. Increasing above 1 without stateful_pvc_enabled = true or a shared NFS /data mount causes each pod to have isolated, potentially conflicting flow state.
workload_typenull (defaults to Deployment)HighFor Node-RED with persistent /data, a StatefulSet with a PVC provides stronger pod-to-storage binding than a Deployment with NFS. Setting stateful_pvc_enabled = true without explicit workload_type automatically resolves to StatefulSet.
stateful_pvc_enabledfalseMediumA PVC-backed StatefulSet is safer than NFS for single-replica Node-RED — it guarantees the same pod always mounts the same storage. However, PVC size is immutable after creation.
quota_memory_requests / quota_memory_limits"" (not enforced)HighMust use binary suffixes ("1Gi", "2048Mi"). Bare integers are treated as bytes by Kubernetes and block all pod scheduling.
database_type"NONE"HighNode-RED has no database dependency. Setting this to POSTGRES or MYSQL provisions an unnecessary Cloud SQL sidecar. The GKE validation guard blocks enable_cloudsql_volume = true when database_type = "NONE".
enable_cloudsql_volumefalseHighSetting true with database_type = "NONE" is blocked at plan time by the GKE validation guard with the message: "enable_cloudsql_volume should not be true when database_type is 'NONE'."
environment_variables{}MediumDo not override NODE_RED_ENABLE_SAFE_MODE = "true" in production — safe mode disables all flows. Do not set NODE_RED_CREDENTIAL_SECRET here; it is managed by the Foundation Module.
session_affinity"ClientIP"MediumNode-RED's editor uses WebSocket connections for the flow deployment UI. Disabling affinity causes editor disconnections and "deploy failed" errors when subsequent requests route to a different pod.
enable_pod_disruption_budgettrueMediumDisabling PDB allows GKE to evict the Node-RED pod during node maintenance, causing a complete service outage and potential flow data loss if the NFS write was in progress.
termination_grace_period_seconds30MediumNode-RED needs time to finish processing in-flight messages before shutdown. Values below 15 may truncate message processing in active flows.
enable_iapfalseHighEnabling IAP without both iap_oauth_client_id and iap_oauth_client_secret is blocked at plan time by the GKE validation guard.
enable_topology_spreadfalseLowWith max_instance_count = 1, topology spread has no effect. Only relevant if multiple replicas are deployed (not recommended for Node-RED).