Azure Container Apps
Deploy Openfuse on Azure Container Apps with Azure Database for PostgreSQL, Key Vault for secrets, and hostname-based routing via custom domains.
This guide covers deploying Openfuse on Azure Container Apps. For the single-server Docker Compose setup, see Docker Compose.
Prerequisites
- An Azure subscription with Container Apps, Azure Database for PostgreSQL, and Key Vault
- A managed PostgreSQL 17+ flexible server with two databases:
openfuseandkeycloak - A domain with wildcard DNS records pointing to your Container Apps environment
- A Container Apps environment with custom domain and TLS configured
Architecture
| Component | Azure Resource | Notes |
|---|---|---|
| API | Container App | Stateless, auto-scales |
| Keycloak | Container App | Min replicas: 1 |
| UI | Container App | Static SPA, or use Azure CDN |
| Config Importer | Container App Job | Execute during deployments |
Custom domain routing
Azure Container Apps support custom domains with SNI-based routing. Configure each app with its hostname:
| Container App | Custom domain | Port |
|---|---|---|
openfuse-api | *.api.<ROOT_DOMAIN> | 3000 |
keycloak | sso.<ROOT_DOMAIN> | 8080 |
openfuse-ui | <ROOT_DOMAIN>, *.<ROOT_DOMAIN> | 80 |
TLS is handled by Azure-managed certificates or your own certificates via Key Vault.
Key Vault secrets
Store secrets in Azure Key Vault and reference them in Container Apps:
# Create secrets
az keyvault secret set --vault-name openfuse-kv --name db-password --value "your-password"
az keyvault secret set --vault-name openfuse-kv --name session-secret --value "your-session-secret"
az keyvault secret set --vault-name openfuse-kv --name kc-admin-password --value "your-kc-password"
# ... repeat for each secretConfig Importer
Run the Config Importer as a Container App Job:
az containerapp job create \
--name openfuse-config-importer \
--resource-group openfuse-rg \
--environment openfuse-env \
--image ghcr.io/openfuseio/openfuse-config-importer:1.0.0 \
--trigger-type Manual \
--replica-timeout 300 \
--env-vars \
KEYCLOAK_URL=http://keycloak IMPORT_VARSUBSTITUTION_ENABLED=true \
IMPORT_VARSUBSTITUTION_UNDEFINEDISTERROR=true \
--secrets \
kc-password=keyvaultref:openfuse-kv/kc-admin-password,identityref:/subscriptions/.../identity \
--secret-env-vars \
KEYCLOAK_PASSWORD=kc-password
# Execute it
az containerapp job start \
--name openfuse-config-importer \
--resource-group openfuse-rgThe importer waits up to 120s for Keycloak to be ready. Run on first deployment and on upgrades that include realm config changes.
API container app
az containerapp create \
--name openfuse-api \
--resource-group openfuse-rg \
--environment openfuse-env \
--image ghcr.io/openfuseio/openfuse-api:1.0.0 \
--target-port 3000 \
--ingress external \
--min-replicas 1 \
--max-replicas 10 \
--env-vars \
ROOT_DOMAIN=openfuse.example.com \
DATABASE_HOST=openfuse-db.postgres.database.azure.com \
DATABASE_SSL=true \
KEYCLOAK_URL=http://keycloak \
KEYCLOAK_EXTERNAL_URL=https://sso.openfuse.example.com \
--secrets \
db-password=keyvaultref:openfuse-kv/db-password,identityref:/subscriptions/.../identity \
--secret-env-vars \
DATABASE_PASSWORD=db-passwordThe API is stateless — scale freely. All replicas must share the same SESSION_SECRET. Database migrations use an advisory lock for safe concurrent startup.
Keycloak container app
az containerapp create \
--name keycloak \
--resource-group openfuse-rg \
--environment openfuse-env \
--image ghcr.io/openfuseio/openfuse-keycloak:1.0.0 \
--args start \
--target-port 8080 \
--ingress external \
--min-replicas 1 \
--env-vars \
KC_DB=postgres \
KC_HOSTNAME=sso.openfuse.example.com \
KC_PROXY_HEADERS=xforwarded \
KC_HTTP_ENABLED=true \
KC_HEALTH_ENABLED=trueSet --min-replicas 1 to avoid cold start delays on the login page.
Next steps
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.
Configuration
Complete environment variable reference for self-hosted Openfuse deployments. Covers platform settings, database, authentication, SMTP, and social login.