Backstage Configuration
OpenChoreo uses Backstage as its developer portal, providing a unified interface for managing organizations, projects, components, and deployments. This guide covers configuration options for customizing Backstage in your OpenChoreo deployment.
Backstage configuration is done via Helm values in the Control Plane chart.
Core Configurationβ
Console/UI URL:
backstage:
appConfig:
app:
baseUrl: "https://console.example.com"
backend:
baseUrl: "https://console.example.com"
OpenChoreo API URL:
openchoreoApi:
ingress:
enabled: true
hosts:
- host: api.example.com
paths:
- path: /
Authenticationβ
By default, OpenChoreo configures Thunder as the identity provider for Backstage with a pre-configured OAuth client for testing purposes. If you want to integrate an external identity provider instead, create an OAuth 2.0 client with the following requirements:
OAuth Client Requirements:
-
Grant Types: The OAuth client must support both:
authorization_code- For user authentication and login flowsclient_credentials- For service-to-service authentication
-
Token Format: Configure the client to issue JWT tokens (not opaque tokens)
-
Redirect URLs: Add the Backstage callback URL:
<protocol>://<backstage-domain>/api/auth/openchoreo-auth/handler/frame- Replace
<protocol>withhttporhttpsand<backstage-domain>with your actual Backstage domain
Helm Configuration:
Once you have created the OAuth client, configure Backstage with the client credentials:
helm upgrade --install openchoreo-control-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-control-plane \
--version 0.11.0 \
--namespace openchoreo-control-plane \
--reuse-values \
--set backstage.auth.clientId="your-client-id" \
--set backstage.auth.clientSecret="your-client-secret" \
--set backstage.auth.redirectUrls\[0\]="<protocol>://<backstage-domain>/api/auth/openchoreo-auth/handler/frame"
See Identity Provider Configuration for detailed setup instructions.
Feature Flagsβ
backstage:
features:
workflows:
enabled: true # Requires Build Plane
observability:
enabled: true # Requires Observability Plane
Resource Configurationβ
backstage:
replicas: 1
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 200m
memory: 256Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 5
Environment Variablesβ
Add custom environment variables to the Backstage deployment:
backstage:
env:
- name: NODE_ENV
value: production
- name: LOG_LEVEL
value: info
- name: PORT
value: "7007"
Commonly Used Variablesβ
| Variable | Description | Default |
|---|---|---|
NODE_ENV | Node.js environment | production |
LOG_LEVEL | Logging verbosity | info |
PORT | HTTP server port | 7007 |
OPENCHOREO_API_URL | OpenChoreo API endpoint | Auto-configured |
THUNDER_BASE_URL | Thunder IdP URL | Auto-configured |
Ingress Configurationβ
backstage:
ingress:
enabled: true
className: "your-ingress-class"
hosts:
- host: console.example.com
paths:
- path: /
tls:
- secretName: console-tls
hosts:
- console.example.com
Service Configurationβ
backstage:
service:
type: ClusterIP
port: 7007
OpenChoreo API Integrationβ
Backstage communicates with the OpenChoreo API for backend operations:
backstage:
openchoreoApi:
url: "" # Auto-configured to internal service URL
The API URL defaults to http://{release-name}-api.{namespace}.svc.cluster.local:8080/api/v1.
Backend Secretβ
For session encryption (should be stable across restarts):
backstage:
backendSecret: "your-32-character-secret-here"
Database Configurationβ
Backstage requires a database to store catalog entities, user settings, and plugin data. OpenChoreo supports two database backends:
| Backend | Use Case | Persistence | Scalability |
|---|---|---|---|
| SQLite (default) | Development, single-replica | Optional (emptyDir or PVC) | Single replica only |
| PostgreSQL | Production, multi-replica | External database | Horizontal scaling |
Default Configuration (SQLite)β
By default, Backstage uses SQLite with an emptyDir volume, which means data is lost when the pod restarts:
backstage:
database:
type: sqlite
sqlite:
persistence:
enabled: false # Uses emptyDir (data lost on restart)
SQLite with Persistenceβ
For development environments where you want data to persist across restarts but don't need horizontal scaling:
backstage:
database:
type: sqlite
sqlite:
mountPath: /app/.config/backstage
persistence:
enabled: true
size: 1Gi
storageClassName: "" # Uses default storage class
accessMode: ReadWriteOnce
SQLite locks the database file, preventing multiple Backstage replicas from running simultaneously. For high-availability deployments, use PostgreSQL.
PostgreSQL for Productionβ
For production deployments requiring high availability and data durability, configure an external PostgreSQL database.
Prerequisitesβ
- Provision a PostgreSQL Database: Use a managed service (AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL) or a self-hosted PostgreSQL instance
- Create a Database: Create a database for Backstage (e.g.,
backstage) - Create a Database User: Create a user with full access to the database
Backstage automatically creates per-plugin databases (e.g., backstage_plugin_catalog, backstage_plugin_auth) using the provided credentials.
Helm Configurationβ
- External PostgreSQL
- In-Cluster PostgreSQL
- Values File
For managed PostgreSQL services or external databases:
helm upgrade --install openchoreo-control-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-control-plane \
--version 0.11.0 \
--namespace openchoreo-control-plane \
--reuse-values \
--set backstage.database.type=postgresql \
--set backstage.database.postgresql.host="postgres.example.com" \
--set backstage.database.postgresql.port=5432 \
--set backstage.database.postgresql.user="backstage" \
--set backstage.database.postgresql.password="your-secure-password" \
--set backstage.database.postgresql.database="backstage"
For PostgreSQL running within the same Kubernetes cluster:
helm upgrade --install openchoreo-control-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-control-plane \
--version 0.11.0 \
--namespace openchoreo-control-plane \
--reuse-values \
--set backstage.database.type=postgresql \
--set backstage.database.postgresql.host="postgres.your-namespace.svc.cluster.local" \
--set backstage.database.postgresql.port=5432 \
--set backstage.database.postgresql.user="backstage" \
--set backstage.database.postgresql.password="your-secure-password" \
--set backstage.database.postgresql.database="backstage"
Using a values file for better secret management:
# backstage-db-values.yaml
backstage:
database:
type: postgresql
postgresql:
host: "postgres.example.com"
port: 5432
user: "backstage"
password: "your-secure-password" # Consider using external secrets
database: "backstage"
helm upgrade --install openchoreo-control-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-control-plane \
--version 0.11.0 \
--namespace openchoreo-control-plane \
--reuse-values \
-f backstage-db-values.yaml
PostgreSQL Configuration Referenceβ
| Parameter | Description | Default |
|---|---|---|
backstage.database.type | Database backend (sqlite or postgresql) | sqlite |
backstage.database.postgresql.host | PostgreSQL server hostname | "" |
backstage.database.postgresql.port | PostgreSQL server port | 5432 |
backstage.database.postgresql.user | Database username | backstage |
backstage.database.postgresql.password | Database password | "" |
backstage.database.postgresql.database | Database name | backstage |
Verifying PostgreSQL Connectionβ
After deploying with PostgreSQL, verify the connection:
# Check Backstage pod is running
kubectl get pods -n openchoreo-control-plane -l app.kubernetes.io/component=backstage
# Verify database environment variables
kubectl exec -n openchoreo-control-plane deployment/openchoreo-ui -- env | grep -E "DATABASE|POSTGRES"
# Check logs for database connection errors
kubectl logs -n openchoreo-control-plane deployment/openchoreo-ui | head -50
If PostgreSQL is configured correctly, Backstage will create per-plugin databases automatically:
# List databases created by Backstage (run against your PostgreSQL instance)
psql -U backstage -d backstage -c "\l" | grep backstage_plugin
Expected output shows databases like backstage_plugin_catalog, backstage_plugin_auth, etc.
Health Checksβ
Backstage health checks are pre-configured:
| Check | Endpoint | Default |
|---|---|---|
| Liveness | /healthcheck | Enabled |
| Readiness | /healthcheck | Enabled |
Example Configurationsβ
- Development
- Production
- API-only Mode
backstage:
enabled: true
replicas: 1
baseUrl: "http://localhost:7007"
ingress:
enabled: true
hosts:
- host: localhost
paths:
- path: /
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 100m
memory: 256Mi
features:
workflows:
enabled: true
observability:
enabled: true
backstage:
enabled: true
replicas: 2
baseUrl: "https://console.example.com"
backendSecret: "your-production-secret-32chars!"
# PostgreSQL for production (required for multi-replica)
database:
type: postgresql
postgresql:
host: "postgres.example.com"
port: 5432
user: "backstage"
password: "your-secure-password"
database: "backstage"
ingress:
enabled: true
hosts:
- host: console.example.com
paths:
- path: /
tls:
- secretName: console-tls
hosts:
- console.example.com
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
targetCPUUtilizationPercentage: 70
features:
workflows:
enabled: true
observability:
enabled: true
For headless deployments where only the API is needed:
backstage:
enabled: false
# Security can also be disabled for development
security:
enabled: false
Troubleshootingβ
Backstage Not Loadingβ
Check pod status and logs:
kubectl get pods -n openchoreo-control-plane -l app.kubernetes.io/name=backstage
kubectl logs -n openchoreo-control-plane deployment/backstage
Authentication Issuesβ
Verify OAuth configuration:
# Check Backstage environment variables
kubectl exec -n openchoreo-control-plane deployment/backstage -- env | grep -E "(AUTH|THUNDER)"
# Check Thunder is running
kubectl get pods -n openchoreo-control-plane -l app.kubernetes.io/name=thunder
API Connection Errorsβ
Verify OpenChoreo API is accessible:
# Check API pod
kubectl get pods -n openchoreo-control-plane -l app.kubernetes.io/name=openchoreo-api
# Test API from Backstage pod
kubectl exec -n openchoreo-control-plane deployment/backstage -- \
curl -s http://openchoreo-control-plane-api:8080/api/v1/health
Database Connection Issuesβ
If Backstage fails to start with database errors:
For SQLite errors:
# Check if the pod has write access to the database directory
kubectl exec -n openchoreo-control-plane deployment/openchoreo-ui -- ls -la /app/.config/backstage
# Check for SQLite-specific errors in logs
kubectl logs -n openchoreo-control-plane deployment/openchoreo-ui | grep -i "sqlite\|database"
For PostgreSQL errors:
# Verify PostgreSQL environment variables are set
kubectl exec -n openchoreo-control-plane deployment/openchoreo-ui -- env | grep POSTGRES
# Test PostgreSQL connectivity from the pod
kubectl exec -n openchoreo-control-plane deployment/openchoreo-ui -- \
nc -zv <postgres-host> 5432
# Check for connection errors in logs
kubectl logs -n openchoreo-control-plane deployment/openchoreo-ui | grep -i "postgres\|connection\|ECONNREFUSED"
Common issues:
| Error | Cause | Solution |
|---|---|---|
ECONNREFUSED | PostgreSQL not reachable | Verify hostname, port, and network policies |
password authentication failed | Invalid credentials | Check backstage.database.postgresql.password |
database does not exist | Missing database | Create the database on PostgreSQL server |
connection.filename is not supported | Outdated Backstage image | Upgrade to latest control plane chart |
Next Stepsβ
- Identity Provider Configuration: Configure an external IdP
- Deployment Topology: Set up organizations and environments
- Helm Charts Reference: Complete Backstage configuration options