docs: deployment golden path guide
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
---
|
||||
id: docker
|
||||
sidebar_label: 001 - Building the Docker image
|
||||
title: Building the Docker image
|
||||
description: How to build your Backstage app into a deployable Docker image
|
||||
---
|
||||
|
||||
Audience: Developers and Admins
|
||||
|
||||
## Summary
|
||||
|
||||
Every production deployment of Backstage starts with a Docker image. The image
|
||||
bundles both the frontend and backend into a single artifact that you can deploy
|
||||
anywhere containers run.
|
||||
|
||||
By the end of this page, you will have a Docker image ready to push to a
|
||||
container registry.
|
||||
|
||||
## What is in the Docker image?
|
||||
|
||||
When you created your app with `@backstage/create-app`, a `Dockerfile` was
|
||||
generated at `packages/backend/Dockerfile`. The build process layers both the
|
||||
frontend and backend into a single image:
|
||||
|
||||
1. The **backend** is compiled and bundled into `packages/backend/dist/`.
|
||||
2. The **frontend** is built and served by the
|
||||
`@backstage/plugin-app-backend` plugin, which is included in the backend
|
||||
by default.
|
||||
3. Production dependencies are installed, and the result is packaged into a
|
||||
slim Node.js image.
|
||||
|
||||
The image runs as a non-root `node` user and sets `NODE_ENV=production`.
|
||||
|
||||
## Building the image
|
||||
|
||||
The recommended approach is a **host build**, where compilation happens on
|
||||
your machine (or CI runner) and Docker only packages the result. This is faster
|
||||
and produces better caching behavior.
|
||||
|
||||
From the root of your repository:
|
||||
|
||||
```shell
|
||||
yarn install --immutable
|
||||
yarn tsc
|
||||
yarn build:backend
|
||||
```
|
||||
|
||||
Then build the Docker image:
|
||||
|
||||
```shell
|
||||
docker image build . -f packages/backend/Dockerfile --tag backstage
|
||||
```
|
||||
|
||||
To verify it works locally:
|
||||
|
||||
```shell
|
||||
docker run -it -p 7007:7007 backstage
|
||||
```
|
||||
|
||||
You should see logs in your terminal and be able to open `http://localhost:7007`
|
||||
in your browser.
|
||||
|
||||
## Running the build in CI
|
||||
|
||||
While you can run this build locally, you will typically run it as part of your
|
||||
CI pipeline. A GitHub Actions workflow might look like this:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
- run: yarn install --immutable
|
||||
- run: yarn tsc
|
||||
- run: yarn build:backend
|
||||
- run: docker image build . -f packages/backend/Dockerfile --tag backstage
|
||||
```
|
||||
|
||||
After building, push the image to your container registry (ECR, GCR, Docker
|
||||
Hub, etc.) so that your deployment platform can pull it.
|
||||
|
||||
:::tip Troubleshooting
|
||||
|
||||
If you run into build issues, two Docker flags can help:
|
||||
|
||||
- `--progress=plain` shows verbose output instead of folded log sections.
|
||||
- `--no-cache` rebuilds all layers from scratch.
|
||||
|
||||
```shell
|
||||
docker image build . -f packages/backend/Dockerfile --tag backstage --progress=plain --no-cache
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Further reading
|
||||
|
||||
For a full multi-stage Docker build (where everything happens inside Docker)
|
||||
or for deploying the frontend separately, see the
|
||||
[Building a Docker image](../../deployment/docker.md) reference documentation.
|
||||
|
||||
## Next steps
|
||||
|
||||
Before deploying, you need to set up two production dependencies: a database and
|
||||
an authentication provider.
|
||||
|
||||
- [Setting up a production database](./002-database.md)
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
id: database
|
||||
sidebar_label: 002 - Database
|
||||
title: Setting up a production database
|
||||
description: How to configure PostgreSQL for your Backstage production deployment
|
||||
---
|
||||
|
||||
Audience: Admins
|
||||
|
||||
## Summary
|
||||
|
||||
During local development, Backstage uses SQLite as a fast in-memory database.
|
||||
SQLite does not persist data across restarts and is not designed for
|
||||
multi-instance deployments, so you need a dedicated database for production.
|
||||
|
||||
By the end of this page, you will have PostgreSQL configured as your Backstage
|
||||
database.
|
||||
|
||||
## Why PostgreSQL?
|
||||
|
||||
PostgreSQL is the recommended production database for Backstage. It handles
|
||||
concurrent connections well, supports the query patterns that Backstage plugins
|
||||
use, and is available as a managed service from every major cloud provider.
|
||||
|
||||
Some options for running PostgreSQL:
|
||||
|
||||
- **Managed services**: Amazon RDS, Google Cloud SQL, Azure Database for
|
||||
PostgreSQL, or similar offerings.
|
||||
- **Self-hosted**: Running PostgreSQL in a container or on a dedicated server.
|
||||
- **In Kubernetes**: Deploying PostgreSQL alongside Backstage (useful for
|
||||
getting started, but managed services are preferred for production).
|
||||
|
||||
## Configuring Backstage to use PostgreSQL
|
||||
|
||||
Open your `app-config.production.yaml` and add the database configuration:
|
||||
|
||||
```yaml title="app-config.production.yaml"
|
||||
backend:
|
||||
database:
|
||||
client: pg
|
||||
connection:
|
||||
host: ${POSTGRES_HOST}
|
||||
port: ${POSTGRES_PORT}
|
||||
user: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
```
|
||||
|
||||
The `${...}` syntax references environment variables, which keeps secrets out
|
||||
of your configuration files. Set these variables in your deployment environment.
|
||||
|
||||
:::caution
|
||||
|
||||
Avoid hardcoding database credentials in configuration files. Use environment
|
||||
variables or a secrets manager provided by your deployment platform.
|
||||
|
||||
:::
|
||||
|
||||
### Optional: SSL connections
|
||||
|
||||
If your database provider requires SSL (most managed services do), add the
|
||||
SSL configuration:
|
||||
|
||||
```yaml title="app-config.production.yaml"
|
||||
backend:
|
||||
database:
|
||||
client: pg
|
||||
connection:
|
||||
host: ${POSTGRES_HOST}
|
||||
port: ${POSTGRES_PORT}
|
||||
user: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
ssl:
|
||||
require: true
|
||||
rejectUnauthorized: true
|
||||
```
|
||||
|
||||
If your provider uses a custom certificate authority, you can reference the
|
||||
CA certificate file:
|
||||
|
||||
```yaml
|
||||
ssl:
|
||||
ca:
|
||||
$file: /path/to/ca/server.crt
|
||||
```
|
||||
|
||||
## How Backstage uses the database
|
||||
|
||||
Each plugin gets its own isolated database schema. Migrations run automatically
|
||||
when the backend starts, so you do not need to run any manual migration steps.
|
||||
The database coordinates state and work distribution between instances, which
|
||||
is what makes horizontal scaling possible later on.
|
||||
|
||||
## Further reading
|
||||
|
||||
For step-by-step PostgreSQL installation instructions and cloud-specific
|
||||
setup guides, see the [Database configuration guide](../../getting-started/config/database.md).
|
||||
|
||||
## Next steps
|
||||
|
||||
With the database in place, the next step is to replace the guest login with
|
||||
a real authentication provider.
|
||||
|
||||
- [Configuring authentication](./003-authentication.md)
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
id: authentication
|
||||
sidebar_label: 003 - Authentication
|
||||
title: Configuring authentication
|
||||
description: How to set up a production authentication provider for Backstage
|
||||
---
|
||||
|
||||
Audience: Developers and Admins
|
||||
|
||||
## Summary
|
||||
|
||||
By default, Backstage uses a guest authentication provider that lets anyone
|
||||
log in without credentials. This is convenient for local development but
|
||||
creates a security risk when deployed to production. Before deploying, you
|
||||
should configure a real authentication provider.
|
||||
|
||||
By the end of this page, you will understand what needs to change and where
|
||||
to find the setup instructions for your chosen provider.
|
||||
|
||||
## Why replace guest authentication?
|
||||
|
||||
The guest provider is explicitly not intended for containerized or production
|
||||
environments. With guest auth enabled, any user who can reach your Backstage
|
||||
instance shares the same identity and has the same level of access. Replacing
|
||||
it is one of the most important steps before going to production.
|
||||
|
||||
:::danger
|
||||
|
||||
Deploying Backstage with the guest authentication provider exposes your
|
||||
instance to unauthorized access. Configure a real provider before deploying.
|
||||
|
||||
:::
|
||||
|
||||
## Choosing an authentication provider
|
||||
|
||||
Backstage supports a wide range of authentication providers. GitHub is a
|
||||
common choice since most developers already have accounts, but you should
|
||||
pick whatever your organization already uses for single sign-on.
|
||||
|
||||
Some popular options:
|
||||
|
||||
| Provider | Good fit when... |
|
||||
| :------------------- | :------------------------------------------------ |
|
||||
| GitHub | Your team uses GitHub and you want a quick setup. |
|
||||
| Microsoft / Azure AD | Your company uses Microsoft Entra ID (Azure AD). |
|
||||
| Google | Your company uses Google Workspace. |
|
||||
| Okta | You use Okta as your identity provider. |
|
||||
| OIDC | You have a generic OpenID Connect provider. |
|
||||
| OAuth2 Proxy | You already use an authenticating reverse proxy. |
|
||||
|
||||
The full list of providers and their configuration is available in the
|
||||
[Authentication documentation](../../auth/index.md).
|
||||
|
||||
## What the setup involves
|
||||
|
||||
Regardless of which provider you choose, the setup follows the same pattern:
|
||||
|
||||
1. **Create an OAuth application** (or equivalent) with your identity
|
||||
provider. You will get a client ID and client secret.
|
||||
2. **Add the provider configuration** to `app-config.yaml` with the
|
||||
credentials, typically using environment variables for secrets.
|
||||
3. **Install the backend auth module** for your chosen provider in
|
||||
`packages/backend`.
|
||||
4. **Configure a sign-in resolver** that maps the authenticated user identity
|
||||
to a Backstage catalog user entity.
|
||||
5. **Update the frontend** to show the correct sign-in page.
|
||||
|
||||
The [Authentication getting started guide](../../getting-started/config/authentication.md)
|
||||
walks through this process step by step using GitHub as the example provider.
|
||||
|
||||
## Production configuration
|
||||
|
||||
Once authentication is configured, make sure that the guest provider is
|
||||
disabled in your production config:
|
||||
|
||||
```yaml title="app-config.production.yaml"
|
||||
auth:
|
||||
providers:
|
||||
guest: null
|
||||
```
|
||||
|
||||
This ensures that even if the guest provider is configured in your base
|
||||
`app-config.yaml` for local development, it is explicitly disabled in
|
||||
production.
|
||||
|
||||
## Next steps
|
||||
|
||||
With both a database and authentication configured, you are ready to deploy.
|
||||
|
||||
- [Deploying to production](./004-deploying.md)
|
||||
@@ -0,0 +1,186 @@
|
||||
---
|
||||
id: deploying
|
||||
sidebar_label: 004 - Deploying
|
||||
title: Deploying to production
|
||||
description: How to deploy your Backstage instance to Kubernetes and other platforms
|
||||
---
|
||||
|
||||
Audience: Admins
|
||||
|
||||
## Summary
|
||||
|
||||
You have a Docker image, a database, and authentication configured. Now it is
|
||||
time to deploy. The best way to deploy Backstage is _the same way_ you deploy
|
||||
other software at your organization. This page covers deploying to Kubernetes
|
||||
as a concrete example and points to resources for other platforms.
|
||||
|
||||
## Deploying to Kubernetes
|
||||
|
||||
Kubernetes is the most common deployment target for Backstage. The deployment
|
||||
involves a few Kubernetes objects: a namespace, secrets, a deployment, and a
|
||||
service.
|
||||
|
||||
### 1. Create a namespace
|
||||
|
||||
```yaml
|
||||
# kubernetes/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: backstage
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl apply -f kubernetes/namespace.yaml
|
||||
```
|
||||
|
||||
### 2. Create secrets
|
||||
|
||||
Store your database credentials and any other secrets (API tokens, auth
|
||||
client secrets) as Kubernetes Secrets:
|
||||
|
||||
```yaml
|
||||
# kubernetes/backstage-secrets.yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: backstage-secrets
|
||||
namespace: backstage
|
||||
type: Opaque
|
||||
data:
|
||||
POSTGRES_USER: <base64-encoded-value>
|
||||
POSTGRES_PASSWORD: <base64-encoded-value>
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
Kubernetes secrets are base64-encoded but not encrypted. Enable
|
||||
[Encryption at Rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
|
||||
for your cluster and consider tools like
|
||||
[SealedSecrets](https://github.com/bitnami-labs/sealed-secrets) for storing
|
||||
secrets in Git.
|
||||
|
||||
:::
|
||||
|
||||
```shell
|
||||
kubectl apply -f kubernetes/backstage-secrets.yaml
|
||||
```
|
||||
|
||||
### 3. Create the deployment
|
||||
|
||||
```yaml
|
||||
# kubernetes/backstage.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backstage
|
||||
namespace: backstage
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: backstage
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: backstage
|
||||
spec:
|
||||
containers:
|
||||
- name: backstage
|
||||
image: <your-registry>/backstage:<tag>
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 7007
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: backstage-secrets
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 7007
|
||||
path: /.backstage/health/v1/readiness
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
port: 7007
|
||||
path: /.backstage/health/v1/liveness
|
||||
```
|
||||
|
||||
Replace `<your-registry>/backstage:<tag>` with the full image URL from your
|
||||
container registry.
|
||||
|
||||
```shell
|
||||
kubectl apply -f kubernetes/backstage.yaml
|
||||
```
|
||||
|
||||
### 4. Create a service
|
||||
|
||||
```yaml
|
||||
# kubernetes/backstage-service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backstage
|
||||
namespace: backstage
|
||||
spec:
|
||||
selector:
|
||||
app: backstage
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: http
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl apply -f kubernetes/backstage-service.yaml
|
||||
```
|
||||
|
||||
### 5. Expose the service
|
||||
|
||||
The Service is not accessible outside the cluster by default. Use a Kubernetes
|
||||
[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
|
||||
or an
|
||||
[external load balancer](https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/)
|
||||
to expose Backstage to your users.
|
||||
|
||||
Make sure the `app.baseUrl` and `backend.baseUrl` values in your
|
||||
`app-config.production.yaml` match the URL where users will access Backstage:
|
||||
|
||||
```yaml title="app-config.production.yaml"
|
||||
app:
|
||||
baseUrl: https://backstage.example.com
|
||||
backend:
|
||||
baseUrl: https://backstage.example.com
|
||||
listen:
|
||||
port: 7007
|
||||
```
|
||||
|
||||
## Other deployment platforms
|
||||
|
||||
Backstage is a standard Node.js application running in a Docker container, so
|
||||
it works on any platform that supports containers:
|
||||
|
||||
- **Amazon ECS**: Create a task definition referencing your Docker image, set
|
||||
up an ECS service, and place it behind an Application Load Balancer.
|
||||
- **Google Cloud Run**: Deploy the image as a Cloud Run service with the
|
||||
appropriate environment variables.
|
||||
- **Azure Container Apps**: Deploy the image and configure ingress through
|
||||
the Azure portal or CLI.
|
||||
- **Docker Compose**: Suitable for smaller installations. Run Backstage and
|
||||
PostgreSQL together using a `docker-compose.yaml`.
|
||||
|
||||
Community-contributed deployment guides are available in the
|
||||
[contrib/docs/tutorials](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/)
|
||||
folder of the Backstage repository.
|
||||
|
||||
## Further reading
|
||||
|
||||
For a detailed guide including setting up PostgreSQL in Kubernetes, see
|
||||
the [Deploying with Kubernetes](../../deployment/k8s.md) reference
|
||||
documentation.
|
||||
|
||||
## Next steps
|
||||
|
||||
Your Backstage instance is deployed. Next, let's look at how to manage
|
||||
configuration effectively.
|
||||
|
||||
- [Config-first development](./005-config-first.md)
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
id: config-first
|
||||
sidebar_label: 005 - Configuration management
|
||||
title: Config-first development
|
||||
description: Managing Backstage configuration across environments
|
||||
---
|
||||
|
||||
Audience: Developers and Admins
|
||||
|
||||
## Summary
|
||||
|
||||
One of the things that makes Backstage easier to operate over time is treating
|
||||
configuration as the primary way to control application behavior. Instead of
|
||||
writing custom code for every change, many behaviors can be toggled, adjusted,
|
||||
or extended through configuration files.
|
||||
|
||||
By the end of this page, you will understand how Backstage configuration
|
||||
layering works and how to manage it across environments.
|
||||
|
||||
## How configuration layering works
|
||||
|
||||
Backstage loads configuration from multiple `app-config*.yaml` files and
|
||||
merges them together. Files loaded later override values from earlier files.
|
||||
The Docker image built in the [first step](./001-docker.md) starts with this
|
||||
command:
|
||||
|
||||
```
|
||||
node packages/backend --config app-config.yaml --config app-config.production.yaml
|
||||
```
|
||||
|
||||
This means `app-config.production.yaml` overrides any values set in
|
||||
`app-config.yaml`. You can use this pattern to keep your base config for
|
||||
local development and override only what changes in production.
|
||||
|
||||
### Common configuration split
|
||||
|
||||
| File | Purpose |
|
||||
| :--------------------------- | :------------------------------------------------- |
|
||||
| `app-config.yaml` | Base configuration shared across all environments. |
|
||||
| `app-config.local.yaml` | Local overrides, not committed to source control. |
|
||||
| `app-config.production.yaml` | Production-specific overrides. |
|
||||
|
||||
## Environment variables in config
|
||||
|
||||
Use the `${VAR_NAME}` syntax to reference environment variables. This is
|
||||
the recommended approach for secrets and values that differ between
|
||||
environments:
|
||||
|
||||
```yaml title="app-config.production.yaml"
|
||||
backend:
|
||||
database:
|
||||
client: pg
|
||||
connection:
|
||||
host: ${POSTGRES_HOST}
|
||||
port: ${POSTGRES_PORT}
|
||||
user: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
```
|
||||
|
||||
This keeps secrets out of your repository and lets the same Docker image be
|
||||
used across environments by changing the variables at deploy time.
|
||||
|
||||
## What to configure vs. what to code
|
||||
|
||||
A good rule of thumb: if a change affects _where_ something connects, _how_
|
||||
it authenticates, or _which_ features are enabled, it belongs in configuration.
|
||||
If it changes _what_ a feature does, it belongs in code.
|
||||
|
||||
Examples of config-driven behavior:
|
||||
|
||||
- Database connection details.
|
||||
- Authentication provider selection and credentials.
|
||||
- Catalog locations and entity providers.
|
||||
- Integration tokens (GitHub, GitLab, etc.).
|
||||
- TechDocs storage backend (local, S3, GCS, Azure).
|
||||
- Proxy endpoints for external services.
|
||||
|
||||
Making configuration your primary lever for environment differences simplifies
|
||||
your CI/CD pipeline. You build one Docker image and deploy it everywhere,
|
||||
varying only the config files and environment variables.
|
||||
|
||||
## Further reading
|
||||
|
||||
For the full configuration reference, see the
|
||||
[Configuration documentation](../../conf/index.md).
|
||||
|
||||
## Next steps
|
||||
|
||||
With your deployment running and configuration managed, you should set up
|
||||
monitoring to keep it healthy.
|
||||
|
||||
- [Monitoring your deployment](./006-monitoring.md)
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: monitoring
|
||||
sidebar_label: 006 - Monitoring
|
||||
title: Monitoring your deployment
|
||||
description: Setting up OpenTelemetry and frontend analytics for your Backstage deployment
|
||||
---
|
||||
|
||||
Audience: Admins
|
||||
|
||||
## Summary
|
||||
|
||||
A production Backstage deployment needs monitoring to track health, diagnose
|
||||
issues, and understand usage patterns. Backstage provides built-in support
|
||||
for OpenTelemetry on the backend and an Analytics API on the frontend.
|
||||
|
||||
By the end of this page, you will know how to set up both.
|
||||
|
||||
## Backend monitoring with OpenTelemetry
|
||||
|
||||
Backstage uses [OpenTelemetry](https://opentelemetry.io/) to report metrics
|
||||
and traces. The setup involves installing a few OpenTelemetry packages,
|
||||
creating an instrumentation file, and loading it before the backend starts.
|
||||
|
||||
Follow the [Setup OpenTelemetry tutorial](../../tutorials/setup-opentelemetry.md)
|
||||
for step-by-step instructions on installing dependencies, configuring
|
||||
exporters (Prometheus for metrics, OTLP for traces), and wiring everything
|
||||
into your backend.
|
||||
|
||||
### Key metrics to monitor
|
||||
|
||||
Backstage plugins emit metrics that give you insight into system health:
|
||||
|
||||
- `catalog_entities_count` - Total number of entities in the catalog.
|
||||
- `catalog.processed.entities.count` - Number of entities processed.
|
||||
- `catalog.processing.duration` - Time spent processing entities.
|
||||
- `scaffolder.task.count` - Number of scaffolder tasks run.
|
||||
- `scaffolder.task.duration` - Time taken by scaffolder tasks.
|
||||
|
||||
These metrics help you set up alerts for things like processing backlogs or
|
||||
unusually slow scaffolder runs.
|
||||
|
||||
### Health checks
|
||||
|
||||
Backstage provides built-in health check endpoints that you can use for
|
||||
liveness and readiness probes in Kubernetes or other orchestrators:
|
||||
|
||||
- `/.backstage/health/v1/readiness` - Returns healthy when the backend is
|
||||
ready to serve traffic.
|
||||
- `/.backstage/health/v1/liveness` - Returns healthy when the backend
|
||||
process is alive.
|
||||
|
||||
## Frontend analytics
|
||||
|
||||
Backstage provides an Analytics API for tracking user behavior on the
|
||||
frontend. This is useful for understanding which plugins get the most use
|
||||
and measuring the return on your Backstage investment.
|
||||
|
||||
Several analytics tools are supported through community plugins:
|
||||
|
||||
- Google Analytics 4
|
||||
- New Relic Browser
|
||||
- Matomo
|
||||
|
||||
See the [Analytics documentation](../../frontend-system/building-plugins/08-analytics.md)
|
||||
for setup instructions.
|
||||
|
||||
For frontend error reporting, consider integrating with a service like
|
||||
Sentry, CloudWatch RUM, or Cloudflare RUM to catch and diagnose client-side
|
||||
errors.
|
||||
|
||||
## Logging
|
||||
|
||||
The backend emits structured JSON logs on stdout by default. These logs
|
||||
include fields like `service`, `plugin`, `level`, and `message` that make
|
||||
them easy to parse with log aggregation tools (Elasticsearch, Datadog,
|
||||
Splunk, etc.).
|
||||
|
||||
## Next steps
|
||||
|
||||
As more users adopt your Backstage instance, you may need to scale the
|
||||
deployment.
|
||||
|
||||
- [Scaling your deployment](./007-scaling.md)
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
id: scaling
|
||||
sidebar_label: 007 - Scaling
|
||||
title: Scaling your deployment
|
||||
description: How to scale Backstage as usage grows
|
||||
---
|
||||
|
||||
Audience: Admins
|
||||
|
||||
## Summary
|
||||
|
||||
A single Backstage instance handles many users well, but as your organization
|
||||
grows and more plugins are added, you may need to scale. This page covers the
|
||||
strategies available.
|
||||
|
||||
## Horizontal scaling
|
||||
|
||||
The most straightforward approach is to run multiple identical instances of
|
||||
Backstage behind a load balancer. All instances share the same external
|
||||
database (and optional cache or search services). The backend plugins
|
||||
coordinate through the database to share state and distribute work.
|
||||
|
||||
In Kubernetes, this is as simple as increasing the replica count in your
|
||||
deployment:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
replicas: 3
|
||||
```
|
||||
|
||||
No additional configuration is needed. The database handles coordination
|
||||
between instances.
|
||||
|
||||
## Splitting the backend
|
||||
|
||||
For larger installations, you can break the backend into multiple services,
|
||||
each running a different set of plugins. For example, you might run the
|
||||
catalog and scaffolder as separate deployments so that heavy catalog
|
||||
processing does not affect scaffolder performance.
|
||||
|
||||
This is a more advanced approach that requires:
|
||||
|
||||
- Separate backend packages, each importing only the plugins they need.
|
||||
- A custom `DiscoveryService` implementation that routes requests to the
|
||||
correct backend based on the plugin ID.
|
||||
- Routing both external (ingress) and internal (backend-to-backend) traffic
|
||||
appropriately.
|
||||
|
||||
See the
|
||||
[backend system documentation](../../backend-system/building-backends/01-index.md#split-into-multiple-backends)
|
||||
for details on how to set this up.
|
||||
|
||||
## Separating the frontend
|
||||
|
||||
By default, the frontend is served from your backend deployment using the
|
||||
`@backstage/plugin-app-backend` plugin. If you need to reduce load on the
|
||||
backend or serve the frontend from a CDN for better performance, you can
|
||||
deploy the frontend separately.
|
||||
|
||||
This involves:
|
||||
|
||||
1. Removing the `@backstage/plugin-app-backend` plugin from the backend.
|
||||
2. Building the frontend as a static bundle.
|
||||
3. Serving it from a separate container (for example, NGINX) or a static
|
||||
hosting provider.
|
||||
|
||||
An example NGINX setup is available in the
|
||||
[contrib/docker/frontend-with-nginx](https://github.com/backstage/backstage/blob/master/contrib/docker/frontend-with-nginx)
|
||||
folder.
|
||||
|
||||
:::note
|
||||
|
||||
When serving the frontend separately, configuration is no longer injected by
|
||||
the backend at runtime. You need to provide the correct configuration at
|
||||
frontend build time.
|
||||
|
||||
:::
|
||||
|
||||
## When to scale
|
||||
|
||||
Here are some signals that indicate you should consider scaling:
|
||||
|
||||
- API response times are increasing.
|
||||
- Catalog processing is falling behind (visible in the
|
||||
`catalog.processing.duration` metric).
|
||||
- Scaffolder tasks are queuing for longer than expected.
|
||||
- Users report slow page loads.
|
||||
|
||||
Start with horizontal scaling (more replicas) before considering backend
|
||||
splitting. It is simpler and handles most growth scenarios.
|
||||
|
||||
## Further reading
|
||||
|
||||
For more details on scaling strategies, see the
|
||||
[Scaling Backstage Deployments](../../deployment/scaling.md) reference
|
||||
documentation.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
id: index
|
||||
title: Deploying Backstage to production
|
||||
description: A guided path for deploying your Backstage app to production
|
||||
---
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You have completed the [create-app golden path](../create-app/index.md) and
|
||||
have a working Backstage app.
|
||||
- Your code is pushed to a source control management system (GitHub, GitLab,
|
||||
etc.).
|
||||
- You have a general understanding of how your company builds and deploys
|
||||
software.
|
||||
|
||||
### What should I get out of this guide?
|
||||
|
||||
This guide walks through everything you need to get your Backstage instance
|
||||
running in a production environment. By the end, you will have:
|
||||
|
||||
- A Docker image containing your Backstage app.
|
||||
- A production database (PostgreSQL) connected to your deployment.
|
||||
- A real authentication provider replacing the default guest login.
|
||||
- A running deployment, whether on Kubernetes, ECS, or another platform.
|
||||
- Monitoring and observability set up with OpenTelemetry.
|
||||
- An understanding of how to scale your deployment as usage grows.
|
||||
|
||||
### Structure
|
||||
|
||||
We start with the Docker image since that is the foundation of any deployment.
|
||||
Then we set up the two critical pre-deploy dependencies: a database and
|
||||
authentication. After that, we walk through deploying to Kubernetes and discuss
|
||||
other deployment options. Finally, we cover operational topics like
|
||||
configuration management, monitoring, and scaling.
|
||||
|
||||
### Next steps
|
||||
|
||||
- [Building the Docker image](./001-docker.md)
|
||||
|
||||
Reference in New Issue
Block a user