Skip to main content

Certification track: Associate Cloud Engineer (ACE)

Mattermost on Google Cloud Run

Mattermost on Google Cloud Run

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


1. Module Overview

Mattermost is an open-source, self-hostable team messaging and collaboration platform — a secure Slack alternative with persistent channels, direct messages, file sharing, integrations, bots, slash commands, and enterprise security features. Mattermost CloudRun is a wrapper module built on top of App CloudRun. It uses App CloudRun for all GCP infrastructure provisioning and injects Mattermost-specific application configuration, database initialisation, and storage via Mattermost Common.

Key Capabilities:

  • Compute: Cloud Run v2 (Gen2), custom Mattermost container, 2 vCPU / 2 Gi by default. Minimum instances default to 1 — Mattermost maintains persistent WebSocket connections for real-time messaging, making scale-to-zero unsuitable for most deployments.
  • Data Persistence: Cloud SQL PostgreSQL 15. GCS FUSE volume mounted at /mattermost/data for persistent file uploads and attachments.
  • Security: Inherits Cloud Armor WAF, IAP, Binary Authorization, and VPC Service Controls from App CloudRun. Mattermost generates its own internal signing keys at first startup and stores them in the database — no application-level secrets are auto-generated by this module.
  • Caching: Redis is optional (enable_redis = false by default). When enabled, Mattermost uses Redis as its distributed cache and session backend — required for correct behaviour across multiple replicas.
  • Editions: Team Edition (free, default) or Enterprise Edition (paid licence required). Controlled by the edition variable.
  • Real-time Messaging: Mattermost maintains WebSocket connections for real-time message delivery. Cloud Run's 60-minute request timeout means timeout_seconds should be set to 3600 for WebSocket-heavy deployments. For production workloads requiring persistent long-lived connections, consider Mattermost GKE.

Project & Application Identity

VariableGroupTypeDefaultDescription
project_id1stringGCP project ID. Required.
tenant_deployment_id1string'demo'Short suffix appended to all resource names.
support_users1list(string)[]Email recipients for IAM access and monitoring alerts.
resource_labels1map(string){}Labels applied to all provisioned resources.
application_name3string'mattermost'Base resource name. Do not change after initial deployment.
display_name3string'Mattermost'Human-readable name shown in the platform UI.
description3string'Mattermost - Open-source team messaging and collaboration'Cloud Run service description.
application_version3string'9.11.2'Mattermost image version tag. Increment to deploy a new release.

Wrapper architecture: Mattermost CloudRun calls Mattermost Common to build an application_config object containing Mattermost-specific environment variables, probe configuration, and the db-init job definition. module_storage_buckets carries any GCS data bucket configured for FUSE mounting. scripts_dir is resolved to the Mattermost Common scripts directory at apply time.


2. IAM & Access Control

Mattermost_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.

No application-level secrets auto-generated: Unlike many other application modules, Mattermost Common does not auto-generate application secrets such as a SECRET_KEY. Mattermost generates its own internal signing keys at first startup and stores them in PostgreSQL. The DB_PASSWORD and ROOT_PASSWORD secrets are provisioned automatically by App CloudRun and consumed by the db-init job.

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, using DB_HOST, DB_USER, and the DB_PASSWORD secret from Secret Manager.

120-second IAM propagation delay: Inherited from App CloudRun — the Mattermost service is not deployed until the delay completes, preventing secret-read failures on the first revision start.


3. Core Service Configuration

A. Compute (Cloud Run)

Mattermost is a Go-based application that is resource-efficient at startup but benefits from consistent CPU allocation for WebSocket connection handling and message delivery. Mattermost CloudRun exposes cpu_limit and memory_limit as top-level variables.

Minimum instance count defaults to 1 (min_instance_count = 1). This prevents scale-to-zero cold starts that would interrupt active WebSocket connections. For development or cost-sensitive environments, min_instance_count = 0 is supported but will cause user sessions to drop when the instance scales down.

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

Container image: container_image_source defaults to 'custom', meaning Cloud Build compiles a custom image using Mattermost Common's Dockerfile (based on the official mattermost/mattermost-team-edition or mattermost/mattermost-enterprise-edition image, depending on edition). Set container_image_source = 'prebuilt' and container_image to an image URI to skip the build step.

VariableGroupDefaultDescription
deploy_application4trueSet false for infrastructure-only deployment (SQL, storage, secrets).
container_image_source4'custom''custom' builds via Cloud Build. 'prebuilt' deploys an existing image URI.
container_image4""Override image URI. Leave empty for Cloud Build to manage the image.
cpu_limit4'2000m'CPU per instance. 2 vCPU recommended for Mattermost.
memory_limit4'2Gi'Memory per instance. 2 Gi is the minimum; increase for large teams.
cpu_always_allocated4trueCPU allocated at all times (instance-based billing). Kept true: real-time WebSocket connections require an unthrottled instance (pair with min_instance_count >= 1).
container_resources4nullWhen set, overrides cpu_limit and memory_limit.
min_instance_count41Keep at 1 for production to avoid WebSocket disruption.
max_instance_count45Cost ceiling for auto-scaling.
container_port48065Mattermost's native HTTP port.
execution_environment4'gen2'Gen2 required for GCS Fuse volume mounts.
timeout_seconds4300Max request duration. Set to 3600 for WebSocket-heavy deployments.
enable_cloudsql_volume4trueInjects the Cloud SQL Auth Proxy sidecar. Set false for TCP.
container_protocol4'http1''http1' or 'h2c'.
enable_image_mirroring4trueMirrors the Mattermost image into Artifact Registry.
traffic_split4[]Percentage-based canary/blue-green traffic allocation.
max_revisions_to_retain47Maximum Cloud Run revisions to keep. Set 0 to disable.
service_annotations4{}Advanced Cloud Run annotations.
service_labels4{}Labels applied to the Cloud Run service.

Differences from App CloudRun defaults:

VariableApp CloudRunMattermost CloudRunReason
container_port80808065Mattermost's native port.
cpu_limit'1000m''2000m'Mattermost handles concurrent WebSocket connections and message indexing.
memory_limit'512Mi''2Gi'Mattermost caches channels, users, and sessions in memory.
min_instance_count01Scale-to-zero drops active user WebSocket connections.
cpu_always_allocatedfalsetrueReal-time WebSocket delivery must not be CPU-throttled between requests.

B. Database (Cloud SQL — PostgreSQL 15)

Mattermost requires PostgreSQL 13 or later — PostgreSQL 15 is the default. Mattermost runs its own schema migrations on startup; no manual database schema setup is needed beyond creating the database and user (handled by the db-init job).

The module uses db_name and db_user shorthand variables that flow through Mattermost Common into the application configuration.

VariableGroupDefaultDescription
database_type12'POSTGRES_15'Cloud SQL database engine. Do not change from PostgreSQL.
db_name12'mattermost'PostgreSQL database name. Do not change after initial deployment.
db_user12'mattermost'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.

C. Storage (GCS FUSE)

Mattermost stores uploaded files, attachments, and plugin data under /mattermost/data. Without persistent storage, all user uploads are lost on container restart or new revision deployment.

GCS FUSE is the recommended storage method for Cloud Run. Mount a GCS bucket at /mattermost/data via gcs_volumes. This provides durable, regionally replicated object storage without the latency overhead of NFS for file operations typical to Mattermost (document uploads, image attachments, plugin data).

NFS (enable_nfs) is also supported for deployments that require POSIX filesystem semantics.

VariableGroupDefaultDescription
enable_nfs11trueProvisions a Cloud Filestore NFS instance. Optional — GCS FUSE is preferred for Mattermost.
nfs_mount_path11'/mattermost/data'Container path where NFS is mounted.
nfs_instance_name11""Existing NFS GCE VM name. Leave empty to auto-discover.
nfs_instance_base_name11'app-nfs'Base name for the inline NFS GCE VM.
create_cloud_storage11trueSet false to skip GCS bucket creation.
storage_buckets11[]Additional GCS buckets to provision.
gcs_volumes11[]GCS buckets to mount via GCS Fuse. Each entry: name, bucket_name, mount_path, readonly, mount_options. Mount at /mattermost/data for persistent uploads.
manage_storage_kms_iam11falseCreates CMEK KMS key and enables CMEK on all storage buckets.
enable_artifact_registry_cmek11falseCreates Artifact Registry KMS key for at-rest image encryption.

Recommended GCS FUSE configuration for Mattermost file storage:

gcs_volumes = [
{
name = "mattermost-data"
bucket_name = "my-project-mattermost-data"
mount_path = "/mattermost/data"
readonly = false
mount_options = [
"implicit-dirs",
"stat-cache-ttl=60s",
"type-cache-ttl=60s"
]
}
]

D. Networking

Cloud Run uses Direct VPC Egress to reach Cloud SQL's private IP. The Auth Proxy sidecar (enable_cloudsql_volume = true) handles the database 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 Mattermost Common when initialization_jobs is left as the default empty list ([]). It uses a postgres-based image and executes Mattermost_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 mattermost database if it does not exist.
  3. Creates the mattermost user with the password from Secret Manager.
  4. Grants the user full privileges on the database.

Mattermost then runs its own schema migrations on first startup — no manual schema setup is required.

VariableGroupDefaultDescription
initialization_jobs13[]One-shot Cloud Run Jobs. Leave empty for Mattermost Common to supply the default db-init job. Non-empty list replaces it entirely. Each entry: name, description, image, command, args, env_vars, secret_env_vars, cpu_limit, memory_limit, timeout_seconds, max_retries, task_count, execution_mode, mount_nfs, mount_gcs_volumes, depends_on_jobs, execute_on_apply, script_path.
cron_jobs13[]Recurring Cloud Run Jobs triggered by Cloud Scheduler. Each entry: name, schedule, image, command, args, env_vars, secret_env_vars, cpu_limit, memory_limit, timeout_seconds, max_retries, task_count, parallelism, mount_nfs, mount_gcs_volumes, script_path, paused.

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 on the service. Google identity authentication is required before requests reach Mattermost. Useful for internal-only deployments where users must authenticate with their organisation's Google Workspace account before reaching the Mattermost login page.

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

C. Binary Authorization

When enable_binary_authorization = true, Cloud Run enforces that deployed Mattermost 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

Mattermost application secrets are stored in Secret Manager and injected natively by Cloud Run at revision start — plaintext is never written to state. User-defined secrets can be added via secret_environment_variables.

VariableGroupDefaultDescription
secret_environment_variables6{}Map of env var name → Secret Manager secret ID. Resolved at runtime.
explicit_secret_values6{}Raw sensitive values written into Secret Manager during deployment.
secret_rotation_period6'2592000s'Secret Manager rotation notification frequency. 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 Mattermost traffic through the LB, preventing direct *.run.app URL access.

B. Cloud CDN

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

Mattermost consideration: Mattermost serves a mix of real-time API traffic (WebSocket, REST) and static assets (JavaScript bundles, CSS, plugin files). Cloud CDN is suited for static asset delivery but should not cache API responses or WebSocket upgrades. Mattermost sets appropriate Cache-Control headers on its static assets, so CDN can be safely enabled for edge caching of the application bundle.

VariableGroupDefaultDescription
enable_cdn10falseEnables Cloud CDN on the HTTPS LB backend. Only effective when enable_cloud_armor = true.
max_images_to_retain107Maximum container images to keep in Artifact Registry. Set 0 to disable.
delete_untagged_images10trueAutomatically deletes untagged 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. Google-managed SSL certificates provisioned per domain.

After the first apply, retrieve the LB IP and create an A record. SSL certificate provisioning takes 10–30 minutes after DNS propagation. Then set site_url to the custom domain so Mattermost generates correct invite links and webhook URLs.


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 Mattermost 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 defaults to 1 — Mattermost maintains active WebSocket connections for real-time messaging, and scale-to-zero would disconnect all active users. max_instance_count defaults to 5, acting as a cost ceiling.

When running multiple instances, Redis (enable_redis = true) is required for distributed session sharing and cache consistency. Without Redis, different instances may serve stale cache or create session conflicts.

B. Traffic Splitting

Traffic splitting is supported for canary deployments.

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

Mattermost exposes a dedicated health endpoint at /api/v4/system/ping that returns HTTP 200 when the application is fully initialised and connected to the database. Health probes target this endpoint.

Mattermost performs schema migrations on first startup. The startup probe allows adequate time for migration to complete before traffic is directed to the new revision.

VariableGroupDefaultDescription
startup_probe14{ enabled=true, type="HTTP", path="/", initial_delay_seconds=60, period_seconds=15, failure_threshold=30 }Startup probe. Container receives no traffic until this succeeds.
liveness_probe14{ enabled=true, type="HTTP", path="/", initial_delay_seconds=60, timeout_seconds=5, period_seconds=30, failure_threshold=3 }Liveness probe. Container is restarted after failure_threshold consecutive failures.
startup_probe_config14{ enabled=true, path="/", initial_delay_seconds=60 }Service-level startup probe.
health_check_config14{ enabled=true, path="/", initial_delay_seconds=60 }Service-level liveness probe.
uptime_check_config14{ enabled=false, path="/" }Cloud Monitoring uptime check (disabled by default). When enabled, alerts notify support_users if unreachable.
alert_policies14[]Cloud Monitoring metric alert policies.

Note on probe path: The startup_probe and liveness_probe default to path = "/" in the Cloud Run module. The GKE variant uses /api/v4/system/ping. For more precise health signalling in Cloud Run, override the path to /api/v4/system/ping.

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 user, writes a new secret version.
  4. After rotation_propagation_delay_sec seconds, the job restarts the Mattermost service.
VariableGroupDefaultDescription
enable_auto_password_rotation12falseEnables automated password rotation.
rotation_propagation_delay_sec1290Seconds to wait after writing the new secret before restarting.

8. Integrations

A. Mattermost Application Settings

VariableGroupDefaultDescription
site_url20""The public URL where Mattermost is accessible. Sets MM_SERVICESETTINGS_SITEURL. Required after first deploy for correct invite links, webhooks, and email notifications. (e.g., 'https://chat.example.com')
edition20'team''team' (free) or 'enterprise' (paid — requires a licence key set via environment_variables). Controls which Mattermost container image is selected.

Site URL is critical. Without site_url, Mattermost defaults to http://localhost:8065 for link generation, causing broken invite links in emails and OAuth callbacks. Set site_url to the Cloud Run service URL (or custom domain) after first deploy.

B. Environment Variables

Mattermost is configured entirely through environment variables using the MM_ prefix. The environment_variables variable accepts any Mattermost configuration key:

VariableGroupDefaultDescription
environment_variables6{}Plain-text env vars. Use for Mattermost configuration such as email, plugins, and service settings.

Common Mattermost configuration variables injected automatically by Mattermost Common:

Environment VariableValuePurpose
MM_SERVICESETTINGS_LISTENADDRESS:8065Bind address for the Mattermost HTTP server.
MM_METRICSSETTINGS_LISTENADDRESS:8067Prometheus metrics endpoint.
MM_FILESETTINGS_DRIVERTYPElocalFile storage type (overridden when GCS FUSE is mounted).
MM_FILESETTINGS_DIRECTORY/mattermost/data/File storage path — matches the GCS FUSE or NFS mount point.
MM_LOGSETTINGS_CONSOLELEVELINFOLog level sent to stdout (captured by Cloud Logging).
MM_LOGSETTINGS_ENABLEFILEfalseFile-based logging disabled — Cloud Run captures stdout to Cloud Logging.
MM_SERVICESETTINGS_TRUSTEDPROXYIPHEADERX-Forwarded-ForEnables correct client IP extraction from Cloud Run and load balancer proxy headers.
MM_EMAILSETTINGS_ENABLEEMAILBATCHINGfalseDisabled for Cloud Run scale-to-zero compatibility. Email batching requires persistent in-memory queues.
MM_CACHEBACKENDredis or memorySet to redis when enable_redis = true; otherwise memory.
MM_REDIS_ADDRESSRedis host:portInjected when enable_redis = true.

C. Redis Cache

Redis is disabled by default (enable_redis = false). Enable Redis for any deployment running more than one instance — without Redis, multiple Mattermost instances cannot share session state or caches, leading to intermittent authentication failures and stale data.

VariableGroupDefaultDescription
enable_redis21falseEnables Redis for Mattermost caching and session storage. Recommended for multi-replica deployments.
redis_host21""Redis server hostname or IP. Leave blank to use the NFS server IP when enable_redis = true. Override with a Memorystore instance for production.
redis_port21'6379'Redis server TCP port (string).
redis_auth21""Redis AUTH password. Leave empty if authentication is not required. Sensitive — never stored in state.

D. Metrics

Mattermost exposes Prometheus-format metrics at port 8067 (/metrics). Enable metrics in Mattermost System Console under Environment → Performance Monitoring, then integrate with Google Cloud Monitoring via a Prometheus remote write endpoint or a scraper running in the same VPC.

E. Backup Import & Recovery

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 successful import.
backup_source7'gcs''gcs' (GCS bucket filename) or 'gdrive' (Drive file ID).
backup_file7'backup.sql'Filename of the backup in the module-managed backups GCS bucket.
backup_format7'sql'Backup format. Options: sql, tar, gz, tgz, tar.gz, zip.

F. Observability & Alerting

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

9. Exploring with the GCP Console

After a successful deployment, the GCP Console is the primary tool for inspecting the live Mattermost deployment.

Cloud Run Service Navigate to Cloud Run in the GCP Console and select the Mattermost service (named app<name><tenant><id> by default, e.g., appmattermostdemo). From the service page you can:

  • View the service URL to access the Mattermost web client.
  • Inspect active revisions and their traffic allocation percentages.
  • Review container configuration including environment variables, mounted volumes, and resource limits.
  • Check the Logs tab to stream Mattermost application logs directly — all stdout output is captured by Cloud Logging.
  • Monitor Metrics for request count, latency (p50, p95, p99), container instance count, memory utilisation, and startup latency.
  • View Revisions to see the history of deployments, current traffic weights, and active revision tags.

Cloud SQL Navigate to SQL and select the PostgreSQL 15 instance. Useful checks:

  • Connections tab: active connection count from the Cloud Run service (via the Auth Proxy).
  • Operations & logs: recent CREATE DATABASE, user grant, and migration activity.
  • Databases tab: verify the mattermost database exists after first deployment.
  • Users tab: confirm the mattermost user was created by the db-init job.
  • Backups: automated and on-demand backups. Cross-check with the backup_schedule variable.

Cloud Storage If gcs_volumes is configured with a data bucket for /mattermost/data, navigate to Cloud Storage and select the bucket. Browse the directory structure that Mattermost creates under the mount point:

  • teams/ — team icons and attachments.
  • users/ — profile pictures.
  • plugins/ — plugin data files. File operations in the bucket reflect uploads and attachments made by Mattermost users.

Secret Manager Navigate to Secret Manager and filter by the deployment's resource labels. Secrets created by App CloudRun for Mattermost include:

  • DB_PASSWORD — the PostgreSQL application user password.
  • ROOT_PASSWORD — the PostgreSQL root/superuser password used by the db-init job. Click a secret to view its versions, access history, and rotation configuration.

Cloud Build Navigate to Cloud Build → History to inspect image build logs. Each deployment creates a build that compiles the Mattermost custom image (when container_image_source = 'custom'). Build logs show the Docker build steps, layer caching behaviour, and push to Artifact Registry.

Artifact Registry Navigate to Artifact Registry and find the repository for the project. The Mattermost image is stored here after each Cloud Build run. Older images are cleaned up according to max_images_to_retain and image_retention_days.

Cloud Monitoring Navigate to Monitoring → Dashboards to see Cloud Run metrics dashboards. If uptime_check_config is enabled, the uptime check appears under Monitoring → Uptime checks. Alert policies created via alert_policies appear under Monitoring → Alerting.


10. Exploring with gcloud

The following gcloud commands are useful for day-to-day operations and troubleshooting after deployment. Replace PROJECT_ID, REGION, and SERVICE_NAME with your actual values.

Describe the Cloud Run service:

gcloud run services describe SERVICE_NAME \
--region=REGION \
--project=PROJECT_ID \
--format="yaml(spec.template.spec.containers[0].env)"

View the service URL and current traffic split:

gcloud run services describe SERVICE_NAME \
--region=REGION \
--project=PROJECT_ID \
--format="table(status.url, status.traffic[].revisionName, status.traffic[].percent)"

List all revisions and their traffic weights:

gcloud run revisions list \
--service=SERVICE_NAME \
--region=REGION \
--project=PROJECT_ID \
--sort-by="~metadata.creationTimestamp" \
--format="table(metadata.name, status.conditions[0].type, status.conditions[0].status, metadata.creationTimestamp)"

Stream live logs from the Mattermost service:

gcloud logging read \
"resource.type=cloud_run_revision AND resource.labels.service_name=SERVICE_NAME" \
--project=PROJECT_ID \
--format="value(textPayload)" \
--freshness=10m \
--order=asc

Check the db-init Cloud Run Job execution history:

gcloud run jobs executions list \
--job=SERVICE_NAME-db-init \
--region=REGION \
--project=PROJECT_ID \
--format="table(metadata.name, status.conditions[0].type, metadata.creationTimestamp)"

Manually trigger the db-init job (e.g., after a database restore):

gcloud run jobs execute SERVICE_NAME-db-init \
--region=REGION \
--project=PROJECT_ID \
--wait

Inspect the Cloud SQL instance and verify database connectivity:

gcloud sql instances describe SQL_INSTANCE_NAME \
--project=PROJECT_ID \
--format="table(name, state, databaseVersion, settings.tier, ipAddresses[].ipAddress)"

List Cloud SQL databases on the instance:

gcloud sql databases list \
--instance=SQL_INSTANCE_NAME \
--project=PROJECT_ID

View Secret Manager secrets for the deployment:

gcloud secrets list \
--project=PROJECT_ID \
--filter="labels.app=mattermost" \
--format="table(name, createTime, replication.automatic)"

Access the latest version of the database password secret:

gcloud secrets versions access latest \
--secret=DB_PASSWORD_SECRET_NAME \
--project=PROJECT_ID

List container images in Artifact Registry:

gcloud artifacts docker images list REGION-docker.pkg.dev/PROJECT_ID/REPO_NAME \
--filter="tags:mattermost" \
--sort-by="~createTime" \
--format="table(IMAGE, TAGS, CREATE_TIME, UPDATE_TIME)"

Force a new deployment (redeploy the latest revision):

gcloud run services update SERVICE_NAME \
--region=REGION \
--project=PROJECT_ID \
--update-env-vars=DEPLOY_TIMESTAMP=$(date +%s)

Check Cloud Monitoring uptime check status:

gcloud monitoring uptime list-configs \
--project=PROJECT_ID \
--format="table(displayName, httpCheck.path, period, selectedRegions)"

View active alert policies:

gcloud alpha monitoring policies list \
--project=PROJECT_ID \
--format="table(displayName, enabled, conditions[0].displayName)"

Inspect the GCS bucket used for Mattermost file storage:

gsutil ls -l gs://BUCKET_NAME/
gsutil du -s gs://BUCKET_NAME/

Check if a specific Mattermost upload file is present:

gsutil stat gs://BUCKET_NAME/teams/TEAM_ID/channels/CHANNEL_ID/attachments/FILE_ID

11. Platform-Managed Behaviours

The following behaviours are applied automatically by Mattermost CloudRun regardless of variable values.

BehaviourImplementationDetail
PostgreSQL 15 requireddatabase_type = "POSTGRES_15" defaultMattermost requires PostgreSQL 13 or later. The database connection string and driver are configured by Mattermost Common.
GCS FUSE volumes for datagcs_volumes configured via Mattermost Common/mattermost/data is wired to a GCS FUSE mount for durable file storage when gcs_volumes is populated.
Image mirroring enabled by defaultenable_image_mirroring = trueThe Mattermost Docker Hub image is mirrored to Artifact Registry before deployment, preventing dependency on external registries.
Minimum 1 instancemin_instance_count = 1 defaultPrevents scale-to-zero from disconnecting active user WebSocket sessions.
No auto-generated app secretsMattermost generates keys on first bootInternal signing keys, session secrets, and symmetric encryption keys are generated by Mattermost itself and stored in PostgreSQL — not in Secret Manager.
Default db-init jobSupplied by Mattermost Common when initialization_jobs = []PostgreSQL database and user are created automatically before Mattermost starts. Override with a non-empty initialization_jobs list to replace.
Proxy header trustMM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER=X-Forwarded-ForRequired for correct client IP extraction when Cloud Run is behind Cloud Armor or a load balancer. Injected automatically.
Email batching disabledMM_EMAILSETTINGS_ENABLEEMAILBATCHING=falseBatching requires persistent in-memory queues incompatible with Cloud Run's stateless execution model.
Site URL env varMM_SERVICESETTINGS_SITEURL set from site_url variableWhen site_url is non-empty, it is injected as MM_SERVICESETTINGS_SITEURL. Set this after first deploy to ensure correct link generation.

12. Variable Reference

All user-configurable variables exposed by Mattermost CloudRun, sorted by UI group then order. | Variable | Group | Default | Description | |---|---|---|---| | project_id | 1 | — | GCP project ID. Required. | | region | 1 | 'us-central1' | GCP region for resource deployment. | | tenant_deployment_id | 1 | 'demo' | Short suffix appended to all resource names. | | support_users | 1 | [] | Email addresses for IAM access and monitoring alerts. | | resource_labels | 1 | {} | Labels applied to all provisioned resources. | | application_name | 3 | 'mattermost' | Base resource name. Do not change after deployment. | | display_name | 3 | 'Mattermost' | Human-readable name shown in the UI. | | description | 3 | 'Mattermost - Open-source team messaging and collaboration' | Service description. | | application_version | 3 | '9.11.2' | Mattermost container image tag. | | 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 | "" | Container image URI. Leave empty for Cloud Build to manage. | | cpu_limit | 4 | '2000m' | CPU per instance. 2 vCPU recommended. | | memory_limit | 4 | '2Gi' | Memory per instance. | | cpu_always_allocated | 4 | true | CPU allocated at all times. Kept true for real-time WebSocket handling. | | container_resources | 4 | null | Overrides cpu_limit and memory_limit when set. | | min_instance_count | 4 | 1 | Keep at 1 to avoid WebSocket disconnections. | | max_instance_count | 4 | 5 | Auto-scaling cost ceiling. | | container_port | 4 | 8065 | Mattermost's native HTTP port. | | execution_environment | 4 | 'gen2' | Gen2 required for GCS Fuse. | | timeout_seconds | 4 | 300 | Max request duration. Set 3600 for WebSocket connections. | | enable_cloudsql_volume | 4 | true | Cloud SQL Auth Proxy sidecar. | | container_protocol | 4 | 'http1' | 'http1' or 'h2c'. | | enable_image_mirroring | 4 | true | Mirrors the Mattermost image into Artifact Registry. | | 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 for Mattermost configuration. | | secret_environment_variables | 6 | {} | Secret Manager references. | | explicit_secret_values | 6 | {} | Raw sensitive values written into Secret Manager. | | 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' | Backup filename in the module-managed backups bucket. | | backup_format | 7 | 'sql' | Backup format. Options: sql, tar, gz, tgz, tar.gz, zip. | | 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. Required on first apply. 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' | 'ALWAYS_ALLOW', 'REQUIRE_ATTESTATION', or 'ALWAYS_DENY'. | | 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 recent container images in Artifact Registry. | | delete_untagged_images | 10 | true | Deletes untagged images from Artifact Registry. | | image_retention_days | 10 | 30 | Days after which images are eligible for deletion. | | create_cloud_storage | 11 | true | Set false to skip GCS bucket creation. | | storage_buckets | 11 | [] | Additional GCS buckets to provision. | | enable_nfs | 11 | true | Provisions NFS shared storage. | | nfs_mount_path | 11 | '/mattermost/data' | Container path where NFS is mounted. | | nfs_instance_name | 11 | "" | Existing NFS GCE VM name. Leave empty to auto-discover. | | nfs_instance_base_name | 11 | 'app-nfs' | Base name for inline NFS VM. | | gcs_volumes | 11 | [] | GCS buckets to mount via GCS Fuse. | | manage_storage_kms_iam | 11 | false | Creates CMEK KMS key and enables CMEK on storage buckets. | | enable_artifact_registry_cmek | 11 | false | Creates Artifact Registry KMS key for at-rest encryption. | | database_type | 12 | 'POSTGRES_15' | Cloud SQL engine. Mattermost requires PostgreSQL. | | db_name | 12 | 'mattermost' | PostgreSQL database name. Do not change after deployment. | | db_user | 12 | 'mattermost' | 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. | | initialization_jobs | 13 | [] | One-shot Cloud Run Jobs. Leave empty for Mattermost Common default db-init job. | | cron_jobs | 13 | [] | Recurring scheduled Cloud Run Jobs. | | startup_probe | 14 | { path="/", initial_delay_seconds=60, failure_threshold=30 } | Startup probe. | | liveness_probe | 14 | { path="/", initial_delay_seconds=60, failure_threshold=3 } | Liveness probe. | | startup_probe_config | 14 | { enabled=true, path="/" } | Service-level startup probe. | | health_check_config | 14 | { enabled=true, path="/" } | Service-level liveness probe. | | uptime_check_config | 14 | { enabled=false, path="/" } | Cloud Monitoring uptime check (disabled by default). | | alert_policies | 14 | [] | Cloud Monitoring metric alert policies. | | site_url | 20 | "" | Public URL for Mattermost. Sets MM_SERVICESETTINGS_SITEURL. | | edition | 20 | 'team' | 'team' (free) or 'enterprise' (paid). | | enable_redis | 21 | false | Redis for Mattermost caching. Required for multi-replica. | | redis_host | 21 | "" | Redis hostname/IP. Defaults to NFS server IP when empty. | | redis_port | 21 | '6379' | Redis TCP port (string). | | redis_auth | 21 | "" | Redis AUTH password. Sensitive. | | 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. Set false to enforce. | | organization_id | 22 | "" | GCP Organization ID for VPC-SC. Auto-discovered when empty. | | enable_audit_logging | 22 | false | Enables detailed Cloud Audit Logs. |


13. 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.

14. 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"CriticalMattermost requires PostgreSQL 13 or later. Setting to a MySQL or SQL Server variant causes Mattermost to fail to start with a driver connection error.
db_name"mattermost"CriticalImmutable after first deployment — changing this causes Mattermost to recreate the database, destroying all message history, users, and configuration.
db_user"mattermost"CriticalImmutable after first deployment — changing this recreates the Cloud SQL user and breaks the database connection.
min_instance_count1HighScale-to-zero (0) causes active WebSocket connections (real-time messaging) to drop for all online users whenever the single instance scales down. Set to 1 for any production deployment.
timeout_seconds300HighMattermost maintains WebSocket connections for real-time messaging. A 5-minute timeout causes Cloud Run to terminate all active WebSocket connections every 5 minutes. Set to 3600 for production WebSocket-heavy deployments.
enable_redisfalseHighWhen running multiple replicas (max_instance_count > 1), Redis is required for distributed session sharing. Without it, users experience intermittent authentication failures and stale data as requests route to different instances with independent memory caches.
site_url""HighWithout site_url, Mattermost uses http://localhost:8065 for link generation. This breaks email invite links, OAuth redirect URIs, and webhook callback URLs. Set to the Cloud Run service URL or custom domain after first deploy.
gcs_volumes[]HighWithout a persistent volume at /mattermost/data, all user file uploads and attachments are stored on the container's ephemeral filesystem. All uploaded files are permanently lost when a new revision is deployed or the container restarts.
edition"team"MediumSetting edition = "enterprise" selects the Enterprise Edition container image. Without a valid licence key set via environment_variables, Mattermost starts in Enterprise trial mode and eventually falls back to Team Edition features.
memory_limit"2Gi"MediumMattermost caches channel lists, user sessions, and message indexes in memory. Reducing below 1Gi causes OOM restarts under moderate team activity. Increase to 4Gi for teams with 100+ active users.
backup_retention_days7MediumSeven days is insufficient for active teams. Increase to 30+ days for any production Mattermost instance to allow point-in-time recovery from data corruption or accidental deletion.
enable_cloud_armorfalseMediumWithout Cloud Armor, Mattermost is exposed directly on the *.run.app URL. For production teams, enable Cloud Armor to protect the API from bot attacks and credential stuffing.
enable_iapfalseLowWith IAP disabled, Mattermost is responsible for its own authentication. Consider enabling IAP for internal-only deployments to add an additional authentication layer before requests reach Mattermost.
secret_propagation_delay30LowOccasionally insufficient in multi-region setups. Increase to 60–90s if secrets are not found during apply.

15. 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.

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.