Building Developer Portals with Backstage

32 minute read     Updated:

Aniket Bhattacharyea %
Aniket Bhattacharyea

This article provides a step-by-step process for setting up Backstage. Earthly guarantees reproducible builds. A great tool to pair with Backstage. Learn more about Earthly.

Medium to large companies typically use several different components and services for operations, including apps developed in-house, third-party services such as Google Cloud Provider (GCP) or Amazon Web Services (AWS), and third-party APIs. Managing all these services can become a complex task, which is why Backstage, an open source project, helps companies create developer portals that consolidate all their services, configurations, and secrets into one place. With Backstage, the portal that you create gives you a place to document each of your services and provides an overview of the services in use, their locations, and interdependencies.

In this article, you’ll learn how to create a developer portal with Backstage.

What Is Backstage?

Picture this: you’re a developer at a growing company with a popular app. One day, you get a complaint from a customer that they’re not receiving emails from the app. You put your debugging glasses on and realize that the app uses a third-party service for sending emails. However, you have no idea what service is being used. You ask around, and it turns out that the developer who set up this integration has left the company. After an entire week of brainstorming, you finally succeed in replacing the component responsible for emails with a shiny new component. But now you realize that some other crucial functionality of the app is broken because you had no idea it depended on the old mailing system.

This is a familiar story in many organizations. As you add more and more software, services, and APIs to your tech stack, keeping track of them becomes increasingly challenging.

Backstage was created because Spotify ran into this same issue. Spotify needed a place to collect and document all its services in one place, and Backstage allowed it to do just that and eventually grow and become the company it is today.

In 2020, Spotify donated Backstage to the Cloud Native Computing Foundation (CNCF), where it received the love and support of the open source community and was developed into a community-driven effort aimed at simplifying development.

The Benefits of Backstage

At its core, Backstage is a developer portal. A developer portal works as the heart of development and allows developers to quickly find what they need.

The following are a few of the reasons Backstage is a great developer portal:

  • Backstage comes with a robust Software Catalog, a centralized system that consolidates and tracks ownership and metadata for all the software in your tech stack (services, websites, libraries, data pipelines, and so on). It works as a single source of truth by providing you with information about the software and letting you explore the dependencies between components.
  • Backstage’s TechDocs feature lets you create a central documentation hub right inside the developer portal. Developers write code that lives with the components, and Backstage can pull this documentation into a centralized system.
  • Backstage Search helps you quickly find the information you need.
  • Backstage’s predefined templates help you easily create components inside Backstage.
  • Backstage can be integrated with various third-party services with little effort.
  • By using existing plugins or creating your own, you can customize Backstage to fit your needs.

Additionally, as previously stated, Backstage is open source, which means you can modify it to your heart’s content and host it in your own architecture.

If some of these features interest you, read on! In the next section, you’ll get a quick hands-on tutorial on how to set up Backstage and use its Software Catalog.

Building a Developer Portal with Backstage

Before you begin this tutorial, you’ll need the latest version of Node.js installed as well as Yarn Classic installed and set up.

Note that you can upgrade to the latest version of Yarn later on, but to create the Backstage instance, you’ll need Yarn Classic.

You’ll also need to install and set up PostgreSQL on your computer.

Setting Up a Backstage Instance

To begin, you need to create a Backstage instance by running the following command:

npx @backstage/create-app@latest

When you’re prompted, enter the name of the directory where you want to set up the instance (eg backstage).

Once the setup is complete, your output will look like this:

// Some output omitted

 Moving to final location:
  moving        backstage ✔
  init          git repository ◜
 Installing dependencies:
  init          git repository ✔
  determining   yarn version ✔
  executing     yarn install ✔
  executing     yarn tsc ✔

🥇  Successfully created backstage


 All set! Now you might want to:
  Run the app: cd backstage && yarn dev
  Set up the software catalog: https://backstage.io/docs/features/software-catalog/configuration
  Add authentication: https://backstage.io/docs/auth/

Navigate to the backstage directory and install the dependencies by running npm install.

Then, start the Backstage server with the following command:

yarn dev

This launches a Backstage instance at http://localhost:3000 and opens a browser window where you’ll be greeted with the default Backstage instance:

The default Backstage instance

Before you proceed with the rest of the article, you’ll need to configure Backstage to use PostgreSQL as the database. By default, Backstage works with an in-memory database, which means any changes you make will be lost when you restart the server. To prevent that, a database such as PostgreSQL is needed where Backstage can store the data.

To configure PostgreSQL, install the pg library by running the following command:

yarn add -cwd packages/backend pg

Open the app-config.yaml file where the configuration for Backstage is stored. You’ll find a database key that looks like this:

database:
    client: better-sqlite3
    connection: ':memory:'

By default, this sets Backstage up to use an in-memory database. You could edit this file to set up the PostgreSQL connection, but that’s not a secure approach because the configuration contains sensitive information, such as the database URL and password. The app-config.yaml file is checked into version control, which means anyone who has access to your company’s version control system can read it.

It’s better to use app-config.local.yaml for sensitive configurations. This file is not checked into version control, and any configuration in this file overrides the same from app-config.yaml. So, open app-config.local.yaml and add the following:

# Backstage override configuration for your local development environment
backend:
  database:
    client: pg
    connection:
      host: 127.0.0.1                
      port: 5432                     
      user: USER
      password: PASSWORD

Replace USER with the PostgreSQL user and PASSWORD with the password.

Restart the Backstage server and look for a line like this:

Performing database migration

This means the database connection is successful.

Setting Up GitHub Authentication

The default Backstage instance doesn’t perform any authentication, and anyone who can access the URL can access the Backstage instance. It’s a good idea to set up authentication for security purposes. With just a few lines of code, you can set up a GitHub login page using OAuth.

First, go to https://github.com/settings/applications/new and create a new OAuth app. Enter http://localhost:3000 in the Homepage URL field and http://localhost:7007/api/auth/github/handler/frame as the Authorization callback URL. Give the app a name and click Register application:

Creating a new OAuth app

On the next page, you’ll be shown a client ID that you’ll need to copy. Click the Generate a new client secret button and copy the generated client secret:

Generating a client secret

Open the app-config.local.yaml file and paste the following YAML code into it:

auth:
  # See https://backstage.io/docs/auth/ to learn about auth providers
  environment: development
  providers:
    github:
      development:
        clientId: YOUR_CLIENT_ID
        clientSecret: YOUR_CLIENT_SECRET

Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with the client ID and client secret you acquired.

Open packages/app/src/App.tsx and add the following imports:

import { githubAuthApiRef } from '@backstage/core-plugin-api';
import { SignInPage } from '@backstage/core-components';

Search for const app = createApp({, and below apis, add the following:

components: {
  SignInPage: props => (
    <SignInPage
      {...props}
      auto
      provider={ {
        id: 'github-auth-provider',
        title: 'GitHub',
        message: 'Sign in using GitHub',
        apiRef: githubAuthApiRef,
      } }
    />
  ),
},

Restart the server, and you’ll be prompted with a login screen:

The GitHub login screen

Once you log in with GitHub, navigate to Settings and verify that your name and email have been taken from GitHub:

The user profile

Note: By default, Backstage comes with a guest sign-in resolver. With this resolver, all users share a single “guest” identity. You can read more about configuring user identities in the official docs.

Exploring the Software Catalog

To better understand some of the benefits of Backstage’s Software Catalog system, let’s imagine a scenario where your company has a product with a Node.js backend and a Python frontend client. You want to add them to Backstage’s Software Catalog.

The apps have already been created and hosted on GitHub to make your life easier. Here’s the Node.js backend and the Python client. You’ll be modifying the repos, so you must fork them to your GitHub account and clone them to your local computer. If you prefer to simply see the end result, both repos have a branch named final that contains the final code.

Note: It isn’t necessary to run the apps to register them in Backstage, but if you want to run them, you can find instructions in the README files in the repos.

To register components in Backstage, each component must have a catalog-info.yaml file. This file contains metadata about the project and acts as the single source of truth for the components. Here, you’ll add the catalog-info.yaml files to both repos.

To start, create a file named catalog-info.yaml in the root of the Node.js app with the following code:

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: Blog-App
  description: This is a dummy Node.js app
  tags:
    - node

spec:
  type: service
  lifecycle: experimental
  owner: user:guest

In this code, the kind key sets the kind of entity. In this case, Component denotes that it’s a piece of software that you’re registering to Backstage. The metadata key records information related to the component, such as name, description, and annotations. Finally, in the spec key, you set the type, lifecycle, and owner of the component.

Commit this file and push the changes to your GitHub repo.

In the Backstage dashboard, click Create, and then click REGISTER EXISTING COMPONENT:

Creating a new component

In the URL field, enter the URL to your repo’s catalog-info.yaml file. It should be something like https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_GITHUB_REPO_NAME>/blob/<BRANCH_NAME>/catalog-info.yaml. Replace <YOUR_GITHUB_USERNAME> with your GitHub username, <YOUR_GITHUB_REPO_NAME> with the name of the repo in your account, and <BRANCH_NAME> with the name of the branch you’re working on:

First step of registering a component

When you click ANALYZE, Backstage fetches the catalog-info.yaml file and extracts the entities from it:

Importing the component

Click IMPORT, and after the component is registered, click View Component. You’ll be taken to the entity page:

The component page

You can see that the name and description have been fetched from the catalog-info.yaml file. On the left side, you’ll find a VIEW SOURCE button that takes you straight to the GitHub repo of the app. On the right-hand side, you’ll find a relations graph that shows the relations of this entity with other entities.

Right now, you can see that the user:guest entity has an ownerOf/ownedBy relationship with this component.

Adding APIs to the Catalog

APIs are at the center of modern software development. Almost every piece of software either exposes an API for other software to communicate with or consumes an API to communicate with other software. The Blog-App component also exposes an API. With Backstage, you can also catalog the API in the Software Catalog.

Open the catalog-info.yaml file and add the following in the spec key:

providesApis:
  - blog-api

This tells Backstage that the Blog-App component provides an API named blog-api.

Now, let’s define the API. Add the code below at the end of the catalog-info.yaml file. As before, replace the GitHub-related parts with information specific to your repo:

---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: blog-api
  description: The Blog API
spec:
  type: openapi
  lifecycle: experimental
  owner: user:guest
  definition:
    $text: https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_GITHUB_REPO_NAME>/blob/<BRANCH_NAME>/api/swagger.yaml

Notice that kind is set to API because this is an API entity, and the definition key refers to the api/swagger.yaml file in the repo. Backstage can generate a Swagger UI using the Swagger file.

The full catalog-info.yaml file looks like this:

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: Blog-App
  description: This is a dummy Node.js app
  annotations:
    backstage.io/managed-by-location: https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_GITHUB_REPO_NAME>/blob/<BRANCH_NAME>/catalog-info.yaml
  tags:
    - node

spec:
  type: service
  lifecycle: experimental
  owner: user:guest
  providesApis:
    - blog-api

---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: blog-api
  description: The Blog API
spec:
  type: openapi
  lifecycle: experimental
  owner: user:guest
  definition:
    $text: https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_GITHUB_REPO_NAME>/blob/<BRANCH_NAME>/api/swagger.yaml

Commit and push the changes.

Once Backstage registers a component, it periodically refreshes the catalog-info.yaml file by re-fetching it. That means once you push your changes, you should see them reflected automatically after a few minutes.

Once the component is refreshed, you’ll see a new entity has been added to the relations graph. The api:blog-api entity has an apiProvidedBy/providesApi relationship with the Blog-App component:

The updated relations graph

If you go to the API tab, you’ll see blog-api listed under Provided APIs:

The list of APIs

Click blog-api, and you’ll see that a Swagger UI has been generated from the Swagger file:

The generated Swagger UI

Adding Dependencies to the Catalog

In a real-world project, components often depend on other components. With Backstage’s robust Software Catalog, you can record the dependencies between components.

In this section, you’ll focus on the Python client, which depends on the Blog-App component and consumes the blog-api API.

Add a catalog-info.yaml file in the repo for the Python client:

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: Python-Client
  description: This is a dummy Python app
  tags:
    - python
    - web
spec:
  type: website
  lifecycle: experimental
  owner: user:guest
  consumesApis:
    - api:blog-api
  dependsOn:
    - component:Blog-App

This is very similar to the metadata for Blog-App. The consumesApis key tells Backstage that this component consumes the blog-api API, and the dependsOn key tells Backstage that this component is dependent on the Blog-App component.

As before, commit and push this code and register the component. You’ll notice that the relations graph shows how the Python-Client component is related to the blog-api API and the Blog-App component:

The newly registered component

If you go to the DEPENDENCIES tab, you’ll see that the Blog-App component shows up as a dependency:

The list of dependencies

Click Blog-App to be taken to its overview page, where you’ll see the relations graph has been updated to include the new Python-Client component:

The updated relations graph

Congratulations! Now you not only have a catalog of your components, but you also have a clear understanding of how they’re related to each other.

Conclusion

Developer portals are a must for any company that uses a lot of services and components in its ecosystem. With a developer portal, you can consolidate all your components in one place, which increases developer productivity and provides a bird’s-eye view of the entire ecosystem.

Backstage helps you build a powerful developer portal with features like a Software Catalog, TechDocs, and Templates. In this article, you learned all about these features as well as how to set up a Backstage instance and register components in the Software Catalog. You also learned how to add APIs and dependencies among components.

Earthly Cloud: Consistent, Fast Builds, Any CI
Consistent, repeatable builds across all environments. Advanced caching for faster builds. Easy integration with any CI. 6,000 build minutes per month included.

Get Started Free

Aniket Bhattacharyea %
Aniket Bhattacharyea
Aniket is a student doing a Master's in Mathematics and has a passion for computers and software.

Published:

Get notified about new articles!
We won't send you spam. Unsubscribe at any time.