HashiCorp Terraform is an infrastructure as code tool. You define cloud and SaaS resources in simple files. You use one workflow to plan and apply changes across providers. It helps teams manage infra safely and repeatably at scale.
This Backstage plugin brings Terraform Cloud or Enterprise signals into your service catalog. It shows recent runs for one or more workspaces for the entity you are viewing. You can see run status and logs without leaving Backstage. It includes a Latest Run card for quick checks. It also offers a Workspace Health view with drift metrics and validation checks. When you need more detail, links take you to the matching view in Terraform.Common use cases are straightforward. Check whether the last plan or apply succeeded while you review a service. Troubleshoot a failed run with logs next to code and docs. Track drift and validation across environments so teams spot risk sooner. Give service owners visibility into infra activity without handing over full Terraform access. The project is active and kept current, which makes it a practical addition for a self hosted Backstage stack.
If you already rely on Terraform Cloud or Enterprise, this plugin helps reduce context switching. It puts the facts you need in the same place you manage services.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the packages
cd packages/app
yarn add @globallogicuki/backstage-plugin-terraform
cd ../backend
yarn add @globallogicuki/backstage-plugin-terraform-backend
Frontend setup
Import the components
Open packages/app/src/components/catalog/EntityPage.tsx
Add the imports
import {
EntityTerraformContent,
EntityTerraformCard,
EntityTerraformLatestRunCard,
EntityTerraformWorkspaceHealthAssessmentsCard,
TerraformWorkspaceHealthAssessments,
isTerraformAvailable,
} from '@globallogicuki/backstage-plugin-terraform';
Add a Terraform tab on the entity page
Place this inside your EntityLayout for services or components so it shows as its own tab
<EntityLayout.Route path="/terraform" title="Terraform">
<EntityTerraformContent />
</EntityLayout.Route>
Optional add cards to the Overview tab
You can show summary cards on the main Overview tab. Wrap them in the availability helper
import { EntitySwitch, EntityLayout } from '@backstage/plugin-catalog';
import { Grid } from '@material-ui/core';
<EntityLayout.Route path="/" title="Overview">
<Grid container spacing={3}>
<EntitySwitch>
<EntitySwitch.Case if={isTerraformAvailable}>
<Grid item xs={12} md={6}>
<EntityTerraformCard />
</Grid>
<Grid item xs={12} md={6}>
<EntityTerraformLatestRunCard />
</Grid>
<Grid item xs={12}>
<EntityTerraformWorkspaceHealthAssessmentsCard />
</Grid>
{/* Or embed the inner workspace health component directly */}
<Grid item xs={12}>
<TerraformWorkspaceHealthAssessments
showDrift={true}
showValidationChecks={true}
/>
</Grid>
</EntitySwitch.Case>
</EntitySwitch>
</Grid>
</EntityLayout.Route>
Entity annotations
Add these annotations to each entity that should show Terraform data. You can set one or more workspaces as a comma separated list
metadata:
annotations:
terraform/organization: yourOrg
terraform/workspaces: workspaceOne,workspaceTwo
Backend setup new backend system
Use this when your backend uses createBackend from the new backend system
Edit packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// core plugins
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-catalog-backend'));
// terraform backend plugin
backend.add(import('@globallogicuki/backstage-plugin-terraform-backend'));
backend.start();
If your app splits backend modules across separate files, add the terraform backend import in the same place where you add other backend modules
Backend config
Provide a Terraform Cloud or Terraform Enterprise API token to the backend. Set it with an env var then read it in app config
app-config.yaml
# backend config omitted for brevity
# example plugin config
terraform:
apiBaseUrl: https://app.terraform.io
token:
$env: TERRAFORM_TOKEN
Set the env var when running the backend
export TERRAFORM_TOKEN=replace_with_your_token
yarn start-backend
Backend setup legacy backend system
Use this when your backend still uses the old ServiceBuilder pattern
Create a plugin router file
packages/backend/src/plugins/terraform.ts
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@globallogicuki/backstage-plugin-terraform-backend';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
identity: env.identity,
httpAuth: env.httpAuth,
});
}
Wire it in the backend index
packages/backend/src/index.ts
import terraform from './plugins/terraform';
// inside the main async function where you set up routers
const terraformEnv = useHotMemoize(module, () => createEnv('terraform'));
const terraformRouter = await terraform(terraformEnv);
// mount under the api path
apiRouter.use('/terraform', terraformRouter);
Add plugin config
app-config.yaml
# backend config omitted for brevity
terraform:
apiBaseUrl: https://app.terraform.io
token:
$env: TERRAFORM_TOKEN
Set the env var before you run the backend
export TERRAFORM_TOKEN=replace_with_your_token
yarn start
Version notes
Keep the frontend and backend packages for this plugin on compatible versions. If you upgrade one, upgrade the other in the same change
Summary of what you should now have
- Frontend package installed in packages app
- Backend package installed in packages backend
- Terraform tab added to EntityPage
- Optional cards added to the Overview tab
- Entity annotations set for organization and workspaces
- Backend plugin registered
- Backend config providing a Terraform API token
Changelog
This changelog is produced from commits made to the Hashicorp Terraform plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.
Breaking changes
- Rename the annotation to
terraform/workspaces
. The oldterraform/workspace
no longer works. Update your catalog files. #52 merged 12 months ago
Features
- Allow multiple workspaces via the
terraform/workspaces
annotation. Use a comma separated list. Backend fetches runs for those workspaces in the org. DenseTable and TerraformLatestRun show all specified workspaces. #52 merged 12 months ago - Add workspace health cards. Show overall health with separate views for drift and validation checks. #86 merged 5 months ago
- Add a contextual link on health cards to open the workspace in Terraform. #94 merged 4 months ago
UI
- Use the Backstage theme palette for chip colors in DenseTable and TerraformLatestRun content. #99 merged 4 months ago
Bug fixes
- Add pluginId to plugins to fix the prepack error during publish. #54 merged 12 months ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.