Backstage
Plataforma de portal interno para desenvolvedores de código aberto do Spotify para gerenciar catálogo de software e experiência do desenvolvedor.
Instalação
Seção intitulada “Instalação”Criando uma Nova Aplicação
Seção intitulada “Criando uma Nova Aplicação”| Comando | Descrição |
|---|---|
npx @backstage/create-app@latest | Criar nova aplicação Backstage |
npx @backstage/create-app@latest --skip-install | Criar app sem instalar dependências |
cd my-backstage-app && yarn install | Instalar dependências |
yarn dev | Iniciar frontend e backend em modo de desenvolvimento |
yarn start | Iniciar apenas o frontend |
yarn start-backend | Iniciar apenas o backend |
yarn build:backend | Compilar backend para produção |
yarn build | Compilar todos os pacotes |
node_modules/.bin/backstage-cli --version | Mostrar versão do CLI Backstage |
Deploy com Docker
Seção intitulada “Deploy com Docker”| Comando | Descrição |
|---|---|
yarn build:backend --config ../../app-config.yaml | Compilar backend com config |
docker build -t backstage -f packages/backend/Dockerfile . | Construir imagem Docker |
docker run -p 7007:7007 backstage | Executar contêiner Backstage |
Comandos da CLI
Seção intitulada “Comandos da CLI”Gerenciamento de Pacotes
Seção intitulada “Gerenciamento de Pacotes”| Comando | Descrição |
|---|---|
yarn backstage-cli package start | Iniciar um pacote em modo dev |
yarn backstage-cli package build | Compilar um pacote |
yarn backstage-cli package lint | Lint do código-fonte do pacote |
yarn backstage-cli package test | Executar testes do pacote |
yarn backstage-cli repo build --all | Compilar todos os pacotes no monorepo |
yarn backstage-cli repo lint --all | Lint de todos os pacotes |
yarn backstage-cli versions:bump | Atualizar dependências Backstage para a última versão |
yarn backstage-cli versions:bump --release next | Atualizar para próximo pre-release |
yarn backstage-cli migrate package-roles | Migrar pacotes para usar roles |
Criação de Plugins
Seção intitulada “Criação de Plugins”| Comando | Descrição |
|---|---|
yarn backstage-cli create-plugin | Criar novo plugin de frontend |
yarn backstage-cli create-plugin --backend | Criar novo plugin de backend |
yarn backstage-cli create-plugin --id my-plugin | Criar plugin com ID específico |
yarn new | Criar componente interativamente a partir de template |
Catálogo de Software
Seção intitulada “Catálogo de Software”Tipos de Entidade
Seção intitulada “Tipos de Entidade”| Comando | Descrição |
|---|---|
Adicionar catalog-info.yaml na raiz do repo | Registrar componente no catálogo |
kind: Component no catalog-info.yaml | Definir um componente de software |
kind: API no catalog-info.yaml | Definir uma entidade de API |
kind: System no catalog-info.yaml | Definir um agrupamento de sistema |
kind: Domain no catalog-info.yaml | Definir um domínio de negócio |
kind: Resource no catalog-info.yaml | Definir recurso de infraestrutura |
kind: Group no catalog-info.yaml | Definir uma equipe/grupo |
kind: User no catalog-info.yaml | Definir um usuário |
kind: Location no catalog-info.yaml | Referenciar outros arquivos de catálogo |
Propriedades de Entidade
Seção intitulada “Propriedades de Entidade”| Comando | Descrição |
|---|---|
Definir spec.owner: team-name | Definir proprietário da entidade |
Definir spec.lifecycle: production | Definir estágio do ciclo de vida da entidade |
Definir spec.type: service | Definir tipo do componente (service, website, library) |
Definir spec.dependsOn: ['component:other'] | Definir dependências |
Definir spec.providesApis: ['api-name'] | Declarar APIs fornecidas |
Definir spec.consumesApis: ['api-name'] | Declarar APIs consumidas |
Definir spec.system: system-name | Atribuir a um sistema |
Definir metadata.annotations para integrações | Conectar a CI/CD, monitoramento, etc. |
Exemplo de catalog-info.yaml
Seção intitulada “Exemplo de catalog-info.yaml”apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Gerencia processamento de pagamentos e faturamento
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: Dashboard de Monitoramento
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
Exemplo de Entidade API
Seção intitulada “Exemplo de Entidade API”apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: payment-api
description: API REST de processamento de pagamentos
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: Criar um pagamento
responses:
"201":
description: Pagamento criado
Exemplo de Sistema e Domínio
Seção intitulada “Exemplo de Sistema e Domínio”apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: billing
description: Sistema de faturamento e processamento de pagamentos
spec:
owner: team-payments
domain: commerce
---
apiVersion: backstage.io/v1alpha1
kind: Domain
metadata:
name: commerce
description: Domínio de e-commerce cobrindo pedidos, pagamentos e fulfillment
spec:
owner: group:engineering-leadership
Templates
Seção intitulada “Templates”Propriedades de Templates
Seção intitulada “Propriedades de Templates”| Comando | Descrição |
|---|---|
kind: Template no template.yaml | Definir um template de software |
Definir spec.type: service | Template cria um serviço |
Definir spec.steps[] para ações do template | Definir etapas de scaffolding |
action: fetch:template | Buscar e renderizar arquivos do template |
action: publish:github | Publicar repo scaffolded no GitHub |
action: publish:github:pull-request | Criar PR em vez de novo repo |
action: catalog:register | Registrar entidade criada no catálogo |
action: github:actions:dispatch | Disparar workflow do GitHub Actions |
Usar ${{ parameters.name }} nos templates | Referenciar parâmetros de entrada do usuário |
Definir spec.parameters[] para campos de formulário | Definir formulário de entrada do template |
Usar ui:widget: textarea nos parâmetros | Personalizar widget do campo de formulário |
Exemplo de Definição de Template
Seção intitulada “Exemplo de Definição de Template”apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: microservice-template
title: Criar um Microsserviço
description: Scaffoldar novo microsserviço com CI/CD, monitoramento e documentação
tags:
- recommended
- microservice
spec:
owner: team-platform
type: service
parameters:
- title: Detalhes do Serviço
required:
- name
- description
- owner
properties:
name:
title: Nome do Serviço
type: string
description: Nome único do serviço
ui:autofocus: true
ui:options:
rows: 5
description:
title: Descrição
type: string
owner:
title: Proprietário
type: string
description: Equipe proprietária deste serviço
ui:field: OwnerPicker
ui:options:
catalogFilter:
kind: Group
- title: Infraestrutura
properties:
language:
title: Linguagem
type: string
enum: ["go", "java", "python", "typescript"]
default: go
database:
title: Banco de Dados
type: string
enum: ["postgres", "mysql", "none"]
default: postgres
enableMonitoring:
title: Ativar Monitoramento
type: boolean
default: true
steps:
- id: fetch-base
name: Buscar Template Base
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
description: ${{ parameters.description }}
owner: ${{ parameters.owner }}
language: ${{ parameters.language }}
- id: publish
name: Publicar no 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: Registrar no Catálogo
action: catalog:register
input:
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
output:
links:
- title: Repositório
url: ${{ steps['publish'].output.remoteUrl }}
- title: Abrir no Catálogo
icon: catalog
entityRef: ${{ steps['register'].output.entityRef }}
Plugins
Seção intitulada “Plugins”Instalando Plugins
Seção intitulada “Instalando Plugins”| Comando | Descrição |
|---|---|
yarn add @backstage/plugin-catalog | Instalar plugin de catálogo |
yarn add @backstage/plugin-techdocs | Instalar plugin TechDocs |
yarn add @backstage/plugin-kubernetes | Instalar plugin Kubernetes |
yarn add @backstage/plugin-github-actions | Instalar plugin GitHub Actions |
yarn add @backstage/plugin-search | Instalar plugin de busca |
yarn add @backstage/plugin-scaffolder | Instalar plugin scaffolder |
yarn add @backstage/plugin-api-docs | Instalar plugin de docs de API |
yarn add @backstage/plugin-cost-insights | Instalar plugin de insights de custos |
Registro de Plugins
Seção intitulada “Registro de Plugins”Registrar plugins de frontend em 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 em 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
Seção intitulada “TechDocs”Operações TechDocs
Seção intitulada “Operações TechDocs”| Comando | Descrição |
|---|---|
npx @techdocs/cli serve | Pré-visualizar TechDocs localmente |
npx @techdocs/cli serve --docker-image techdocs-container | Servir usando imagem Docker personalizada |
npx @techdocs/cli generate | Gerar site estático TechDocs |
npx @techdocs/cli generate --source-dir . | Gerar de diretório específico |
npx @techdocs/cli publish --publisher-type googleGcs | Publicar TechDocs no GCS |
npx @techdocs/cli publish --publisher-type awsS3 | Publicar TechDocs no S3 |
Adicionar anotação backstage.io/techdocs-ref | Habilitar TechDocs para entidade |
Criar diretório docs/ com mkdocs.yml | Configurar fonte de TechDocs |
Definir techdocs.builder: 'local' na config | Usar builder TechDocs local |
Definir techdocs.builder: 'external' na config | Usar builder CI/CD externo |
Exemplo de mkdocs.yml para TechDocs
Seção intitulada “Exemplo 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
Configuração de Busca
Seção intitulada “Configuração de Busca”| Comando | Descrição |
|---|---|
yarn add @backstage/plugin-search | Instalar frontend de busca |
yarn add @backstage/plugin-search-backend | Instalar backend de busca |
yarn add @backstage/plugin-search-backend-module-catalog | Adicionar collator de busca do catálogo |
yarn add @backstage/plugin-search-backend-module-techdocs | Adicionar collator de busca TechDocs |
Configurar motor de busca no app-config.yaml | Configurar Lunr, Elasticsearch ou PgStore |
Definir search.pg na config | Usar PostgreSQL para busca |
Definir search.elasticsearch na config | Usar Elasticsearch para busca |
Configuração
Seção intitulada “Configuração”Configurações Principais
Seção intitulada “Configurações Principais”| Comando | Descrição |
|---|---|
Editar app-config.yaml | Arquivo de configuração principal |
Editar app-config.local.yaml | Sobrescritas de desenvolvimento local |
Editar app-config.production.yaml | Configuração de produção |
Definir app.baseUrl na config | Configurar URL do frontend |
Definir backend.baseUrl na config | Configurar URL do backend |
Definir backend.database na config | Configurar conexão com banco de dados |
Definir backend.cors.origin na config | Configurar origens CORS |
Definir auth.providers na config | Configurar provedores de autenticação |
Definir catalog.locations[] na config | Adicionar fontes de entidades do catálogo |
Definir catalog.rules[] na config | Definir regras de validação de entidades |
Definir integrations.github[] na config | Configurar token de integração GitHub |
Exemplo de app-config.yaml
Seção intitulada “Exemplo de app-config.yaml”app:
title: Portal do Desenvolvedor da Minha Empresa
baseUrl: http://localhost:3000
organization:
name: Minha Empresa
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 Relacionamentos de Entidades
Seção intitulada “Diagrama de Relacionamentos de Entidades”| Relacionamento | De | Para | Descrição |
|---|---|---|---|
ownerOf | Group/User | Component/API | Grupo é proprietário da entidade |
ownedBy | Component/API | Group/User | Entidade é de propriedade do grupo |
consumesApi | Component | API | Componente usa uma API |
providesApi | Component | API | Componente expõe uma API |
dependsOn | Component | Component/Resource | Componente depende de outro |
dependencyOf | Component/Resource | Component | É uma dependência de |
partOf | Component | System | Componente pertence ao sistema |
hasPart | System | Component | Sistema contém componente |
parentOf | Group | Group | Relacionamento de equipe pai |
childOf | Group | Group | Relacionamento de equipe filho |
memberOf | User | Group | Usuário pertence ao grupo |
hasMember | Group | User | Grupo contém usuário |
Melhores Práticas
Seção intitulada “Melhores Práticas”-
Usar catalog-info.yaml em todo repositório — garanta que todos os serviços, bibliotecas e APIs estejam registrados no catálogo para visibilidade completa.
-
Definir propriedade significativa — toda entidade deve ter um campo
ownerapontando para um Group válido, permitindo responsabilidade e roteamento. -
Anotar entidades de forma rica — adicione anotações para CI/CD, monitoramento, PagerDuty e documentação para tornar o catálogo um verdadeiro hub.
-
Criar templates para caminhos dourados — use o scaffolder para definir formas padronizadas de criar novos serviços, garantindo consistência.
-
Implementar TechDocs — mantenha documentação junto ao código usando o plugin TechDocs e
mkdocs.ymlpara documentação viva. -
Usar descoberta GitHub — configure
github-discoverynas localizações do catálogo para descobrir e registrar repositórios automaticamente. -
Modelar sua organização — defina Groups e Users para refletir a estrutura da sua equipe, habilitando rastreamento de propriedade e páginas de equipe.
-
Manter app-config.yaml consciente do ambiente — use
app-config.local.yamlpara desenvolvimento e variáveis de ambiente para secrets de produção. -
Construir um ecossistema de plugins — crie plugins personalizados de frontend e backend para estender o Backstage com ferramentas específicas da sua organização.
-
Definir Systems e Domains — modele a arquitetura de alto nível usando Systems e Domains para dar aos desenvolvedores um mapa da sua plataforma.