Hashicorp Terraform logo

Backstage Hashicorp Terraform Plugin

Created by GlobalLogic UK&I

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

Copy
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

Copy
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

Copy
<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

Copy
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

Copy
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

Copy
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

Copy
# 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

Copy
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

Copy
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

Copy
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

Copy
# backend config omitted for brevity

terraform:
  apiBaseUrl: https://app.terraform.io
  token:
    $env: TERRAFORM_TOKEN

Set the env var before you run the backend

Copy
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 old terraform/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