This is a workspace directory containing multiple Open Service Portal repositories for unified development.
This workspace contains the following repositories:
- app-portal/ - Main Backstage application
- catalog/ - Template catalog (XRDs/Compositions definitions)
- catalog-orders/ - XR instances created from Backstage templates
- template-dns-record/ - DNS record management template
- template-cloudflare-dnsrecord/ - DNS management via External-DNS
- template-whoami/ - Demo application template
- template-whoami-service/ - Composite service (app + DNS)
- service-nodejs-template/ - Node.js service template
- service-mongodb-template/ - MongoDB database service
- service-mongodb-golden-path-template/ - MongoDB with best practices
- service-firewall-template/ - Network firewall rules
- service-dnsrecord-template/ - DNS record management
- service-cluster-template/ - Kubernetes cluster provisioning
To set up this workspace, clone each repository:
# Clone the workspace (this repository)
git clone git@github.com:open-service-portal/portal-workspace.git open-service-portal
cd open-service-portal
# Clone core application repository
git clone git@github.com:open-service-portal/app-portal.git
# Clone all repositories with the sync script
./scripts/repos-sync.sh
Each repository has its own development workflow. See CLAUDE.md for detailed development commands and architecture information.
# Start Backstage
cd app-portal
yarn install
yarn start
- Frontend: http://localhost:3000
- Backend API: http://localhost:7007
- CLAUDE.md - Development instructions for Claude Code
- Cluster Overview - Kubernetes cluster architecture
- DNS Management - DNS management with External-DNS
- Manifests - Platform manifest documentation
- Catalog Setup - How to create and manage Crossplane templates
- Configuration - Environment and provider configuration
- GitHub App Setup - Configure GitHub authentication
- Secret Management - Managing secrets with SOPS
- Kubernetes cluster (Kind, Rancher Desktop, Minikube, or cloud)
- kubectl configured
- Helm installed
# Run unified setup script for any Kubernetes cluster
./scripts/cluster-setup.sh
# This installs:
# - NGINX Ingress Controller
# - Flux GitOps with catalog watcher (for XRDs/Compositions)
# - Flux GitOps with catalog-orders watcher (for XR instances)
# - Crossplane v2.0 with namespaced XRs
# - Composition functions (go-templating, patch-and-transform, etc.)
# - Base environment configurations
# - provider-kubernetes with RBAC
# - provider-helm for chart deployments
# - External-DNS for DNS management (supports multiple providers)
# - Backstage service account + token
Configure your cluster after setup:
# Option 1: Auto-detect cluster from kubectl context (recommended)
./scripts/cluster-config.sh
# The config script will:
# - Create Backstage configuration (app-config.{context}.local.yaml)
# - Configure External-DNS with Cloudflare credentials (if provided)
# - Update EnvironmentConfigs
# - Configure Flux to watch catalog-orders
For the generic cluster-config.sh
, create an environment file matching your context:
# For rancher-desktop
cp .env.rancher-desktop.example .env.rancher-desktop
# Edit with your settings
vim .env.rancher-desktop
We use External-DNS for DNS management, which supports namespace isolation and multiple DNS providers.
-
Configure credentials in your environment file:
# For production (.env.openportal) CLOUDFLARE_API_TOKEN=your-api-token CLOUDFLARE_ZONE_ID=your-zone-id CLOUDFLARE_ZONE_NAME=openportal.dev # For local with real DNS (.env.rancher-desktop) BASE_DOMAIN=localhost # For local app access CLOUDFLARE_API_TOKEN=your-token # Optional: for real DNS CLOUDFLARE_ZONE_NAME=openportal.dev # Zone for DNS records
-
Apply configuration:
./scripts/config.sh # Auto-detects cluster
DNS records are created via CloudflareDNSRecord XRs or DNSEndpoint resources:
Option 1: Using CloudflareDNSRecord XR (recommended)
apiVersion: openportal.dev/v1alpha1
kind: CloudflareDNSRecord
metadata:
name: my-app
namespace: my-namespace
spec:
name: my-app
type: A
value: "192.168.1.100"
ttl: 300
Option 2: Direct DNSEndpoint
apiVersion: externaldns.openportal.dev/v1alpha1
kind: DNSEndpoint
metadata:
name: my-app-dns
namespace: my-namespace
spec:
endpoints:
- dnsName: my-app.openportal.dev
recordType: A
targets: ['192.168.1.100']
We provide scripts to manage Crossplane templates:
# Check status of all templates (releases and PRs)
./scripts/template-status.sh
# Reload all templates in the cluster
./scripts/template-reload.sh
# Create a new release for a template
./scripts/template-release.sh template-name
We use a GitOps catalog pattern for managing Crossplane templates:
- Create Template: Follow the pattern in
template-dns-record/
- Register in Catalog: Add to
catalog/templates/
- Flux Syncs: Automatically discovers and installs templates
- Use Template: Create XRs directly in your namespace (no claims needed!)
See Crossplane Catalog Setup for details.
- Developers create XRs directly in their namespaces
- No need for separate claim resources
- Better namespace isolation and standard RBAC
- Flux manages all deployments
- Central catalog for template discovery
- Git as single source of truth
- Pipeline mode compositions with functions
- Shared environment configurations
- Reusable transformation logic
cluster-setup.sh
- Universal K8s cluster setup with all platform componentscluster-config.sh
- Auto-detect and configure based on kubectl contextcluster-cleanup.sh
- Remove all platform components cleanlycluster-kubeconfig.sh
- Extract and manage kubeconfig files
template-status.sh
- Check template releases and PR statustemplate-reload.sh
- Reload templates with finalizer handlingtemplate-release.sh
- Automate GitHub releases for templates
repos-sync.sh
- Clone/update all nested repositories
The app-portal includes custom plugins:
- kubernetes-ingestor - Enhanced Kubernetes resource monitoring
- scaffolder actions - Custom actions for template processing
This workspace parent directory is version controlled separately to maintain:
- Workspace-level documentation (this README, CLAUDE.md)
- Shared configurations and setup scripts
- Cross-repository documentation
- Unified cluster setup and management scripts
The actual repository directories are excluded via .gitignore
.