Open Service Portal - Backstage Application
A Backstage based Internal Developer Platform for self-service cloud-native infrastructure.
🚀 Quick Start
Prerequisites
- 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
Setup
# 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
yarn start
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
🔐 Secret Management
This project uses SOPS for secret encryption. Secrets are stored encrypted in the repository and automatically decrypted when you enter the directory.
Adding Team Members
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
📚 Documentation
For detailed setup instructions, see our portal-workspace documentation:
- GitHub App configuration
- SOPS secret management
- Creating service templates
- Troubleshooting
🎨 Service Templates
Templates are auto-discovered from repositories matching service-*-template
pattern.
Example: service-nodejs-template
🧑💻 Development
Commands
# Development
yarn start # Start both frontend and backend
yarn start:log # Start with timestamped logging (Unix/Linux/macOS only)
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
Logging Scripts (Unix/Linux/macOS only)
The yarn start:log
and yarn install:log
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.
Environment Variables
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!
📦 Project Structure
packages/
├── app/ # Frontend React application
│ ├── src/
│ │ ├── App.tsx # Main app component
│ │ └── components/ # Shared UI components
│ └── package.json
└── backend/ # Backend Node.js services
├── src/
│ ├── index.ts # Backend plugin setup
│ └── scaffolder/ # Custom scaffolder actions
└── package.json
Configuration Files
app-config.yaml
- Base configurationapp-config.production.yaml
- Production overridesapp-config.local.yaml
- Local overrides (gitignored).sops.yaml
- SOPS encryption configuration.envrc
- Direnv auto-loader with SOPS decryption
🐛 Troubleshooting
Secrets Not Loading
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
SSH Key with Passphrase
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
Port Already in Use
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
Build Failures
# Clean everything and rebuild
yarn clean
rm -rf node_modules
yarn install
yarn build:backend
🤝 Contributing
See CONTRIBUTING.md for guidelines.
📄 License
Apache 2.0