Skip to main content

Moodle CloudRun Module — Configuration Guide

Moodle is the world's most popular open-source Learning Management System (LMS), used by educational institutions, corporations, and online learning platforms worldwide. This module deploys Moodle on Google Cloud Run using a custom PHP 8.3/Apache container, backed by a managed Cloud SQL PostgreSQL instance and shared NFS storage for course materials.

Moodle CloudRun is a wrapper module built on top of App CloudRun. It delegates all GCP infrastructure provisioning to App CloudRun (Cloud Run service, Cloud SQL, networking, Secret Manager, GCS, CI/CD) and uses a Moodle Common sub-module to supply Moodle-specific application configuration, secret generation, and initialization logic. The Moodle Common outputs feed into App CloudRun's application_config, module_env_vars, module_secret_env_vars, module_explicit_secret_values, and module_storage_buckets inputs.

This guide documents variables that are unique to Moodle CloudRun or that have Moodle-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 Moodle CloudRun provides

  • A PHP 8.3/Apache container auto-built from a custom Dockerfile and deployed as a Cloud Run service. enable_image_mirroring defaults to false — there is no external prebuilt image to mirror.
  • A Cloud SQL PostgreSQL instance as the Moodle database backend. MOODLE_DB_TYPE = "pgsql" is hardcoded and cannot be changed.
  • Cloud SQL Auth Proxy via Unix socketenable_cloudsql_volume = true is forced in moodle.tf within the moodle_module local (the application_modules merge), and is not exposed as a configurable variable. The socket path is configured by cloudsql_volume_mount_path (default "/cloudsql").
  • NFS (Cloud Filestore) enabled by default (enable_nfs = true) as the Moodle moodledata directory, mounted at nfs_mount_path (default "/mnt/nfs").
  • Redis enabled by default (enable_redis = true) for PHP session handling and Moodle application cache. Required for horizontal scaling across multiple Cloud Run instances.
  • A Cloud Scheduler job auto-provisioned on every deployment to trigger admin/cron.php every minute using a secure, auto-generated cron password.
  • An additional moodle-data GCS bucket provisioned automatically via module_storage_buckets, alongside any user-defined storage_buckets.
  • MOODLE_CRON_PASSWORD and MOODLE_SMTP_PASSWORD auto-generated by Moodle Common and stored in Secret Manager. DB_PASSWORD auto-generated by App CloudRun and injected via module_secret_env_vars.

Key differences from App CloudRun defaults

FeatureApp CloudRun defaultMoodle CloudRun default
enable_cloudsql_volumefalsetrue (forced — not a variable)
enable_nfsfalsetrue
enable_redisfalsetrue
enable_image_mirroringtruefalse
memory_limit"512Mi""2Gi"
max_instance_count13
container_port80808080
Health probe path/healthz/health.php
DB typeuser-configuredPostgreSQL (forced)
Cron schedulernoneauto-provisioned (* * * * *)
Extra GCS bucketnonemoodle-data auto-provisioned

§2 · IAM & Project Identity

These variables configure the GCP project target, deployment identity, and platform metadata. Their semantics are identical to the App CloudRun equivalents — refer to App_CloudRun §2 for full detail.

VariableDefaultDescription
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. Override with a project-specific account for production.
support_users[]Email addresses granted IAM access and added to monitoring alert channels.
resource_labels{}Labels applied to all module-managed resources.
module_description(Moodle LMS description string)Platform UI description. Do not modify unless customising the module.
module_documentation"https://docs.radmodules.dev/docs/modules/Moodle_CloudRun"External documentation URL displayed in the platform UI.
module_dependency["Services GCP"]Platform modules that must be deployed before this one.
deployment_id""Optional fixed deployment ID. Auto-generated when blank.

§3 · Core Service Configuration

§3.A · Application Identity

display_name is a Moodle-specific alias for the application_display_name input in App CloudRun. description is passed only to Moodle Common — it is not forwarded to App CloudRun's application_description. Similarly, db_name and db_user (documented in §7.C) are aliases for application_database_name / application_database_user in Moodle Common, not in App CloudRun directly.

VariableDefaultDescription
application_name"moodle"Base name for the Cloud Run service, Artifact Registry repo, Secret Manager secrets, and GCS buckets. Do not change after initial deployment — renaming requires manual resource migration.
display_name"Moodle LMS"Human-readable name in the platform UI and Cloud Run console. Mapped to application_display_name in App CloudRun.
description"Moodle LMS - Online learning and course management platform"Description passed to Moodle Common (used as the db-init job description and application description within the Common layer). It is not forwarded to App CloudRun's application_description input.
application_version"4.5.1"Container image version tag. Increment to trigger a new Cloud Build run and deploy a new Cloud Run revision.

§3.B · Resource Sizing

cpu_limit and memory_limit are exposed as dedicated top-level variables rather than requiring the full container_resources object. min_instance_count and max_instance_count are user-configurable (unlike Ghost, where they are hardcoded).

VariableDefaultDescription
cpu_limit"1000m"CPU limit per container instance. Increase to "2000m" for production with concurrent students. CPUs above "1000m" require cpu_always_allocated = true to prevent throttling during idle periods.
memory_limit"2Gi"Memory limit per container instance. PHP 8.3 with OPcache and active sessions typically consumes 0.5–1.5 Gi; 2 Gi provides adequate headroom.
min_instance_count0Minimum live instances. Scale-to-zero is enabled by default (0). Set to 1 for production to eliminate cold-start latency between student sessions.
max_instance_count3Maximum concurrent instances. Moodle scales horizontally when Redis manages PHP sessions.
container_port8080Port Apache/PHP-FPM binds to inside the container. Cloud Run routes HTTP traffic to this port.
timeout_seconds300Maximum request duration before Cloud Run returns 504. Increase for course imports or large file uploads (maximum 3600).
execution_environment"gen2"Cloud Run generation. "gen2" is required for NFS volume mounts.
deploy_applicationtrueSet false to provision infrastructure (secrets, storage, IAM) without deploying the container. Useful for staged rollouts.
enable_image_mirroringfalseDisabled — Moodle uses a custom Dockerfile; there is no external prebuilt image to mirror.

enable_cloudsql_volume is forced to true in moodle.tf and is not exposed as a variable. Moodle connects to Cloud SQL via the Auth Proxy Unix socket at cloudsql_volume_mount_path (default "/cloudsql").

§3.C · Environment Variables & Secrets

The following variables are automatically injected by Moodle CloudRun via module_env_vars in addition to any user-defined environment_variables. Override any auto-injected default by supplying the same key in your environment_variables map.

Auto-injected plain-text variables:

VariableInjected valueNotes
MOODLE_DB_TYPE"pgsql"Hardcoded. Cannot be changed. Set in the moodle_module local via an environment_variables merge.
ENABLE_REVERSE_PROXY"TRUE" / "FALSE""TRUE" only when application_domains is non-empty (Cloud Armor + custom domain in use). Set in the moodle_module local.
MOODLE_DATA_DIRvalue of nfs_mount_path"/mnt/nfs" by default.
DATA_PATHvalue of nfs_mount_path"/mnt/nfs" by default.
MOODLE_SITE_NAME"Moodle LMS"Override via environment_variables.
MOODLE_SITE_FULLNAME"Moodle Learning Management System"Override via environment_variables.
LANGUAGE"en"Override via environment_variables.
MOODLE_ADMIN_USER"admin"Override via environment_variables.
MOODLE_ADMIN_EMAIL"admin@example.com"Override before going live.
MOODLE_SKIP_INSTALL"no"Override via environment_variables.
MOODLE_UPDATE"yes"Override via environment_variables.
MOODLE_SMTP_HOST""Set to your SMTP hostname for outbound email.
MOODLE_SMTP_PORT"587"Override if not using submission port.
MOODLE_SMTP_USER""Set to your SMTP username.
MOODLE_SMTP_SECURE"tls""tls" or "ssl".
MOODLE_SMTP_AUTH"LOGIN"Override if using a different auth mechanism.
MOODLE_REDIS_ENABLEDtostring(enable_redis)"true" by default.
MOODLE_REDIS_HOSTredis_host, "$(NFS_SERVER_IP)", or ""When enable_redis = true and redis_host = "", the literal string "$(NFS_SERVER_IP)" is injected. cloudrun-entrypoint.sh expands this placeholder to the actual NFS server IP at container start-up. When enable_redis = false, this is set to "".
MOODLE_REDIS_PORTvalue of redis_port"6379" by default.
MOODLE_REDIS_PASSWORDvalue of redis_auth"" by default.

Auto-injected secrets (module_secret_env_vars):

DB_PASSWORD is automatically sourced from Secret Manager (generated by App CloudRun) and merged in alongside any secrets generated by Moodle Common (including MOODLE_CRON_PASSWORD and MOODLE_SMTP_PASSWORD). These are never exposed in Terraform state.

User-configurable variables:

VariableDefaultDescription
environment_variables{}Plain-text key/value pairs injected into the Cloud Run revision. Use to override any auto-injected default above or to supply additional PHP/Moodle settings.
secret_environment_variables{}Map of env var name → Secret Manager secret name. Resolved at runtime; plaintext never stored in Terraform state.
secret_propagation_delay30Seconds to wait after secret creation before proceeding with dependent operations.
secret_rotation_period"2592000s"Pub/Sub notification period for Secret Manager rotation reminders (30 days).

§3.D · Networking

VariableDefaultDescription
ingress_settings"all""all" permits public internet traffic. Use "internal-and-cloud-load-balancing" when the service is fronted by Cloud Armor.
vpc_egress_setting"PRIVATE_RANGES_ONLY"Routes only RFC 1918 traffic via the VPC connector. Set "ALL_TRAFFIC" for strict egress or on-premises connectivity.
cloudsql_volume_mount_path"/cloudsql"Container path where the Cloud SQL Auth Proxy Unix socket is mounted. Must match the socket path referenced in Moodle's database config. enable_cloudsql_volume is always true.
container_protocol"http1"HTTP protocol version. Use "h2c" only if the application supports HTTP/2 cleartext.
service_annotations{}Kubernetes-style annotations applied to the Cloud Run service for advanced configuration.
service_labels{}Additional labels applied to the Cloud Run service resource.

§3.E · Initialization & Bootstrap

Auto-provisioned Cloud Scheduler cron job:

Moodle CloudRun always creates a Cloud Scheduler job targeting Moodle's built-in cron endpoint. This job is hardcoded and cannot be disabled via variables.

PropertyValue
Schedule* * * * * (every minute)
MethodGET
Targethttps://<service_url>/admin/cron.php?password=<MOODLE_CRON_PASSWORD>
Deadline320s
TimezoneEtc/UTC

The MOODLE_CRON_PASSWORD is auto-generated by Moodle Common, stored in Secret Manager, and embedded in the scheduler job URL at provision time.

User-defined jobs:

VariableDefaultDescription
initialization_jobs[]Cloud Run jobs executed once during deployment for tasks such as database setup, plugin installation, or seed data loading. Each job runs sequentially in the order listed.
cron_jobs[]Recurring Cloud Run jobs triggered by Cloud Scheduler. Supplement (not replace) the auto-provisioned Moodle cron job.

For the initialization_jobs and cron_jobs object schemas refer to App_CloudRun §3.E.


§4 · Advanced Security

§4.A · Secret Management

Three secrets are auto-generated and stored in Secret Manager on every deployment:

SecretGenerated byInjected as
DB_PASSWORDApp CloudRunDB_PASSWORD environment variable
MOODLE_CRON_PASSWORDMoodle CommonEmbedded in Cloud Scheduler job URL
MOODLE_SMTP_PASSWORDMoodle CommonMOODLE_SMTP_PASSWORD environment variable
VariableDefaultDescription
secret_rotation_period"2592000s"Duration between Secret Manager rotation Pub/Sub notifications (30 days). Set null to disable. Format: "<seconds>s".
secret_propagation_delay30Seconds to wait after secret creation before dependent operations proceed. Increase if deployments fail with "secret not found" errors. Valid range: 0–300.
enable_auto_password_rotationfalseDeploys an automated database password rotation job using Cloud Run and Eventarc. Rotates on the secret_rotation_period schedule.
rotation_propagation_delay_sec90Seconds to wait after password rotation before restarting Cloud Run to pick up the new value.

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

IAP enforces Google identity authentication before users reach Moodle. Useful for internal institutional deployments where access should be restricted to staff or enrolled students with Google accounts.

VariableDefaultDescription
enable_iapfalseEnables Cloud Run native IAP. When true, configure iap_authorized_users and/or iap_authorized_groups.
iap_authorized_users[]Individual users or service accounts granted access. Format: "user:email@example.com".
iap_authorized_groups[]Google Groups granted access. Format: "group:name@example.com". Preferred for institution-level access management.

§4.C · Cloud Armor & CDN

Cloud Armor provides a WAF security policy fronted by a Global HTTPS Load Balancer. When application_domains is non-empty, MOODLE_REVERSE_PROXY and ENABLE_REVERSE_PROXY are automatically set to "true" / "TRUE" so Moodle generates correct HTTPS URLs behind the load balancer.

VariableDefaultDescription
enable_cloud_armorfalseEnables Cloud Armor WAF + Global HTTPS Load Balancer. Configure application_domains with your custom domain names.
application_domains[]Custom domain names associated with the load balancer. Google-managed SSL certificates are provisioned automatically. DNS must point to the LB IP before cert provisioning succeeds.
enable_cdnfalseEnables Cloud CDN on the load balancer to cache static assets at Google edge locations. Only active when enable_cloud_armor = true.
admin_ip_ranges[]IP CIDR ranges permitted to bypass certain network restrictions for administrative access.

§4.D · VPC Service Controls

VariableDefaultDescription
enable_vpc_scfalseRestricts GCP API access to requests from within a VPC-SC perimeter, preventing data exfiltration. Requires an existing VPC-SC perimeter in the project.

§4.E · Binary Authorization

VariableDefaultDescription
enable_binary_authorizationfalseEnforces a Binary Authorization policy requiring container images to carry a valid attestation before deployment. Requires a policy and attestor to be pre-configured in the project.

§5 · Traffic & Ingress

§5.A · Ingress Controls

VariableDefaultOptionsDescription
ingress_settings"all"all / internal / internal-and-cloud-load-balancing"all" allows public internet traffic directly to Cloud Run. "internal" restricts to VPC and Google internal services. "internal-and-cloud-load-balancing" is required when Cloud Armor is in front.
vpc_egress_setting"PRIVATE_RANGES_ONLY"ALL_TRAFFIC / PRIVATE_RANGES_ONLY"PRIVATE_RANGES_ONLY" routes only RFC 1918 outbound traffic via VPC. Use "ALL_TRAFFIC" when all egress must pass through a firewall or on-premises network.

§5.B · Traffic Management

VariableDefaultDescription
traffic_split[]Allocates traffic across Cloud Run revisions for canary or blue-green deployments. All entries must sum to 100. Empty list sends all traffic to the latest revision. Example: [{ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST", percent = 90 }, { type = "TRAFFIC_TARGET_ALLOCATION_TYPE_REVISION", revision = "moodle-00003", percent = 10 }].

§5.C · Custom Domains & Load Balancer

Custom domains require enable_cloud_armor = true. The module provisions a Global HTTPS Load Balancer with Google-managed SSL certificates. Setting application_domains also activates MOODLE_REVERSE_PROXY = "true" and ENABLE_REVERSE_PROXY = "TRUE" automatically so Moodle generates correct HTTPS URLs behind the load balancer.

VariableDefaultDescription
application_domains[]List of custom domains (e.g. ["moodle.university.edu"]). DNS A records must point to the load balancer IP before SSL certificates can be provisioned.
enable_cdnfalseEnables Cloud CDN on the load balancer. Caches static assets (JS, CSS, images) at Google's edge nodes, reducing latency for geographically distributed students.
admin_ip_ranges[]CIDR ranges permitted to bypass network restrictions for administrative access.

§6 · CI/CD Integration

§6.A · GitHub & Cloud Build

Moodle uses a custom Dockerfile (enable_image_mirroring = false). Cloud Build compiles the image from source on every trigger, builds and tags it in Artifact Registry, then deploys a new Cloud Run revision.

VariableDefaultDescription
enable_cicd_triggerfalseCreates a Cloud Build trigger that builds and deploys on every push to the configured branch.
github_repository_url""Full HTTPS URL of the GitHub repository (e.g. "https://github.com/my-org/moodle-app"). Required when enable_cicd_trigger = true.
github_token""GitHub Personal Access Token for repository authentication. Required scopes: repo, admin:repo_hook, workflow. Mutually exclusive with github_app_installation_id.
github_app_installation_id""Cloud Build GitHub App installation ID. Preferred over PAT for organisation repositories. Mutually exclusive with github_token.
cicd_trigger_config{ branch_pattern = "^main$" }Controls branch filter, included/ignored file paths, trigger name, and build substitutions.

§6.B · Cloud Deploy Pipelines

VariableDefaultDescription
enable_cloud_deployfalseSwitches from direct Cloud Build deployments to a managed Cloud Deploy pipeline with defined promotion stages. Requires enable_cicd_trigger = true.
cloud_deploy_stages[dev, staging, prod(approval)]Ordered promotion stages. Each stage maps to a Cloud Deploy target and associated Cloud Run service. Set require_approval = true for manual sign-off before production promotion.
enable_binary_authorizationfalseSee §4.E.

§7 · Reliability & Data

§7.A · Health Probes

Moodle exposes startup_probe and liveness_probe as dedicated top-level variables (not the startup_probe_config / health_check_config names used in Django). Both default to the /health.php endpoint, which reflects PHP availability and database connectivity — more accurate for Moodle readiness than a generic path.

VariableDefaultDescription
startup_probe{ enabled=true, type="HTTP", path="/health.php", initial_delay_seconds=0, timeout_seconds=10, period_seconds=30, failure_threshold=20 }Determines when the instance is ready to receive traffic. failure_threshold=20 with period_seconds=30 allows up to 10 minutes of startup time — sufficient for first-boot schema creation and plugin registration.
liveness_probe{ enabled=true, type="HTTP", path="/health.php", initial_delay_seconds=120, timeout_seconds=10, period_seconds=60, failure_threshold=3 }Periodically checks whether the running instance is healthy. initial_delay_seconds=120 prevents premature restarts during the post-startup period.
uptime_check_config{ enabled=true, path="/", check_interval="60s", timeout="10s" }Cloud Monitoring uptime check. Probes the service from multiple global locations and fires an alert if the endpoint becomes unreachable.

§7.B · Storage

NFS (Cloud Filestore):

VariableDefaultDescription
enable_nfstrueProvisions a Cloud Filestore NFS instance and mounts it into the container. Used as the Moodle moodledata directory for uploaded files, course materials, and user submissions. Requires execution_environment = "gen2".
nfs_mount_path"/mnt/nfs"Container path where the NFS volume is mounted. Injected as MOODLE_DATA_DIR and DATA_PATH.

GCS buckets:

An additional moodle-data bucket is always provisioned automatically via module_storage_buckets in moodle.tf. It is created regardless of the storage_buckets variable value.

VariableDefaultDescription
storage_buckets[{ name_suffix = "data" }]Additional GCS buckets to provision. Each entry defines a suffix, storage class, versioning, and access controls.
create_cloud_storagetrueSet false to skip provisioning storage_buckets (the moodle-data bucket is unaffected).
gcs_volumes[]GCS buckets to mount as GCS Fuse filesystem volumes inside the container.
nfs_instance_name""Name of an existing NFS GCE VM to use. When set, targets this instance directly instead of auto-discovering one. Leave empty to auto-discover a Services GCP-managed instance.
nfs_instance_base_name"app-nfs"Base name for the inline NFS GCE VM when no existing instance is found. The deployment ID is appended for uniqueness.
manage_storage_kms_iamfalseWhen true, creates a CMEK KMS keyring and storage encryption key and enables CMEK on all storage buckets.
enable_artifact_registry_cmekfalseWhen true, enables at-rest encryption of container images with a customer-managed key in Artifact Registry.

§7.C · Database

Moodle requires PostgreSQL. db_name and db_user are passed to Moodle Common where they configure the database name and user for initialization jobs and the application config. They are not forwarded directly to App CloudRun's application_database_name / application_database_user inputs — Moodle Common embeds them in the config output which App CloudRun consumes. MOODLE_DB_TYPE = "pgsql" is hardcoded — setting a non-PostgreSQL database type will prevent Moodle from starting.

VariableDefaultDescription
db_name"moodle"PostgreSQL database name created within the Cloud SQL instance. Injected as DB_NAME. Do not change after initial deployment — Moodle stores all data here and renaming requires manual migration.
db_user"moodle"PostgreSQL user for the Moodle application. Injected as DB_USER. Password auto-generated and injected as DB_PASSWORD.
database_password_length32Length of the auto-generated database password (16–64 characters).
enable_auto_password_rotationfalseAutomates database password rotation via Cloud Run + Eventarc. See §4.A.
rotation_propagation_delay_sec90Seconds to wait after password rotation before restarting Cloud Run.

pg_trgm extension: Required by Moodle for full-text search performance. This extension is created automatically by the db-init.sh script (part of the Moodle Common default initialization jobs) — no user configuration is needed.

§7.D · Backup & Recovery

backup_uri is the Moodle-specific name for the backup_file input in App CloudRun. The mapping is applied in main.tf (backup_file = var.backup_uri).

VariableDefaultDescription
backup_schedule"0 2 * * *"Cron expression (UTC) for the automated backup job. Leave empty to disable.
backup_retention_days7Days to retain backup files in GCS before automatic deletion.
enable_backup_importfalseTriggers a one-time import job to restore the backup at backup_uri. Runs after the database is provisioned. Test in a non-production environment before enabling on a populated database.
backup_source"gcs"Source of the backup file: "gcs" (full GCS URI) or "gdrive" (Google Drive file ID).
backup_uri""For GCS: full URI e.g. "gs://my-bucket/backups/moodle.sql.gz". For Google Drive: the file ID from the share URL. Mapped to backup_file in App CloudRun.
backup_format"sql"Format of the backup file. Accepted: sql, gz, tar, tgz, tar.gz, zip.

§8 · Integrations

§8.A · Redis Cache

Redis is enabled by default (enable_redis = true) because Cloud Run routes requests across multiple instances simultaneously. Without a shared session store, users would be logged out whenever a request reached a different instance. MOODLE_REDIS_* variables are injected automatically (see §3.C). redis_port is typed as a string (not integer).

VariableDefaultDescription
enable_redistrueEnables Redis as the PHP session handler and Moodle application cache backend.
redis_host""Redis server hostname or IP. When empty and enable_redis = true, defaults to the NFS server IP. Override with a Cloud Memorystore instance IP for production.
redis_port"6379"Redis port (string type). Change if the Redis instance is not on the default port.
redis_auth""Redis AUTH password. Leave empty if the instance does not require authentication. Treated as sensitive.

For production deployments with multiple Cloud Run instances, provision a Cloud Memorystore for Redis instance and set redis_host to its IP. The default NFS-server-as-Redis-host approach is suitable for development only.

§8.B · Custom SQL Scripts

VariableDefaultDescription
enable_custom_sql_scriptsfalseRuns .sql files from a GCS bucket against the Moodle database after provisioning. Use for schema migrations, pg_trgm extension installation, or seed data.
custom_sql_scripts_bucket""GCS bucket name (without gs:// prefix) containing the SQL scripts.
custom_sql_scripts_path""Path prefix within the bucket. All .sql files under this prefix are executed in lexicographic order.
custom_sql_scripts_use_rootfalseExecute scripts as the root database user. Enable when scripts require elevated privileges (e.g. CREATE EXTENSION).

§8.C · Observability

VariableDefaultDescription
uptime_check_config{ enabled=true, path="/", check_interval="60s", timeout="10s" }Cloud Monitoring uptime check. Probes the service from multiple global locations and fires an alert if unreachable.
alert_policies[]Cloud Monitoring alert policies. Each policy monitors a single metric and notifies support_users when the threshold is exceeded.
service_annotations{}Cloud Run service-level annotations.
service_labels{}Additional labels on the Cloud Run service.

§8.D · SMTP & Outbound Email

Moodle sends course notifications, grade reports, and account emails via SMTP. There are no dedicated Terraform variables for SMTP configuration — override the auto-injected defaults (see §3.C) using environment_variables:

environment_variables = {
MOODLE_SMTP_HOST = "smtp.sendgrid.net"
MOODLE_SMTP_PORT = "587"
MOODLE_SMTP_USER = "apikey"
MOODLE_SMTP_SECURE = "tls"
MOODLE_ADMIN_EMAIL = "admin@university.edu"
MOODLE_SITE_NAME = "University LMS"
}

secret_environment_variables = {
MOODLE_SMTP_PASSWORD = "moodle-smtp-password" # Secret Manager secret name
}

MOODLE_SMTP_PASSWORD is auto-generated by Moodle Common and stored in Secret Manager. Override its value in Secret Manager with your actual SMTP credential after deployment.


§9 · Platform-Managed Behaviours

The following behaviours are applied automatically by Moodle CloudRun regardless of the variable values in your tfvars file. They cannot be overridden by user configuration.

BehaviourDetail
enable_cloudsql_volume = trueForced in moodle.tf locals merge. Moodle always connects to Cloud SQL via the Auth Proxy Unix socket. Not exposed as a variable.
MOODLE_DB_TYPE = "pgsql"Hardcoded in moodle.tf via the moodle_module environment_variables merge. PostgreSQL is the only supported Moodle database backend on this platform.
ENABLE_REVERSE_PROXY conditionalSet to "TRUE" only when application_domains is non-empty. Set to "FALSE" otherwise. Injected via the moodle_module environment_variables merge. Note: MOODLE_REVERSE_PROXY is not injected by Moodle CloudRun; only ENABLE_REVERSE_PROXY is set.
Cloud Scheduler cron jobAlways created (* * * * *). Targets admin/cron.php with an auto-generated cron password. Cannot be disabled via variables.
moodle-data GCS bucketAlways provisioned via the hardcoded module_storage_buckets in moodle.tf, independent of the user-defined storage_buckets variable.
MOODLE_CRON_PASSWORD secretAuto-generated by Moodle Common. Embedded in the Cloud Scheduler job URL.
MOODLE_SMTP_PASSWORD secretAuto-generated by Moodle Common. Override the generated value in Secret Manager with the real SMTP credential.
DB_PASSWORD secretAuto-generated by App CloudRun. Injected via module_secret_env_vars.
scripts_dirSet to Moodle Common's bundled scripts/ directory. Cannot be overridden via tfvars.

§10 · Variable Reference

Complete reference of all Moodle CloudRun variables, their defaults, and the UI metadata group they belong to.

VariableDefaultGroup
module_description(Moodle LMS description)0
module_documentation"https://docs.radmodules.dev/docs/modules/Moodle_CloudRun"0
module_dependency["Services GCP"]0
module_services(list of GCP services)0
credit_cost500
require_credit_purchasesfalse0
enable_purgetrue0
public_accesstrue0
deployment_id""0
resource_creator_identity"rad-module-creator@tec-rad-ui-2b65.iam.gserviceaccount.com"0
project_id(required)1
tenant_deployment_id"demo"1
support_users[]1
resource_labels{}1
application_name"moodle"2
display_name"Moodle LMS"2
description"Moodle LMS - Online learning and course management platform"2
application_version"4.5.1"2
deploy_applicationtrue3
cpu_limit"1000m"3
memory_limit"2Gi"3
min_instance_count03
max_instance_count33
container_port80803
execution_environment"gen2"3
timeout_seconds3003
service_annotations{}3
service_labels{}3
enable_image_mirroringfalse3
traffic_split[]3
container_protocol"http1"3
cloudsql_volume_mount_path"/cloudsql"3
ingress_settings"all"4
vpc_egress_setting"PRIVATE_RANGES_ONLY"4
enable_iapfalse4
iap_authorized_users[]4
iap_authorized_groups[]4
environment_variables{}5
secret_environment_variables{}5
secret_propagation_delay305
secret_rotation_period"2592000s"5
backup_schedule"0 2 * * *"6
backup_retention_days76
enable_backup_importfalse6
backup_source"gcs"6
backup_uri""6
backup_format"sql"6
enable_cicd_triggerfalse7
github_repository_url""7
github_token""7
github_app_installation_id""7
cicd_trigger_config{ branch_pattern = "^main$" }7
enable_cloud_deployfalse7
cloud_deploy_stages[dev, staging, prod(approval)]7
enable_binary_authorizationfalse7
enable_custom_sql_scriptsfalse8
custom_sql_scripts_bucket""8
custom_sql_scripts_path""8
custom_sql_scripts_use_rootfalse8
enable_cloud_armorfalse9
admin_ip_ranges[]9
application_domains[]9
enable_cdnfalse9
create_cloud_storagetrue10
storage_buckets[{ name_suffix = "data" }]10
enable_nfstrue10
nfs_mount_path"/mnt/nfs"10
gcs_volumes[]10
nfs_instance_name""8
nfs_instance_base_name"app-nfs"8
manage_storage_kms_iamfalse10
enable_artifact_registry_cmekfalse10
db_name"moodle"11
db_user"moodle"11
database_password_length3211
enable_auto_password_rotationfalse11
rotation_propagation_delay_sec9011
initialization_jobs[]12
cron_jobs[]12
startup_probe{ path="/health.php", failure_threshold=20, period_seconds=30 }13
liveness_probe{ path="/health.php", initial_delay_seconds=120, period_seconds=60 }13
uptime_check_config{ enabled=true, path="/", check_interval="60s" }13
alert_policies[]13
enable_redistrue21
redis_host""21
redis_port"6379"21
redis_auth""21
enable_vpc_scfalse22
vpc_cidr_ranges[]22
vpc_sc_dry_runtrue22
organization_id""22
enable_audit_loggingfalse22
max_images_to_retain79
delete_untagged_imagestrue9
image_retention_days309
max_revisions_to_retain73

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
project_id(required)CriticalNo default — deployment fails immediately.
database_type"POSTGRES_15"CriticalMoodle supports both MySQL and PostgreSQL, but this module defaults to PostgreSQL 15. Changing to MYSQL requires verifying the Moodle config generation logic wires MySQL-specific settings. Setting NONE breaks all data persistence.
enable_nfstrueCriticalMoodle stores all moodledata (course files, user submissions, plugin caches, session data) on NFS. Without NFS, the moodledata directory is ephemeral — uploaded course materials and student submissions are lost on every new revision. Multiple instances will have inconsistent data directories. NFS is mandatory for any real Moodle deployment.
enable_redistrueHighMoodle uses Redis for session storage and application caching. Without Redis, multiple Cloud Run instances use isolated PHP file sessions — students hitting different instances lose their sessions between page loads. Redis is essential for multi-instance Moodle deployments.
redis_host"" (auto-resolves to NFS IP)HighWhen redis_host = "" the module uses the NFS server IP. If enable_nfs = false and redis_host is also empty, Moodle cannot initialise sessions and will fail to serve authenticated pages.
cron_jobs[] (none configured)CriticalMoodle requires a cron job running php /var/www/html/admin/cli/cron.php at least every minute (recommended every 5 minutes) to process course notifications, grade calculations, forum digests, assignment reminders, and scheduled tasks. Without cron, these functions are silently skipped — grade changes may not notify students, forum digests never send, and scheduled quiz windows do not open or close.
memory_limit"2Gi"HighThe default is 2Gi. Moodle with active plugin suites (Turnitin, H5P, BigBlueButton) can require 4–8Gi per instance under load. Insufficient memory causes PHP fatal errors during course rendering or file processing. Never run below 1Gi.
cpu_limit"1000m"MediumMoodle course rendering and quiz grading are CPU-intensive. For deployments with concurrent student activity, 2000m is recommended to avoid request queuing.
min_instance_count0HighThe default is 0 (scale-to-zero). Cold starts for Moodle are 30–60 seconds (PHP init + database connection pool). Students arriving during a cold start experience login failures or 504 timeouts. Set to 1 for any scheduled exam or live class period.
execution_environment"gen2"HighNFS mounts require gen2. Changing to "gen1" with enable_nfs = true causes the Cloud Run service to fail to start with a volume mount error.
application_database_name"moodle"CriticalImmutable after first deployment — changing this recreates the database, destroying all course data, enrolments, grades, and user accounts.
application_database_user"moodle"CriticalImmutable after first deployment — changing this recreates the user, breaks the existing database connection, and locks out the application.
database_password_length32MediumMinimum 16 enforced. Moodle config stores the database password — longer passwords reduce brute-force risk on the Cloud SQL endpoint.
ingress_settings"all"Medium"all" exposes the Moodle admin panel to the public internet. Consider enable_iap = true or Cloud Armor rules to restrict /admin access to known IP ranges.
enable_cloud_armorfalseMediumMoodle login pages are common targets for credential stuffing, particularly for institutions with many student accounts. Cloud Armor WAF is recommended for any public-facing LMS.
enable_backup_importfalseCriticalRequires backup_uri to be set and accessible. Enabling with an empty backup_uri causes the restore job to fail during apply.
backup_retention_days7HighEducational data including grades and course records must be retained longer than 7 days for compliance. Increase to at least 30 days; 90+ days for accredited institutions.
timeout_seconds300MediumMoodle operations like course backup/restore, gradebook exports, and plugin installations can exceed 300 seconds. Increase to 3600 for deployments performing heavy administrative operations via HTTP.
enable_custom_sql_scriptsfalseMediumRequires custom_sql_scripts_bucket and custom_sql_scripts_path when enabled. Leaving them empty with the flag true causes the init job to fail.
secret_propagation_delay30LowIncrease to 60–90 seconds in multi-region deployments to prevent "secret not found" errors during apply.
enable_iapfalseMediumMoodle admin access is protected only by Moodle's own auth when IAP is disabled. Recommended for institutional 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.