Project: Backstage (App Definition and Development / Application Definition & Image Build)
File: writing.md

id: writing title: Writing Backstage Configuration Files description: Documentation on Writing Backstage Configuration Files Configuration is stored in YAML format in `app-config.yaml` files. This configuration is shared between the frontend and backend and it looks something like this: ```yaml app: title: Backstage Example App baseUrl: http://localhost:3000 backend: listen: 0.0.0.0:7007 baseUrl: http://localhost:7007 organization: name: CNCF proxy: /my/api: target: https://example.com/api/ changeOrigin: true pathRewrite: ^/proxy/my/api/: / ``` Configuration files are typically checked in and stored in the repo that houses the rest of the Backstage application. The particular configuration that is available to each Backstage app depends on what plugins and packages are installed. To view the configuration reference for your own project, including what configuration keys available and whether they are needed by the frontend, use the following command: ```sh yarn backstage-cli config:docs ``` Individual configuration values can be overridden using environment variables prefixed with `APPCONFIG`. Everything following that prefix in the environment variable name will be used as the config key, with `_` replaced by `.`. For example, to override the `app.baseUrl` value, set the `APPCONFIGapp_baseUrl` environment variable to the desired value. The value of the environment variable is parsed as JSON, but it will fall back to being interpreted as a string if it fails to parse. Note that if you for example want to pass on the string `"false"`, you need to wrap it in double quotes, e.g. `export APPCONFIGexample='"false"'`. While it may be tempting to use environment variable overrides for supplying a lot of configuration values, we recommend using them sparingly. Try to stick to using configuration files, and only use environment variables for things like reusing deployment artifacts across staging and production environments. Note that environment variables work for frontend configuration too. They are picked up by the serve tasks of `@backstage/cli` for local development, and are injected by the entrypoint of the nginx container serving the frontend in a production build. It is possible to have multiple configuration files (bundled and/or remote\*), both to support different environments, but also to define configuration that is local to specific packages. The configuration files to load are selected using a `--config <local-path|url>` flag, and it is possible to load any number of files. Paths are relative to the working directory of the executed process, for example `package/backend`. This means that to select a config file in the repo root when running the backend, you would use `--config ../../my-config.yaml`, and for config file on a config server you would use `--config https://some.domain.io/app-config.yaml` Note: In case URLs are passed, it is also needed to set the remote option in the loadBackendConfig call. If no `config` flags are specified, the default behavior is to load `app-config.yaml` and, if it exists, `app-config.local.yaml` from the repo root. In the provided project setup, `app-config.local.yaml` is `.gitignore`'d, making it a good place to add config overrides and secrets for local development. Note that if any config flags are provided, the default `app-config.yaml` files are NOT loaded. To include them you need to explicitly include them with a flag, for example: ```shell yarn start --config ../../app-config.yaml --config ../../app-config.staging.yaml --config https://some.domain.io/app-config.yaml ``` All loaded configuration files are merged together using the following rules: Configurations have different priority, higher priority means you replace values from configurations with lower priority. Primitive values are completely replaced, as are arrays and all of their contents. Objects are merged together deeply, meaning that if any of the included configs contain a value for a given path, it will be found. A `null` value in a config file will be treated as an explicit absence of

This means that the reading will not fall back to a lower priority config, but it will still be treated as if the configuration was not present. The priority of the configurations is determined by the following rules, in order: Configuration from the `APPCONFIG` environment variables has the highest priority, followed by files. Files loaded with config flags are ordered by priority, where the last flag has the highest priority. If no config flags are provided, `app-config.local.yaml` has higher priority than `app-config.yaml`. Includes are supported via special data loading keys that are prefixed with `$`, which in turn provide a number of different ways to read in data. To load in an external configuration value, supply an object with one of the special include keys, for example `$env` or `$file`. A full list of supported include keys can be found below. For example, the following will read the config key `backend.mySecretKey` from the environment variable `MYSECRETKEY`: ```yaml backend: mySecretKey: $env: MYSECRETKEY ``` With the above configuration, calling `config.getString('backend.mySecretKey')` will return the value of the environment variable `MYSECRETKEY` when the backend started up. All includes are loaded at startup, so changing the contents of files or environment variables will not be reflected at runtime. Below is a list of the currently supported methods for loading includes. This reads a string value from an environment variable. For example, the following configuration loads the string value from the `MY_SECRET` environment variable. ```yaml $env: MY_SECRET ``` Note however, that it's often more convenient to use instead. This reads a string value from the entire contents of a text file. The file path is relative to the source config file. For example, the following reads the contents of `my-secret.txt` relative to the config file itself: ```yaml $file: ./my-secret.txt ``` The `$include` keyword can be used to load configuration values from an external file. It's able to load and parse data from `.json`, `.yml`, and `.yaml` files. It's also possible to include a URL fragment (`#`) to point to a value at the given path in the file, using a dot-separated list of keys. For example, the following would read `my-secret-key` from `my-secrets.json`: ```yaml $include: ./my-secrets.json#deployment.key ``` Example `my-secrets.json` file: ```json { "deployment": { "key": "my-secret-key" } } ``` Configuration files support environment variable substitution via a `${MY_VAR}` syntax. For example: ```yaml app: baseUrl: https://${HOST} ``` Note that all environment variables must be available, or the entire configuration value will evaluate to `undefined`. The substitution syntax can be escaped using `$${...}`, which will be resolved as `${...}`. Parameter substitution syntax (e.g. `${MY_VAR:-default-value}`) is also supported to provide a default or fallback value for a given environment variable if it is unset, or is declared but has no value. For example: ```yaml app: baseUrl: https://${HOST:-localhost:3000} ``` In the above example, when `HOST` is unset or has no value, it will be substituted with `localhost:3000`. The Includes and Environment Variable Substitutions can be combined to do something like read a secrets configuration for a specific environment. For example: ```yaml integrations: github: host: github.com apps: $include: secrets.${BACKSTAGE_ENVIRONMENT}.yaml ``` Example `secrets.prod.yaml`: ```yaml appId: 1 webhookUrl: https://smee.io/foo clientId: someGithubAppClientId clientSecret: someGithubAppClientSecret webhookSecret: someWebhookSecret privateKey: | --BEGIN RSA PRIVATE KEY-- SomeRsaPrivateKeySecurelyStored --END RSA PRIVATE KEY-- ``` Warning: Sensitive information, such as private keys, should not be hard coded. We recommend that this entire file should be a secret and stored as such in a secure storage solution like Vault, to ensure they are neither exposed nor misused. This example key part only shows the format on how to use the yaml | syntax to make sure that the key is valid.