Open Service Portal Workspace
This is a workspace directory containing multiple Open Service Portal repositories for unified development.
Repository Structure
This workspace contains the following repositories:
Core Application
- app-portal/ - Main Backstage application
Crossplane Templates & GitOps
- 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 Templates (Backstage)
- 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
Setup
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
Development
Each repository has its own development workflow. See CLAUDE.md for detailed development commands and architecture information.
Quick Start
# Start Backstage
cd app-portal
yarn install
yarn start
- Frontend: http://localhost:3000
- Backend API: http://localhost:7007
Documentation
- CLAUDE.md - Development instructions for Claude Code
- Annotation Strategy - Annotation namespace guidelines ⭐ Important
- 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 Setup
Prerequisites
- Kubernetes cluster (Kind, Rancher Desktop, Minikube, or cloud)
- kubectl configured
- Helm installed
Automated Cluster Setup
# 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
Environment Configuration
Configure your cluster after setup:
# Option 1: Auto-detect cluster from kubectl context (recommended)
./scripts/cluster-config.sh
# The config script will:
# - Extract cluster name from context (multiple contexts can share same cluster)
# - Create Backstage configuration (app-config.{cluster}.local.yaml)
# - Configure External-DNS with Cloudflare credentials (if provided)
# - Update EnvironmentConfigs
# - Configure Flux to watch catalog-orders using cluster name
For the generic cluster-config.sh, create an environment file matching your cluster name (not context):
# For rancher-desktop cluster
cp .env.rancher-desktop.example .env.rancher-desktop
# Edit with your settings
vim .env.rancher-desktop
# For OpenPortal cluster (shared by multiple contexts with different auth methods)
cp .env.openportal.example .env.openportal
vim .env.openportal
Note: Configuration uses cluster names, allowing multiple contexts (e.g., different auth methods) to share the same config.
DNS Management with External-DNS
We use External-DNS for DNS management, which supports namespace isolation and multiple DNS providers.
Setup
-
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
Creating DNS Records
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']
Template Management
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
Crossplane Templates
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.
Key Features
Crossplane v2 with Namespaced XRs
- Developers create XRs directly in their namespaces
- No need for separate claim resources
- Better namespace isolation and standard RBAC
GitOps Everything
- Flux manages all deployments
- Central catalog for template discovery
- Git as single source of truth
Modern Infrastructure as Code
- Pipeline mode compositions with functions
- Shared environment configurations
- Reusable transformation logic
Scripts Reference
Cluster Management
cluster-setup.sh- Universal K8s cluster setup with all platform componentscluster-config.sh- Auto-detect cluster name and configure (cluster-based, not context-based)cluster-cleanup.sh- Remove all platform components cleanlycluster-kubeconfig.sh- Extract and manage kubeconfig files
Template Management
template-status.sh- Check template releases and PR statustemplate-reload.sh- Reload templates with finalizer handlingtemplate-release.sh- Automate GitHub releases for templates
Repository Management
repos-sync.sh- Clone/update all nested repositories
Custom Plugins
The app-portal includes custom plugins:
- kubernetes-ingestor - Enhanced Kubernetes resource monitoring
- scaffolder actions - Custom actions for template processing
Note
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.