diff --git a/docs/golden-path/deployment/004-deploying.md b/docs/golden-path/deployment/004-deploying.md index eb900bbcd5..7ef0f4545a 100644 --- a/docs/golden-path/deployment/004-deploying.md +++ b/docs/golden-path/deployment/004-deploying.md @@ -2,185 +2,109 @@ id: deploying sidebar_label: 004 - Deploying title: Deploying to production -description: How to deploy your Backstage instance to Kubernetes and other platforms +description: How to deploy your Backstage instance to production --- 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. +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. Backstage is designed to run as +a stateless Node.js application backed by an external PostgreSQL database, +so it fits into most existing deployment pipelines without special tooling. -## Deploying to Kubernetes +This page describes what every Backstage deployment needs, regardless of +platform, and points to the reference guides for specific targets. -Kubernetes is the most common deployment target for Backstage. The deployment -involves a few Kubernetes objects: a namespace, secrets, a deployment, and a -service. +## What every deployment needs -### 1. Create a namespace +Whichever platform you choose, the deployment will need to take care of the +following concerns: -```yaml -# kubernetes/namespace.yaml -apiVersion: v1 -kind: Namespace -metadata: - name: backstage -``` +- **A container image** built from your repository and pushed to a registry + your runtime can pull from. The image you built in + [Building the Docker image](./001-docker.md) is the artifact that gets + deployed. +- **Configuration and secrets** delivered to the running container as + environment variables or mounted files. This includes database + credentials, auth provider client secrets, and any integration tokens. +- **A reachable PostgreSQL database** that the running instance can connect + to using the credentials from the previous step. See + [Configuring the database](./002-database.md) for details. +- **A network entry point** — typically an ingress, load balancer, or + reverse proxy — that exposes the backend on port `7007` to your users + over HTTPS. +- **A health-checked runtime** that can restart the container if it stops + responding and roll out new versions when you publish a new image. +- **`app.baseUrl` and `backend.baseUrl`** in your + `app-config.production.yaml` set to the public URL where users will + access Backstage. Auth providers and the frontend rely on these matching + the actual entry point: -```shell -kubectl apply -f kubernetes/namespace.yaml -``` + ```yaml title="app-config.production.yaml" + app: + baseUrl: https://backstage.example.com + backend: + baseUrl: https://backstage.example.com + listen: + port: 7007 + ``` -### 2. Create secrets +## Choosing a deployment target -Store your database credentials and any other secrets (API tokens, auth -client secrets) as Kubernetes Secrets: +Backstage runs anywhere a Node.js container can run. Pick the option that +matches what your organization already operates — you do not need to adopt +new infrastructure to run Backstage. -```yaml -# kubernetes/backstage-secrets.yaml -apiVersion: v1 -kind: Secret -metadata: - name: backstage-secrets - namespace: backstage -type: Opaque -data: - POSTGRES_USER: - POSTGRES_PASSWORD: -``` +| Target | Good fit when... | +| :----------------------- | :---------------------------------------------------------------------- | +| Kubernetes | Your organization already runs services on Kubernetes. | +| Amazon ECS / Fargate | You are on AWS and prefer managed container scheduling. | +| Google Cloud Run | You want a fully managed, request-driven container runtime on GCP. | +| Azure Container Apps | You are on Azure and want a managed container platform. | +| A traditional VM or PaaS | You prefer running the Node.js process directly behind a reverse proxy. | +| Docker Compose | You are running a small installation or proof of concept. | -:::note +Backstage maintains a reference guide for the Kubernetes path in +[Deploying with Kubernetes](../../deployment/k8s.md), which walks through +namespaces, secrets, the deployment, the service, and connecting to +PostgreSQL inside the cluster. -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. +For other platforms, the +[community-contributed deployment guides](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/) +in the Backstage repository cover targets such as ECS, Cloud Run, and +Docker Compose, and the [deployment overview](../../deployment/index.md) +explains the underlying model that all of these guides share. -::: +## Operational concerns -```shell -kubectl apply -f kubernetes/backstage-secrets.yaml -``` +A few operational details apply to every deployment and are worth getting +right before opening Backstage up to your users: -### 3. Create the deployment +- **Run multiple replicas** behind your load balancer. Backstage is + stateless, so multiple instances can serve traffic against the same + PostgreSQL database. We cover this further in + [Scaling Backstage](./007-scaling.md). +- **Store secrets securely.** Container platforms typically offer a + secrets primitive — Kubernetes Secrets, AWS Secrets Manager, GCP Secret + Manager, Azure Key Vault, and so on. Reference these from your + configuration with environment variables rather than committing + credentials. +- **Enable health checks.** Wire your platform's readiness and liveness + probes to the Backstage health endpoints so unhealthy instances are + taken out of rotation and restarted automatically. +- **Run behind HTTPS.** Terminate TLS at your ingress, load balancer, or + reverse proxy and make sure the public URL is what `app.baseUrl` and + `backend.baseUrl` are set to. -```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: /backstage: - 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 `/backstage:` 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. +If you need to run Backstage behind a corporate proxy, see the +[corporate proxy guide](../../tutorials/corporate-proxy.md). ## Next steps Your Backstage instance is deployed. Next, let's look at how to manage -configuration effectively. +configuration effectively across environments. - [Config-first development](./005-config-first.md)