NodeRED CloudRun 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 Google Cloud Run Gen2 with NFS-backed persistent flow storage and optional Redis context storage.
NodeRED CloudRun is a wrapper module built on top of App CloudRun. It delegates all GCP infrastructure provisioning to App CloudRun (Cloud Run service, networking, Secret Manager, GCS, NFS, CI/CD) and uses a NodeRED Common sub-module to supply Node-RED-specific application configuration. The NodeRED Common outputs feed into App CloudRun's application_config, module_storage_buckets, and scripts_dir inputs.
This guide documents variables that are unique to NodeRED CloudRun or that have Node-RED-specific defaults differing from the App CloudRun base module. For full documentation of variables with identical semantics, refer to the
App_CloudRun Configuration Guide.
§1 · Module Overview
What NodeRED CloudRun provides
- A Node-RED container (prebuilt
nodered/node-red image from Docker Hub, enable_image_mirroring = true) deployed on Cloud Run Gen2, 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. NFS is the recommended backend as it survives container restarts and new deployments.
NODE_RED_CREDENTIAL_SECRET auto-generated by the Foundation Module and stored in Secret Manager. This secret encrypts Node-RED's stored credentials (passwords in flows). Its length is controlled by database_password_length.
NODE_RED_ENABLE_SAFE_MODE = "false" always injected, ensuring flows execute on startup.
- Optional Redis for Node-RED context storage (
enable_redis = false by default). When enabled, Redis allows context data to persist across restarts and be shared between instances.
- Scale-to-zero support (
min_instance_count = 0). Because Node-RED flows are stateful, max_instance_count defaults to 1 — increase only if using Redis-backed external context storage.
- No Cloud SQL is required or used.
enable_cloudsql_volume defaults to false.
Key differences from App CloudRun defaults
| Feature | App CloudRun default | NodeRED CloudRun default |
|---|
container_port | 8080 | 1880 |
cpu_limit | "1000m" | "1000m" |
memory_limit | "512Mi" | "1Gi" |
min_instance_count | 0 | 0 |
max_instance_count | 1 | 1 |
enable_nfs | false | true |
nfs_mount_path | "/mnt/nfs" | "/data" |
enable_cloudsql_volume | false | false (unused) |
enable_redis | false | false |
enable_image_mirroring | true | true |
| Health probe path | /healthz | / |
| Database backend | varies | none ("NONE") |
§2 · IAM & Project Identity
| Variable | Default | Description |
|---|
project_id | (required) | GCP project into which all resources are deployed. |
tenant_deployment_id | "demo" | Short suffix appended to resource names to allow multiple deployments in the same project. |
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 Cloud Run description) | Platform UI description. |
module_documentation | "https://docs.radmodules.dev/docs/modules/NodeRED_CloudRun" | External documentation URL. |
module_dependency | ["Services GCP"] | Platform modules that must be deployed first. |
module_services | (Cloud Run, NFS, GCS, etc.) | GCP services used by this module. |
credit_cost | 50 | Platform credits consumed on deployment. |
require_credit_purchases | false | Enforces credit balance check. |
enable_purge | true | Permits full resource deletion on destroy. |
public_access | true | Visibility to all platform users. |
deployment_id | "" | Optional fixed deployment ID. Auto-generated when blank. |
§3 · Core Service Configuration
§3.A · Application Identity
| Variable | Default | Description |
|---|
application_name | "nodered" | Base name for the Cloud Run service, Artifact Registry repo, Secret Manager secrets, and GCS buckets. Do not change after initial deployment — changing it forces resource recreation. |
display_name | "Node-RED" | Human-readable name in the platform UI and Cloud Run console. |
application_version | "latest" | Container image version tag. Maps to the nodered/node-red Docker Hub tag (e.g. "4.0.9", "3.1.14", "latest"). |
§3.B · Resource Sizing & Runtime
| Variable | Default | Description |
|---|
deploy_application | true | Set false to provision infrastructure without deploying the container. |
cpu_limit | "1000m" | CPU limit per container instance. Node-RED is lightweight; 1 vCPU is sufficient for most deployments. |
memory_limit | "1Gi" | Memory limit per container instance. Node-RED requires a minimum of 256Mi; 512Mi–1Gi is recommended. |
min_instance_count | 0 | Minimum live instances. 0 enables scale-to-zero. Set to 1 to keep Node-RED always warm and avoid cold-start delays. |
max_instance_count | 1 | Maximum concurrent instances. Keep at 1 unless flows are stateless or Redis-backed context storage is in use. |
execution_environment | "gen2" | Cloud Run generation. Must be "gen2" for NFS volume mounts to function. |
timeout_seconds | 300 | Maximum request duration before a 504 is returned. |
cpu_always_allocated | false | When false, CPU is throttled when Node-RED is idle — reducing cost. Set true only if background tasks require continuous CPU. |
enable_image_mirroring | true | Mirrors nodered/node-red into Artifact Registry to avoid Docker Hub rate limits. |
traffic_split | [] | Allocates traffic across Cloud Run revisions for canary/blue-green deployments. All entries must sum to 100. |
max_revisions_to_retain | 7 | Maximum Cloud Run revisions kept after each deployment. Set to 0 to disable pruning. |
container_protocol | "http1" | HTTP protocol version. Valid values: "http1", "h2c". |
service_annotations | {} | Custom annotations applied to the Cloud Run service resource. |
service_labels | {} | Custom labels applied to the Cloud Run service resource. |
§3.C · Environment Variables & Secrets
The following variable is always injected automatically and must not be set manually in environment_variables:
NODE_RED_CREDENTIAL_SECRET — auto-generated by App CloudRun using database_password_length.
Do not set in environment_variables: NODE_RED_CREDENTIAL_SECRET.
| Variable | Default | Description |
|---|
environment_variables | {} | Plain-text key/value pairs injected into the Cloud Run revision. Use for Node-RED configuration such as NODE_RED_ENABLE_PROJECTS = "true" or NODE_OPTIONS = "--max-old-space-size=256". |
secret_environment_variables | {} | Map of env var name → Secret Manager secret name. Resolved at runtime; plaintext never stored in Terraform state. |
secret_propagation_delay | 30 | Seconds to wait after secret creation before dependent operations proceed. |
secret_rotation_period | "2592000s" | Rotation notification period (30 days). Set null to disable. Must use "Ns" format. |
§3.D · Networking
| Variable | Default | Description |
|---|
ingress_settings | "all" | Controls which traffic sources can reach the Cloud Run service. "all" for public internet, "internal" for VPC-only, or "internal-and-cloud-load-balancing". |
vpc_egress_setting | "PRIVATE_RANGES_ONLY" | Routes only RFC 1918 traffic via VPC. Set "ALL_TRAFFIC" for strict egress control or on-premises connectivity. |
cloudsql_volume_mount_path | "/cloudsql" | Not used by Node-RED. Kept for API compatibility. |
container_protocol | "http1" | HTTP protocol version. |
IAP and Node-RED: Enabling enable_iap = true adds Google identity authentication in front of the Cloud Run URL. This is recommended for production — the Node-RED editor exposes full flow editing and credential management and should not be left publicly accessible without authentication.
§3.E · Initialization & Bootstrap
| Variable | Default | Description |
|---|
initialization_jobs | [] | Cloud Run jobs executed once during deployment. Node-RED requires no initialization jobs — use for custom flow imports or palette installations. |
cron_jobs | [] | Recurring Cloud Run jobs triggered by Cloud Scheduler. Use for periodic flow exports or maintenance tasks. |
§4 · Advanced Security
§4.A · Credential Secret Management
NODE_RED_CREDENTIAL_SECRET is auto-generated by App CloudRun using a random password of database_password_length characters. This secret encrypts all credentials stored in Node-RED flows (passwords, API keys). Back up this secret value before destroying the module — flows with encrypted credentials cannot be restored without the original key.
| Variable | Default | Description |
|---|
database_password_length | 32 | Length of the auto-generated NODE_RED_CREDENTIAL_SECRET. Valid range: 16–64. |
enable_auto_password_rotation | false | Automates credential secret rotation via Cloud Run + Eventarc. |
rotation_propagation_delay_sec | 90 | Seconds to wait after rotation before Cloud Run restarts to pick up the new value. |
secret_rotation_period | "2592000s" | Duration between Secret Manager rotation notifications (30 days). |
secret_propagation_delay | 30 | Seconds to wait after secret creation before dependent operations proceed. |
§4.B · Identity-Aware Proxy (IAP)
| Variable | Default | Description |
|---|
enable_iap | false | Enables Cloud Run native IAP. Recommended for production Node-RED deployments to prevent unauthorised flow access. |
iap_authorized_users | [] | Individual users or service accounts. Format: "user:email@example.com". |
iap_authorized_groups | [] | Google Groups. Format: "group:name@example.com". |
§4.C · Cloud Armor & CDN
| Variable | Default | Description |
|---|
enable_cloud_armor | false | Enables Cloud Armor WAF + Global HTTPS Load Balancer. When enabled, configure application_domains. |
application_domains | [] | Custom domain names. Google-managed SSL certificates provisioned automatically. DNS must resolve before cert provisioning. |
enable_cdn | false | Enables Cloud CDN. Only active when enable_cloud_armor = true. |
admin_ip_ranges | [] | CIDR ranges for administrative access bypass. |
§4.D · VPC Service Controls
| Variable | Default | Description |
|---|
enable_vpc_sc | false | Restricts GCP API access to a VPC-SC perimeter. |
vpc_cidr_ranges | [] | VPC subnet CIDR ranges for the network access level. Auto-discovered when empty. |
vpc_sc_dry_run | true | When 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_logging | false | Enables detailed Cloud Audit Logs. |
§4.E · Binary Authorization
| Variable | Default | Description |
|---|
enable_binary_authorization | false | Enforces Binary Authorization attestation policy. Requires a policy and attestor pre-configured in the project. |
§5 · Traffic & Ingress
§5.A · Ingress Controls
| Variable | Default | Options | Description |
|---|
ingress_settings | "all" | all / internal / internal-and-cloud-load-balancing | Controls which traffic sources reach the service. |
vpc_egress_setting | "PRIVATE_RANGES_ONLY" | ALL_TRAFFIC / PRIVATE_RANGES_ONLY | Controls VPC routing for outbound traffic. |
§5.B · Traffic Management
| Variable | Default | Description |
|---|
traffic_split | [] | Allocates traffic across Cloud Run revisions. All entries must sum to exactly 100. Each entry requires type and percent; revision is required when type = "TRAFFIC_TARGET_ALLOCATION_TYPE_REVISION". |
max_revisions_to_retain | 7 | Maximum number of Cloud Run revisions to keep after deployment. 0–100. |
§6 · CI/CD Integration
§6.A · GitHub & Cloud Build
Node-RED uses the prebuilt Docker Hub image (enable_image_mirroring = true). No custom Dockerfile build is required unless extending the base image.
| Variable | Default | Description |
|---|
enable_cicd_trigger | false | Creates a Cloud Build trigger that builds and deploys on push to the configured branch. |
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 for organisation repositories. |
cicd_trigger_config | { branch_pattern = "^main$" } | Controls branch filter, included/ignored paths, trigger name, and build substitutions. |
§6.B · Cloud Deploy Pipelines
| Variable | Default | Description |
|---|
enable_cloud_deploy | false | Switches to a Cloud Deploy pipeline with defined promotion stages. Requires enable_cicd_trigger = true. |
cloud_deploy_stages | [dev, staging, prod(approval)] | Ordered promotion stages with optional manual approval gates. |
§7 · Reliability & Data
§7.A · Health Probes
Node-RED responds to HTTP GET on / with the editor UI. This path is used for both startup and liveness probes. A 30-second initial delay is sufficient as Node-RED starts quickly.
| Variable | Default | Description |
|---|
startup_probe | { enabled=true, type="HTTP", path="/", initial_delay_seconds=30, timeout_seconds=5, period_seconds=10, failure_threshold=3 } | Startup probe. Checks the Node-RED editor UI path. |
liveness_probe | { enabled=true, type="HTTP", path="/", initial_delay_seconds=30, timeout_seconds=5, period_seconds=30, failure_threshold=3 } | Liveness probe. Restarts the container if the editor is unresponsive. |
uptime_check_config | { enabled=true, path="/", check_interval="60s", timeout="10s" } | Cloud Monitoring uptime check from global locations. |
alert_policies | [] | List of metric-threshold alert policies. Each entry requires name, metric_type, comparison, threshold_value, duration_seconds. |
§7.B · Storage (NFS & GCS)
| Variable | Default | Description |
|---|
enable_nfs | true | Provisions a Cloud Filestore NFS instance and mounts it at nfs_mount_path. Node-RED stores all persistent data (flows, credentials, installed nodes) in /data — NFS is the recommended backend. Requires execution_environment = "gen2". |
nfs_mount_path | "/data" | Container path for the NFS volume. Must match Node-RED's data directory. |
nfs_instance_name | "" | Name of an existing NFS GCE VM. Leave empty to auto-discover or create a new one. |
nfs_instance_base_name | "app-nfs" | Base name for the inline NFS GCE VM when creating a new instance. |
create_cloud_storage | true | Controls whether the module provisions the GCS buckets in storage_buckets. |
storage_buckets | [{ name_suffix = "data" }] | GCS buckets to provision. The NodeRED Common sub-module adds a "nodered-storage" bucket via module_storage_buckets. |
gcs_volumes | [] | GCS buckets mounted as GCS Fuse volumes inside the container. Requires execution_environment = "gen2". |
manage_storage_kms_iam | false | Creates a CMEK KMS keyring and enables CMEK encryption on all storage buckets. |
enable_artifact_registry_cmek | false | Enables CMEK encryption for the Artifact Registry repository. |
§7.C · Backup & Recovery
| Variable | Default | Description |
|---|
backup_schedule | "0 2 * * *" | Cron expression (UTC) for the automated NFS backup job. Leave empty to disable. |
backup_retention_days | 7 | Days to retain backup files in GCS before automatic deletion. |
enable_backup_import | false | Triggers a one-time restore job during deployment. Configure backup_source and backup_uri first. |
backup_source | "gcs" | Source for backup import: "gcs" (full GCS URI) or "gdrive" (Google Drive file). |
backup_uri | "" | Full GCS URI of the backup file (e.g. "gs://my-bucket/backups/nodered.tar"). Mapped to backup_file in App CloudRun. |
backup_format | "tar" | Format of the backup file. Accepted: tar, gz, sql, etc. |
§8 · Integrations
§8.A · Redis (Context Storage)
Redis allows Node-RED to store flow context data externally, enabling it to persist across restarts and (optionally) be shared between multiple instances. When enable_redis = true and redis_host = "", configure redis_host explicitly to point at a Redis or Cloud Memorystore instance. Unlike N8N, there is no automatic NFS-server-IP fallback for redis_host — the validation guard (validation.tf) enforces that at least one of redis_host or enable_nfs is set when enable_redis = true.
| Variable | Default | Description |
|---|
enable_redis | false | Enables Redis for Node-RED context storage. Injects REDIS_HOST and REDIS_PORT into the container. |
redis_host | "" | Redis hostname or IP address. Required when enable_redis = true (unless enable_nfs = true). |
redis_port | "6379" | Redis TCP port (string). |
redis_auth | "" | Redis authentication password. Sensitive. Leave empty if authentication is not configured. |
§8.B · Custom SQL (Unused)
Node-RED has no relational database. These variables are exposed for API compatibility with App CloudRun and have no effect:
| Variable | Default | Description |
|---|
enable_custom_sql_scripts | false | No-op for Node-RED. |
custom_sql_scripts_bucket | "" | No-op for Node-RED. |
custom_sql_scripts_path | "" | No-op for Node-RED. |
custom_sql_scripts_use_root | false | No-op for Node-RED. |
§8.C · Artifact Registry Image Management
| Variable | Default | Description |
|---|
max_images_to_retain | 7 | Maximum number of recent container images to keep in Artifact Registry. 0 disables. |
delete_untagged_images | true | Automatically deletes untagged container images. |
image_retention_days | 30 | Days after which images are eligible for age-based deletion. 0 disables. |
§8.D · Observability
| Variable | Default | Description |
|---|
uptime_check_config | { enabled = true, path = "/" } | Cloud Monitoring uptime check configuration. |
alert_policies | [] | List of metric-threshold alert policies. |
service_annotations | {} | Annotations applied to the Cloud Run service resource. |
service_labels | {} | Labels applied to the Cloud Run service. |
The following are set automatically and cannot be overridden via input variables.
Environment Variables (always injected)
| Variable | Value / Source | Notes |
|---|
NODE_RED_ENABLE_SAFE_MODE | "false" | Injected by NodeRED Common; ensures flows execute on startup. Override to "true" in environment_variables if needed. |
NODE_RED_CREDENTIAL_SECRET | Secret Manager ref (auto-generated) | Generated by App CloudRun using database_password_length. Encrypts stored credentials. |
Structural Wiring
| Behaviour | Detail |
|---|
container_image_source | Always "prebuilt" — forced in main.tf, not user-configurable. |
container_build_config | Always { enabled = false } — forced in main.tf. |
application_config | { nodered = module.nodered_app.config } — the NodeRED Common config object keyed as "nodered". |
module_env_vars | Always {} — no additional Foundation-level env vars injected. |
module_secret_env_vars | Always {} — no auto-generated secrets from NodeRED Common. |
module_storage_buckets | module.nodered_app.storage_buckets — the "nodered-storage" GCS bucket defined in NodeRED Common. |
scripts_dir | abspath("${module.nodered_app.path}/scripts") — resolves to NodeRED Common's scripts/ directory. |
backup_file mapping | var.backup_uri is mapped to backup_file in App CloudRun. |
enable_cloudsql_volume | Always false in the NodeRED Common config. User-exposed variable is kept for API compatibility. |
| Import blocks | Disabled (imports.tf contains only a comment). Idempotency is maintained via preserved Terraform state between CI runs. |
§10 · Variable Reference
Complete list of all input variables, grouped by UI section.
| Group | Variable | Type | Default | Updatable |
|---|
| 0 | module_description | string | (long description) | — |
| 0 | module_documentation | string | "https://docs.radmodules.dev/docs/modules/NodeRED_CloudRun" | — |
| 0 | module_dependency | list(string) | ["Services GCP"] | — |
| 0 | module_services | list(string) | (service list) | — |
| 0 | credit_cost | number | 50 | — |
| 0 | require_credit_purchases | bool | false | — |
| 0 | enable_purge | bool | true | — |
| 0 | public_access | bool | true | — |
| 0 | deployment_id | string | "" | yes |
| 0 | resource_creator_identity | string | "rad-module-creator@…" | yes |
| 1 | project_id | string | — | — |
| 1 | tenant_deployment_id | string | "demo" | yes |
| 1 | support_users | list(string) | [] | yes |
| 1 | resource_labels | map(string) | {} | yes |
| 2 | application_name | string | "nodered" | yes |
| 2 | display_name | string | "Node-RED" | yes |
| 2 | application_version | string | "latest" | yes |
| 3 | deploy_application | bool | true | yes |
| 3 | cpu_limit | string | "1000m" | yes |
| 3 | memory_limit | string | "1Gi" | yes |
| 3 | min_instance_count | number | 0 | yes |
| 3 | max_instance_count | number | 1 | yes |
| 3 | execution_environment | string | "gen2" | yes |
| 3 | timeout_seconds | number | 300 | yes |
| 3 | cpu_always_allocated | bool | false | yes |
| 3 | enable_cloudsql_volume | bool | false | yes |
| 3 | service_annotations | map(string) | {} | yes |
| 3 | service_labels | map(string) | {} | yes |
| 3 | enable_image_mirroring | bool | true | yes |
| 3 | traffic_split | list(object) | [] | yes |
| 3 | max_revisions_to_retain | number | 7 | yes |
| 3 | container_protocol | string | "http1" | yes |
| 3 | cloudsql_volume_mount_path | string | "/cloudsql" | yes |
| 4 | ingress_settings | string | "all" | yes |
| 4 | vpc_egress_setting | string | "PRIVATE_RANGES_ONLY" | yes |
| 4 | enable_iap | bool | false | yes |
| 4 | iap_authorized_users | list(string) | [] | yes |
| 4 | iap_authorized_groups | list(string) | [] | yes |
| 5 | environment_variables | map(string) | {} | yes |
| 5 | secret_environment_variables | map(string) | {} | yes |
| 5 | secret_rotation_period | string | "2592000s" | yes |
| 5 | secret_propagation_delay | number | 30 | yes |
| 6 | backup_schedule | string | "0 2 * * *" | yes |
| 6 | backup_retention_days | number | 7 | yes |
| 6 | enable_backup_import | bool | false | yes |
| 6 | backup_source | string | "gcs" | yes |
| 6 | backup_uri | string | "" | yes |
| 6 | backup_format | string | "tar" | yes |
| 7 | enable_cicd_trigger | bool | false | yes |
| 7 | github_repository_url | string | "" | yes |
| 7 | github_token | string | "" | yes |
| 7 | github_app_installation_id | string | "" | yes |
| 7 | cicd_trigger_config | object | { branch_pattern = "^main$" } | yes |
| 7 | enable_cloud_deploy | bool | false | yes |
| 7 | cloud_deploy_stages | list(object) | [dev, staging, prod(approval)] | yes |
| 7 | enable_binary_authorization | bool | false | yes |
| 8 | enable_custom_sql_scripts | bool | false | yes |
| 8 | custom_sql_scripts_bucket | string | "" | yes |
| 8 | custom_sql_scripts_path | string | "" | yes |
| 8 | custom_sql_scripts_use_root | bool | false | yes |
| 9 | enable_cloud_armor | bool | false | yes |
| 9 | admin_ip_ranges | list(string) | [] | yes |
| 9 | application_domains | list(string) | [] | yes |
| 9 | enable_cdn | bool | false | yes |
| 9 | max_images_to_retain | number | 7 | yes |
| 9 | delete_untagged_images | bool | true | yes |
| 9 | image_retention_days | number | 30 | yes |
| 10 | create_cloud_storage | bool | true | yes |
| 10 | storage_buckets | list(object) | [{ name_suffix = "data" }] | yes |
| 10 | enable_nfs | bool | true | yes |
| 10 | nfs_mount_path | string | "/data" | yes |
| 10 | nfs_instance_name | string | "" | yes |
| 10 | nfs_instance_base_name | string | "app-nfs" | yes |
| 10 | gcs_volumes | list(object) | [] | yes |
| 10 | manage_storage_kms_iam | bool | false | yes |
| 10 | enable_artifact_registry_cmek | bool | false | yes |
| 11 | database_password_length | number | 32 | yes |
| 11 | enable_auto_password_rotation | bool | false | yes |
| 11 | rotation_propagation_delay_sec | number | 90 | yes |
| 12 | initialization_jobs | list(object) | [] | yes |
| 12 | cron_jobs | list(object) | [] | yes |
| 13 | startup_probe | object | (HTTP /, 30s delay) | yes |
| 13 | liveness_probe | object | (HTTP /, 30s delay) | yes |
| 13 | uptime_check_config | object | { enabled = true, path = "/" } | yes |
| 13 | alert_policies | list(object) | [] | yes |
| 20 | enable_redis | bool | false | yes |
| 20 | redis_host | string | "" | yes |
| 20 | redis_port | string | "6379" | yes |
| 20 | redis_auth | string | "" | yes |
| 21 | enable_vpc_sc | bool | false | yes |
| 21 | vpc_cidr_ranges | list(string) | [] | yes |
| 21 | vpc_sc_dry_run | bool | true | yes |
| 21 | organization_id | string | "" | yes |
| 21 | enable_audit_logging | bool | false | yes |
§11 · Outputs
| Output | Description |
|---|
service_url | The Cloud Run service URL for the deployed Node-RED instance (e.g. https://appnodered<tenant><id>-<project_number>.<region>.run.app). |
§12 · Configuration Examples
Basic Deployment
Deploys Node-RED with 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 IAP, Redis context storage, Cloud Armor, and CI/CD.
# config/advanced.tfvars
resource_creator_identity = ""
project_id = "my-project-123"
tenant_deployment_id = "prod"
application_name = "nodered"
display_name = "Node-RED"
application_version = "4.0.9"
# Scaling
cpu_limit = "1000m"
memory_limit = "1Gi"
min_instance_count = 1
max_instance_count = 1
# Redis context storage
enable_redis = true
redis_host = "10.0.0.5"
redis_port = "6379"
# Security
enable_iap = true
iap_authorized_users = ["user:admin@example.com"]
enable_cloud_armor = true
application_domains = ["nodered.example.com"]
# CI/CD
enable_cicd_trigger = true
enable_cloud_deploy = 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-memory"
metric_type = "run.googleapis.com/container/memory/utilizations"
comparison = "COMPARISON_GT"
threshold_value = 0.85
duration_seconds = 300
aggregation_period = "60s"
}
]
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).
| Variable | Sensible Default | Risk | Consequence of Incorrect Value |
|---|
NODE_RED_CREDENTIAL_SECRET (auto-generated, length from database_password_length) | Auto-generated random string stored in Secret Manager | Critical | This secret encrypts all flow credentials at rest in the flows_cred.json file. If this secret is rotated or changed after flows are deployed, Node-RED cannot decrypt existing credentials — all stored secrets (API keys, passwords, tokens) in flows are permanently lost and must be re-entered. |
enable_auto_password_rotation | false | Critical | Enabling automatic rotation of NODE_RED_CREDENTIAL_SECRET changes the encryption key used for credentials. All existing encrypted credentials become unreadable after rotation. Only enable if you have a process to re-encrypt credentials after each rotation. |
database_password_length | 32 | Medium | Controls the length of the auto-generated NODE_RED_CREDENTIAL_SECRET. Valid range: 16–64. Values outside this range are rejected by the built-in variable validation. Shorter lengths reduce encryption entropy. |
enable_nfs | true | Critical | Node-RED stores all flow definitions, credentials, and installed custom nodes in its /data directory. Without NFS (or another persistent volume), every Cloud Run restart or scale event starts Node-RED with a completely empty /data directory — all flows, nodes, and settings are lost. |
nfs_mount_path | "/mnt/nfs" | High | Node-RED's entrypoint script configures /data to point to the NFS mount. Changing this path without a corresponding update to the Node-RED settings file causes flows to be written to the ephemeral container filesystem. |
execution_environment | "gen2" | High | NFS mounts require the gen2 execution environment. Changing to gen1 causes NFS mount failures and container startup errors. |
application_name | "nodered" | Critical | Immutable after first deploy. Changing it renames all GCP resources, triggers full resource recreation, and the NFS instance is disconnected from the new deployment. |
min_instance_count | 0 | High | Scale-to-zero causes cold starts of 10–20 seconds. More importantly, when Node-RED scales back up after idle, it must remount the NFS volume before the health check passes. If a webhook fires during this window, it will be lost. Set to 1 for production webhook workloads. |
max_instance_count | 1 | High | Node-RED's flow state and context are stored locally. Running multiple instances without session affinity causes each instance to have different context state. Node-RED is not designed for active-active horizontal scaling — keep max_instance_count = 1. |
memory_limit | "1Gi" | Medium | The default is adequate for standard flows. Flows that process large payloads, use the node-red-contrib-image-tools node, or install heavy npm dependencies can require 2Gi or more. |
cpu_limit | "1000m" | Low | Node-RED is primarily I/O-bound. However, CPU-intensive function nodes or heavy message transformation can cause throttling at values below 500m. |
database_type | "NONE" | High | Node-RED does not require a database. Setting this to POSTGRES or MYSQL enables the Cloud SQL Auth Proxy sidecar unnecessarily, increasing startup time and cost. Leave as "NONE". |
enable_cloudsql_volume | false | Medium | Node-RED has no database. Setting enable_cloudsql_volume = true with database_type = "NONE" causes the Cloud SQL Auth Proxy sidecar to fail to start, blocking the main container. |
secret_environment_variables | {} | Medium | Do not manually set NODE_RED_CREDENTIAL_SECRET via secret_environment_variables. It is auto-managed by the Foundation Module via database_password_length. Overriding it breaks the credential encryption key management. |
environment_variables | {} | Medium | Do not set NODE_RED_ENABLE_SAFE_MODE = "true" in production — safe mode disables all flows, preventing any automation from running. It is injected as "false" by default. |
ingress_settings | "all" | Medium | Setting to "internal" blocks all incoming webhook messages from external services. Use "internal-and-cloud-load-balancing" with Cloud Armor for production deployments receiving public webhooks. |
vpc_egress_setting | "PRIVATE_RANGES_ONLY" | Medium | Setting to "all-traffic" routes outbound Node-RED HTTP calls through the VPC connector. If VPC firewall rules restrict external egress, all http request nodes calling public APIs will fail. |
enable_iap | false | High | Enabling IAP without valid iap_authorized_users or iap_authorized_groups causes all requests to return 403, blocking access to the Node-RED editor. |
enable_cloud_armor | false | Medium | The Node-RED editor UI is publicly accessible by default. Enable Cloud Armor with admin_ip_ranges to restrict editor access in production. |
enable_redis | false | Low | Node-RED does not use Redis natively. Enabling Redis provisions the connection strings but they are not used by Node-RED core. Only enable if custom nodes explicitly require Redis. |
secret_rotation_period | "2592000s" (30 days) | Low | This governs the SMTP password rotation period. Very short rotation periods can cause Node-RED SMTP nodes to use stale credentials during the propagation window. |
Destroying Resources
Known Deletion Issue: Serverless IPv4 Address Release
When destroying a Cloud Run deployment, you may encounter an error similar to:
Error: Error waiting for Subnetwork to be deleted: The following serverless IPv4 address(es) on subnet ... are still in use.
Cause: GCP holds serverless IPv4 addresses on the VPC subnet asynchronously after a Cloud Run service is deleted. These addresses are released by GCP approximately 20–30 minutes after the Cloud Run service is removed. Terraform/OpenTofu cannot complete the subnet or VPC deletion until they are fully released.
Resolution: Wait 20–30 minutes after the initial destroy attempt, then re-run the destroy command:
The second run will succeed once GCP has released the reserved addresses.