Instalación de Backstage como Portal de Desarrollador

Backstage es la plataforma de portal de desarrollador de código abierto creada por Spotify que centraliza herramientas, servicios y documentación técnica en un solo lugar. Esta guía cubre la instalación y configuración de Backstage en Linux, incluyendo el catálogo de software, plantillas de scaffolding, TechDocs y la integración con Kubernetes.

Requisitos Previos

  • Node.js 18 o 20 (LTS)
  • Yarn 1.22+ o npm
  • Docker (para despliegue en contenedores)
  • PostgreSQL 13+ (recomendado para producción, SQLite para desarrollo)
  • Git y acceso a GitHub/GitLab para integración del catálogo
  • Mínimo 4 GB de RAM, 8 GB recomendado
# Instalar Node.js 20 LTS en Ubuntu
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs

# Instalar Yarn
npm install -g yarn

# Verificar versiones
node --version
yarn --version

Instalación de Backstage

# Instalar el CLI de Backstage
npx @backstage/create-app@latest

# El asistente preguntará por el nombre de la aplicación
# Introducir el nombre deseado, por ejemplo: mi-portal

El proceso crea la estructura del proyecto:

mi-portal/
├── app-config.yaml          # Configuración principal
├── app-config.production.yaml
├── packages/
│   ├── app/                 # Frontend React
│   └── backend/             # Backend Node.js
└── plugins/                 # Plugins personalizados
# Entrar al directorio del proyecto
cd mi-portal

# Instalar dependencias
yarn install

# Iniciar en modo desarrollo
yarn dev

Backstage estará disponible en http://localhost:3000.

Configuración del Catálogo de Software

El catálogo es el núcleo de Backstage. Edita app-config.yaml:

# Configuración del catálogo y fuentes de datos
catalog:
  import:
    entityFilename: catalog-info.yaml
    pullRequestBranchName: backstage-integration
  rules:
    - allow: [Component, System, API, Resource, Location, Template, User, Group]
  locations:
    # Importar catálogo desde un repositorio Git
    - type: url
      target: https://github.com/tu-org/catalogo/blob/main/all-components.yaml
      rules:
        - allow: [Component, System, API]
    # Archivo local de entidades de ejemplo
    - type: file
      target: ../../examples/entities.yaml

Crea un archivo catalog-info.yaml en cada repositorio de tu organización:

# catalog-info.yaml - Definición de un servicio en el catálogo
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: servicio-pagos
  description: Servicio de procesamiento de pagos
  annotations:
    github.com/project-slug: mi-org/servicio-pagos
    backstage.io/techdocs-ref: dir:.
  tags:
    - java
    - pagos
    - produccion
spec:
  type: service
  lifecycle: production
  owner: equipo-fintech
  system: plataforma-pagos
  providesApis:
    - api-pagos-v2

Configura la integración con GitHub:

# Añadir a app-config.yaml
integrations:
  github:
    - host: github.com
      token: ${GITHUB_TOKEN}  # Variable de entorno con el token

auth:
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}

Plantillas de Scaffolder

El Scaffolder permite crear nuevos servicios desde plantillas estandarizadas:

# template.yaml - Plantilla para crear microservicios Node.js
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: microservicio-nodejs
  title: Microservicio Node.js
  description: Crea un microservicio Node.js con la estructura estándar de la empresa
  tags:
    - nodejs
    - microservicio
spec:
  owner: equipo-plataforma
  type: service
  parameters:
    - title: Información del servicio
      required:
        - nombre
        - descripcion
      properties:
        nombre:
          title: Nombre del servicio
          type: string
          description: Nombre único del microservicio
          pattern: '^[a-z][a-z0-9-]*$'
        descripcion:
          title: Descripción
          type: string
        owner:
          title: Equipo propietario
          type: string
          ui:field: OwnerPicker
  steps:
    - id: fetch-base
      name: Generar estructura base
      action: fetch:template
      input:
        url: ./skeleton
        values:
          nombre: ${{ parameters.nombre }}
          descripcion: ${{ parameters.descripcion }}
    - id: publish
      name: Publicar en GitHub
      action: publish:github
      input:
        allowedHosts: ['github.com']
        description: ${{ parameters.descripcion }}
        repoUrl: github.com?repo=${{ parameters.nombre }}&owner=mi-org
  output:
    links:
      - title: Repositorio
        url: ${{ steps['publish'].output.remoteUrl }}

Configuración de TechDocs

TechDocs permite renderizar documentación Markdown directamente en Backstage:

# Instalar la CLI de TechDocs
npm install -g @techdocs/cli

# Instalar MkDocs y los plugins necesarios
pip install mkdocs mkdocs-techdocs-core
# mkdocs.yml - Configuración de documentación para un servicio
site_name: Servicio de Pagos
site_description: Documentación del servicio de procesamiento de pagos
nav:
  - Inicio: index.md
  - Arquitectura: arquitectura.md
  - API: api.md
  - Guías: guias/
plugins:
  - techdocs-core

Habilitar TechDocs en la configuración de Backstage:

# app-config.yaml
techdocs:
  builder: 'local'  # 'external' para producción con S3/GCS
  generator:
    runIn: 'docker'
  publisher:
    type: 'local'
    local:
      publishDirectory: '/tmp/techdocs'

Sistema de Plugins

Backstage tiene un ecosistema rico de plugins. Instalar el plugin de SonarQube como ejemplo:

# Instalar el plugin de SonarQube en el frontend
cd packages/app
yarn add @backstage/plugin-sonarqube

# Instalar el backend del plugin
cd ../backend
yarn add @backstage/plugin-sonarqube-backend
// packages/app/src/components/catalog/EntityPage.tsx
// Añadir la tarjeta de SonarQube a la página de entidades
import { EntitySonarQubeCard } from '@backstage/plugin-sonarqube';

// Dentro del componente de la página de servicios:
<Grid item md={6}>
  <EntitySonarQubeCard variant="gridItem" />
</Grid>

Integración con Kubernetes

# Instalar el plugin de Kubernetes
cd packages/app
yarn add @backstage/plugin-kubernetes

cd packages/backend
yarn add @backstage/plugin-kubernetes-backend

Configurar la conexión al clúster en app-config.yaml:

kubernetes:
  serviceLocatorMethod:
    type: 'multiTenant'
  clusterLocatorMethods:
    - type: 'config'
      clusters:
        - url: https://mi-cluster.example.com
          name: produccion
          authProvider: 'serviceAccount'
          serviceAccountToken: ${K8S_SERVICE_ACCOUNT_TOKEN}
          caData: ${K8S_CA_DATA}

Anotar los componentes en el catálogo para que Backstage muestre sus recursos Kubernetes:

# En el catalog-info.yaml del servicio
metadata:
  annotations:
    backstage.io/kubernetes-id: servicio-pagos
    backstage.io/kubernetes-namespace: produccion

Despliegue en Producción

# Construir la imagen Docker de producción
yarn build:backend --config app-config.yaml --config app-config.production.yaml

# Construir la imagen del frontend
yarn workspace app build

# Crear el Dockerfile multi-stage
cat << 'EOF' > Dockerfile
FROM node:20-bookworm-slim AS build
WORKDIR /app
COPY . .
RUN yarn install --frozen-lockfile
RUN yarn build

FROM node:20-bookworm-slim
WORKDIR /app
COPY --from=build /app/packages/backend/dist ./dist
COPY --from=build /app/node_modules ./node_modules
CMD ["node", "dist/index.cjs.js"]
EOF

# Construir y ejecutar el contenedor
docker build -t mi-backstage:latest .
docker run -d -p 7007:7007 \
  -e GITHUB_TOKEN=tu_token \
  -e POSTGRES_HOST=db.ejemplo.com \
  mi-backstage:latest

Configurar PostgreSQL para producción:

# app-config.production.yaml
backend:
  database:
    client: pg
    connection:
      host: ${POSTGRES_HOST}
      port: ${POSTGRES_PORT}
      user: ${POSTGRES_USER}
      password: ${POSTGRES_PASSWORD}
      database: backstage

Solución de Problemas

# Verificar los logs de la aplicación
yarn dev 2>&1 | tail -50

# Depurar problemas de catálogo
# En la consola de Backstage: Settings > Diagnostics

# Verificar la conexión a la base de datos
psql -h $POSTGRES_HOST -U backstage -d backstage -c "SELECT version();"

# Limpiar la caché y reinstalar dependencias
yarn clean
rm -rf node_modules
yarn install

# Verificar que todas las variables de entorno están configuradas
env | grep -E 'GITHUB|POSTGRES|AUTH'

Error "Entity not found" en el catálogo:

# Forzar la re-importación del catálogo
# En la interfaz de Backstage: Catalog > kebab menu > Refresh
# O desde la API:
curl -X POST http://localhost:7007/api/catalog/locations \
  -H 'Content-Type: application/json' \
  -d '{"type": "url", "target": "https://github.com/mi-org/repo/blob/main/catalog-info.yaml"}'

Conclusión

Backstage unifica el ecosistema de desarrollo de tu organización en un portal centralizado que mejora la productividad, la descubribilidad de servicios y la adopción de estándares. La clave está en poblar el catálogo con las entidades reales de tu organización y crear plantillas de Scaffolder que reflejen las mejores prácticas de tu equipo. Con TechDocs y los plugins de Kubernetes y CI/CD, Backstage se convierte en el punto de entrada definitivo para cualquier desarrollador.