Skip to main content

Certification track: Associate Cloud Engineer (ACE)

Umami on Google Cloud Run

Umami on Google Cloud Run

This document provides a comprehensive reference for the modules/Umami_CloudRun Terraform module. It covers architecture, IAM, configuration variables, Umami-specific behaviours, and operational patterns for deploying Umami on Google Cloud Run (v2).


1. Module Overview

Umami is a privacy-focused, lightweight, open-source web analytics platform — a self-hosted alternative to Google Analytics. It collects website traffic and event data without cookies or personal data, making it GDPR, CCPA, and PECR compliant out of the box. Umami CloudRun is a wrapper module built on top of App CloudRun. It uses App CloudRun for all GCP infrastructure provisioning and injects Umami-specific application configuration, database initialisation, and secret management via Umami Common.

Key Capabilities:

  • Compute: Cloud Run v2 (Gen2), Next.js container, 1 vCPU / 512Mi by default. Scale-to-zero (min_instance_count = 0) supported; max_instance_count defaults to 3.
  • Data Persistence: Cloud SQL PostgreSQL 15. Umami is a stateless analytics service — all data lives in PostgreSQL. No GCS storage is provisioned by default.
  • Security: APP_SECRET auto-generated by Umami Common and stored in Secret Manager. Inherits Cloud Armor WAF, IAP, Binary Authorization, and VPC Service Controls from App CloudRun.
  • Privacy: No cookies used by default, no personal data stored, fully GDPR/CCPA/PECR compliant.
  • Health endpoint: Umami exposes /api/heartbeat as its health endpoint. Both startup and liveness probes target this path.
  • CI/CD: Custom Cloud Build image pipeline by default; Cloud Deploy progressive delivery optional.
  • Tracking: After deployment, embed <script async src="https://<your-url>/script.js" data-website-id="..."></script> in tracked websites.

Project & Application Identity

VariableGroupTypeDefaultDescription
project_id1stringGCP project ID. Required.
region1string'us-central1'GCP region for all resources.
tenant_deployment_id2string'demo'Short suffix appended to all resource names.
support_users2list(string)[]Email recipients for monitoring alerts.
resource_labels2map(string){}Labels applied to all provisioned resources.
application_name3string'umami'Base resource name. Do not change after initial deployment.
application_display_name3string'Umami'Human-readable name shown in the GCP Console.
application_description3string'Umami Analytics on Cloud Run'Cloud Run service description.
application_version3string'postgresql-latest'Umami image version tag. Use a postgresql- prefixed tag (e.g., postgresql-latest, postgresql-v2.11.3).

Wrapper architecture: Umami CloudRun calls Umami Common to build an application_config object containing Umami-specific environment variables, probe configuration, and the db-init job definition. module_secret_env_vars carries APP_SECRET from Umami Common. The DATABASE_URL is constructed at runtime from the DB_* platform variables injected by App CloudRun. scripts_dir is resolved to abspath("${module.umami_app.path}/scripts") at apply time.

PostgreSQL note: Umami requires PostgreSQL 15. database_type = "POSTGRES_15" is the default and should not be changed.

Default admin credentials: On first deployment, log in with username admin and password umami. Change these immediately after first login.


2. IAM & Access Control

Umami_CloudRun delegates all IAM provisioning to App_CloudRun. The Cloud Run SA, Cloud Build SA, IAP service agent, and password rotation role sets are identical to those in App_CloudRun.

Auto-generated application secret: Umami Common generates APP_SECRET at apply time using random_password (32 characters, no special characters). It is written to Secret Manager and injected into the Cloud Run container as the APP_SECRET environment variable. Plaintext is never stored in Terraform state after initial apply.

Database initialisation identity: The db-init Cloud Run Job runs under the Cloud Run SA. It connects to Cloud SQL PostgreSQL via the Auth Proxy Unix socket (since enable_cloudsql_volume = true by default), using DB_HOST (the socket path under /cloudsql), DB_USER, and DB_PASSWORD (from Secret Manager).

30-second secret propagation delay: Umami Common inserts a propagation wait after creating secrets. The secret_propagation_delay variable (default 30 seconds) controls how long dependent resources wait after secret creation before proceeding.

For the complete role tables and IAP, password rotation, and public access details, see App_CloudRun.


3. Core Service Configuration

A. Compute (Cloud Run)

Umami is a lightweight Next.js application with modest resource requirements. Umami CloudRun exposes cpu_limit and memory_limit as dedicated top-level variables.

Scale-to-zero is supported (min_instance_count = 0 by default). Umami cold starts are fast — the application is lightweight and has no slow startup operations.

Startup CPU Boost is always enabled (hardcoded in App CloudRun).

Container image: container_image_source defaults to 'custom', meaning Cloud Build builds a wrapper image that maps the platform's DB_* environment variables to Umami's DATABASE_URL. Set container_image_source = 'prebuilt' and configure DATABASE_URL manually to deploy the official ghcr.io/umami-software/umami image directly.

VariableGroupDefaultDescription
deploy_application4trueSet false for infrastructure-only deployment (SQL, secrets).
container_image_source4'custom''custom' builds via Cloud Build (maps DB_* to DATABASE_URL). 'prebuilt' deploys an existing image URI.
container_image4'ghcr.io/umami-software/umami'Base image. Override to use a custom-built image or mirrored copy.
cpu_limit4'1000m'CPU per instance. 1 vCPU is sufficient for most Umami deployments.
memory_limit4'512Mi'Memory per instance. Increase to 1Gi for high-traffic sites.
min_instance_count40Minimum instances. Set to 1 to avoid cold starts.
max_instance_count43Maximum instances. Umami scales horizontally — all state is in PostgreSQL.
container_port43000Umami's native HTTP port.
execution_environment4'gen2'Gen2 recommended for performance.
timeout_seconds4300Max request duration.
enable_cloudsql_volume4trueDefault true — Umami connects via Unix socket.
cpu_always_allocated4falseRequest-based billing — CPU is billed only while serving a request. Set true to allocate CPU at all times (instance-based billing).
traffic_split4[]Percentage-based canary/blue-green traffic allocation.
service_annotations4{}Advanced Cloud Run annotations.
service_labels4{}Labels applied to the Cloud Run service.

Differences from App CloudRun defaults:

VariableApp CloudRunUmami CloudRunReason
container_port80803000Umami's native Next.js port.
cpu_limit'1000m''1000m'Same — Umami is lightweight.
memory_limit'512Mi''512Mi'Same — Umami has modest memory needs.
max_instance_count13Umami scales horizontally safely — all state is in PostgreSQL.

B. Database (Cloud SQL — PostgreSQL 15)

Umami requires PostgreSQL 15. The module provisions a Cloud SQL PostgreSQL 15 instance and creates a dedicated database and user for Umami.

DATABASE_URL construction: The custom entrypoint (in custom image mode) constructs DATABASE_URL from the platform-injected DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, and DB_PORT variables. This avoids the need to pass a plaintext connection string.

VariableGroupDefaultDescription
database_type12'POSTGRES_15'Cloud SQL engine. Must be POSTGRES_15 for Umami.
application_database_name12'umami'PostgreSQL database name. Do not change after initial deployment.
application_database_user12'umami'PostgreSQL application user. Password auto-generated and stored in Secret Manager.
database_password_length1232Auto-generated password length. Range: 16–64.
enable_auto_password_rotation12falseAutomated zero-downtime password rotation.
rotation_propagation_delay_sec1290Seconds to wait after rotation before restarting the service.
enable_postgres_extensions12falseEnables installation of PostgreSQL extensions after provisioning.
postgres_extensions12[]PostgreSQL extensions to install (e.g., ['uuid-ossp']).

C. Storage (GCS)

No storage by default. Umami is a stateless analytics service — all data lives in PostgreSQL. storage_buckets defaults to an empty list. Provision additional buckets only if needed for custom use cases (e.g., backup exports).

VariableGroupDefaultDescription
create_cloud_storage11trueControls whether the module provisions GCS buckets defined in storage_buckets.
storage_buckets11[]GCS buckets to provision. Empty by default — Umami requires no file storage.
enable_nfs11falseProvisions a Cloud Filestore NFS instance. Not required for Umami.
nfs_mount_path11'/mnt/nfs'Container path where NFS is mounted. Only used when enable_nfs = true.
gcs_volumes11[]GCS buckets to mount via GCS Fuse (requires gen2).
manage_storage_kms_iam11falseCreates a CMEK KMS keyring and enables CMEK on all storage buckets.
enable_artifact_registry_cmek11falseCreates an Artifact Registry KMS key for at-rest image encryption.

D. Networking

Cloud Run uses Direct VPC Egress to reach Cloud SQL's internal IP. Because enable_cloudsql_volume = true is the default, the Auth Proxy sidecar handles the Cloud SQL connection via Unix socket.

VariableGroupDefaultDescription
ingress_settings5'all''all' — public internet; 'internal' — VPC only; 'internal-and-cloud-load-balancing' — forces traffic through the HTTPS Load Balancer.
vpc_egress_setting5'PRIVATE_RANGES_ONLY''PRIVATE_RANGES_ONLY' routes only RFC 1918 traffic via VPC. 'ALL_TRAFFIC' routes all egress via VPC.

E. Initialization & Bootstrap

A db-init Cloud Run Job is automatically provisioned by Umami Common when initialization_jobs is left as the default empty list ([]). It uses a PostgreSQL client image and executes Umami_Common/scripts/db-init.sh, which performs the following idempotent operations:

  1. Connects to Cloud SQL PostgreSQL via the Auth Proxy Unix socket.
  2. Creates the umami database user with the password from Secret Manager.
  3. Creates the umami database if it does not exist.
  4. Grants the umami user full privileges on the database.

Umami itself runs its own Prisma-based database migrations on first startup — the db-init job only pre-creates the database and user so that Umami's migrations can run successfully.

VariableGroupDefaultDescription
initialization_jobs13[]One-shot Cloud Run Jobs. Leave empty for Umami Common to supply the default db-init job. Non-empty list replaces it entirely.
cron_jobs13[]Recurring jobs triggered by Cloud Scheduler.
additional_services13[]Additional Cloud Run services deployed alongside the main application.

4. Advanced Security

A. Cloud Armor WAF

When enable_cloud_armor = true, a Global HTTPS Load Balancer with a Cloud Armor WAF policy (OWASP Top 10, adaptive DDoS, 500 req/min rate limiting) is provisioned in front of Cloud Run.

VariableGroupDefaultDescription
enable_cloud_armor10falseProvisions Global HTTPS LB + Cloud Armor WAF. Required for custom domains, CDN, and DDoS protection.
admin_ip_ranges10[]CIDR ranges exempted from WAF rules (e.g., office VPN, CI/CD egress IPs).

B. Identity-Aware Proxy (IAP)

When enable_iap = true, Cloud Run's native IAP integration is enabled directly on the service. Google identity authentication is required before requests reach Umami. Useful for restricting analytics access to internal team members only.

VariableGroupDefaultDescription
enable_iap5falseEnables IAP natively on the Cloud Run service.
iap_authorized_users5[]Users/service accounts granted access. Format: 'user:email' or 'serviceAccount:sa@...'.
iap_authorized_groups5[]Google Groups granted access. Format: 'group:name@example.com'.

Note: IAP protects the Umami dashboard. The tracking script (/script.js) and event endpoint (/api/send) must remain publicly accessible for tracked websites to report data. If applying IAP, ensure tracking paths are exempted or use a separate ingress configuration.

C. Binary Authorization

When enable_binary_authorization = true, Cloud Run enforces that deployed images carry a valid cryptographic attestation.

VariableGroupDefaultDescription
enable_binary_authorization8falseEnforces image attestation. Requires a Binary Authorization policy and attestor pre-configured in the project.

D. VPC Service Controls

When enable_vpc_sc = true, all GCP API calls from this module are bound within an existing VPC-SC perimeter.

VariableGroupDefaultDescription
enable_vpc_sc22falseRegisters module API calls within the project's VPC-SC perimeter. A perimeter must already exist before enabling.

E. Secret Manager Integration

Umami's APP_SECRET is stored in Secret Manager and injected natively by Cloud Run at revision start — plaintext is never written to Terraform state.

VariableGroupDefaultDescription
secret_environment_variables6{}Map of env var name → Secret Manager secret ID. Resolved at runtime; never stored in state.
secret_rotation_period6'2592000s'Frequency at which Secret Manager emits rotation notifications. Default: 30 days.
secret_propagation_delay630Seconds to wait after secret creation before dependent resources proceed.

5. Traffic & Ingress

A. HTTPS Load Balancer

When enable_cloud_armor = true, a Global HTTPS Load Balancer backed by a Serverless NEG is provisioned. Traffic flows: Internet → Cloud Armor → Global HTTPS LB → Serverless NEG → Cloud Run.

Setting ingress_settings = 'internal-and-cloud-load-balancing' forces all Umami traffic through the LB, preventing direct *.run.app URL access.

See App_CloudRun for full architecture details.

B. Cloud CDN

When enable_cdn = true (requires enable_cloud_armor = true), Cloud CDN is attached to the HTTPS Load Balancer backend.

Umami consideration: Umami's dashboard is a dynamic Next.js application. Cloud CDN is useful for caching Umami's static assets (JavaScript bundles, CSS) but should not cache API responses (/api/*) which contain live analytics data. Ensure appropriate Cache-Control headers are set.

VariableGroupDefaultDescription
enable_cdn10falseEnables Cloud CDN on the HTTPS LB backend. Only effective when enable_cloud_armor = true.
max_images_to_retain107Maximum number of recent container images to keep in Artifact Registry. Set 0 to disable.
delete_untagged_images10trueAutomatically deletes untagged (dangling) images from Artifact Registry.
image_retention_days1030Days after which images are eligible for deletion. Set 0 to disable age-based deletion.

C. Custom Domains

Custom domains are attached to the Global HTTPS Load Balancer via application_domains. Google-managed SSL certificates are provisioned automatically. DNS must point to the load balancer IP after apply.

VariableGroupDefaultDescription
application_domains10[]Custom domain names for the HTTPS LB. Google-managed SSL certificates provisioned per domain. (e.g., ['analytics.example.com'])

After the first apply, retrieve the LB IP and create an A record. SSL certificate provisioning takes 10–30 minutes after DNS propagation.


6. CI/CD & Delivery

A. Cloud Build Triggers

When enable_cicd_trigger = true, a Cloud Build GitHub connection and push trigger are provisioned. The trigger builds and deploys a custom Umami image when code is pushed to the configured branch.

VariableGroupDefaultDescription
enable_cicd_trigger8falseProvisions a Cloud Build GitHub trigger. Requires github_repository_url and credentials.
github_repository_url8""Full HTTPS URL of the GitHub repository.
github_token8""GitHub PAT (repo, admin:repo_hook scopes). Required on first apply. Sensitive.
github_app_installation_id8""GitHub App installation ID (preferred for organisation repos).
cicd_trigger_config8{ branch_pattern = "^main$" }Advanced trigger config: branch_pattern, included_files, ignored_files, trigger_name, substitutions.

B. Cloud Deploy Pipeline

When enable_cloud_deploy = true (requires enable_cicd_trigger = true), the CI/CD pipeline is upgraded to a managed Cloud Deploy delivery pipeline with sequential promotion stages.

VariableGroupDefaultDescription
enable_cloud_deploy8falseProvisions a Cloud Deploy pipeline. Requires enable_cicd_trigger = true.
cloud_deploy_stages8[dev, staging, prod(approval)]Ordered promotion stages. Each: name, target_name, service_name, require_approval, auto_promote.

7. Reliability & Scheduling

A. Scaling & Concurrency

min_instance_count = 0 (scale-to-zero) by default. Umami cold starts are fast — the Next.js application starts in a few seconds with no heavy first-boot operations. max_instance_count = 3 by default. Umami scales horizontally safely because all state is in PostgreSQL.

B. Traffic Splitting

Traffic splitting is supported. Umami stores all analytics data in PostgreSQL (shared across all instances), making canary deployments safe — any revision can serve requests and write to the same database.

VariableGroupDefaultDescription
traffic_split4[]Percentage-based traffic allocation across named revisions. All entries must sum to 100. Empty sends 100% to the latest revision.

C. Health Probes & Uptime Monitoring

Umami exposes /api/heartbeat as its dedicated health endpoint. Both the startup and liveness probes target this path.

VariableGroupDefaultDescription
startup_probe14{ path="/api/heartbeat", initial_delay_seconds=30, timeout_seconds=10, period_seconds=10, failure_threshold=30 }Startup readiness probe. Container receives no traffic until this succeeds.
liveness_probe14{ path="/api/heartbeat", initial_delay_seconds=30, timeout_seconds=10, period_seconds=30, failure_threshold=3 }Liveness probe. Container is restarted after failure_threshold consecutive failures.
startup_probe_config14{ enabled=true, path="/api/heartbeat", initial_delay_seconds=30 }Cloud Run startup probe (passed directly to App CloudRun).
health_check_config14{ enabled=true, path="/api/heartbeat" }Cloud Run liveness probe (passed directly to App CloudRun).
uptime_check_config14{ enabled=false, path="/api/heartbeat" }Cloud Monitoring uptime check (disabled by default). When enabled, alerts notify support_users if unreachable.
alert_policies14[]Cloud Monitoring metric alert policies.

D. Auto Password Rotation

When enable_auto_password_rotation = true, a zero-downtime password rotation pipeline is provisioned:

  1. Secret Manager emits a rotation notification at every secret_rotation_period interval.
  2. Eventarc fires a Cloud Run rotation Job.
  3. The job generates a new password, updates the Cloud SQL PostgreSQL user, writes a new secret version.
  4. After rotation_propagation_delay_sec seconds, the job restarts the Umami service.
VariableGroupDefaultDescription
enable_auto_password_rotation12falseEnables automated password rotation.
rotation_propagation_delay_sec1290Seconds to wait after writing the new secret before restarting the service.
secret_rotation_period6'2592000s'Rotation frequency. Default: 30 days.

8. Integrations

A. Redis Cache

Redis is disabled by default (enable_redis = false). Umami does not require Redis — all state is stored in PostgreSQL. Enable only if integrating an external caching layer for custom use cases.

VariableGroupDefaultDescription
enable_redis16falseEnables Redis by injecting REDIS_HOST and REDIS_PORT env vars. Umami does not require Redis.
redis_host16""Redis server hostname or IP. Only used when enable_redis = true.
redis_port16'6379'Redis server TCP port (string).

B. Backup Import & Recovery

When enable_backup_import = true, a dedicated Cloud Run Job restores an existing database backup into the provisioned Cloud SQL PostgreSQL instance.

VariableGroupDefaultDescription
backup_schedule7'0 2 * * *'Cron expression (UTC) for automated daily backups.
backup_retention_days77Days to retain backup files in GCS.
enable_backup_import7falseTriggers a one-time restore on apply. Set false after a successful import.
backup_source7'gcs''gcs' (full GCS URI) or 'gdrive' (Drive file ID).
backup_file7'backup.sql'Filename of the backup to import.
backup_format7'sql'Backup file format. Options: sql, tar, gz, tgz, tar.gz, zip, auto.

C. Observability & Alerting

VariableGroupDefaultDescription
uptime_check_config14{ enabled=false, path="/api/heartbeat" }Uptime check configuration: enabled, path, check_interval, timeout. Disabled by default.
alert_policies14[]Metric alert policies. Each: name, metric_type, comparison, threshold_value, duration_seconds, aggregation_period.
support_users2[]Email addresses notified by uptime and alert policy triggers.

D. Exploring with the GCP Console

After a successful deployment, explore the Umami installation in the GCP Console:

Cloud Run service: Navigate to Cloud Run in the GCP Console. Find the service named app<application_name><tenant_deployment_id><deployment_id> (e.g., appumamidemoxyz). Click the service to view:

  • The service URL — use this to access the Umami dashboard.
  • Revisions tab — lists all deployed revisions with traffic percentages.
  • Logs tab — streams container logs including Umami startup and request logs.
  • Metrics tab — shows request count, latency, instance count, and CPU/memory utilisation.
  • Configuration tab — shows the current container image, environment variables (non-sensitive), and resource limits.

Cloud SQL instance: Navigate to SQL in the GCP Console. Find the instance named app-sql-<deployment_id>. Click the instance to view:

  • Overview — connection name, region, PostgreSQL version, storage usage.
  • Databases — the umami database.
  • Users — the umami application user.
  • Connections — active connections from the Cloud Run service via Auth Proxy.
  • Backups — automated backup schedule and restore points.

Secret Manager: Navigate to Security → Secret Manager. Find secrets named secret-<tenant_resource_prefix>-<application_name>-app-secret (or similar). Click a secret to view:

  • Secret versions and creation timestamps.
  • Access log entries showing when Cloud Run read the secret.
  • Replication policy.

Artifact Registry: Navigate to Artifact Registry. Find the repository for this deployment. Click to view mirrored Umami images, their tags, sizes, and retention policy status.

Cloud Monitoring uptime checks: If uptime_check_config.enabled = true was set, navigate to Monitoring → Uptime checks and find the check for this Umami deployment targeting /api/heartbeat. View check results, response time, and failure history across GCP regions.

E. Exploring with gcloud

Use these gcloud commands to inspect the Umami deployment from the command line. Replace PROJECT_ID, REGION, and DEPLOYMENT_ID with your values.

# List Cloud Run services in the project
gcloud run services list \
--project=PROJECT_ID \
--region=REGION \
--format="table(name,status.url,status.conditions[0].type)"

# Describe the Umami Cloud Run service
gcloud run services describe SERVICE_NAME \
--project=PROJECT_ID \
--region=REGION \
--format="yaml(status.url,spec.template.spec.containers[0].resources)"

# View the latest revision
gcloud run revisions list \
--project=PROJECT_ID \
--region=REGION \
--service=SERVICE_NAME \
--format="table(name,status.conditions[0].type,spec.containerConcurrency,metadata.creationTimestamp)"

# Tail Cloud Run logs
gcloud run services logs tail SERVICE_NAME \
--project=PROJECT_ID \
--region=REGION

# Check Cloud SQL instance status
gcloud sql instances describe INSTANCE_NAME \
--project=PROJECT_ID \
--format="table(name,state,databaseVersion,settings.tier)"

# List databases in the Cloud SQL instance
gcloud sql databases list \
--instance=INSTANCE_NAME \
--project=PROJECT_ID

# List Cloud SQL users
gcloud sql users list \
--instance=INSTANCE_NAME \
--project=PROJECT_ID

# List Secret Manager secrets for this deployment
gcloud secrets list \
--project=PROJECT_ID \
--filter="name~umami" \
--format="table(name,createTime,replication.auto)"

# Describe the APP_SECRET secret
gcloud secrets describe SECRET_NAME \
--project=PROJECT_ID

# View uptime check results (Cloud Monitoring)
gcloud monitoring uptime list-configs \
--project=PROJECT_ID \
--format="table(displayName,httpCheck.path,period,timeout)"

# List Artifact Registry images for Umami
gcloud artifacts docker images list \
REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY_NAME \
--project=PROJECT_ID \
--format="table(image,tags,createTime)"

# Check Cloud Run IAM policy
gcloud run services get-iam-policy SERVICE_NAME \
--project=PROJECT_ID \
--region=REGION

# View Cloud Build triggers for this deployment
gcloud builds triggers list \
--project=PROJECT_ID \
--filter="name~umami" \
--format="table(name,createTime,github.push.branch)"

9. Platform-Managed Behaviours

The following behaviours are applied automatically by Umami CloudRun regardless of variable values. They cannot be overridden via tfvars.

BehaviourImplementationDetail
PostgreSQL 15 requireddatabase_type = "POSTGRES_15" defaultUmami requires PostgreSQL. MySQL and other engines are unsupported.
DATABASE_URL constructed at runtimeCustom entrypoint in Umami Common imageThe custom image mode builds a wrapper that assembles DATABASE_URL from platform-injected DB_* variables. Using prebuilt mode requires manual DATABASE_URL configuration.
APP_SECRET auto-generatedrandom_password in Umami Common32-character alphanumeric secret, stored in Secret Manager, injected as APP_SECRET.
No storage buckets by defaultstorage_buckets = [] defaultUmami is stateless — no GCS buckets are provisioned unless explicitly configured.
Image mirroring enabled by defaultenable_image_mirroring = trueMirrors from GitHub Container Registry (ghcr.io) into Artifact Registry to avoid rate limits.
Default db-init jobSupplied by Umami Common when initialization_jobs = []PostgreSQL database and user created automatically before Umami runs its own migrations.
Prisma migrations at startupUmami container behaviourUmami runs its own Prisma database migrations on each startup. The db-init job only pre-creates the database and user.
No Redis requiredenable_redis = false defaultUmami uses only PostgreSQL for all data storage. Redis is not required.
Scripts directoryscripts_dir = abspath("${module.umami_app.path}/scripts")Initialization scripts are sourced from Umami Common, not from the deployment directory.

Inline infrastructure (when no Services_GCP stack is present) is identical to App_CloudRun §9 — App_CloudRun provisions an inline VPC, Cloud NAT, Cloud SQL instance, service accounts, and GCP APIs as required. See App_CloudRun for the full inline resource inventory and teardown notes.


10. Variable Reference

All user-configurable variables exposed by Umami CloudRun, sorted by UI group then order. | Variable | Group | Default | Description | |---|---|---|---| | resource_creator_identity | 0 | (platform SA) | Service account used by Terraform to manage resources. | | project_id | 1 | — | GCP project ID. Required. | | region | 1 | 'us-central1' | GCP region for all resources. | | tenant_deployment_id | 2 | 'demo' | Short suffix appended to all resource names. | | support_users | 2 | [] | Email addresses for monitoring alerts. | | resource_labels | 2 | {} | Labels applied to all provisioned resources. | | application_name | 3 | 'umami' | Base resource name. Do not change after initial deployment. | | application_display_name | 3 | 'Umami' | Human-readable name shown in the GCP Console. | | application_description | 3 | 'Umami Analytics on Cloud Run' | Service description. | | application_version | 3 | 'postgresql-latest' | Umami container image tag. Use postgresql- prefixed tags. | | deploy_application | 4 | true | Set false for infrastructure-only deployment. | | container_image_source | 4 | 'custom' | 'custom' (Cloud Build) or 'prebuilt' (existing image). | | container_image | 4 | 'ghcr.io/umami-software/umami' | Container image URI. | | container_build_config | 4 | { enabled=true } | Cloud Build config for custom image builds. | | enable_image_mirroring | 4 | true | Mirrors Umami image into Artifact Registry. | | cpu_limit | 4 | '1000m' | CPU per instance. | | memory_limit | 4 | '512Mi' | Memory per instance. | | min_instance_count | 4 | 0 | Minimum instances (0 = scale-to-zero). | | max_instance_count | 4 | 3 | Maximum instances. | | container_port | 4 | 3000 | Umami's native port. | | container_protocol | 4 | 'http1' | 'http1' or 'h2c'. | | execution_environment | 4 | 'gen2' | Cloud Run execution environment generation. | | timeout_seconds | 4 | 300 | Max request duration. | | cpu_always_allocated | 4 | false | Request-based billing by default. Set true to allocate CPU at all times. | | enable_cloudsql_volume | 4 | true | Mount Cloud SQL Auth Proxy Unix socket. | | cloudsql_volume_mount_path | 4 | '/cloudsql' | Container path for Auth Proxy socket. | | traffic_split | 4 | [] | Canary/blue-green traffic allocation. | | max_revisions_to_retain | 4 | 7 | Maximum Cloud Run revisions to keep. | | service_annotations | 4 | {} | Advanced Cloud Run annotations. | | service_labels | 4 | {} | Labels applied to the Cloud Run service. | | ingress_settings | 5 | 'all' | 'all', 'internal', or 'internal-and-cloud-load-balancing'. | | vpc_egress_setting | 5 | 'PRIVATE_RANGES_ONLY' | 'PRIVATE_RANGES_ONLY' or 'ALL_TRAFFIC'. | | enable_iap | 5 | false | Enables IAP natively on the Cloud Run service. | | iap_authorized_users | 5 | [] | Users/SAs granted IAP access. | | iap_authorized_groups | 5 | [] | Google Groups granted IAP access. | | environment_variables | 6 | {} | Plain-text env vars (e.g., { DISABLE_TELEMETRY = "1" }). | | secret_environment_variables | 6 | {} | Secret Manager references. | | secret_propagation_delay | 6 | 30 | Seconds to wait after secret creation. | | secret_rotation_period | 6 | '2592000s' | Secret Manager rotation notification frequency. | | backup_schedule | 7 | '0 2 * * *' | Cron expression (UTC) for automated backups. | | backup_retention_days | 7 | 7 | Days to retain backup files in GCS. | | enable_backup_import | 7 | false | Triggers a one-time restore on apply. | | backup_source | 7 | 'gcs' | 'gcs' or 'gdrive'. | | backup_file | 7 | 'backup.sql' | Filename of the backup to import. | | backup_format | 7 | 'sql' | Backup format: sql, tar, gz, tgz, tar.gz, zip, auto. | | enable_cicd_trigger | 8 | false | Provisions a Cloud Build GitHub trigger. | | github_repository_url | 8 | "" | Full HTTPS URL of the GitHub repository. | | github_token | 8 | "" | GitHub PAT. Sensitive. | | github_app_installation_id | 8 | "" | GitHub App installation ID. | | cicd_trigger_config | 8 | { branch_pattern = "^main$" } | Advanced Cloud Build trigger config. | | enable_cloud_deploy | 8 | false | Provisions a Cloud Deploy progressive delivery pipeline. | | cloud_deploy_stages | 8 | [dev, staging, prod(approval)] | Ordered Cloud Deploy promotion stages. | | enable_binary_authorization | 8 | false | Enforces image attestation on deployment. | | binauthz_evaluation_mode | 8 | 'ALWAYS_ALLOW' | Binary Authorization enforcement mode. Not referenced in this module. | | enable_custom_sql_scripts | 9 | false | Runs SQL scripts from GCS after provisioning. | | custom_sql_scripts_bucket | 9 | "" | GCS bucket containing SQL scripts. | | custom_sql_scripts_path | 9 | "" | Path prefix within the bucket. | | custom_sql_scripts_use_root | 9 | false | Run scripts as the root DB user. | | enable_cloud_armor | 10 | false | Provisions Global HTTPS LB + Cloud Armor WAF. | | admin_ip_ranges | 10 | [] | CIDR ranges exempted from WAF rules. | | application_domains | 10 | [] | Custom domains with Google-managed SSL certificates. | | enable_cdn | 10 | false | Enables Cloud CDN on the HTTPS LB backend. | | max_images_to_retain | 10 | 7 | Maximum number of container images to keep in Artifact Registry. | | delete_untagged_images | 10 | true | Automatically deletes untagged images from Artifact Registry. | | image_retention_days | 10 | 30 | Days after which images are eligible for deletion. | | create_cloud_storage | 11 | true | Controls GCS bucket provisioning. | | storage_buckets | 11 | [] | GCS buckets to provision. Empty by default — Umami needs no file storage. | | enable_nfs | 11 | false | Provisions NFS shared storage. Not required for Umami. | | nfs_mount_path | 11 | '/mnt/nfs' | Container NFS mount path. | | gcs_volumes | 11 | [] | GCS buckets to mount via GCS Fuse. | | manage_storage_kms_iam | 11 | false | Creates CMEK KMS key for storage buckets. | | enable_artifact_registry_cmek | 11 | false | Creates Artifact Registry KMS key for at-rest image encryption. | | database_type | 12 | 'POSTGRES_15' | Cloud SQL engine. Must be POSTGRES_15 for Umami. | | application_database_name | 12 | 'umami' | PostgreSQL database name. Do not change after initial deployment. | | application_database_user | 12 | 'umami' | PostgreSQL application user. | | database_password_length | 12 | 32 | Auto-generated password length. Range: 16–64. | | enable_auto_password_rotation | 12 | false | Automated zero-downtime password rotation. | | rotation_propagation_delay_sec | 12 | 90 | Seconds to wait after rotation before restarting the service. | | enable_postgres_extensions | 12 | false | Enables installation of PostgreSQL extensions. | | postgres_extensions | 12 | [] | PostgreSQL extensions to install. | | initialization_jobs | 13 | [] | One-shot Cloud Run Jobs. Leave empty for Umami Common to supply the default db-init job. | | cron_jobs | 13 | [] | Recurring scheduled Cloud Run Jobs. | | additional_services | 13 | [] | Additional Cloud Run services deployed alongside Umami. | | startup_probe | 14 | { path="/api/heartbeat", initial_delay_seconds=30, failure_threshold=30 } | Startup probe. | | liveness_probe | 14 | { path="/api/heartbeat", initial_delay_seconds=30, failure_threshold=3 } | Liveness probe. | | startup_probe_config | 14 | { enabled=true, path="/api/heartbeat" } | Cloud Run startup probe (passed directly to App CloudRun). | | health_check_config | 14 | { enabled=true, path="/api/heartbeat" } | Cloud Run liveness probe (passed directly to App CloudRun). | | uptime_check_config | 14 | { enabled=false, path="/api/heartbeat" } | Cloud Monitoring uptime check (disabled by default). | | alert_policies | 14 | [] | Cloud Monitoring metric alert policies. | | enable_redis | 16 | false | Enables Redis env var injection. Not required for Umami. | | redis_host | 16 | "" | Redis hostname/IP. Only used when enable_redis = true. | | redis_port | 16 | '6379' | Redis TCP port (string). | | enable_vpc_sc | 22 | false | Registers API calls within the project's VPC-SC perimeter. | | vpc_cidr_ranges | 22 | [] | VPC subnet CIDR ranges for VPC-SC network access level. | | vpc_sc_dry_run | 22 | true | Logs VPC-SC violations without blocking. | | organization_id | 22 | "" | GCP Organization ID for VPC-SC. Auto-discovered from project when empty. | | enable_audit_logging | 22 | false | Enables detailed Cloud Audit Logs. |


11. Outputs

OutputDescription
service_nameName of the Cloud Run service.
service_urlPublic URL of the Cloud Run service.
service_locationGCP region where the Cloud Run service is deployed.
project_idGCP project ID.
deployment_idDeployment ID suffix used in resource names.
database_instance_nameName of the Cloud SQL PostgreSQL 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.
github_repository_urlGitHub repository URL connected for CI/CD.

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"CriticalUmami only supports PostgreSQL. Setting to MySQL or another engine will break the DATABASE_URL construction and cause Umami to fail at startup with a database connection error.
application_database_name"umami"CriticalImmutable after first deployment — changing this causes Terraform to recreate the database, destroying all analytics data collected by Umami.
application_database_user"umami"CriticalImmutable after first deployment — changing this recreates the Cloud SQL user, invalidating all stored credentials and breaking Umami's database connection.
container_port3000CriticalUmami listens on port 3000. Changing this without matching the container's bound port causes Cloud Run health probes to fail and the service to be marked unhealthy.
container_image_source"custom"HighThe custom mode builds a wrapper image that assembles DATABASE_URL from DB_* variables. Using "prebuilt" with the official Umami image requires manually providing DATABASE_URL as an environment variable — without it, Umami cannot connect to PostgreSQL and will crash on startup.
application_version"postgresql-latest"MediumAlways use a postgresql- prefixed tag (e.g., postgresql-latest, postgresql-v2.11.3). Plain version tags (e.g., latest) are not published for the PostgreSQL variant of Umami and will result in a container pull error.
admin_password(change on first login)CriticalThe default Umami admin credentials are admin / umami — widely known. Failure to change these on first login exposes your analytics dashboard and all tracked data to anyone who knows the URL.
enable_iapfalseMediumWithout IAP, anyone who knows the Cloud Run URL can access the Umami dashboard login page. Umami's own authentication is the only barrier. Enable IAP or ensure ingress_settings = "internal" for private deployments.
ingress_settings"all"Medium"all" exposes Umami publicly. The tracking script endpoint must be publicly accessible for tracked websites to report data, but the admin dashboard should be restricted for sensitive deployments. Consider using IAP or a custom domain with restricted access for the admin paths.
min_instance_count0LowScale-to-zero is safe for Umami — cold starts are fast (a few seconds). However, the first request after a cold start will experience slight latency. Set to 1 for time-sensitive analytics dashboards.
memory_limit"512Mi"Medium512Mi is the default and sufficient for moderate traffic. High-traffic sites with many concurrent dashboard users or complex queries may experience OOM. Increase to 1Gi if you observe memory pressure in Cloud Monitoring.
enable_backup_importfalseCriticalRequires a valid backup file to be accessible at backup_file. Enabling with an invalid path causes the restore Cloud Run job to fail during apply.
backup_retention_days7MediumSeven days is minimal for production analytics. Losing analytics history has direct business impact. Increase to 30+ days for any long-term analytics deployment.
secret_propagation_delay30LowOccasionally insufficient in multi-region setups. Increase to 60–90s if secret-read errors are observed during apply.
vpc_sc_dry_runtrueMediumVPC-SC dry run logs violations but does not block them. After verifying no false positives in Cloud Logging, switch to false for actual enforcement. Leaving as true permanently provides no security benefit.

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.