A Backstage based Internal Developer Platform for self-service cloud-native infrastructure.
π Now running Backstage v1.42.0 with New Frontend System architecture!
- Node.js 20
- Yarn package manager
- direnv (for automatic environment loading)
- SOPS (for secret decryption)
- age (SOPS dependency for SSH key support)
- SSH key configured in GitHub
# Clone and install
git clone https://github.com/open-service-portal/app-portal.git
cd app-portal
yarn install
# Allow direnv to load environment (auto-decrypts secrets)
direnv allow
# Start the application (auto-detects kubectl context)
yarn start # Using yarn (traditional Node.js way)
# OR
./start.js # Direct execution (Unix-style) π
The application automatically detects your current kubectl context and loads the appropriate configuration file (e.g., app-config.rancher-desktop.local.yaml
for local development).
The secrets are automatically decrypted using SOPS when you enter the directory with direnv. Your SSH key is used for decryption - no additional configuration needed!
Frontend: http://localhost:3000
Backend API: http://localhost:7007
Configuration is now split into focused modules for better maintainability:
app-config/auth.yaml
- Authentication providersapp-config/backend.yaml
- Backend settingsapp-config/catalog.yaml
- Catalog configurationapp-config/ingestor.yaml
- Kubernetes/Crossplane ingestorsapp-config/integrations.yaml
- GitHub/GitLab integrations- See Modular Config Documentation for details
Advanced Crossplane integration with 16,000+ lines of code:
- Discovers XRDs from Kubernetes clusters
- Generates Backstage templates automatically
- Creates API documentation entities
- Includes CLI tools for debugging
- See Crossplane Ingestor Documentation for details
This project uses SOPS for secret encryption. Secrets are stored encrypted in the repository and automatically decrypted when you enter the directory.
To grant a new team member access to decrypt secrets:
-
Get their SSH public key:
ssh-add -L # They run this to get their public key
-
Add it to
.sops.yaml
:creation_rules: - age: >- existing-key, ssh-ed25519 NEW_PUBLIC_KEY_HERE
-
Re-encrypt the secrets:
sops updatekeys .env.enc sops updatekeys github-app-key.pem.enc
For detailed setup instructions, see our portal-workspace documentation:
- GitHub App configuration
- SOPS secret management
- Creating service templates
- Troubleshooting
Templates are auto-discovered from repositories matching service-*-template
pattern.
Example: service-nodejs-template
# Development - Choose your style!
# Traditional Node.js style
yarn start # Start with auto-detected kubectl context config
yarn start:log # Same as above, with timestamped logging
# Direct execution (Unix-style)
./start.js # Start with auto-detected config
./start.js --log # With timestamped logging
# Build commands
yarn build:backend # Build backend only
yarn build:all # Build everything for production
# Installation
yarn install # Standard installation
yarn install:log # Install with timestamped logging (Unix/Linux/macOS only)
# Testing
yarn test # Run tests
yarn test:all # Run tests with coverage
yarn test:e2e # Run E2E tests
# Code Quality
yarn lint # Lint changed files
yarn lint:all # Lint all files
yarn prettier:check # Check formatting
yarn fix # Auto-fix issues
# Utilities
yarn clean # Clean build artifacts
yarn new # Create new Backstage plugin
Both yarn start
and ./start
automatically detect your current kubectl context and load the matching configuration:
- Detects context via
kubectl config current-context
- Loads
app-config.{context}.local.yaml
if it exists - Falls back to base
app-config.yaml
if no context-specific config found - Shows which configuration is being used during startup
Logging can be enabled through multiple methods:
yarn start:log
- Using yarn script./start.js --log
- Direct execution with flagyarn install:log
- For installation logging
These commands capture timestamped logs for debugging:
# Default: logs to ./logs directory
yarn install:log
yarn start:log
# Custom log directory via environment variable
BACKSTAGE_LOG_DIR=/tmp yarn start:log
BACKSTAGE_LOG_DIR=~/debugging yarn install:log
Note: These logging scripts use shell-specific syntax and are only compatible with Unix-based systems (Linux, macOS). Windows users should use the standard yarn start
and yarn install
commands.
All secrets are managed through SOPS encryption. The .envrc
file automatically:
- Loads Node.js version via nvm
- Decrypts
.env.enc
to load GitHub App credentials - Decrypts
github-app-key.pem.enc
for GitHub App authentication
No manual environment variable setup needed!
packages/
βββ app/ # Frontend React application (New Frontend System)
β βββ src/
β β βββ App.tsx # Main app with createApp (New System)
β β βββ components/ # Shared UI components
β βββ package.json
βββ backend/ # Backend Node.js services (New Backend System)
βββ src/
β βββ index.ts # Backend plugin setup (New System)
β βββ scaffolder/ # Custom scaffolder actions
βββ package.json
app-config.yaml
- Base configuration (Updated for v1.42.0)app-config.production.yaml
- Production overridesapp-config.{context}.local.yaml
- Context-specific overrides (gitignored, auto-loaded by yarn start).sops.yaml
- SOPS encryption configuration.envrc
- Direnv auto-loader with SOPS decryption
This app uses Backstage's New Frontend System with:
- Automatic Plugin Discovery: Plugins are auto-discovered via
packages: all
- Extension System: Custom extensions for routing and components
- Alpha Plugin Exports: All plugins use
/alpha
subpath exports - Modern Architecture: Clean separation of concerns with the new system
- Uses
@backstage/frontend-defaults
instead of@backstage/app-defaults
- Plugin loading via
features: [pluginAlpha]
instead ofplugins: [plugin]
- Extension-based routing instead of manual JSX routes
- New Backend System with automatic plugin registration
Breaking Change: The Kubernetes plugin now requires additional configuration:
# app-config.yaml
kubernetes:
serviceLocatorMethod:
type: 'multiTenant' # NEW: How services are located
clusterLocatorMethods: # EXISTING: Where clusters are found
- type: 'config'
clusters: [...]
Why this change?
serviceLocatorMethod: multiTenant
enables multi-cluster, multi-namespace service discovery- Supports distributed services across different clusters (local dev + production)
- Required for New Backend System - Kubernetes plugin won't work without it
- Backward compatible with existing
clusterLocatorMethods
configuration
If you see authentication errors:
# Check if SSH key is loaded
ssh-add -L
# If "The agent has no identities", add your SSH key:
ssh-add ~/.ssh/id_ed25519 # or ~/.ssh/id_rsa
# Test SOPS decryption manually
sops -d --input-type dotenv --output-type dotenv .env.enc
# Re-allow direnv
direnv allow
If your SSH key is protected with a passphrase, SOPS behavior can be inconsistent:
Try adding your key to ssh-agent first:
ssh-add ~/.ssh/id_ed25519
# Enter passphrase once
cd app-portal
# May work without passphrase prompt, or may still ask once
If you still get passphrase prompts:
- You might need to enter it once per terminal session
- Sometimes SOPS uses ssh-agent, sometimes it doesn't
- This is a known SOPS limitation
Most reliable solution - Dedicated key without passphrase:
# Create a separate key for SOPS (development only)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_sops -N ""
# Add the public key to .sops.yaml
cat ~/.ssh/id_ed25519_sops.pub
# Give this to your team lead to add to .sops.yaml
If ports 3000 or 7007 are in use:
# Find process using port
lsof -i :3000
lsof -i :7007
# Or use different ports in app-config.yaml
# Clean everything and rebuild
yarn clean
rm -rf node_modules
yarn install
yarn build:backend
- Modular Configuration - How configuration is organized
- Environment Variables - Required environment variables
- Secret Management - SOPS encryption setup
- Crossplane Ingestor - Advanced XRD discovery and transformation
- Kubernetes Ingestor - Basic Kubernetes resource discovery
- Custom Scaffolder Actions - Custom template actions
- CLAUDE.md - AI assistant guidance for this repository
- Testing Guide - Running tests and writing new ones
- Troubleshooting - Common issues and solutions
Detailed guides in plugins/crossplane-ingestor/docs/
:
- CLI Usage - Using CLI tools
- Developer Guide - Architecture and development
- Metadata Flow - How metadata is processed
- XRD Ingestion - Ingestion pipeline
See CONTRIBUTING.md for guidelines.
Apache 2.0