Skip to main content

Matomo on Google Cloud Run

Matomo on Google Cloud Run

Matomo is the leading open-source web analytics platform — a privacy-focused, self-hosted alternative to Google Analytics used by over a million websites. This module deploys Matomo on Cloud Run v2 on top of the App_CloudRun foundation, which provisions and manages the shared Google Cloud infrastructure.

This guide focuses on the cloud services Matomo uses and how to explore and operate them from the Google Cloud Console and the command line. For the mechanics common to every Cloud Run application — service identity, ingress and load balancing, scaling and concurrency, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, backups, and the deployment lifecycle — refer to the App_CloudRun foundation guide rather than repeating them here.


1. Overview

Matomo runs as a PHP/Apache container (the official matomo:5-apache image) on Cloud Run v2. The deployment wires together a focused set of Google Cloud services:

CapabilityGoogle Cloud serviceNotes
ComputeCloud Run v2PHP/Apache service, 1 vCPU / 2 GiB by default, request-based autoscaling
DatabaseCloud SQL for MySQL 8.0Required — Matomo supports only MySQL/MariaDB
Shared filesFilestore (NFS)Persists the Matomo document root /var/www/html (gen2 required)
Object storageCloud StorageA dedicated matomo-data bucket provisioned automatically
CacheRedisEnabled by default; falls back to the NFS host IP when no Redis host is given
SecretsSecret ManagerDatabase password managed automatically
IngressCloud Run URL / Cloud Load BalancingDefault run.app URL, optional external HTTPS load balancer + custom domain

Sensible defaults worth knowing up front:

  • MySQL 8.0 is mandatory. Matomo requires MySQL/MariaDB; PostgreSQL is not supported.
  • The official prebuilt image is deployed directly. container_image_source = "prebuilt" means no Cloud Build step — the matomo:<application_version> image is mirrored into Artifact Registry (to avoid Docker Hub rate limits) and deployed as-is.
  • The database connection is TCP over the VPC, not a socket. enable_cloudsql_volume = false by default: the Foundation injects the Cloud SQL instance's private IP as MATOMO_DATABASE_HOST, and Matomo's PHP client connects directly over the private network. There is no Auth Proxy socket sidecar.
  • MATOMO_DATABASE_* env vars pre-fill the installer. Host, username, database name, and password are injected by the Foundation; MATOMO_DATABASE_ADAPTER=mysql and MATOMO_DATABASE_TABLES_PREFIX=matomo_ are set by Matomo_Common.
  • NFS persists the document root. nfs_mount_path defaults to /var/www/html, where Matomo keeps config.ini.php, installed plugins, and generated assets. The image entrypoint populates an empty volume from /usr/src/matomo on first start.
  • A db-init job runs on every apply to idempotently create the Matomo MySQL database and user.
  • Scale-to-zero by default. min_instance_count = 0 and max_instance_count = 1; cold starts take 10–30 seconds. Set min_instance_count = 1 for always-on production.
  • The database password is generated automatically and stored in Secret Manager. Matomo has no other application secrets.

2. Google Cloud Services & How to Explore Them

All commands assume PROJECT and REGION are set. Service and resource names are reported in the deployment Outputs.

A. Cloud Run — the Matomo service

Matomo runs as a Cloud Run v2 service that autoscales by request load between the minimum and maximum instance counts. Each deployment creates an immutable revision; traffic can be split across revisions for safe rollouts.

  • Console: Cloud Run → select the service for revisions, traffic, logs, and metrics.
  • CLI:
    gcloud run services list --project "$PROJECT" --region "$REGION"
    gcloud run services describe <service-name> --project "$PROJECT" --region "$REGION"
    gcloud run revisions list --service <service-name> --project "$PROJECT" --region "$REGION"

See App_CloudRun for scaling, concurrency, execution environment, and traffic splitting.

B. Cloud SQL for MySQL 8.0

Matomo stores all analytics data (visits, reports, users, site configuration) in a managed Cloud SQL for MySQL 8.0 instance. The service connects over the instance's private IP across the VPC (no public IP, no proxy socket): the Foundation injects the private IP as MATOMO_DATABASE_HOST. On first deploy a db-init Job creates the application database and user.

  • Console: SQL → select the instance for connections, backups, flags, metrics.
  • CLI:
    gcloud sql instances list --project "$PROJECT"
    gcloud sql instances describe <instance-name> --project "$PROJECT"
    gcloud sql connect <instance-name> --user=<db-user> --project "$PROJECT"

The instance name, database, user, and password secret are in the Outputs. See App_CloudRun for the connection model, backups, and password rotation.

C. Filestore (NFS) and Cloud Storage

Matomo's document root /var/www/html — configuration (config.ini.php), installed plugins, and generated assets — is written to a Filestore (NFS) share mounted into the service so it survives restarts and scale-from-zero. A dedicated Cloud Storage bucket (matomo-data) is also provisioned automatically. The gen2 execution environment is required for NFS mounts.

  • Console: Filestore → Instances; Cloud Storage → Buckets.
  • CLI:
    gcloud filestore instances list --project "$PROJECT"
    gcloud storage buckets list --project "$PROJECT"
    gcloud storage ls gs://<data-bucket>/ # bucket name is in the Outputs

See App_CloudRun for the NFS mount, GCS Fuse, and CMEK.

D. Redis cache

Redis backs Matomo's object cache, reducing database load and improving page load times. When no external Redis host is configured and NFS is enabled, the NFS host IP is used as the Redis endpoint.

  • Console: Memorystore → Redis (if using a managed instance).
  • CLI:
    redis-cli -h <redis-host> ping
    redis-cli -h <redis-host> info keyspace

E. Secret Manager

The database password is stored in Secret Manager and injected into the service at runtime as MATOMO_DATABASE_PASSWORD; plaintext never appears in configuration. Matomo requires no other application secrets.

  • Console: Security → Secret Manager.
  • CLI:
    gcloud secrets list --project "$PROJECT"
    gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"

See App_CloudRun for injection and rotation details.

F. Networking & ingress

The service is reachable at its run.app URL by default. An external HTTPS load balancer with a custom domain, Cloud CDN, and Cloud Armor can be layered on; ingress settings and VPC egress control connectivity. The tracking snippet you embed in your websites points at this URL (or your custom domain).

  • Console: Cloud Run (service URL); Network services → Load balancing.
  • CLI:
    gcloud run services describe <service-name> --region "$REGION" --format='value(status.url)'
    gcloud compute addresses list --project "$PROJECT"

See App_CloudRun.

G. Cloud Logging & Monitoring

Container logs flow to Cloud Logging; Cloud Run and Cloud SQL metrics flow to Cloud Monitoring, with optional uptime checks and alert policies.

  • Console: Logging → Logs Explorer; Monitoring → Dashboards / Alerting.
  • CLI:
    gcloud run services logs read <service-name> --project "$PROJECT" --region "$REGION" --limit 50

3. Matomo Application Behaviour

  • First-deploy database setup. A db-init Job (image mysql:8.0-debian) connects to Cloud SQL — preferring the Auth Proxy Unix socket when mounted, falling back to a TCP connection over the private IP — and idempotently creates the Matomo database, creates the application user, and grants full privileges. It also verifies the application user can connect, which both catches credential problems early and warms MySQL 8's caching_sha2_password auth cache so the PHP client's subsequent TCP connections use the fast auth path. The job runs on every apply and is safe to re-run.
  • Web installer completes setup. The db-init job creates only the empty database; browsing to the service URL for the first time launches Matomo's web installer, whose database screen is pre-filled from the injected MATOMO_DATABASE_* env vars. You create the superuser account and register your first tracked website there.
  • Document-root persistence. On first start the official image's entrypoint copies the Matomo application from /usr/src/matomo into the (empty) NFS volume at /var/www/html. All subsequent state — config.ini.php, plugins, generated assets — persists there across restarts and version upgrades.
  • Database connection is plain TCP. With enable_cloudsql_volume = false, Matomo's PHP MySQL client connects to the Cloud SQL private IP over the VPC. The MATOMO_DATABASE_ADAPTER=mysql and MATOMO_DATABASE_TABLES_PREFIX=matomo_ env vars are set by Matomo_Common.
  • Report archiving. Out of the box Matomo processes reports on page view (browser-triggered archiving), which suits low-to-medium traffic and the module's scale-to-zero default. For high-traffic sites, schedule console core:archive via the cron_jobs input so report processing runs as a Cloud Run Job instead of inside visitor requests.
  • Health path. Startup uses a TCP probe (port-listening) with a generous 20-failure threshold to cover the first-boot copy from /usr/src/matomo; liveness targets / over HTTP, which returns 200 — or 302 to the installer on a fresh deploy — once Apache and PHP are up.
  • PHP tuning variables are build args. php_memory_limit, upload_max_filesize, and post_max_size apply only when container_image_source = "custom" (they are Docker build args); with the default prebuilt image they have no effect.

4. Configuration Variables

Variables are grouped exactly as they appear on the deployment platform. Only settings specific to or notable for Matomo are listed; every other input is inherited from App_CloudRun with its standard behaviour.

Group 1 — Project & Identity

VariableDefaultDescription
project_id(required)Target Google Cloud project.
regionus-central1Region for the service and regional resources.

Group 2 — Deployment Environment

VariableDefaultDescription
tenant_deployment_iddemoShort suffix that makes resource names unique per environment.
support_users[]Emails granted project access and monitoring alerts.
resource_labels{}Labels applied to all resources.

Group 3 — Application Identity

VariableDefaultDescription
application_namematomoBase name for resources. Do not change after first deploy.
display_nameMatomoFriendly name shown in the Console.
application_version5-apacheMatomo image tag — use an Apache variant tag; increment to roll out a new revision.
php_memory_limit / upload_max_filesize / post_max_size512M / 64M / 64MPHP tuning build args — only effective with container_image_source = "custom".

All other inputs in this group follow standard App_CloudRun behaviour.

Group 4 — Runtime & Scaling

VariableDefaultDescription
deploy_applicationtrueSet false to provision infrastructure only.
container_image_sourceprebuiltDeploys the official Matomo image directly; custom builds via Cloud Build.
container_image""Leave empty to use matomo:<application_version>.
cpu_limit1000mCPU per instance; 1 vCPU minimum for Matomo.
memory_limit2GiMemory per instance; 2 GiB recommended for report generation.
min_instance_count0Scale-to-zero; set 1 for always-on production.
max_instance_count1Keep at 1 unless shared NFS + session affinity are confirmed multi-instance-safe.
container_port80Matomo runs on Apache, which listens on port 80.
enable_cloudsql_volumefalseMatomo connects over TCP private IP (MATOMO_DATABASE_HOST) — no proxy socket.
execution_environmentgen2Required for the NFS mount.
enable_image_mirroringtrueMirror the image into Artifact Registry to avoid Docker Hub rate limits.

All other inputs follow standard App_CloudRun behaviour.

Group 5 — Access & Ingress Control

VariableDefaultDescription
enable_iapfalseRequire Google sign-in via Identity-Aware Proxy. Note: IAP in front of Matomo also blocks the public tracking endpoint.
ingress_settingsallWhich networks may reach the service. Trackers on public websites need all (or LB-fronted).
vpc_egress_settingPRIVATE_RANGES_ONLYPrivate-IP traffic (including Cloud SQL) routes via the VPC.

All other inputs follow standard App_CloudRun behaviour.

Group 6 — Environment Variables & Secrets

VariableDefaultDescription
environment_variables{}Extra plain env vars. MATOMO_DATABASE_ADAPTER and MATOMO_DATABASE_TABLES_PREFIX are injected automatically; the MATOMO_DATABASE_HOST/USERNAME/DBNAME/PASSWORD set comes from the Foundation.
secret_environment_variables{}Map of env var → Secret Manager secret name.

All other inputs follow standard App_CloudRun behaviour.

Group 7 — Backup & Restore

VariableDefaultDescription
backup_schedule0 2 * * *Automated backup cron (UTC).
backup_retention_days7Retention; raise for production/compliance.
enable_backup_import / backup_source / backup_uri / backup_formatrestore optionsRestore from a backup on deploy.

Groups 8–10 — CI/CD, Custom SQL, Domain & Cloud Armor

Standard App_CloudRun behaviour — see App_CloudRun. Key inputs: enable_cicd_trigger, enable_cloud_deploy, enable_binary_authorization, enable_custom_sql_scripts, application_domains, enable_cdn, enable_cloud_armor.

Group 11 — Storage & Filesystem

VariableDefaultDescription
enable_nfstrueShared Filestore volume for the Matomo document root. Requires gen2.
nfs_mount_path/var/www/htmlMatomo's document root — config, plugins, and assets persist here.
create_cloud_storage / storage_buckets[{ name_suffix = "data" }]Additional buckets; the matomo-data bucket is always provisioned automatically.

All other inputs follow standard App_CloudRun behaviour.

Group 12 — Database Backend

VariableDefaultDescription
database_typeMYSQL_8_0Matomo requires MySQL — do not change to PostgreSQL.
db_namematomoMySQL database name. Immutable after first deploy.
db_usermatomoApplication user. Immutable after first deploy.
database_password_length32Generated password length (16–64).
enable_auto_password_rotationfalseAutomated DB password rotation.

All other inputs follow standard App_CloudRun behaviour.

Group 13 — Jobs & Scheduled Tasks

VariableDefaultDescription
initialization_jobs[]Leave empty to use the built-in db-init job (mysql:8.0-debian).
cron_jobs[]Recurring jobs — the natural home for a scheduled console core:archive on high-traffic sites.

Group 14 — Observability & Health

VariableDefaultDescription
startup_probeTCP, 30s initial delay, 15s period, 20 failuresGenerous threshold for the first-boot document-root copy.
liveness_probeHTTP /, 300s initial delay, 60s period, 3 failuresMatomo serves 200/302 on / once PHP and Apache are up.
uptime_check_configdisabled, path /Cloud Monitoring uptime check — off by default; enable for production.
alert_policies[]Metric alert policies.

Group 21 — Redis Cache

VariableDefaultDescription
enable_redistrueUse Redis as Matomo's object cache backend.
redis_host""Redis endpoint. Leave empty to use the NFS host IP.
redis_port6379Redis port.
redis_auth""Optional Redis auth password (sensitive).

Group 22 — VPC Service Controls & Audit Logging

VariableDefaultDescription
enable_vpc_scfalseEnforce a VPC-SC perimeter.
vpc_cidr_ranges / vpc_sc_dry_run(set)Access level CIDRs / dry-run mode.
enable_audit_loggingfalseDetailed Cloud Audit Logs.

5. Outputs

Returned on a successful deployment — the quickest way to locate and explore the running resources.

OutputDescription
service_nameCloud Run service name.
service_urlDefault run.app URL of the service.
service_locationRegion the service runs in.
stage_servicesStage-specific service URLs (Cloud Deploy).
load_balancer_ip / load_balancer_urlExternal HTTPS load balancer IP / URL (when enabled).
database_instance_nameCloud SQL instance name.
database_name / database_userApplication database name / user.
database_password_secretSecret Manager secret holding the DB password.
database_host / database_portDB endpoint / port.
storage_bucketsCreated Cloud Storage buckets (includes the matomo-data bucket).
network_name / network_exists / regionsVPC network, presence, regions.
container_image / container_registryDeployed image and Artifact Registry repo.
monitoring_enabled / monitoring_notification_channels / uptime_check_namesMonitoring status, channels, uptime checks.
initialization_jobsNames of the setup jobs.
deployment_id / tenant_id / resource_prefixNaming identifiers.
project_id / project_numberProject identifiers.
cicd_enabled / github_repository_url / github_repository_owner / github_repository_name / cicd_configurationCI/CD status and details.
artifact_registry_repository / cloudbuild_trigger_name / cloudbuild_trigger_idRegistry and build trigger.
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_modeVPC-SC status.
audit_logging_enabled / artifact_registry_cmek_enabledAudit logging and CMEK status.

6. Configuration Pitfalls & Sensible Defaults

Risk: Critical (data loss / outage / security) — High (service degraded) — Medium (cost or partial degradation) — Low (minor).

SettingSensible valueRiskConsequence if wrong
database_typeMYSQL_8_0CriticalMatomo supports only MySQL/MariaDB; any other engine breaks the installer.
db_name / db_userset onceCriticalImmutable after first deploy; renaming recreates the DB/user and destroys all analytics data.
enable_nfstrueCriticalWithout the persistent document root, config.ini.php and plugins are lost on every restart — Matomo re-enters the installer.
nfs_mount_path/var/www/htmlCriticalMounting anywhere else leaves the document root on ephemeral disk.
container_port80CriticalApache listens on 80; mismatching it fails all health probes.
enable_backup_importfalse unless restoringCriticalEnabling without a valid backup_uri fails the import job.
execution_environmentgen2HighNFS mounts require gen2; gen1 cannot mount Filestore.
enable_cloudsql_volumefalseHighMatomo is wired for TCP via MATOMO_DATABASE_HOST (private IP); flipping to the socket without rewiring the host env leaves the installer pointing at an unreachable host.
application_versionApache variant tag (e.g. 5-apache)HighThe fpm/alpine variants have no Apache and don't serve HTTP on port 80.
max_instance_count1HighMultiple instances against the same NFS document root are not validated for Matomo session/config safety.
memory_limit2GiHighToo little memory fails PHP report generation and archive processing.
enable_redistrueMediumWithout an object cache, all cache reads hit MySQL, increasing load.
min_instance_count0 (dev) / 1 (prod)Medium0 adds a 10–30 s cold start for the first tracked pageview after idle.
cron_jobs (core:archive)set for high trafficMediumBrowser-triggered archiving slows visitor-facing requests on busy sites.
enable_iapfalse for public trackersMediumIAP in front of the service blocks the tracking endpoint your websites call.
uptime_check_config.enabledtrue for prodLowNo external availability signal; failures surface only via user reports.
php_memory_limit etc.defaultsLowBuild args only — silently inert with the default prebuilt image.

For the foundation behaviour referenced throughout — service identity, scaling and concurrency, ingress and load balancing, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, backups, and image mirroring — see App_CloudRun. Matomo-specific application configuration shared with the GKE variant is described in Matomo_Common.