Skip to main content

Windmill GKE Module — Configuration Guide

This guide describes every configuration variable available in the Windmill_GKE module. Windmill_GKE is a wrapper module that combines the generic App_GKE infrastructure module with the Windmill_Common shared application configuration to deploy the Windmill developer platform on Google Kubernetes Engine (GKE) Autopilot.

Most configuration options in Windmill GKE map directly to the same options in App GKE. Where a variable is identical in behaviour, this guide references the App GKE guide rather than repeating the same documentation. Only the variables and defaults that are specific to Windmill are described in full here.

Note: Variables marked as platform-managed are set and maintained by the platform. You do not normally need to change them.


Standard Configuration Reference

Configuration AreaApp GKE.md SectionWindmill-Specific Notes
Module Metadata & Configuration§1 Module OverviewWindmill-specific module_description and module_services defaults are pre-set.
Project & Identity§2 IAM & Access ControlIdentical.
Application Identity§3.A Compute (GKE Autopilot)Windmill-specific defaults; see Group 2: Application Identity.
Runtime & Scaling§3.A Compute (GKE Autopilot)Windmill-specific defaults for container_port, cpu_limit, memory_limit; see Group 3: Runtime & Scaling.
Environment Variables & Secrets§3 Core Service ConfigurationWindmill env vars injected by Windmill Common; see Group 5: Environment Variables & Secrets.
Networking & Network Policies§3.D Networking & Network PoliciesIdentical.
Initialization Jobs & CronJobs§3.E Initialization Jobs & CronJobsdb-init PostgreSQL 16 job supplied automatically by Windmill Common; see Group 8.
Storage — GCS§3.C Storage (NFS / GCS / GCS Fuse)windmill-data GCS bucket provisioned automatically.
Database Configuration§3.B Database (Cloud SQL)PostgreSQL 16 required; see Group 11: Database Configuration.
Observability & Health Checks§3.A Compute (GKE Autopilot)Probes target /api/version; see Group 13: Observability & Health.
Cloud Armor WAF§4.A Cloud Armor WAFIdentical.
Identity-Aware Proxy§4.B Identity-Aware Proxy (IAP)Identical.
Binary Authorization§4.C Binary AuthorizationIdentical.
VPC Service Controls§4.D VPC Service ControlsIdentical.
Traffic & Ingress§5 Traffic & IngressIdentical.
Custom Domain & Static IP§5.C Static IP ReservationBASE_URL and BASE_INTERNAL_URL should match the domain.
Cloud Build Triggers§6.A Cloud Build TriggersIdentical.
Cloud Deploy Pipeline§6.B Cloud Deploy PipelineIdentical.
Pod Disruption Budgets§7.A Pod Disruption BudgetsIdentical.
Redis Cache§8.A Redis / Memorystoreenable_redis defaults to false; see Group 14: Redis Cache.

How Windmill GKE Relates to App GKE

Windmill GKE passes all variables through to App GKE and adds a Windmill Common sub-module that supplies Windmill-specific defaults and application configuration. The main effects are:

  1. PostgreSQL 16 is required. Windmill requires PostgreSQL 16. database_type defaults to "POSTGRES_16" — the only module in this repository with this requirement.
  2. MODE=server,worker is injected automatically. Windmill runs both the API server and script execution workers in a single process on GKE. For separate worker scaling, define additional Kubernetes Deployments.
  3. DISABLE_NSJAIL=true is required. GKE Autopilot does not provide CAP_SYS_ADMIN or user namespaces. Windmill's Linux namespace isolation is disabled automatically.
  4. A windmill-data GCS bucket is provisioned automatically. Windmill Common provides a bucket for workflow outputs and artefacts.
  5. A db-init job runs on first deployment. Windmill Common supplies a default db-init Kubernetes Job using postgres:16-alpine to initialise the Windmill database schema.
  6. SMTP password placeholder secret. Windmill Common provisions {prefix}-smtp-password in Secret Manager as a placeholder. Replace before enabling email features.
  7. Health probes target /api/version. Windmill exposes /api/version as its primary health endpoint.

Group 0: Module Metadata & Configuration

Identical to App_GKE. See App_GKE §1.

Windmill-specific defaults:

VariableWindmill GKE DefaultNotes
module_description"Windmill: Deploy Windmill developer platform on GKE Autopilot…"Pre-populated with Windmill-specific description.
credit_cost150GKE deployments cost more credits than Cloud Run.

Group 1: Project & Identity

Identical to App_GKE. See App_GKE §2.


Group 2: Application Identity

Windmill-specific defaults:

VariableWindmill GKE DefaultApp GKE DefaultNotes
application_name"windmill""gkeapp"Base name for all GCP and Kubernetes resources. Do not change after deployment.
display_name"Windmill"(not in App GKE)Human-readable name for the platform UI.
description"Windmill developer platform"(not in App GKE)Deployment description.
application_version"latest""1.0.0"Windmill release version.

Group 3: Runtime & Scaling

Windmill-specific defaults and behaviour:

VariableWindmill GKE DefaultApp GKE DefaultNotes
container_port80008080Windmill's native HTTP port.
cpu_limit"2000m""1000m"Combined server+worker process requires more CPU.
memory_limit"2Gi""512Mi"Worker execution requires additional memory.
min_instance_count11At least one Windmill pod always running.
max_instance_count33Maximum pod replicas.
container_image_source"custom""custom"Windmill Common supplies a bundled Dockerfile using ghcr.io/windmill-labs/windmill as the base.
enable_cloudsql_volumetruetrueCloud SQL Auth Proxy sidecar for PostgreSQL connection.

The remaining runtime variables behave as described in App_GKE Group 3.


Group 4: Access & Networking

Identical to App_GKE. See App_GKE §4 and App_GKE §5.

VariableDefaultDescription
enable_iapfalseEnables Identity-Aware Proxy authentication.
iap_authorized_users[]Users/service accounts granted IAP access.
iap_authorized_groups[]Google Groups granted IAP access.
enable_custom_domainfalseConfigures Ingress for custom domain with managed SSL.
application_domains[]Custom domain names.
reserve_static_iptrueReserves a Global Static IP for the load balancer.
enable_cloud_armorfalseEnables a Cloud Armor WAF security policy.
admin_ip_ranges[]Admin CIDR ranges permitted through Cloud Armor.
enable_vpc_scfalseEnables VPC Service Controls perimeter enforcement.

Group 5: Environment Variables & Secrets

Windmill Common injects all Windmill-specific environment variables automatically. The following are hardcoded:

VariableValueDescription
MODEserver,workerCombined server and worker mode.
NUM_WORKERS3Number of worker threads per pod.
WORKER_GROUPdefaultWorker group name.
DISABLE_NSJAILtrueRequired on GKE Autopilot (no CAP_SYS_ADMIN).
JSON_FMTtrueStructured JSON logging for Cloud Logging.
RUST_LOGwindmill=infoLog verbosity.
BASE_URLvar.service_urlPublic-facing service URL.
BASE_INTERNAL_URLvar.service_urlInternal service URL.
METRICS_ADDR:9001Prometheus metrics endpoint.

User-supplied variables are merged on top of these defaults via var.environment_variables.

The WINDMILL_SMTP_PASS secret is injected automatically from Windmill Common. Replace the placeholder value in Secret Manager before enabling email features.

VariableDefaultDescription
environment_variables{}Additional env vars merged with Windmill defaults.
secret_environment_variables{}Additional Secret Manager references. WINDMILL_SMTP_PASS is auto-injected.
service_url""Public URL for BASE_URL/BASE_INTERNAL_URL. Set to your domain or load balancer IP.

Group 6: Backup & Maintenance

Identical to App_GKE. See App_GKE §3.B.

VariableDefaultNotes
backup_schedule"0 2 * * *"Daily at 02:00 UTC.
backup_retention_days77-day retention. Increase for production (30–90 days).
enable_backup_importfalseOne-time restore on deploy.

Group 7: CI/CD & GitHub Integration

Identical to App_GKE. See App_GKE §6.

Variables available: enable_cicd_trigger, github_repository_url, github_token, github_app_installation_id, cicd_trigger_config, enable_cloud_deploy, cloud_deploy_stages, enable_binary_authorization.


Group 8: Jobs & Scheduled Tasks

Windmill default db-init job:

When initialization_jobs is left as the default empty list, Windmill Common supplies a db-init job:

FieldValue
Job namedb-init
Imagepostgres:16-alpine
PurposeInitialises the Windmill PostgreSQL 16 database schema and user
Execute on every applytrue
CPU / Memory1000m / 512Mi

Override initialization_jobs with a non-empty list to replace this default. The cron_jobs variable behaves identically to App GKE.


Group 9–10: Storage & Filesystem

GCS data bucket:

Windmill Common automatically provisions a windmill-data GCS bucket for workflow outputs and artefacts. You do not need to define it in storage_buckets.

Bucketname_suffixPurpose
Auto-provisionedwindmill-dataWorkflow outputs and artefact storage

The create_cloud_storage, storage_buckets, and gcs_volumes variables behave as described in App_GKE §3.C.

NFS (enable_nfs) is disabled by default — Windmill does not require NFS shared storage.


Group 11: Database Configuration

Windmill-specific defaults and restrictions:

VariableWindmill GKE DefaultApp GKE DefaultNotes
database_type"POSTGRES_16""POSTGRES"Windmill requires PostgreSQL 16. This is the only module in the repository with this requirement.
db_name"windmill"(not in App GKE)Database name passed to Windmill Common.
db_user"windmill"(not in App GKE)Database user passed to Windmill Common.

Automatic password rotation:

VariableDefaultDescription
enable_auto_password_rotationfalseDeploys automated database password rotation.
rotation_propagation_delay_sec90Seconds to wait after rotation before restarting pods.

Group 13: Observability & Health

Windmill exposes /api/version as its primary health endpoint. This is different from most modules that use /healthz.

Startup probe (startup_probeWindmill Common):

FieldWindmill DefaultApp GKE DefaultNotes
path"/api/version""/healthz"Windmill's version endpoint confirms the service is ready.
initial_delay_seconds3010Allows Windmill 30 seconds to start and connect to the database.
failure_threshold63Additional tolerance for first-boot database initialisation.

Liveness probe (liveness_probeWindmill Common):

FieldWindmill DefaultApp GKE DefaultNotes
path"/api/version""/healthz"Same endpoint as startup probe.
initial_delay_seconds3015Gives Windmill time to stabilise.

App GKE-standard probes:

Override recommended: startup_probe_config and health_check_config default to path = "/healthz". Override both to path = "/api/version" to match Windmill's actual health endpoint.

The uptime_check_config and alert_policies variables behave as described in App_GKE §3.A.


Group 14: Reliability Policies

Identical to App_GKE. See App_GKE §7.

Variables available: enable_pod_disruption_budget, pdb_min_available, enable_topology_spread, topology_spread_strict.


Group 14: Redis Cache

Redis is disabled by default (enable_redis = false). Windmill does not require Redis for core operation. Enable for specific caching use cases.

VariableDefaultDescription
enable_redisfalseEnables Redis. Not required for standard Windmill operation.
redis_host""Redis hostname or IP.
redis_port"6379"Redis port (string).
redis_auth""Redis AUTH password. Sensitive.

Group 17: GKE Backend Configuration

Identical to App_GKE. See App_GKE §3.A.

Notable defaults for Windmill:

VariableDefaultNotes
workload_typenullDefaults to Deployment. Set StatefulSet if persistent local storage is needed.
session_affinity"None"Windmill API is stateless; session affinity is not required.
service_type"LoadBalancer"Exposes Windmill via an external load balancer.

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
service_url / BASE_URL (via Common)Auto-predicted from GKE service URLHighBASE_URL and BASE_INTERNAL_URL are set from service_url in Windmill Common. An incorrect or empty value breaks OAuth callbacks, webhook endpoints, and Windmill UI deep-links. Verify the predicted GKE service URL (load balancer IP or custom domain) matches the actual external endpoint before the first deploy.
database_typePOSTGRES_15CriticalThe GKE module description references PostgreSQL 16 in the database instance name output. Ensure the Cloud SQL instance version matches what Windmill's migration job expects. Using a mismatched version causes the init job to fail with unsupported migration SQL, leaving the database uninitialised.
db_namewindmillHighChanging after first deploy causes Windmill to connect to an empty database, producing migration errors at startup and a non-functional service.
db_userwindmillHighChanging after deploy breaks the database connection unless Cloud SQL user grants and the Secret Manager password are updated simultaneously.
enable_cloudsql_volumetrueCriticalWindmill connects to Cloud SQL via the Auth Proxy Unix socket. Disabling this causes database connection failures and Windmill enters CrashLoopBackOff immediately on startup.
cpu_limit2000mHighGKE Windmill runs in combined mode on single-replica deployments. Insufficient CPU throttles worker script execution. Each worker needs approximately 500m CPU; the default 3 workers require at least 2000m total.
memory_limit2GiHighWindmill executes arbitrary user scripts in worker subprocesses. Python and TypeScript jobs with large dependencies can exceed 512Mi easily. OOM kills during script execution cause job failures with no visible error in the Windmill UI.
min_instance_count1HighSetting to 0 enables scale-to-zero via HPA. Scheduled Windmill jobs will be missed while the pod is scaled down; webhook triggers will return 503 until the pod is ready. Keep at least 1 replica running at all times.
container_protocolhttp1HighWindmill's HTTP server uses HTTP/1.1. Setting to h2c causes the GKE load balancer to use h2c framing for requests that Windmill does not support, resulting in 502 errors for all API and UI traffic.
quota_memory_requests / quota_memory_limits"4Gi" / "8Gi"CriticalMust use binary unit suffixes (e.g., "4Gi", "8192Mi"). Bare integers are treated as bytes by Kubernetes, creating a near-zero memory quota that immediately blocks all pod scheduling.
smtp_* via Secret ManagerDummy SMTP password secret created at deployMediumSMTP is only functional when all of WINDMILL_SMTP_HOST, WINDMILL_SMTP_PORT, WINDMILL_SMTP_FROM, and the SMTP password secret are properly configured together. Partial SMTP configuration causes silent email delivery failures with no runtime error.
enable_redisfalseMediumRedis enables Windmill's distributed queue. Without Redis on GKE multi-replica deployments, each pod processes only its own local queue — jobs submitted to one pod are invisible to others, causing unpredictable load distribution and potential job duplication.
worker_group (via environment_variables)"default"MediumWindmill uses worker groups to route jobs to specific worker pools. If a flow or script specifies a custom worker group that does not exist, the job sits in the queue indefinitely with no timeout or error.
stateful_pvc_enabledfalseMediumWindmill state is in Cloud SQL and GCS. Enabling StatefulSet PVCs adds persistent storage not used by Windmill, wastes resources, and can block pod rescheduling when the PVC cannot be mounted on the new node.
enable_pod_disruption_budgettrueMediumDisabling PDB allows GKE node upgrades to evict all Windmill pods simultaneously, causing a service outage and losing all in-flight job execution state.
backup_schedule"0 2 * * *"MediumAn empty string disables automated backups. Windmill stores all scripts, flows, variables, resources, and job history in PostgreSQL. Without backups, any Cloud SQL failure results in complete loss of all automation definitions.
enable_iapfalseMediumIAP requires iap_oauth_client_id and iap_oauth_client_secret. Enabling without both values leaves the backend either fully blocked or unprotected. External webhook sources cannot reach IAP-protected endpoints without explicit allowlisting.
enable_vpc_scfalseHighRequires explicit organization_id. Without it, VPC Service Controls are silently skipped, giving a false sense of perimeter security.
enable_auto_password_rotationfalseMediumWhen enabled, the Cloud SQL password rotates on schedule. The Windmill pod must be restarted after rotation; otherwise it continues using the old (now invalid) password until connections fail and the pod enters CrashLoopBackOff.

Module Outputs

OutputDescription
service_nameName of the Kubernetes service.
service_urlService URL.
service_external_ipExternal IP of the load balancer.
project_idGCP project ID.
deployment_idDeployment ID suffix.
namespaceKubernetes namespace.
database_instance_nameName of the Cloud SQL PostgreSQL 16 instance.
database_nameName of the application database.
database_userName of the application database user.
database_password_secretSecret Manager secret name for the database password.
storage_bucketsCreated GCS storage buckets.
container_imageContainer image used for the deployment.
cicd_enabledWhether the CI/CD pipeline is enabled.
kubernetes_readytrue when the GKE cluster endpoint is reachable and all Kubernetes resources are deployed. false on the first apply of a new inline cluster.