Skip to main content

Odoo CloudRun Module — Configuration Guide

Odoo CloudRun deploys Odoo Community Edition on Google Cloud Run, backed by Cloud SQL PostgreSQL and a Cloud Filestore NFS volume for shared file storage. It is a wrapper module built on top of App CloudRun. All GCP infrastructure (Cloud Run service, networking, Cloud SQL, GCS, secrets, CI/CD) is provisioned by App CloudRun. Odoo CloudRun adds Odoo-specific application configuration, two platform-managed initialisation jobs, the master-password secret, and runtime defaults tuned for Odoo's startup characteristics.

The module uses Odoo Common as a sub-module to resolve application configuration, secrets, and storage bucket lists, which are then passed into App CloudRun via application_config, module_secret_env_vars, and module_storage_buckets.


§1 · Module Overview

AttributeValue
Underlying platformApp CloudRun
Sub-moduleOdoo Common
ApplicationOdoo Community Edition
Default version18.0 (nightly build channel)
DatabaseCloud SQL PostgreSQL (required)
Persistent storageCloud Filestore NFS (enable_nfs = true by default)
Default container port8069
Default image sourcecustom (Cloud Build from Odoo nightly Dockerfile)
Max instances default1 (increase only after configuring Redis session store)
RedisOptional session store; enable_redis = false by default
Platform-managed jobsnfs-init (directory setup) + db-init (database creation)
Platform-managed secretODOO_MASTER_PASS (auto-generated, stored in Secret Manager)

Wrapper Architecture

Odoo_CloudRun (variables.tf / odoo.tf / main.tf)
└─ Odoo_Common ← resolves app config, scripts, master-pass secret
└─ App_CloudRun ← provisions all GCP infrastructure

Odoo Common outputs:

  • config → merged into application_config passed to App CloudRun
  • odoo_master_pass_secret_id → injected as ODOO_MASTER_PASS via module_secret_env_vars
  • storage_buckets → merged into module_storage_buckets
  • path → used to resolve scripts_dir

§2 · IAM & Project Identity

VariableDefaultDescription
project_idGCP project ID. All resources are created in this project. Grant the Owner role to rad-module-creator@tec-rad-ui-2b65.iam.gserviceaccount.com.
tenant_deployment_id"demo"Short suffix appended to resource names. Use "prod", "staging", etc. to deploy multiple environments in the same project.
resource_creator_identity"rad-module-creator@…"Service account used by Terraform. Override with a project-specific SA for production.
support_users[]Email addresses of users granted IAM access and added as alert notification recipients.
resource_labels{}Key-value labels applied to all resources (cost centre, team, environment).
deployment_id""Optional fixed deployment ID. A random hex ID is generated when left empty.

§3 · Core Service Configuration

§3.A · Application Identity

VariableDefaultDescription
application_name"odoo"Internal identifier used as the base name for the Cloud Run service, Artifact Registry repository, Secret Manager secrets, and GCS buckets. Do not change after initial deployment.
application_display_name"Odoo ERP"Human-readable name shown in the platform UI, Cloud Run console, and monitoring dashboards. Safe to update at any time.
application_description"Odoo ERP on Cloud Run"Brief description populated into the Cloud Run service description field.
application_version"18.0"Odoo release version. Maps directly to the nightly build channel used in the Dockerfile (ODOO_VERSION build arg). Supported values: "18.0", "17.0", "16.0". Changing this when container_image_source = "custom" triggers a new Cloud Build run.

application_display_name and application_description are passed to Odoo Common as display_name and description, then merged into the application_config object consumed by App CloudRun.

§3.B · Resource Sizing

Odoo is memory-intensive. Its Python workers and database connection pool typically consume 1.5–3 Gi under normal load. cpu_limit and memory_limit are dedicated top-level variables that take precedence over container_resources when both are set.

VariableDefaultDescription
cpu_limit"1000m"CPU allocated per instance. Increase to "2000m" or higher for production. CPU above "1000m" requires min_instance_count >= 1.
memory_limit"1Gi"Memory per instance. Minimum "2Gi" recommended for production; below "2Gi" causes OOM kills under load.
container_resources{ cpu_limit = "1000m", memory_limit = "512Mi" }Structured resource object. Takes precedence over cpu_limit / memory_limit when explicitly set.
min_instance_count0Scale-to-zero by default. Set to 1 for production to eliminate cold starts (60–180 s for Odoo).
max_instance_count1Keep at 1 until Redis session store is configured; multiple instances without Redis cause session inconsistency.
timeout_seconds300Maximum request duration (0–3600 s). Increase for long Odoo operations such as report generation or data imports.
execution_environment"gen2"Required for NFS mounts. Do not change to "gen1" when enable_nfs = true.

Recommended production sizing:

cpu_limit          = "2000m"
memory_limit = "4Gi"
min_instance_count = 1
max_instance_count = 3 # only after configuring Redis

§3.C · Environment Variables & Secrets

VariableDefaultDescription
environment_variables{}Plain-text environment variables injected at runtime. Use for SMTP settings, feature flags, and other non-sensitive config.
secret_environment_variables{}Map of env var name → Secret Manager secret name. Values resolved at runtime; never stored in plaintext.
explicit_secret_values{}Raw sensitive values written into Secret Manager during deployment. Use to set a custom ODOO_MASTER_PASS or SMTP password. Sensitive; never stored in Terraform state in plaintext.
secret_rotation_period"2592000s"Rotation reminder period (30 days default). Set null to disable.
secret_propagation_delay30Seconds to wait after secret creation before dependent operations proceed.

Configuring SMTP for Odoo email notifications:

environment_variables = {
SMTP_HOST = "smtp.sendgrid.net"
SMTP_PORT = "587"
SMTP_USER = "apikey"
SMTP_SSL = "true"
EMAIL_FROM = "noreply@yourcompany.example.com"
}

secret_environment_variables = {
SMTP_PASSWORD = "odoo-smtp-password" # Secret Manager secret name
}

To set a known master password instead of the auto-generated one:

explicit_secret_values = {
ODOO_MASTER_PASS = "your-chosen-master-password"
}

§3.D · Networking

VariableDefaultDescription
ingress_settings"all"Traffic sources permitted to reach Cloud Run. "all" = public internet; "internal" = VPC only; "internal-and-cloud-load-balancing" = when fronted by a GLB.
vpc_egress_setting"PRIVATE_RANGES_ONLY"Outbound VPC routing. "PRIVATE_RANGES_ONLY" routes RFC 1918 traffic via VPC; "ALL_TRAFFIC" routes all egress via VPC.
container_port8069Port Odoo listens on inside the container. Do not change unless the Odoo server config binds to a different port.
container_protocol"http1"HTTP version: "http1" or "h2c". Use "http1" for Odoo.
cloudsql_volume_mount_path"/cloudsql"Path where the Cloud SQL Auth Proxy Unix socket is mounted. Only used when enable_cloudsql_volume = true.
enable_cloudsql_volumetrueInjects Cloud SQL Auth Proxy sidecar for Unix socket connections to Cloud SQL. Disable only when connecting via TCP.

§3.E · Container Image & Build

Odoo CloudRun defaults to building a custom container image from the official Odoo nightly packages via Cloud Build. Set container_image_source = "prebuilt" to skip the build and deploy a pre-existing image directly.

VariableDefaultDescription
container_image_source"custom""custom" = build from source using Cloud Build; "prebuilt" = deploy an existing image directly.
container_image""Full image URI (e.g. "us-docker.pkg.dev/my-project/repo/odoo:18.0"). Used when container_image_source = "prebuilt" or to override the built image.
container_build_config{ enabled = true }Cloud Build configuration: dockerfile_path, context_path, build_args, artifact_repo_name. Set enabled = false to skip the build step.
enable_image_mirroringtrueMirrors the image into Artifact Registry before deploy. Recommended to avoid Docker Hub rate limits.
deploy_applicationtrueSet false to provision infrastructure only without deploying the container (useful for staged rollouts).

§4 · Advanced Security

§4.A · Automated Password Rotation

VariableDefaultDescription
enable_auto_password_rotationfalseDeploys a Cloud Run + Eventarc automated rotation job. Rotates the database password on the schedule set by secret_rotation_period.
rotation_propagation_delay_sec90Seconds to wait after rotation before Cloud Run restarts to pick up the new value.
secret_rotation_period"2592000s"Rotation reminder interval. Also used as the trigger period when enable_auto_password_rotation = true.

§4.B · VPC Service Controls

VariableDefaultDescription
enable_vpc_scfalseEnforces VPC-SC perimeter. Restricts GCP API calls to requests originating inside the perimeter. Requires an existing VPC-SC perimeter in the project.
vpc_cidr_ranges[]VPC subnet CIDR ranges for the VPC-SC network access level. Auto-discovered from the VPC when empty; falls back to 10.0.0.0/8 if discovery finds nothing.
vpc_sc_dry_runtrueWhen true, VPC-SC violations are logged but not blocked — recommended for initial rollout. Set false to actively enforce the perimeter.
organization_id""GCP Organization ID for the VPC-SC Access Context Manager policy. Auto-discovered when empty. Must be set explicitly when the project is nested under a folder.
enable_audit_loggingfalseEnables detailed Cloud Audit Logs (DATA_READ, DATA_WRITE, ADMIN_READ) for all supported GCP services. Recommended for compliance-sensitive environments.

§4.C · Identity-Aware Proxy

VariableDefaultDescription
enable_iapfalseEnables Cloud Run native IAP. Requires Google identity authentication before the application is accessible.
iap_authorized_users[]Users granted access: "user:alice@example.com", "serviceAccount:sa@project.iam.gserviceaccount.com".
iap_authorized_groups[]Google Groups granted access: "group:engineering@example.com".

§4.D · Cloud Armor & CDN

VariableDefaultDescription
enable_cloud_armorfalseProvisions a Global HTTPS Load Balancer with a Cloud Armor WAF policy (OWASP Top 10, DDoS mitigation). Required when application_domains is set.
application_domains[]Custom domains. Google-managed SSL certificates are provisioned per domain. DNS must point to the GLB IP before cert provisioning completes.
enable_cdnfalseEnables Cloud CDN on the GLB to cache static assets at edge. Only used when enable_cloud_armor = true.
admin_ip_ranges[]IP CIDR ranges permitted for direct administrative access.

§4.E · Binary Authorization

VariableDefaultDescription
enable_binary_authorizationfalseEnforces Binary Authorization policy. Images must carry a valid attestation before deployment. Requires a Binary Authorization policy and attestor to be configured in the project.

§5 · Traffic & Ingress

§5.A · Traffic Splitting

Canary or blue-green deployments can be configured by splitting traffic across Cloud Run revisions. All entries must sum to exactly 100%.

VariableDefaultDescription
traffic_split[]List of traffic allocations. Each entry: { type, percent, revision?, tag? }. Leave empty to send all traffic to the latest revision.

Example — canary deployment:

traffic_split = [
{ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST", percent = 90 },
{ type = "TRAFFIC_TARGET_ALLOCATION_TYPE_REVISION", percent = 10, revision = "odoo-00003-abc" },
]

§5.B · Service Annotations & Labels

VariableDefaultDescription
service_annotations{}Kubernetes-style annotations applied to the Cloud Run service resource. Use for advanced Cloud Run config not exposed as a first-class attribute.
service_labels{}Labels applied to the Cloud Run service (in addition to resource_labels).

§6 · CI/CD Integration

§6.A · GitHub Integration

VariableDefaultDescription
enable_cicd_triggerfalseEnables a Cloud Build trigger that automatically builds and deploys when code is pushed to the configured repository.
github_repository_url""Full HTTPS URL of the GitHub repository. Required when enable_cicd_trigger = true.
github_token""GitHub PAT for repository authentication. Mutually exclusive with github_app_installation_id.
github_app_installation_id""Cloud Build GitHub App installation ID. Preferred for organisation repositories.
cicd_trigger_config{ branch_pattern = "^main$" }Advanced trigger config: branch_pattern, included_files, ignored_files, trigger_name, substitutions.

§6.B · Cloud Deploy

VariableDefaultDescription
enable_cloud_deployfalseSwitches CI/CD from direct Cloud Build deployments to a managed Cloud Deploy pipeline. Requires enable_cicd_trigger = true.
cloud_deploy_stages[dev, staging, prod]Ordered promotion stages. Each stage: name, require_approval, auto_promote. prod requires approval by default.

§7 · Reliability & Data

§7.A · Health Probes

Odoo performs database schema validation and full module installation on first boot, taking 2–10 minutes. The module exposes two sets of probe variable names:

  • startup_probe / liveness_probe — passed to Odoo Common; these are the primary variables to configure for Odoo probe tuning.
  • startup_probe_config / health_check_config — the App CloudRun interface names, also passed directly. They have Odoo-specific /web/health defaults.

When both are supplied, startup_probe_config / health_check_config take precedence on the App CloudRun side; startup_probe / liveness_probe apply via Odoo Common.

VariableDefaultDescription
startup_probe{ enabled = true, type = "TCP", path = "/", initial_delay_seconds = 60, timeout_seconds = 10, period_seconds = 30, failure_threshold = 3 }TCP port check on startup. More reliable than HTTP during Odoo's boot phase. For first deployments with schema creation, increase failure_threshold to 6.
liveness_probe{ enabled = true, type = "HTTP", path = "/web/health", initial_delay_seconds = 120, timeout_seconds = 60, period_seconds = 120, failure_threshold = 3 }HTTP check against /web/health, which returns 200 only when Odoo has a live database connection. period_seconds = 120 avoids unnecessary database load.
startup_probe_config{ enabled = true, path = "/web/health", initial_delay_seconds = 180, timeout_seconds = 60, period_seconds = 120, failure_threshold = 3 }Structured App CloudRun startup probe with Odoo-tuned defaults.
health_check_config{ enabled = true, path = "/web/health", initial_delay_seconds = 30, timeout_seconds = 5, period_seconds = 30, failure_threshold = 3 }Structured App CloudRun liveness probe with Odoo-tuned defaults.

§7.B · Storage

VariableDefaultDescription
enable_nfstrueProvisions a Cloud Filestore NFS instance. Required for Odoo filestore, session, and extra-addons directories. Requires execution_environment = "gen2".
nfs_mount_path"/mnt/nfs"Container mount path for the NFS volume as seen by App CloudRun. Odoo Common always passes nfs_mount_path = "/mnt" inside application_config; this variable controls the top-level NFS mount that App CloudRun provisions. The nfs-init job creates subdirectories (/mnt/filestore, /mnt/sessions, /mnt/extra-addons) under /mnt.
nfs_instance_name""Name of an existing NFS GCE VM to use. When set, targets this instance directly instead of auto-discovering one.
nfs_instance_base_name"app-nfs"Base name for the inline NFS GCE VM created when no existing NFS server is found.
storage_buckets[{ name_suffix = "data" }]GCS buckets to provision. Odoo Common may provision additional buckets via module_storage_buckets.
create_cloud_storagetrueSet false to skip GCS bucket provisioning.
gcs_volumes[]GCS buckets to mount as GCS Fuse volumes inside the container.
manage_storage_kms_iamfalseCreates a CMEK KMS keyring and storage key, grants the GCS service account the Cloud KMS encrypter/decrypter role, and enables CMEK encryption on all storage buckets.
enable_artifact_registry_cmekfalseCreates an Artifact Registry KMS key and grants the Artifact Registry service identity the encrypter/decrypter role, enabling CMEK at-rest encryption for container images.

§7.C · Database

Odoo requires PostgreSQL. application_database_name and application_database_user are the Odoo-specific defaults for the database and user provisioned by App CloudRun. All DB connection variables (DB_NAME, DB_USER, DB_PASSWORD, etc.) are injected automatically — see §9 Platform-Managed Behaviours.

VariableDefaultDescription
application_database_name"odoo"PostgreSQL database name. Injected as DB_NAME. Do not change after initial deployment.
application_database_user"odoo"PostgreSQL user. Password auto-generated; injected as DB_PASSWORD.
database_password_length32Auto-generated password length (16–64 characters).
enable_auto_password_rotationfalseAutomates password rotation via Cloud Run + Eventarc. See §4.A.
rotation_propagation_delay_sec90Seconds to wait after rotation before Cloud Run restarts.

§7.D · Backup & Recovery

VariableDefaultDescription
backup_schedule"0 2 * * *"Cron expression (UTC) for automated backups. Leave empty to disable.
backup_retention_days7Days to retain backup files before automatic deletion.
enable_backup_importfalseTriggers a one-time import job to restore a backup on the next terraform apply.
backup_source"gcs"Source: "gcs" (filename in the backups bucket) or "gdrive" (Google Drive file ID).
backup_file"backup.sql"For GCS: filename in the backups bucket. For Google Drive: the file ID from the share URL.
backup_format"sql"Format: sql, gz, tar, tgz, tar.gz, zip, auto.

§8 · Integrations

§8.A · Redis Session Store

When max_instance_count > 1, Redis is required. Without it each instance has its own session store and users are logged out on requests landing on different instances.

VariableDefaultDescription
enable_redisfalseConfigures Odoo to use Redis for session storage. Injects SESSION_REDIS, REDIS_HOST, and REDIS_PORT automatically. Requires redis_host to be set.
redis_host""Redis hostname or IP. For Cloud Memorystore use the primary endpoint IP. Required when enable_redis = true.
redis_port"6379"Redis TCP port (string).
redis_auth""Redis AUTH password. Leave empty if authentication is not enabled. Treated as sensitive.

§8.B · Custom SQL Scripts

VariableDefaultDescription
enable_custom_sql_scriptsfalseRuns .sql files from GCS against the Odoo database after provisioning. Useful for schema migrations or seed data.
custom_sql_scripts_bucket""GCS bucket name (without gs://) containing the scripts.
custom_sql_scripts_path""Path prefix within the bucket. Files are run in lexicographic order; use numeric prefixes (e.g. 001_schema.sql).
custom_sql_scripts_use_rootfalseRun scripts as the root database user (for extension creation, role management).

§8.C · Jobs & Scheduled Tasks

User-defined initialization and cron jobs are passed through to App CloudRun in addition to the two platform-managed jobs (nfs-init and db-init — see §9).

VariableDefaultDescription
initialization_jobs[]Cloud Run jobs executed once during deployment. Each job requires at least one of command, args, or script_path.
cron_jobs[]Recurring Cloud Scheduler-triggered jobs. Each entry requires name and schedule (cron format, UTC).
additional_services[]Additional Cloud Run services deployed alongside Odoo (e.g. Celery workers, background processors). Each service URL can be injected into Odoo via output_env_var_name.

§8.D · Observability

VariableDefaultDescription
uptime_check_config{ enabled = true, path = "/" }Cloud Monitoring uptime check. check_interval and timeout use "Ns" format.
alert_policies[]Metric-threshold alert policies. Each entry: name, metric_type, comparison, threshold_value, duration_seconds.
service_annotations{}Kubernetes-style annotations on the Cloud Run service resource.
service_labels{}Labels on the Cloud Run service (in addition to resource_labels).

§9 · Platform-Managed Behaviours

These are set automatically by the module and cannot be overridden via input variables.

Initialisation Jobs (always run)

JobWhat it does
nfs-initMounts the Filestore NFS share and creates /mnt/filestore, /mnt/sessions, and /mnt/extra-addons with ownership 101:101 (Odoo process user). Must succeed before the Cloud Run service starts.
db-initCreates the Odoo database and application user using credentials from Secret Manager. Runs after nfs-init.

Environment Variables (always injected)

VariableValue / SourceNotes
ODOO_MASTER_PASSSecret Manager refAuto-generated 16-char alphanumeric password stored as app<app_name><tenant_id><random_hex>-master-password (where random_hex is an internally-generated suffix, not the user-supplied deployment_id). The secret ID is passed via module_secret_env_vars. Used for Odoo's database management interface.
DB_PASSWORDSecret Manager refAuto-generated database password from App CloudRun; injected for the Odoo application user.
ROOT_PASSWORDSecret Manager refSame auto-generated database password; used by db-init for superuser setup.

Structural Wiring

BehaviourDetail
scripts_dirResolved as abspath("${module.odoo_app.path}/scripts") — points to Odoo Common's bundled scripts.
module_env_varsEmpty {}. All Odoo env vars are set via environment_variables or auto-injected by App CloudRun.
module_secret_env_vars{ ODOO_MASTER_PASS = module.odoo_app.odoo_master_pass_secret_id }.
module_storage_bucketsmodule.odoo_app.storage_buckets from Odoo Common.
application_configBuilt from Odoo Common config merged with container_image_source, container_image, container_port, and container_resources overrides when set.

§10 · Variable Reference

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

GroupVariableTypeDefaultUpdatable
0module_descriptionstring(long description)
0module_documentationstring"https://docs.radmodules.dev/docs/modules/Odoo_CloudRun"
0module_dependencylist(string)["Services GCP"]
0module_serviceslist(string)(service list)
0credit_costnumber50
0require_credit_purchasesboolfalse
0enable_purgebooltrue
0public_accessbooltrue
0deployment_idstring""yes
0resource_creator_identitystring"rad-module-creator@…"yes
1project_idstringyes
1tenant_deployment_idstring"demo"yes
1support_userslist(string)[]yes
1resource_labelsmap(string){}yes
2application_namestring"odoo"
2application_display_namestring"Odoo ERP"yes
2application_descriptionstring"Odoo ERP on Cloud Run"yes
2application_versionstring"18.0"yes
3deploy_applicationbooltrueyes
3container_image_sourcestring"custom"yes
3container_imagestring""yes
3container_build_configobject{ enabled = true }yes
3enable_image_mirroringbooltrueyes
3cpu_limitstring"1000m"yes
3memory_limitstring"1Gi"yes
3container_resourcesobject{ cpu_limit = "1000m", memory_limit = "512Mi" }yes
3min_instance_countnumber0yes
3max_instance_countnumber1yes
3container_portnumber8069yes
3container_protocolstring"http1"yes
3execution_environmentstring"gen2"yes
3timeout_secondsnumber300yes
3enable_cloudsql_volumebooltrueyes
3cloudsql_volume_mount_pathstring"/cloudsql"yes
3traffic_splitlist(object)[]yes
3service_annotationsmap(string){}yes
3service_labelsmap(string){}yes
3max_revisions_to_retainnumber7yes
4ingress_settingsstring"all"yes
4vpc_egress_settingstring"PRIVATE_RANGES_ONLY"yes
4enable_iapboolfalseyes
4iap_authorized_userslist(string)[]yes
4iap_authorized_groupslist(string)[]yes
5environment_variablesmap(string){}yes
5secret_environment_variablesmap(string){}yes
5secret_rotation_periodstring"2592000s"yes
5secret_propagation_delaynumber30yes
5explicit_secret_valuesmap(string){}yes
6backup_schedulestring"0 2 * * *"yes
6backup_retention_daysnumber7yes
6enable_backup_importboolfalseyes
6backup_sourcestring"gcs"yes
6backup_filestring"backup.sql"yes
6backup_formatstring"sql"yes
7enable_cicd_triggerboolfalseyes
7github_repository_urlstring""yes
7github_tokenstring""yes
7github_app_installation_idstring""yes
7cicd_trigger_configobject{ branch_pattern = "^main$" }yes
7enable_cloud_deployboolfalseyes
7cloud_deploy_stageslist(object)[dev, staging, prod]yes
7enable_binary_authorizationboolfalseyes
8enable_custom_sql_scriptsboolfalseyes
8custom_sql_scripts_bucketstring""yes
8custom_sql_scripts_pathstring""yes
8custom_sql_scripts_use_rootboolfalseyes
9enable_cloud_armorboolfalseyes
9admin_ip_rangeslist(string)[]yes
9application_domainslist(string)[]yes
9enable_cdnboolfalseyes
9max_images_to_retainnumber7yes
9delete_untagged_imagesbooltrueyes
9image_retention_daysnumber30yes
10create_cloud_storagebooltrueyes
10storage_bucketslist(object)[{ name_suffix = "data" }]yes
10enable_nfsbooltrue
10nfs_mount_pathstring"/mnt/nfs"
10nfs_instance_namestring""yes
10nfs_instance_base_namestring"app-nfs"yes
10gcs_volumeslist(object)[]yes
10manage_storage_kms_iamboolfalseyes
10enable_artifact_registry_cmekboolfalseyes
11application_database_namestring"odoo"
11application_database_userstring"odoo"
11database_password_lengthnumber32yes
11enable_auto_password_rotationboolfalseyes
11rotation_propagation_delay_secnumber90yes
12initialization_jobslist(object)[]yes
12cron_jobslist(object)[]yes
12additional_serviceslist(object)[]yes
13startup_probeobject{ type = "TCP", initial_delay_seconds = 60, … }yes
13liveness_probeobject{ type = "HTTP", path = "/web/health", initial_delay_seconds = 120, … }yes
13startup_probe_configobject{ path = "/web/health", initial_delay_seconds = 180, … }yes
13health_check_configobject{ path = "/web/health", initial_delay_seconds = 30, … }yes
13uptime_check_configobject{ enabled = true, path = "/" }yes
13alert_policieslist(object)[]yes
21enable_redisboolfalseyes
21redis_hoststring""yes
21redis_portstring"6379"yes
21redis_authstring""yes
22enable_vpc_scboolfalseyes
22vpc_cidr_rangeslist(string)[]yes
22vpc_sc_dry_runbooltrueyes
22organization_idstring""yes
22enable_audit_loggingboolfalseyes

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"CriticalOdoo requires PostgreSQL exclusively. Setting to MYSQL will cause Odoo to fail at startup with a database driver error — Odoo's ORM (psycopg2) is PostgreSQL-only. Setting NONE leaves Odoo with no database and prevents any ERP functionality.
enable_nfstrueCriticalOdoo stores all file attachments, binary fields, and the filestore (images, documents, compiled assets) under its data directory. Without NFS, all attachments and uploaded documents are ephemeral — lost on every container revision and not shared across multiple instances. Odoo running without NFS is suitable only for stateless testing.
enable_redisfalseMediumRedis is not enabled by default for Odoo. Odoo can use Redis for session storage in multi-worker deployments. Without Redis, multiple Cloud Run instances use isolated sessions — enabling Redis with a valid redis_host is recommended for production deployments with multiple instances.
redis_host""HighRequired when enable_redis = true. An empty redis_host with enable_redis = true causes Odoo session connection failures at startup.
application_version"18.0"HighOdoo uses application_version to select the nightly build URL. An invalid or non-existent version tag (e.g., a specific patch version that is not a nightly tag) causes the Cloud Build step to fail when downloading the Odoo source. Always use a valid major version string ("18.0", "17.0").
container_image_source"custom"HighOdoo requires a custom-built image to wire the PostgreSQL socket path, addons directory, and filestore paths. Using "prebuilt" with an upstream Odoo image that is not configured for Cloud SQL Unix socket connections will fail to connect to the database.
execution_environment"gen2"HighNFS mounts require gen2. Changing to "gen1" while enable_nfs = true causes the Cloud Run service to fail to start with a volume mount error.
memory_limitvariesHighOdoo is a heavy Python application. Running with less than 2Gi causes out-of-memory errors during module installation and heavy ERP operations. For production with accounting, manufacturing, and e-commerce modules, provision 4–8Gi.
cpu_limitvariesMediumOdoo workers are CPU-intensive under concurrent user load. Reduce below 1000m at your own risk — Odoo's long-polling (gevent) worker requires consistent CPU availability.
min_instance_count1HighScale-to-zero (0) causes Odoo cold starts of 30–60 seconds. Odoo also has background schedulers that require a live instance — cold starts disrupt cron job execution. Keep at 1 for any production ERP deployment.
application_database_name"odoo"CriticalImmutable after first deployment — changing this recreates the database and destroys all ERP data including accounting records, inventory, customers, and orders.
application_database_user"odoo"CriticalImmutable after first deployment — changing this recreates the user and breaks all database connections.
ingress_settings"all"High"all" exposes the Odoo web portal to the public internet. The Odoo database manager page (/web/database/manager) should be protected — it allows unauthenticated database creation and deletion. Restrict access via Cloud Armor or set a strong ODOO_MASTER_PASS.
explicit_secret_values (ODOO_ADMIN_PASSWD)CriticalThe Odoo master password (ODOO_ADMIN_PASSWD) is used to access the database manager and perform critical database operations. If left at the default or set to a weak value, any user who can reach /web/database/manager can drop the Odoo database. Always set a strong, unique master password.
enable_backup_importfalseCriticalRequires a valid backup_uri (or backup_file). Enabling with an empty path causes the restore job to fail during apply.
backup_retention_days7HighOdoo contains critical business data (financial records, contracts, orders). Seven days is insufficient for most businesses. Increase to 30+ days; many jurisdictions require financial data retention for 7 years.
enable_cloud_armorfalseHighThe Odoo database manager and admin portal should be protected from public internet access. Cloud Armor WAF is strongly recommended for any production ERP deployment.
timeout_seconds300MediumOdoo module installation, data migration, and large report generation can exceed 300 seconds. Increase to 3600 for deployments that run long administrative operations via HTTP.
secret_propagation_delay30LowIncrease to 60–90 seconds in multi-region projects to prevent sporadic "secret not found" errors during apply.
enable_iapfalseMediumOdoo admin panel and CRM data are sensitive. Enabling IAP adds a layer of authentication before reaching the Odoo login screen. Recommended for internal ERP deployments.
database_password_length32MediumThe minimum enforced is 16. For a business-critical ERP, do not reduce the default 32-character password.

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.