Backstage
Plataforma de portal interno para desarrolladores de código abierto por Spotify para gestionar catálogos de software y experiencia del desarrollador.
Instalación
Sección titulada «Instalación»Crear una Nueva Aplicación
Sección titulada «Crear una Nueva Aplicación»| Comando | Descripción |
|---|---|
npx @backstage/create-app@latest | Crear nueva aplicación Backstage |
npx @backstage/create-app@latest --skip-install | Crear app sin instalar dependencias |
cd my-backstage-app && yarn install | Instalar dependencias |
yarn dev | Iniciar frontend y backend en modo desarrollo |
yarn start | Iniciar solo el frontend |
yarn start-backend | Iniciar solo el backend |
yarn build:backend | Compilar backend para producción |
yarn build | Compilar todos los paquetes |
node_modules/.bin/backstage-cli --version | Mostrar versión del CLI de Backstage |
Despliegue con Docker
Sección titulada «Despliegue con Docker»| Comando | Descripción |
|---|---|
yarn build:backend --config ../../app-config.yaml | Compilar backend con configuración |
docker build -t backstage -f packages/backend/Dockerfile . | Compilar imagen Docker |
docker run -p 7007:7007 backstage | Ejecutar contenedor Backstage |
Comandos del CLI
Sección titulada «Comandos del CLI»Gestión de Paquetes
Sección titulada «Gestión de Paquetes»| Comando | Descripción |
|---|---|
yarn backstage-cli package start | Iniciar un paquete en modo desarrollo |
yarn backstage-cli package build | Compilar un paquete |
yarn backstage-cli package lint | Ejecutar lint del código fuente del paquete |
yarn backstage-cli package test | Ejecutar tests del paquete |
yarn backstage-cli repo build --all | Compilar todos los paquetes del monorepo |
yarn backstage-cli repo lint --all | Ejecutar lint en todos los paquetes |
yarn backstage-cli versions:bump | Actualizar dependencias de Backstage a la última versión |
yarn backstage-cli versions:bump --release next | Actualizar a pre-release siguiente |
yarn backstage-cli migrate package-roles | Migrar paquetes para usar roles |
Creación de Plugins
Sección titulada «Creación de Plugins»| Comando | Descripción |
|---|---|
yarn backstage-cli create-plugin | Crear nuevo plugin de frontend |
yarn backstage-cli create-plugin --backend | Crear nuevo plugin de backend |
yarn backstage-cli create-plugin --id my-plugin | Crear plugin con ID específico |
yarn new | Crear componente interactivamente desde plantilla |
Catálogo de Software
Sección titulada «Catálogo de Software»Tipos de Entidad
Sección titulada «Tipos de Entidad»| Comando | Descripción |
|---|---|
Agregar catalog-info.yaml a la raíz del repo | Registrar componente en el catálogo |
kind: Component en catalog-info.yaml | Definir un componente de software |
kind: API en catalog-info.yaml | Definir una entidad API |
kind: System en catalog-info.yaml | Definir una agrupación de sistema |
kind: Domain en catalog-info.yaml | Definir un dominio de negocio |
kind: Resource en catalog-info.yaml | Definir recurso de infraestructura |
kind: Group en catalog-info.yaml | Definir un equipo/grupo |
kind: User en catalog-info.yaml | Definir un usuario |
kind: Location en catalog-info.yaml | Referenciar otros archivos del catálogo |
Propiedades de Entidad
Sección titulada «Propiedades de Entidad»| Comando | Descripción |
|---|---|
Establecer spec.owner: team-name | Establecer propiedad de la entidad |
Establecer spec.lifecycle: production | Establecer etapa del ciclo de vida de la entidad |
Establecer spec.type: service | Establecer tipo de componente (service, website, library) |
Establecer spec.dependsOn: ['component:other'] | Definir dependencias |
Establecer spec.providesApis: ['api-name'] | Declarar APIs proporcionadas |
Establecer spec.consumesApis: ['api-name'] | Declarar APIs consumidas |
Establecer spec.system: system-name | Asignar a un sistema |
Establecer metadata.annotations para integraciones | Conectar con CI/CD, monitoreo, etc. |
Ejemplo de catalog-info.yaml
Sección titulada «Ejemplo de catalog-info.yaml»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
Ejemplo de Entidad API
Sección titulada «Ejemplo de Entidad API»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
Ejemplo de System y Domain
Sección titulada «Ejemplo de System y Domain»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
Plantillas
Sección titulada «Plantillas»Propiedades de Plantilla
Sección titulada «Propiedades de Plantilla»| Comando | Descripción |
|---|---|
kind: Template en template.yaml | Definir una plantilla de software |
Establecer spec.type: service | La plantilla crea un servicio |
Establecer spec.steps[] para acciones de plantilla | Definir pasos de scaffolding |
action: fetch:template | Obtener y renderizar archivos de plantilla |
action: publish:github | Publicar repo scaffoldeado en GitHub |
action: publish:github:pull-request | Crear PR en lugar de nuevo repo |
action: catalog:register | Registrar entidad creada en el catálogo |
action: github:actions:dispatch | Disparar flujo de trabajo de GitHub Actions |
Usar ${{ parameters.name }} en plantillas | Referenciar parámetros de entrada del usuario |
Establecer spec.parameters[] para campos de formulario | Definir formulario de entrada de la plantilla |
Usar ui:widget: textarea en parameters | Personalizar widget del campo de formulario |
Ejemplo de Definición de Plantilla
Sección titulada «Ejemplo de Definición de Plantilla»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
Sección titulada «Plugins»Instalar Plugins
Sección titulada «Instalar Plugins»| Comando | Descripción |
|---|---|
yarn add @backstage/plugin-catalog | Instalar plugin de catálogo |
yarn add @backstage/plugin-techdocs | Instalar plugin de TechDocs |
yarn add @backstage/plugin-kubernetes | Instalar plugin de Kubernetes |
yarn add @backstage/plugin-github-actions | Instalar plugin de GitHub Actions |
yarn add @backstage/plugin-search | Instalar plugin de búsqueda |
yarn add @backstage/plugin-scaffolder | Instalar plugin de scaffolder |
yarn add @backstage/plugin-api-docs | Instalar plugin de documentación de API |
yarn add @backstage/plugin-cost-insights | Instalar plugin de análisis de costos |
Registro de Plugins
Sección titulada «Registro de Plugins»Registrar plugins de frontend en packages/app/src/App.tsx:
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>
);
Registrar plugins de backend en packages/backend/src/index.ts:
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
Sección titulada «TechDocs»Operaciones de TechDocs
Sección titulada «Operaciones de TechDocs»| Comando | Descripción |
|---|---|
npx @techdocs/cli serve | Previsualizar TechDocs localmente |
npx @techdocs/cli serve --docker-image techdocs-container | Servir usando imagen Docker personalizada |
npx @techdocs/cli generate | Generar sitio estático de TechDocs |
npx @techdocs/cli generate --source-dir . | Generar desde directorio específico |
npx @techdocs/cli publish --publisher-type googleGcs | Publicar TechDocs en GCS |
npx @techdocs/cli publish --publisher-type awsS3 | Publicar TechDocs en S3 |
Agregar anotación backstage.io/techdocs-ref | Habilitar TechDocs para entidad |
Crear directorio docs/ con mkdocs.yml | Configurar fuente de TechDocs |
Establecer techdocs.builder: 'local' en config | Usar constructor local de TechDocs |
Establecer techdocs.builder: 'external' en config | Usar constructor externo de CI/CD |
Ejemplo de mkdocs.yml para TechDocs
Sección titulada «Ejemplo de mkdocs.yml para TechDocs»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
Búsqueda
Sección titulada «Búsqueda»Configuración de Búsqueda
Sección titulada «Configuración de Búsqueda»| Comando | Descripción |
|---|---|
yarn add @backstage/plugin-search | Instalar frontend de búsqueda |
yarn add @backstage/plugin-search-backend | Instalar backend de búsqueda |
yarn add @backstage/plugin-search-backend-module-catalog | Agregar collator de búsqueda del catálogo |
yarn add @backstage/plugin-search-backend-module-techdocs | Agregar collator de búsqueda de TechDocs |
Configurar motor de búsqueda en app-config.yaml | Configurar Lunr, Elasticsearch o PgStore |
Establecer search.pg en config | Usar PostgreSQL para búsqueda |
Establecer search.elasticsearch en config | Usar Elasticsearch para búsqueda |
Configuración
Sección titulada «Configuración»Configuración Principal
Sección titulada «Configuración Principal»| Comando | Descripción |
|---|---|
Editar app-config.yaml | Archivo de configuración principal |
Editar app-config.local.yaml | Sobrecargas de desarrollo local |
Editar app-config.production.yaml | Configuración de producción |
Establecer app.baseUrl en config | Configurar URL del frontend |
Establecer backend.baseUrl en config | Configurar URL del backend |
Establecer backend.database en config | Configurar conexión de base de datos |
Establecer backend.cors.origin en config | Configurar orígenes CORS |
Establecer auth.providers en config | Configurar proveedores de autenticación |
Establecer catalog.locations[] en config | Agregar fuentes de entidades del catálogo |
Establecer catalog.rules[] en config | Definir reglas de validación de entidades |
Establecer integrations.github[] en config | Configurar token de integración con GitHub |
Ejemplo de app-config.yaml
Sección titulada «Ejemplo de app-config.yaml»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}
Diagrama de Relaciones de Entidades
Sección titulada «Diagrama de Relaciones de Entidades»| Relación | Desde | Hacia | Descripción |
|---|---|---|---|
ownerOf | Group/User | Component/API | El grupo es propietario de la entidad |
ownedBy | Component/API | Group/User | La entidad es propiedad del grupo |
consumesApi | Component | API | El componente usa una API |
providesApi | Component | API | El componente expone una API |
dependsOn | Component | Component/Resource | El componente depende de otro |
dependencyOf | Component/Resource | Component | Es una dependencia de |
partOf | Component | System | El componente pertenece a un sistema |
hasPart | System | Component | El sistema contiene un componente |
parentOf | Group | Group | Relación de equipo padre |
childOf | Group | Group | Relación de equipo hijo |
memberOf | User | Group | El usuario pertenece al grupo |
hasMember | Group | User | El grupo contiene al usuario |
Mejores Prácticas
Sección titulada «Mejores Prácticas»-
Usa catalog-info.yaml en cada repositorio — asegúrate de que todos los servicios, bibliotecas y APIs estén registrados en el catálogo para tener visibilidad completa.
-
Establece propiedad significativa — cada entidad debe tener un campo
ownerapuntando a un Group válido, habilitando responsabilidad y enrutamiento. -
Anota las entidades ricamente — agrega anotaciones para CI/CD, monitoreo, PagerDuty y documentación para hacer del catálogo un verdadero centro de información.
-
Crea plantillas para caminos dorados — usa el scaffolder para definir formas estandarizadas de crear nuevos servicios, asegurando consistencia.
-
Implementa TechDocs — mantén la documentación junto al código usando el plugin de TechDocs y
mkdocs.ymlpara documentación viva. -
Usa GitHub discovery — configura
github-discoveryen las ubicaciones del catálogo para descubrir y registrar repositorios automáticamente. -
Modela tu organización — define Groups y Users para reflejar la estructura de tu equipo, habilitando seguimiento de propiedad y páginas de equipo.
-
Mantén app-config.yaml consciente del entorno — usa
app-config.local.yamlpara desarrollo y variables de entorno para secretos de producción. -
Construye un ecosistema de plugins — crea plugins personalizados de frontend y backend para extender Backstage con las herramientas específicas de tu organización.
-
Define Systems y Domains — modela la arquitectura de alto nivel usando Systems y Domains para dar a los desarrolladores un mapa de tu plataforma.