Backstage
Open-Source-Plattform für interne Entwicklerportale von Spotify zur Verwaltung von Software-Katalogen und der Developer Experience.
Installation
Abschnitt betitelt „Installation“Neue Anwendung erstellen
Abschnitt betitelt „Neue Anwendung erstellen“| Befehl | Beschreibung |
|---|---|
npx @backstage/create-app@latest | Neue Backstage-Anwendung erstellen |
npx @backstage/create-app@latest --skip-install | App ohne Abhängigkeiten installieren erstellen |
cd my-backstage-app && yarn install | Abhängigkeiten installieren |
yarn dev | Frontend und Backend im Entwicklungsmodus starten |
yarn start | Nur Frontend starten |
yarn start-backend | Nur Backend starten |
yarn build:backend | Backend für Produktion bauen |
yarn build | Alle Pakete bauen |
node_modules/.bin/backstage-cli --version | Backstage CLI-Version anzeigen |
Docker-Deployment
Abschnitt betitelt „Docker-Deployment“| Befehl | Beschreibung |
|---|---|
yarn build:backend --config ../../app-config.yaml | Backend mit Konfiguration bauen |
docker build -t backstage -f packages/backend/Dockerfile . | Docker-Image bauen |
docker run -p 7007:7007 backstage | Backstage-Container ausführen |
CLI-Befehle
Abschnitt betitelt „CLI-Befehle“Paketverwaltung
Abschnitt betitelt „Paketverwaltung“| Befehl | Beschreibung |
|---|---|
yarn backstage-cli package start | Paket im Entwicklungsmodus starten |
yarn backstage-cli package build | Paket bauen |
yarn backstage-cli package lint | Paket-Quellcode linten |
yarn backstage-cli package test | Paket-Tests ausführen |
yarn backstage-cli repo build --all | Alle Pakete im Monorepo bauen |
yarn backstage-cli repo lint --all | Alle Pakete linten |
yarn backstage-cli versions:bump | Backstage-Abhängigkeiten auf neueste Version aktualisieren |
yarn backstage-cli versions:bump --release next | Auf nächstes Pre-Release aktualisieren |
yarn backstage-cli migrate package-roles | Pakete zur Verwendung von Rollen migrieren |
Plugin-Erstellung
Abschnitt betitelt „Plugin-Erstellung“| Befehl | Beschreibung |
|---|---|
yarn backstage-cli create-plugin | Neues Frontend-Plugin erstellen |
yarn backstage-cli create-plugin --backend | Neues Backend-Plugin erstellen |
yarn backstage-cli create-plugin --id my-plugin | Plugin mit bestimmter ID erstellen |
yarn new | Interaktiv Komponente aus Vorlage erstellen |
Software-Katalog
Abschnitt betitelt „Software-Katalog“Entity-Arten
Abschnitt betitelt „Entity-Arten“| Befehl | Beschreibung |
|---|---|
catalog-info.yaml zum Repo-Root hinzufügen | Komponente im Katalog registrieren |
kind: Component in catalog-info.yaml | Software-Komponente definieren |
kind: API in catalog-info.yaml | API-Entity definieren |
kind: System in catalog-info.yaml | System-Gruppierung definieren |
kind: Domain in catalog-info.yaml | Business-Domain definieren |
kind: Resource in catalog-info.yaml | Infrastruktur-Ressource definieren |
kind: Group in catalog-info.yaml | Team/Gruppe definieren |
kind: User in catalog-info.yaml | Benutzer definieren |
kind: Location in catalog-info.yaml | Andere Katalog-Dateien referenzieren |
Entity-Eigenschaften
Abschnitt betitelt „Entity-Eigenschaften“| Befehl | Beschreibung |
|---|---|
spec.owner: team-name setzen | Entity-Eigentümer festlegen |
spec.lifecycle: production setzen | Entity-Lifecycle-Phase festlegen |
spec.type: service setzen | Komponententyp festlegen (service, website, library) |
spec.dependsOn: ['component:other'] setzen | Abhängigkeiten definieren |
spec.providesApis: ['api-name'] setzen | Bereitgestellte APIs deklarieren |
spec.consumesApis: ['api-name'] setzen | Konsumierte APIs deklarieren |
spec.system: system-name setzen | Einem System zuweisen |
metadata.annotations für Integrationen setzen | Mit CI/CD, Monitoring etc. verbinden |
catalog-info.yaml Beispiel
Abschnitt betitelt „catalog-info.yaml Beispiel“apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Handles payment processing and billing
annotations:
github.com/project-slug: org/payment-service
backstage.io/techdocs-ref: dir:.
jenkins.io/job-full-name: payment-service/main
pagerduty.com/service-id: PABC123
sonarqube.org/project-key: org_payment-service
tags:
- java
- payments
links:
- url: https://dashboard.example.com/payments
title: Monitoring Dashboard
icon: dashboard
- url: https://wiki.example.com/payment-service
title: Wiki
spec:
type: service
lifecycle: production
owner: team-payments
system: billing
providesApis:
- payment-api
consumesApis:
- user-api
- notification-api
dependsOn:
- resource:payments-db
- component:auth-service
API-Entity-Beispiel
Abschnitt betitelt „API-Entity-Beispiel“apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: payment-api
description: Payment processing REST API
tags:
- rest
- payments
spec:
type: openapi
lifecycle: production
owner: team-payments
system: billing
definition: |
openapi: "3.0.0"
info:
title: Payment API
version: 1.0.0
paths:
/payments:
post:
summary: Create a payment
responses:
"201":
description: Payment created
System- und Domain-Beispiel
Abschnitt betitelt „System- und Domain-Beispiel“apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: billing
description: Billing and payment processing system
spec:
owner: team-payments
domain: commerce
---
apiVersion: backstage.io/v1alpha1
kind: Domain
metadata:
name: commerce
description: E-commerce domain covering orders, payments, and fulfillment
spec:
owner: group:engineering-leadership
Templates
Abschnitt betitelt „Templates“Template-Eigenschaften
Abschnitt betitelt „Template-Eigenschaften“| Befehl | Beschreibung |
|---|---|
kind: Template in template.yaml | Software-Template definieren |
spec.type: service setzen | Template erstellt einen Service |
spec.steps[] für Template-Aktionen setzen | Scaffolding-Schritte definieren |
action: fetch:template | Template-Dateien abrufen und rendern |
action: publish:github | Erstelltes Repo auf GitHub veröffentlichen |
action: publish:github:pull-request | PR statt neuem Repo erstellen |
action: catalog:register | Erstellte Entity im Katalog registrieren |
action: github:actions:dispatch | GitHub Actions Workflow auslösen |
${{ parameters.name }} in Templates verwenden | Benutzereingabe-Parameter referenzieren |
spec.parameters[] für Formularfelder setzen | Template-Eingabeformular definieren |
ui:widget: textarea in Parametern verwenden | Formularfeld-Widget anpassen |
Template-Definitions-Beispiel
Abschnitt betitelt „Template-Definitions-Beispiel“apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: microservice-template
title: Create a Microservice
description: Scaffold a new microservice with CI/CD, monitoring, and docs
tags:
- recommended
- microservice
spec:
owner: team-platform
type: service
parameters:
- title: Service Details
required:
- name
- description
- owner
properties:
name:
title: Service Name
type: string
description: Unique name of the service
ui:autofocus: true
ui:options:
rows: 5
description:
title: Description
type: string
owner:
title: Owner
type: string
description: Team that owns this service
ui:field: OwnerPicker
ui:options:
catalogFilter:
kind: Group
- title: Infrastructure
properties:
language:
title: Language
type: string
enum: ["go", "java", "python", "typescript"]
default: go
database:
title: Database
type: string
enum: ["postgres", "mysql", "none"]
default: postgres
enableMonitoring:
title: Enable Monitoring
type: boolean
default: true
steps:
- id: fetch-base
name: Fetch Base Template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
description: ${{ parameters.description }}
owner: ${{ parameters.owner }}
language: ${{ parameters.language }}
- id: publish
name: Publish to GitHub
action: publish:github
input:
allowedHosts: ["github.com"]
repoUrl: github.com?owner=my-org&repo=${{ parameters.name }}
description: ${{ parameters.description }}
defaultBranch: main
repoVisibility: internal
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
output:
links:
- title: Repository
url: ${{ steps['publish'].output.remoteUrl }}
- title: Open in Catalog
icon: catalog
entityRef: ${{ steps['register'].output.entityRef }}
Plugins
Abschnitt betitelt „Plugins“Plugins installieren
Abschnitt betitelt „Plugins installieren“| Befehl | Beschreibung |
|---|---|
yarn add @backstage/plugin-catalog | Katalog-Plugin installieren |
yarn add @backstage/plugin-techdocs | TechDocs-Plugin installieren |
yarn add @backstage/plugin-kubernetes | Kubernetes-Plugin installieren |
yarn add @backstage/plugin-github-actions | GitHub Actions-Plugin installieren |
yarn add @backstage/plugin-search | Such-Plugin installieren |
yarn add @backstage/plugin-scaffolder | Scaffolder-Plugin installieren |
yarn add @backstage/plugin-api-docs | API-Docs-Plugin installieren |
yarn add @backstage/plugin-cost-insights | Cost-Insights-Plugin installieren |
Plugin-Registrierung
Abschnitt betitelt „Plugin-Registrierung“Frontend-Plugins in packages/app/src/App.tsx registrieren:
import { CatalogGraphPage } from '@backstage/plugin-catalog-graph';
import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
import { SearchPage } from '@backstage/plugin-search';
const routes = (
<FlatRoutes>
<Route path="/catalog" element={<CatalogIndexPage />} />
<Route path="/catalog/:namespace/:kind/:name" element={<CatalogEntityPage />}>
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
<EntityOverviewContent />
</EntityLayout.Route>
<EntityLayout.Route path="/api" title="API">
<EntityApiContent />
</EntityLayout.Route>
<EntityLayout.Route path="/docs" title="Docs">
<EntityTechDocsContent />
</EntityLayout.Route>
</EntityLayout>
</Route>
<Route path="/docs" element={<TechDocsReaderPage />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/catalog-graph" element={<CatalogGraphPage />} />
</FlatRoutes>
);
Backend-Plugins in packages/backend/src/index.ts registrieren:
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-catalog-backend'));
backend.add(import('@backstage/plugin-catalog-backend-module-github-org'));
backend.add(import('@backstage/plugin-scaffolder-backend'));
backend.add(import('@backstage/plugin-techdocs-backend'));
backend.add(import('@backstage/plugin-search-backend'));
backend.add(import('@backstage/plugin-search-backend-module-catalog'));
backend.add(import('@backstage/plugin-search-backend-module-techdocs'));
backend.add(import('@backstage/plugin-auth-backend'));
backend.add(import('@backstage/plugin-auth-backend-module-github-provider'));
backend.add(import('@backstage/plugin-kubernetes-backend'));
backend.start();
TechDocs
Abschnitt betitelt „TechDocs“TechDocs-Operationen
Abschnitt betitelt „TechDocs-Operationen“| Befehl | Beschreibung |
|---|---|
npx @techdocs/cli serve | TechDocs lokal voranzeigen |
npx @techdocs/cli serve --docker-image techdocs-container | Mit benutzerdefiniertem Docker-Image bereitstellen |
npx @techdocs/cli generate | Statische TechDocs-Site generieren |
npx @techdocs/cli generate --source-dir . | Aus bestimmtem Verzeichnis generieren |
npx @techdocs/cli publish --publisher-type googleGcs | TechDocs nach GCS veröffentlichen |
npx @techdocs/cli publish --publisher-type awsS3 | TechDocs nach S3 veröffentlichen |
backstage.io/techdocs-ref-Annotation hinzufügen | TechDocs für Entity aktivieren |
docs/-Verzeichnis mit mkdocs.yml erstellen | TechDocs-Quelle einrichten |
techdocs.builder: 'local' in Konfiguration setzen | Lokalen TechDocs-Builder verwenden |
techdocs.builder: 'external' in Konfiguration setzen | Externen CI/CD-Builder verwenden |
TechDocs mkdocs.yml Beispiel
Abschnitt betitelt „TechDocs mkdocs.yml Beispiel“site_name: Payment Service
nav:
- Home: index.md
- Architecture: architecture.md
- API Reference: api-reference.md
- Runbooks:
- Deployment: runbooks/deployment.md
- Incident Response: runbooks/incident-response.md
plugins:
- techdocs-core
markdown_extensions:
- admonition
- pymdownx.highlight
- pymdownx.superfences
Such-Einrichtung
Abschnitt betitelt „Such-Einrichtung“| Befehl | Beschreibung |
|---|---|
yarn add @backstage/plugin-search | Such-Frontend installieren |
yarn add @backstage/plugin-search-backend | Such-Backend installieren |
yarn add @backstage/plugin-search-backend-module-catalog | Katalog-Such-Collator hinzufügen |
yarn add @backstage/plugin-search-backend-module-techdocs | TechDocs-Such-Collator hinzufügen |
Suchmaschine in app-config.yaml konfigurieren | Lunr, Elasticsearch oder PgStore einrichten |
search.pg in Konfiguration setzen | PostgreSQL für Suche verwenden |
search.elasticsearch in Konfiguration setzen | Elasticsearch für Suche verwenden |
Konfiguration
Abschnitt betitelt „Konfiguration“Kerneinstellungen
Abschnitt betitelt „Kerneinstellungen“| Befehl | Beschreibung |
|---|---|
app-config.yaml bearbeiten | Hauptkonfigurationsdatei |
app-config.local.yaml bearbeiten | Lokale Entwicklungsüberschreibungen |
app-config.production.yaml bearbeiten | Produktionskonfiguration |
app.baseUrl in Konfiguration setzen | Frontend-URL konfigurieren |
backend.baseUrl in Konfiguration setzen | Backend-URL konfigurieren |
backend.database in Konfiguration setzen | Datenbankverbindung konfigurieren |
backend.cors.origin in Konfiguration setzen | CORS-Origins konfigurieren |
auth.providers in Konfiguration setzen | Authentifizierungs-Provider konfigurieren |
catalog.locations[] in Konfiguration setzen | Katalog-Entity-Quellen hinzufügen |
catalog.rules[] in Konfiguration setzen | Entity-Validierungsregeln definieren |
integrations.github[] in Konfiguration setzen | GitHub-Integrations-Token konfigurieren |
app-config.yaml Beispiel
Abschnitt betitelt „app-config.yaml Beispiel“app:
title: My Company Developer Portal
baseUrl: http://localhost:3000
organization:
name: My Company
backend:
baseUrl: http://localhost:7007
listen:
port: 7007
cors:
origin: http://localhost:3000
methods: [GET, HEAD, PATCH, POST, PUT, DELETE]
database:
client: pg
connection:
host: ${POSTGRES_HOST}
port: ${POSTGRES_PORT}
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
integrations:
github:
- host: github.com
token: ${GITHUB_TOKEN}
auth:
environment: development
providers:
github:
development:
clientId: ${GITHUB_CLIENT_ID}
clientSecret: ${GITHUB_CLIENT_SECRET}
catalog:
import:
entityFilename: catalog-info.yaml
pullRequestBranchName: backstage-integration
rules:
- allow: [Component, System, API, Resource, Location, Domain, Group, User]
locations:
- type: url
target: https://github.com/my-org/backstage-catalog/blob/main/all-components.yaml
- type: github-discovery
target: https://github.com/my-org
- type: github-org
target: https://github.com/my-org
techdocs:
builder: local
generator:
runIn: local
publisher:
type: local
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- url: ${K8S_CLUSTER_URL}
name: production
authProvider: serviceAccount
serviceAccountToken: ${K8S_TOKEN}
Entity-Beziehungsdiagramm
Abschnitt betitelt „Entity-Beziehungsdiagramm“| Beziehung | Von | Zu | Beschreibung |
|---|---|---|---|
ownerOf | Group/User | Component/API | Gruppe besitzt die Entity |
ownedBy | Component/API | Group/User | Entity gehört der Gruppe |
consumesApi | Component | API | Komponente nutzt eine API |
providesApi | Component | API | Komponente stellt eine API bereit |
dependsOn | Component | Component/Resource | Komponente hängt von anderer ab |
dependencyOf | Component/Resource | Component | Ist Abhängigkeit von |
partOf | Component | System | Komponente gehört zu System |
hasPart | System | Component | System enthält Komponente |
parentOf | Group | Group | Übergeordnete Team-Beziehung |
childOf | Group | Group | Untergeordnete Team-Beziehung |
memberOf | User | Group | Benutzer gehört zur Gruppe |
hasMember | Group | User | Gruppe enthält Benutzer |
Best Practices
Abschnitt betitelt „Best Practices“-
catalog-info.yaml in jedem Repository verwenden — Sicherstellen, dass alle Services, Bibliotheken und APIs im Katalog registriert sind, für vollständige Sichtbarkeit.
-
Sinnvolle Eigentümerschaft festlegen — Jede Entity sollte ein
owner-Feld haben, das auf eine gültige Gruppe verweist, um Verantwortlichkeit und Routing zu ermöglichen. -
Entities reichhaltig annotieren — Annotationen für CI/CD, Monitoring, PagerDuty und Dokumentation hinzufügen, um den Katalog zu einem echten Zentrum zu machen.
-
Templates für Golden Paths erstellen — Den Scaffolder verwenden, um standardisierte Wege zur Erstellung neuer Services zu definieren und Konsistenz sicherzustellen.
-
TechDocs implementieren — Dokumentation neben dem Code pflegen mit dem TechDocs-Plugin und
mkdocs.ymlfür lebende Dokumentation. -
GitHub Discovery verwenden —
github-discoveryin Katalog-Locations konfigurieren, um Repositories automatisch zu entdecken und zu registrieren. -
Organisation modellieren — Groups und Users definieren, die die Teamstruktur widerspiegeln, um Eigentümer-Tracking und Team-Seiten zu ermöglichen.
-
app-config.yaml umgebungsbewusst halten —
app-config.local.yamlfür Entwicklung und Umgebungsvariablen für Produktionsgeheimnisse verwenden. -
Plugin-Ökosystem aufbauen — Benutzerdefinierte Frontend- und Backend-Plugins erstellen, um Backstage mit den spezifischen Tools der Organisation zu erweitern.
-
Systems und Domains definieren — Die übergeordnete Architektur mit Systems und Domains modellieren, um Entwicklern eine Karte der Plattform zu geben.