Skip to main content
Openfuse

Google Cloud Run

Deploy Openfuse on Google Cloud Run with Cloud SQL, Cloud Run Jobs for the Config Importer, and Cloud Load Balancing for hostname-based routing.

This guide covers deploying Openfuse on Google Cloud Run. For the single-server Docker Compose setup, see Docker Compose.

Prerequisites

  • A Google Cloud project with Cloud Run, Cloud SQL, and Secret Manager enabled
  • A managed PostgreSQL 17+ instance (Cloud SQL) with two databases: openfuse and keycloak
  • A domain with wildcard DNS records
  • A global external Application Load Balancer for hostname-based routing

Architecture

ComponentCloud Run ResourceNotes
APIServiceStateless, auto-scales
KeycloakServiceMin instances: 1 (avoid cold starts)
UIServiceStatic SPA, or use Cloud CDN
Config ImporterJobExecute during deployments

Load balancer routing

Cloud Run services get individual URLs by default, but Openfuse requires hostname-based routing. Use a global external Application Load Balancer with URL maps:

Host rulePathBackend service
*.api.<ROOT_DOMAIN>/*API (serverless NEG)
sso.<ROOT_DOMAIN>/*Keycloak (serverless NEG)
Default/*UI (serverless NEG)

TLS terminates at the load balancer using Google-managed certificates.

Secret Manager

Store secrets in Google Secret Manager:

echo -n "your-db-password" | gcloud secrets create openfuse-db-password --data-file=-
echo -n "your-session-secret" | gcloud secrets create openfuse-session-secret --data-file=-
# ... repeat for each secret

Reference in Cloud Run services:

gcloud run services update openfuse-api \
  --set-secrets=DATABASE_PASSWORD=openfuse-db-password:latest,SESSION_SECRET=openfuse-session-secret:latest

Config Importer

Run the Config Importer as a Cloud Run Job:

# Create the job
gcloud run jobs create openfuse-config-importer \
  --image ghcr.io/openfuseio/openfuse-config-importer:1.0.0 \
  --region us-central1 \
  --set-env-vars KEYCLOAK_URL=http://keycloak-internal:8080 \
  --set-env-vars IMPORT_VARSUBSTITUTION_ENABLED=true \
  --set-env-vars IMPORT_VARSUBSTITUTION_UNDEFINEDISTERROR=true \
  --set-secrets KEYCLOAK_PASSWORD=openfuse-kc-admin-password:latest \
  # ... remaining env vars and secrets

# Execute it
gcloud run jobs execute openfuse-config-importer \
  --region us-central1 \
  --wait

The importer waits up to 120s for Keycloak to be ready. Run on first deployment and on upgrades that include realm config changes.

API service

gcloud run deploy openfuse-api \
  --image ghcr.io/openfuseio/openfuse-api:1.0.0 \
  --region us-central1 \
  --port 3000 \
  --min-instances 1 \
  --set-env-vars ROOT_DOMAIN=openfuse.example.com \
  --set-env-vars DATABASE_HOST=/cloudsql/project:region:instance \
  --set-env-vars DATABASE_SSL=true \
  --set-env-vars KEYCLOAK_URL=http://keycloak-internal:8080 \
  --set-env-vars KEYCLOAK_EXTERNAL_URL=https://sso.openfuse.example.com \
  --set-secrets=DATABASE_PASSWORD=openfuse-db-password:latest,SESSION_SECRET=openfuse-session-secret:latest \
  --add-cloudsql-instances project:region:instance

The API is stateless — Cloud Run auto-scales based on traffic. All instances must share the same SESSION_SECRET. Database migrations use an advisory lock, so concurrent startups won't conflict.

Keycloak service

gcloud run deploy keycloak \
  --image ghcr.io/openfuseio/openfuse-keycloak:1.0.0 \
  --region us-central1 \
  --port 8080 \
  --min-instances 1 \
  --args start \
  --set-env-vars KC_DB=postgres \
  --set-env-vars KC_HOSTNAME=sso.openfuse.example.com \
  --set-env-vars KC_PROXY_HEADERS=xforwarded \
  --set-env-vars KC_HTTP_ENABLED=true \
  --set-env-vars KC_HEALTH_ENABLED=true \
  --set-secrets KC_DB_PASSWORD=openfuse-db-password:latest \
  --add-cloudsql-instances project:region:instance

Set --min-instances 1 to avoid cold start delays on the login page.

Next steps

On this page