PlatformEngr® Backstage course

Cheat notes · Module 02 · The portal and its catalog

Configuration, secrets and Postgres

A five-minute review for when you have done this module and want it back in your head. Open the full module for the steps and the lab, or the full text to print.

The idea

Everything is configuration: one YAML file in Git with placeholders, the values from the environment. Config files layer (objects merge, lists replace), secrets never reach Git or the browser, and scripts call the API with a configured token.

Remember

  • Config layers: app-config.yaml, then app-config.local.yaml if present, or the files given with --config. Later files override keys. Lists are replaced, not merged.
  • Environment variables: ${POSTGRES_PASSWORD} is read at backend start; ${POSTGRES_HOST:-localhost} has a default. A missing value is only an error when a plugin needs it.
  • Frontend visibility: each plugin's config schema marks what the browser may see. Secrets are never sent.
  • External access: scripts and CI call the API with a token in backend.auth.externalAccess; each token has a subject, so logs show who called.
  • Postgres: one database per plugin (backstage_plugin_catalog, backstage_plugin_scaffolder, ...).
  • .env stays on your laptop and is git-ignored. yarn start does not read it: load it with set -a && . ./.env && set +a in every terminal.

Pitfalls

  • A typo in a variable name on a fresh laptop: Missing required config value at 'backend.auth.externalAccess[0].options.token' and the backend shuts down. Plain config:check passes; --strict catches it. Keep a .env.example with every name.
  • A variable left over in your shell from an earlier session hides the same mistake. Test from a fresh terminal.
  • Pasting config:print --with-secrets output anywhere.

Commands

set -a && . ./.env && set +aLoad .env into this terminal
yarn backstage-cli config:print --frontendWhat the browser receives
yarn backstage-cli config:printThe backend view, secrets shown as <secret>
yarn backstage-cli config:check --strictFail on a missing required value, not only on a wrong shape
curl -H "Authorization: Bearer $PORTAL_API_TOKEN" localhost:7007/api/catalog/entitiesCall the API as a script
git check-ignore .envProve Git ignores the secrets file

Placeholders in app-config.yaml

backend:
  auth:
    externalAccess:
      - type: static
        options:
          token: ${PORTAL_API_TOKEN}
          subject: portal-cli
  database:
    client: pg
    connection:
      host: ${POSTGRES_HOST:-localhost}
      password: ${POSTGRES_PASSWORD}

Test yourself

Answer in your head first, then open the answer.

You set catalog.locations in app-config.local.yaml. What happens to the list in app-config.yaml?

It is replaced. Lists in a later file replace the whole list; objects merge.

Why is the database password safe in app-config.yaml?

The file only holds ${POSTGRES_PASSWORD}. The value comes from the environment and is never sent to the browser.

What does config:check --strict add?

It fails when a required value is missing, not only when the shape is wrong.

Where module 02 leaves you: The portal is called Acme Portal, stores its data in Postgres in Docker, and accepts a static API token from .env. The config change is merged in your portal repo; .env is not in Git.