Wordpress CloudRun Module — Configuration Guide
Wordpress_CloudRun is a pre-configured wrapper around the App_CloudRun module that deploys WordPress on Google Cloud Run Gen2.
Every variable in this module is passed through to App CloudRun. The wrapper's role is to supply WordPress-appropriate defaults and to call the Wordpress Common sub-module, which generates the application's container build context, PHP configuration, MySQL connection settings, Redis object cache configuration, and WordPress-specific secrets. You configure this module exactly as you would App CloudRun; the sections below highlight only the variables whose defaults or behaviour differ meaningfully from App CloudRun, or that are unique to this wrapper.
Where to look: If a variable you are configuring is not described here, consult the App_CloudRun Configuration Guide. All
App_CloudRunfeatures — access and networking, IAP, Cloud Armor, CDN, CI/CD, Cloud Deploy, Binary Authorization, traffic splitting, and VPC Service Controls — are available inWordpress_CloudRunwith identical behaviour and configuration.
§1 Module Overview
| Property | Value |
|---|---|
| Sub-module | Wordpress Common |
| Default application name | wordpress |
| Default display name | Wordpress |
| Default version | latest |
| Container port | 80 |
| Execution environment | gen2 |
| Database engine | MySQL 8.0 |
| Default DB name | wp |
| Default DB user | wp |
| NFS enabled | true (mount: /mnt/nfs) |
| Redis enabled | true (object cache) |
| Image source | custom (Cloud Build) |
| Platform-managed job | db-init (injected by Wordpress Common when initialization_jobs = []) |
Wordpress Common generates the Dockerfile (based on the official wordpress image), PHP configuration (php.ini overrides), WordPress wp-config.php template, and WordPress-specific secrets. Redis object caching is enabled by default; Wordpress Common injects the required WP_REDIS_HOST and WP_REDIS_PORT environment variables when enable_redis = true.
Note on MySQL: This module uses MySQL 8.0, not PostgreSQL. The Cloud SQL Auth Proxy sidecar (enable_cloudsql_volume = true) provides a Unix socket connection. Attempting to disable enable_cloudsql_volume without switching to TCP-based connectivity will break the database connection.
§2 IAM & Project Identity
Behaviour is identical to App CloudRun. The following variables are passed through unchanged.
| Variable | Default | Notes |
|---|---|---|
project_id | (required) | Target GCP project |
tenant_deployment_id | "demo" | Appended to resource names |
resource_creator_identity | "rad-module-creator@..." | Terraform executor SA |
resource_labels | {} | Applied to all resources |
support_users | [] | Alert recipients & IAM members |
§3 Core Service Configuration
§3.A Application Identity
| Variable | Default | Notes |
|---|---|---|
application_name | "wordpress" | Base name for Cloud Run service, secrets, Artifact Registry |
display_name | "Wordpress" | Human-readable name in UI and dashboards |
description | "Wordpress CMS on Cloud Run" | Used by Wordpress Common for internal labelling |
application_version | "latest" | Image tag; change to a specific version (e.g. "6.5") for reproducible deployments |
Note: this module uses display_name and description (not application_display_name / application_description). display_name is forwarded to App CloudRun as application_display_name; description is used only within Wordpress Common and is not passed to App CloudRun.
WordPress-specific PHP configuration variables:
| Variable | Default | Notes |
|---|---|---|
php_memory_limit | "512M" | PHP memory limit; increase for heavy plugin or media use |
upload_max_filesize | "64M" | Max single upload file size |
post_max_size | "64M" | Max POST body size; must be ≥ upload_max_filesize |
§3.B Resource Sizing
| Variable | Default | Notes |
|---|---|---|
cpu_limit | "1000m" | 1 vCPU; increase for high-traffic or plugin-heavy sites |
memory_limit | "2Gi" | 2 GiB; WordPress with PHP 8.x and caching plugins |
min_instance_count | 0 | Scale-to-zero by default; set to 1 to eliminate cold starts |
max_instance_count | 1 | Single-instance default; NFS shared state required before increasing |
timeout_seconds | 300 | Increase for plugin installs, theme updates, or large media imports |
container_resources can be used to override cpu_limit and memory_limit with a structured object including requests and ephemeral storage:
container_resources = {
cpu_limit = "2000m"
memory_limit = "4Gi"
}
When container_resources is set (non-null), it takes precedence over the flat cpu_limit and memory_limit variables.
§3.C Environment Variables & Secrets
Plain-text variables via environment_variables; sensitive values via secret_environment_variables.
Module-injected secrets (provisioned by Wordpress Common, injected via module_secret_env_vars):
WordPress auth keys and salts are auto-generated by Wordpress Common and stored in Secret Manager. The secret IDs are injected as environment variables at runtime. The exact variable names follow WordPress conventions (e.g. WORDPRESS_AUTH_KEY, WORDPRESS_SECURE_AUTH_KEY, WORDPRESS_LOGGED_IN_KEY, WORDPRESS_NONCE_KEY, and their corresponding salts).
The database password is auto-generated by App CloudRun and wired through the module.
User-supplied variables (non-sensitive):
environment_variables = {
WORDPRESS_DEBUG = "false"
WP_MEMORY_LIMIT = "512M"
}
User-supplied secrets:
secret_environment_variables = {
SENDGRID_API_KEY = "my-sendgrid-secret"
}
§3.D Networking
Key defaults:
| Variable | Default |
|---|---|
ingress_settings | "all" |
vpc_egress_setting | "PRIVATE_RANGES_ONLY" |
execution_environment | "gen2" |
enable_cloudsql_volume | true |
cloudsql_volume_mount_path | "/cloudsql" |
container_protocol | "http1" |
The Cloud SQL Auth Proxy sidecar is required for MySQL Unix socket connectivity. Disable only when switching to TCP-based MySQL access. Set container_protocol = "h2c" to enable HTTP/2 communication between the load balancer and the Cloud Run service.
§3.E Container Image & Build
| Variable | Default | Notes |
|---|---|---|
container_image_source | "custom" | "custom" triggers Cloud Build; "prebuilt" deploys an existing image |
container_image | "" | Leave empty for Cloud Build output; set for prebuilt image URI |
enable_image_mirroring | true | Mirrors image to Artifact Registry before deployment |
There is no container_build_config user variable in this module; the build configuration is fully managed by Wordpress Common.
§4 Advanced Security
§4.A Identity-Aware Proxy
enable_iap = true
iap_authorized_groups = ["group:wordpress-admins@example.com"]
§4.B VPC Service Controls
enable_vpc_sc = true # group=22; requires existing VPC-SC perimeter
§4.C Cloud Armor & CDN
enable_cloud_armor = true
application_domains = ["www.example.com"]
enable_cdn = true
§4.D Binary Authorization
enable_binary_authorization = true
§4.E Secret Rotation
secret_rotation_period = "2592000s" # 30-day notification
enable_auto_password_rotation = false
rotation_propagation_delay_sec = 90
§5 Traffic & Ingress
§5.A Traffic Splitting
traffic_split = [
{ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST", percent = 90 },
{ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_REVISION", revision = "wordpress-00002", percent = 10 },
]
§5.B Ingress Control
ingress_settings = "internal-and-cloud-load-balancing"
vpc_egress_setting = "ALL_TRAFFIC"
§6 CI/CD Integration
§6.A Cloud Build Trigger
enable_cicd_trigger = true
github_repository_url = "https://github.com/my-org/wordpress-site"
github_token = "ghp_xxxx" # or use github_app_installation_id
cicd_trigger_config = {
branch_pattern = "^main$"
included_files = ["wp-content/**", "Dockerfile"]
}
§6.B Cloud Deploy Pipeline
enable_cloud_deploy = true
cloud_deploy_stages = [
{ name = "dev", require_approval = false },
{ name = "staging", require_approval = false },
{ name = "prod", require_approval = true },
]
§7 Reliability & Data
§7.A Health Probes
Wordpress CloudRun uses only startup_probe and liveness_probe (passed to Wordpress Common). There is no separate startup_probe_config / health_check_config interface in this module.
| Variable | Default | Notes |
|---|---|---|
startup_probe.type | "TCP" | TCP check during startup |
startup_probe.initial_delay_seconds | 30 | |
startup_probe.timeout_seconds | 10 | |
startup_probe.period_seconds | 15 | |
startup_probe.failure_threshold | 20 | High threshold to allow PHP/WP initialisation |
liveness_probe.type | "HTTP" | HTTP check during steady state |
liveness_probe.path | "/wp-admin/install.php" | Confirms PHP and database connection |
liveness_probe.initial_delay_seconds | 300 | Long delay for first-boot database setup |
liveness_probe.timeout_seconds | 60 | |
liveness_probe.period_seconds | 60 | |
liveness_probe.failure_threshold | 3 |
The liveness_probe uses /wp-admin/install.php because this page requires a working PHP runtime and database connection, making it a reliable indicator of application health.
§7.B Backup & Recovery
| Variable | Default | Notes |
|---|---|---|
backup_schedule | "0 2 * * *" | Daily at 02:00 UTC |
backup_retention_days | 7 | GCS lifecycle rule |
enable_backup_import | false | One-time restore on deploy |
backup_source | "gcs" | "gcs" or "gdrive" |
backup_uri | "" | Full GCS URI or Google Drive file ID |
backup_format | "sql" | sql, tar, gz, tgz, tar.gz, zip, auto |
Note: this module uses backup_uri (aliased to backup_file in main.tf).
§7.C Scheduled Jobs
cron_jobs = [{
name = "wp-cron"
schedule = "*/5 * * * *"
image = "wordpress:latest"
command = ["wp", "cron", "event", "run", "--due-now"]
}]
§7.D Observability
uptime_check_config = {
enabled = true
path = "/"
check_interval = "60s"
timeout = "10s"
}
alert_policies = [{
name = "high-latency"
metric_type = "run.googleapis.com/request_latencies"
comparison = "COMPARISON_GT"
threshold_value = 2000
duration_seconds = 300
aggregation_period = "60s"
}]
§8 Integrations
§8.A Redis Object Cache
Redis is enabled by default (enable_redis = true). Wordpress Common injects Redis connection details when enabled. Leave redis_host empty to use the default Redis configuration supplied by Wordpress Common.
enable_redis = true
redis_host = "10.0.0.5" # leave "" for default; set for external Memorystore
redis_port = "6379" # string type
redis_auth = ""
When enable_redis = false, no Redis environment variables are injected and the WordPress object cache operates in memory-only mode.
§8.B NFS Storage
NFS is used for the WordPress wp-content directory (uploads, themes, plugins).
enable_nfs = true
nfs_mount_path = "/mnt/nfs"
Wordpress Common configures WordPress to use this mount path for persistent file storage. Disable NFS only for single-container, stateless deployments where uploads are stored externally.
§8.C GCS Fuse Volumes
gcs_volumes = [{
name = "wp-uploads"
bucket_name = "my-wp-uploads-bucket"
mount_path = "/var/www/html/wp-content/uploads"
readonly = false
}]
§8.D Additional Services
Wordpress CloudRun does not expose the additional_services variable. Co-deployed services are not supported in this module's interface. (This variable is available in Wordpress GKE.)
§9 Platform-Managed Behaviours
The following are set or injected automatically and do not require configuration.
Database credentials (MySQL 8.0)
App CloudRun generates a random MySQL password and stores it in Secret Manager. Wordpress Common injects the password as WORDPRESS_DB_PASSWORD and constructs the database host path for the Unix socket connection.
WordPress authentication keys and salts
Wordpress Common auto-generates all eight WordPress authentication keys and salts on first deploy (e.g. WORDPRESS_AUTH_KEY, WORDPRESS_LOGGED_IN_KEY, and their _SALT counterparts). These are stored in Secret Manager and injected at runtime.
PHP configuration
Wordpress Common applies php_memory_limit, upload_max_filesize, and post_max_size to the container's php.ini during the Cloud Build step. These do not need to be set in environment_variables.
Redis injection
When enable_redis = true, Wordpress Common injects WP_REDIS_HOST and WP_REDIS_PORT into the container environment and configures the Redis Object Cache plugin. The plugin must be installed in the WordPress image for caching to activate.
Probe endpoints
The liveness probe uses /wp-admin/install.php, which returns 200 when WordPress is installed and 302 (redirect) when it is not. The TCP startup probe (type = "TCP") confirms the Apache web server is listening before HTTP checks begin. The high failure_threshold = 20 on the startup probe provides approximately 5 minutes of tolerance for first-boot database setup.
§10 Variable Reference
The table below covers all variables unique to or with notable defaults in Wordpress_CloudRun. For the full set of inherited variables, see the App_CloudRun Variable Reference.
| Variable | Type | Default | Group | Notes |
|---|---|---|---|---|
application_name | string | "wordpress" | 2 | Base resource name |
display_name | string | "Wordpress" | 2 | UI display name (forwarded as application_display_name) |
description | string | "Wordpress CMS on Cloud Run" | 2 | Used by Wordpress Common only |
application_version | string | "latest" | 2 | Image tag |
php_memory_limit | string | "512M" | 2 | PHP memory limit |
upload_max_filesize | string | "64M" | 2 | Max upload file size |
post_max_size | string | "64M" | 2 | Max POST body size |
deploy_application | bool | true | 3 | Set false to provision infra without deploying the container |
cpu_limit | string | "1000m" | 3 | 1 vCPU |
memory_limit | string | "2Gi" | 3 | 2 GiB |
container_resources | object | null | 3 | Overrides cpu_limit/memory_limit when set |
min_instance_count | number | 0 | 3 | Scale-to-zero |
max_instance_count | number | 1 | 3 | |
container_port | number | 80 | 3 | Apache default |
container_protocol | string | "http1" | 3 | "http1" or "h2c" |
execution_environment | string | "gen2" | 3 | "gen1" or "gen2" |
timeout_seconds | number | 300 | 3 | Max request duration (0–3600 s) |
container_image_source | string | "custom" | 3 | "prebuilt" or "custom" |
container_image | string | "" | 3 | Override for prebuilt |
enable_image_mirroring | bool | true | 3 | Mirror to Artifact Registry |
max_revisions_to_retain | number | 7 | 3 | Old revisions pruned beyond this count |
max_images_to_retain | number | 7 | 9 | Artifact Registry image retention guard |
delete_untagged_images | bool | true | 9 | Delete dangling/untagged images |
image_retention_days | number | 30 | 9 | Age-based image deletion (0 = disabled) |
enable_cloudsql_volume | bool | true | 3 | Required for MySQL Unix socket |
cloudsql_volume_mount_path | string | "/cloudsql" | 3 | Socket path |
service_annotations | map(string) | {} | 3 | Cloud Run service annotations |
service_labels | map(string) | {} | 3 | Cloud Run service labels |
db_name | string | "wp" | 11 | MySQL database name |
db_user | string | "wp" | 11 | MySQL user |
database_password_length | number | 32 | 11 | 16–64 characters |
enable_nfs | bool | true | 10 | Cloud Filestore mount |
nfs_mount_path | string | "/mnt/nfs" | 10 | Container mount path |
nfs_instance_name | string | "" | 8 | Explicit NFS VM name; empty = auto-discover |
nfs_instance_base_name | string | "app-nfs" | 8 | Base name for inline NFS VM |
storage_buckets | list | [{ name_suffix = "data" }] | 10 | GCS buckets |
create_cloud_storage | bool | true | 10 | Skip bucket creation when false |
manage_storage_kms_iam | bool | false | 10 | Enable CMEK for GCS buckets |
enable_artifact_registry_cmek | bool | false | 10 | Enable CMEK for Artifact Registry |
backup_uri | string | "" | 6 | Full GCS URI or Drive ID (passed as backup_file to App CloudRun) |
backup_format | string | "sql" | 6 | "sql", "tar", "gz", "tgz", "tar.gz", "zip", "auto" |
secret_rotation_period | string | "2592000s" | 5 | Pub/Sub rotation notification period; null to disable |
secret_propagation_delay | number | 30 | 5 | Seconds to wait after secret create/update |
enable_redis | bool | true | 20 | Redis object cache (on by default) |
redis_host | string | "" | 20 | Leave empty for default |
redis_port | string | "6379" | 20 | String type |
redis_auth | string | "" | 20 | Sensitive |
startup_probe | object | { type="TCP", initial_delay_seconds=30, failure_threshold=20 } | 13 | |
liveness_probe | object | { type="HTTP", path="/wp-admin/install.php", initial_delay_seconds=300 } | 13 | |
initialization_jobs | list | [] | 12 | When empty, Wordpress Common injects the db-init job automatically |
enable_vpc_sc | bool | false | 21 | VPC Service Controls |
vpc_cidr_ranges | list(string) | [] | 21 | CIDR ranges for VPC-SC access level; auto-discovered when empty |
vpc_sc_dry_run | bool | true | 21 | Log-only mode; set false to enforce |
organization_id | string | "" | 21 | GCP org ID for VPC-SC; auto-discovered when empty |
enable_audit_logging | bool | false | 21 | Enable DATA_READ/WRITE audit logs |
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 |
|---|---|---|---|
project_id | (required) | Critical | No default — deployment fails immediately. |
database_type | "MYSQL_8_0" | Critical | WordPress requires MySQL. Setting to POSTGRES or NONE breaks database connectivity — WordPress's wpdb class only supports MySQL. |
enable_nfs | true | Critical | WordPress stores all uploaded media, installed plugins, and themes under wp-content/. Without NFS, the wp-content directory is ephemeral — every new Cloud Run revision wipes all plugins, themes, and media uploads. This makes WordPress on Cloud Run non-functional for any real site. |
nfs_mount_path | "/mnt/nfs" | High | The WordPress container startup script symlinks /var/www/html/wp-content to the NFS path. If the path does not match the startup script expectations, the symlink is broken and WordPress cannot find plugins or themes. |
container_image_source | "custom" | High | WordPress requires a custom build that wires the NFS wp-content symlink, the Cloud SQL socket path, and PHP configuration. Using "prebuilt" with the upstream wordpress Docker Hub image will not have these integrations and will fail to connect to Cloud SQL via Unix socket. |
enable_redis | false | Medium | WordPress without a persistent object cache hits MySQL for every page request. For sites with plugin-heavy pages or moderate traffic, enabling Redis with the WP Redis plugin reduces database load by 60–90% and dramatically improves page load times. |
redis_host | "" | High | Required when enable_redis = true. Leaving empty causes the WordPress Redis Object Cache plugin to fail silently — WordPress falls back to no caching rather than erroring, masking the misconfiguration. |
php_memory_limit | "512M" | Medium | Many WordPress plugins (WooCommerce, Elementor, ACF) require 256M–512M of PHP memory. The default 512M is sufficient for most sites. Reducing below 256M causes plugin activation failures and white screen of death (WSOD). |
upload_max_filesize | "64M" | Medium | Sites publishing high-resolution images or video need a higher limit. The default 64M is insufficient for video uploads. Must be less than or equal to post_max_size. |
post_max_size | "64M" | Medium | Must be greater than or equal to upload_max_filesize. Setting upload_max_filesize > post_max_size silently truncates uploads. |
application_database_name | "wordpress" | Critical | Immutable after first deployment — changing this recreates the database and destroys all WordPress posts, users, settings, and media records. |
application_database_user | "wordpress" | Critical | Immutable after first deployment — changing this recreates the user and breaks the existing database connection. |
min_instance_count | 1 | Medium | Scale-to-zero (0) causes 10–20 second cold starts. WordPress is not designed for serverless — cold starts disrupt persistent connections. For sites with consistent traffic, min_instance_count = 1 is required. |
memory_limit | varies | High | Running WordPress with popular plugins (WooCommerce, Elementor) requires at least 2Gi of container memory. The minimum viable value depends on the plugin ecosystem. Insufficient memory causes PHP fatal errors. |
ingress_settings | "all" | Medium | "all" exposes the WordPress admin panel (/wp-admin) to the public internet. Consider enabling Cloud Armor WAF rules to restrict /wp-admin and /wp-login.php access to known IP ranges. |
enable_cloud_armor | false | High | WordPress login pages (/wp-login.php, xmlrpc.php) are prime targets for brute-force and credential stuffing attacks. Cloud Armor WAF is strongly recommended for any public WordPress site. |
execution_environment | "gen2" | High | NFS mounts require Cloud Run gen2. Changing to "gen1" with enable_nfs = true causes the service to fail to start with a volume mount error. |
enable_backup_import | false | Critical | Requires backup_uri to be valid and accessible. Enabling with an empty backup_uri causes the restore job to fail during tofu apply. |
backup_retention_days | 7 | Medium | Seven days is inadequate for e-commerce or news sites. Losing more than a week of WooCommerce orders or content is a serious business risk. Increase to 30+ days. |
database_password_length | 32 | Medium | Do not reduce. The minimum enforced by validation is 16, but 32+ is recommended for production database credentials. |
enable_cicd_trigger | false | Low | Requires github_repository_url and either github_token or github_app_installation_id when enabled. Enabling without these causes the Cloud Build trigger creation to fail. |
secret_propagation_delay | 30 | Low | May be insufficient in multi-region projects. Increase to 60s if Secret Manager reads intermittently fail during deployment. |
enable_iap | false | Medium | With IAP disabled, WordPress admin access is protected only by WordPress authentication. Enabling IAP is recommended for admin-only Cloud Run deployments. |
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:
tofu destroy
The second run will succeed once GCP has released the reserved addresses.