Powerful Backstage Templates | An EKS & Terraform Example

Introduction

Hey there, folks! Today, we’re diving deep into the world of Backstage Software Templates. If you’ve ever struggled with setting up new projects, you’re gonna love this. Stick around, and you’ll learn how to save time and keep your codebase consistent. Not only that, you’ll see how to run a GitHub Actions pipeline to generate an EKS cluster via Terraform all from a Backstage Software Template.

Video

Below is a video explanation and demo.

Video Chapters

You can skip to the relevant chapters below:

  • 00:00 – Intro with Animation

  • 05:29 – Demo Starts

  • 09:18 – Detailed Explanation

  • 18:18 – EKS Cluster Created

  • 19:58 – Final Remarks

Code

Join the Newsletter and get FREE access to the Source Code

Understanding Backstage Software Templates

Backstage software templates are the lifeblood of software projects. Imagine not having to reinvent the wheel every time you start something new. That’s what these templates are here for. They’re customizable, reusable, and incredibly handy. You can now as a Platform Engineer, enable your developers to scaffold new applications while maintaining governance. So let’s unpack what this all means. What is Backstage.io?

Before diving into the specifics of software templates, it’s essential to understand what Backstage is. Developed by Spotify and open-sourced for the broader community, Backstage serves as a developer portal that provides a unified view of all your software documentation, resources, and tooling. It’s a one-stop shop that helps you manage, monitor, and document your software ecosystem, reducing cognitive load and speeding up development.

Key Features of Backstage Software Templates

  1. Standardization
    Software templates allow for the standardization of the code base across multiple projects. By using templates, you can ensure that every project follows best practices, reducing code smells and maintenance costs in the long term.
  2. Extensibility
    Backstage is designed to be extensible. This philosophy extends to its software templates, which can be customized to fit your organization’s unique needs.
  3. Version ControlTemplates in Backstage are version-controlled, meaning that teams can adopt new changes progressively without affecting existing projects.
  4. Multi-step Templating

Backstage supports multi-step templating, allowing you to use different tools and templating languages in your workflow. This ensures that your template can be as simple or as complex as necessary.

  • Parameterization

Software templates support parameterization, allowing developers to input specific variables during the creation process, like service names, paths, or any other custom metadata.

  • Automatic CI/CD Integration

Backstage seamlessly integrates with various CI/CD solutions, making it possible to automate the entire software delivery process, right from template instantiation.

Core Components of Software Templates

So you’re amped up about Backstage Software Templates. But what makes a template tick? That’s what we’re going to look into in this section. Grab a coffee or your beverage of choice, and let’s go.

Template Metadata: What Is It and Why Does It Matter?

What is Template Metadata?

First off, let’s get into template metadata. Think of it like your template’s DNA or its blueprint. It’s the set of data that outlines what your template is about, what it does, and how it should behave. In Backstage, this is typically configured in a YAML file. Here you specify everything from the template title to service parameters and more.

The Importance of Metadata

Now, why is this so critical? For starters, metadata dictates the template’s behavior in your software catalog. It specifies component metadata such as the service type, ownership, and lifecycle stage, among others. This is crucial for searchability, organization, and governance of your templates within Backstage.

Software Components in Backstage

Understanding Software Components

Alright, next on our list: software components. If metadata is the blueprint, software components are the bricks and mortar of your projects. In Backstage, a software component can be anything from a microservice, a data pipeline, or even a library.

How They Fit in a Template

Software components are usually defined within the template metadata, and they become the primary units that the template will create or modify. You specify these in your YAML file under name properties or core type, depending on what exactly you’re setting up.

The Role of Components in Software Projects

These components are the modular pieces that will make up your entire application or service. They are pivotal in maintaining a consistent architecture across different projects. Also, by defining these in your templates, you ensure that new projects or services spun off from these templates follow the same best practices and architectural guidelines.

Template Input: Making Your Templates Dynamic

Let’s see how to enable our developers to use template inputs.

Form Input Parameters: Let the User Choose!

What Are Form Input Parameters?

Form input parameters, or what you might call ‘plain input,’ are the questions your template asks when someone wants to create a new component or service. Whether it’s the service name, the GitHub username, or even custom fields like environment variables, form input parameters let the user customize the new project to their liking.

Why do They Matter?

Imagine this: You want to create a new microservice, and the template asks you about the scale, the tech stack, and other essentials. These form input parameters then translate into template variables that your template uses to create a personalized instance. Pretty cool, huh?

Template Variables: The Building Blocks of Dynamism

What Are They?

Template variables are, in essence, the placeholders in your template. They get replaced by the actual values that the user inputs. These variables could be anything from the repository location type to log input settings. They’re your tool for making each new project or component uniquely configured.

Where to Define Them?

These variables are generally defined in your YAML file within the template metadata. When the template runs, these variables get populated with the real deal, based on user input or other dynamic sources.

Leveraging Template Variables for Greater Flexibility

The real magic happens when you leverage these template variables across multiple aspects of your software projects. Need to link a new component to an existing repository? Use a template variable for the repo URL. Want to have conditional pull request logic based on the tech stack chosen? Template variables are your best friend here too.

Demo: Building a Nodejs App using Backstage Template

This is where the rubber meets the road, folks. We’re going to build an EKS cluster using Terraform and Terraform Cloud. And guess what? We’re triggering all this with a GitHub Action. The best part is that developers can get this all by filling out the form generated by our template. No need for them to learn Terraform.

Setting Up the Environment

First things first, let’s see the usage from a developer’s perspective. Fire up your Backstage app. Click on Create and you’ll be greeted with various templates you’ve got set up. We’re interested in a specific one that spins up a Node.js app and an AWS EKS cluster using Terraform. Hit that Choose button to get started.

Choosing the Template

Filling Out the Form

It’s just a simple form to get your app running.

  • Name your app (node-app-eks for example).
  • Choose a repo location and name it the same as your app (node-app-eks).
  • Provide your cluster details such as cluster name (my-new-eks-cluster) and AWS region.
Filling Out the Form

Behind the Scenes

After you hit Create, Backstage does all the magic for you. You’ll get:

  • A new GitHub repository with essential files (index.js, package.json, and catalog-info.yaml).
  • A running GitHub Actions workflow that sets up your EKS cluster.

Checking the Status

Go back to your Backstage UI, you’ll see your new app or component listed there. For curious minds, you can even see the status of your EKS cluster being set up in real-time.

GitHub Actions Status in The Backstage UI CI/CD Tab

Monitoring the Build Process

From a platform engineer’s perspective, you can also check the GitHub Actions and Terraform Cloud to see how things are progressing.

GitHub Actions Running
Terraform Cloud Run

Deep Dive into the Template Configuration

For those geeking out on how all of this is set up, take a look at the template.yaml file in your Backstage repo. It’s a Kubernetes-like manifest that sets the steps for what happens when you create a new app. Let’s break it up into bite size pieces.

The Metadata: Meet Your Template

metadata:
  name: eks-cluster
  title: Node.js App on AWS EKS Cluster
  description: Deploy a Node.js App on AWS EKS Cluster using Terraform

This is the template metadata. You got your name, title, and description all laid out. It’s the “Hey, look at me! Here’s what I can do!” part of your template.

User’s Choices: The Template Input

parameters:
  - title: Fill in some steps
    required:
      - name
    properties:
      name:
        title: App Name
        type: string
  # ...other parameters

Here’s where input for our template gets real. The user has to fill in a couple of details. The first one is the app name.

More Template Input: Choose Your Adventure

- title: Choose a Repo location
  required:
    - repoUrl
  properties:
    repoUrl:
      title: Repository Location
      type: string
      ui:field: RepoUrlPicker
      ui:options:
        allowedHosts:
          - github.com

Setting the repository location is crucial. Are you using GitHub input or some other repository? No worries, we’ll specify all this here.

Basic EKS Cluster Configuration: Tailor It to Your Needs

- title: Basic EKS Cluster Configuration
  required:
    - clusterName
    - region
    - action
  properties:
    clusterName:
      title: Cluster Name
      type: string
  # ...other properties

You’re not just launching an EKS cluster. You’re customizing that bad boy. You got form input parameters for the cluster name, AWS region, and actions like apply or destroy.

The Steps: Doing the Actual Work

steps:
  - id: fetch-base
    name: Fetch Base
    action: fetch:template
    input:
      url: ./content
      values:
        name: ${{ parameters.name }}
  # ...other steps

This is where the magic happens. These are scaffolder backend steps, also known as template actions, that fetch templates, publish to GitHub, and even trigger GitHub actions.

Output: What You Get in the End

output:
  links:
    - title: Repository
      url: ${{ steps['publish'].output.remoteUrl }}
    - title: Open in catalog
      icon: catalog
      entityRef: ${{ steps['register'].output.entityRef }}

After all the magic is done, what do you get? A created repository, a new component registered in your catalog, and a new shiny EKS cluster. Pretty slick. Now let’s bring everything together with our demo.

Below is the complete template.yaml file for you:

# Define the API version and kind of resource
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
# Template metadata. Here's your intro to what this template does.
metadata:
  name: eks-cluster
  title: Node.js App on AWS EKS Cluster
  description: Deploy a Node.js App on AWS EKS Cluster using Terraform
# The specification for how the template behaves
spec:
  # Who owns this template. Generally, it could be a team or individual
  owner: user:guest
  # The type of service this template deploys
  type: service
  # User-input parameters. Makes your templates dynamic!
  parameters:
    # Ask the user to input some basic app details
    - title: Fill in some steps
      required:
        - name
      properties:
        name:
          title: App Name
          type: string
          description: Unique name for your app
          ui:autofocus: true  # This field gets auto-focused in UI
          ui:options:
            rows: 5  # Number of rows in the input area
    # Ask the user where they want to store the code
    - title: Choose a Repo location
      required:
        - repoUrl
      properties:
        repoUrl:
          title: Repository Location
          type: string
          ui:field: RepoUrlPicker  # A special UI component for selecting repo URLs
          ui:options:
            allowedHosts:
              - github.com  # Allowed hosts for repository
    # Parameters for setting up the EKS cluster
    - title: Basic EKS Cluster Configuration
      required:
        - clusterName
        - region
        - action
      properties:
        clusterName:
          title: Cluster Name
          type: string
          description: The name of your EKS cluster
          ui:autofocus: true
        region:
          title: AWS Region
          type: string
          description: The AWS region where the cluster will be deployed
          enum:
            - us-east-1
            - us-west-2
        action:
          title: Action
          type: string
          description: Action to perform (apply/destroy)
          enum:
            - apply
            - destroy
  # Steps that the template will execute in order
  steps:
    # Fetch the base template
    - id: fetch-base
      name: Fetch Base
      action: fetch:template
      input:
        url: ./content  # Where the base content is stored
        values:
          name: ${{ parameters.name }}
    # Publish the code to a GitHub repo
    - id: publish
      name: Publish
      action: publish:github
      input:
        allowedHosts: ['github.com']
        description: This is ${{ parameters.name }}
        repoUrl: ${{ parameters.repoUrl }}
    # Trigger a GitHub Action to set up the EKS cluster
    - id: github-action
      name: Trigger GitHub Action
      action: github:actions:dispatch
      input:
        workflowId: manage-eks-cluster.yml  # GitHub Action workflow ID
        repoUrl: 'github.com?repo=aws-eks&owner=samgabrail'
        branchOrTagName: 'main'  # The branch to run this action on
        workflowInputs:
          clusterName: ${{ parameters.clusterName }}
          awsRegion: ${{ parameters.region }}
          action: ${{ parameters.action }}
    # Register the new component in the Backstage catalog
    - id: register
      name: Register
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
        catalogInfoPath: '/catalog-info.yaml'  # Where the catalog info is stored
  # Output links to the user after the template execution
  output:
    links:
      - title: Repository
        url: ${{ steps['publish'].output.remoteUrl }}
      - title: Open in catalog
        icon: catalog
        entityRef: ${{ steps['register'].output.entityRef }}

The GitHub Actions Pipeline

How about we take a closer look at the GitHub Actions Pipeline? Notice that the Trigger GitHub Action step dispatches a GitHub action in a different repo. This is a repo that the Platform Engineering team would set up. It’s where the Terraform code to stand up our EKS cluster is defined along with the GitHub Action pipeline. Below is the GitHub Action pipeline file called manage-eks-cluster.yml.

# Define the name of the GitHub Action workflow
name: Manage EKS Cluster
# This workflow is manually triggered using the GitHub Actions UI
on:
  workflow_dispatch:
    # Define inputs that are required for the manual trigger
    inputs:
      clusterName:
        description: 'Name of the EKS cluster'  # What's this input for?
        required: true  # Is it optional or required?
      awsRegion:
        description: 'AWS Region for the cluster'
        required: true
      action:
        description: 'Action to perform (apply/destroy)'
        required: true
# Define jobs to be executed in this workflow
jobs:
  # Job for applying (creating or updating) the EKS cluster
  apply_cluster:
    # Use the latest Ubuntu runner
    runs-on: ubuntu-latest
    
    # Only run this job if the action input is "apply"
    if: ${{ github.event.inputs.action == 'apply' }}
    # Define the steps for this job
    steps:
    
    # Step to checkout the code from the repository
    - name: Checkout code
      uses: actions/checkout@v2
      
    # Step to setup Terraform CLI
    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}  # GitHub secret for Terraform Cloud API token
      
    # Initialize Terraform (downloads providers, etc.)
    - name: Terraform Init
      run: terraform init
      working-directory: Terraform  # Where should this command be run?
      
    # Step to format Terraform code, ensures it's neat
    - name: Terraform Format
      run: terraform fmt
      working-directory: Terraform
      
    # Step to validate the Terraform code (syntax, values, etc.)
    - name: Terraform Validate
      run: terraform validate
      working-directory: Terraform
      
    # Step to apply the Terraform plan
    - name: Terraform Apply
      run: terraform apply -var clusterName=${{ github.event.inputs.clusterName }} -var awsRegion=${{ github.event.inputs.awsRegion }} -auto-approve
      working-directory: Terraform

  # Job for destroying the EKS cluster
  destroy_cluster:
    runs-on: ubuntu-latest
    
    # Only run this job if the action input is "destroy"
    if: ${{ github.event.inputs.action == 'destroy' }}
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
      
    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1
      with:
        cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}
        
    - name: Terraform Init
      run: terraform init
      working-directory: Terraform
      
    - name: Terraform FMT
      run: terraform fmt
      working-directory: Terraform
      
    - name: Terraform Validate
      run: terraform validate
      working-directory: Terraform
      
    # Step to destroy all resources defined in Terraform
    - name: Terraform Destroy
      run: terraform destroy -var clusterName=${{ github.event.inputs.clusterName }} -var awsRegion=${{ github.event.inputs.awsRegion }} -auto-approve
      working-directory: Terraform

Wrapping Up

Looks like our EKS cluster is up and ready! It took roughly 24 minutes, but imagine the time saved compared to manually setting this up or going through a ticketing system.

Backstage Output

This is what the developers will see in the Backstage UI without the need to go to Terraform Cloud or GitHub Actions.

GitHub Actions Job Complete in Backstage
EKS Cluster Output in Backstage

Terraform Cloud Output

This is the view that the Platform Engineers would look at in Terraform Cloud.

EKS Cluster Created

Conclusion

Alright, peeps, that wraps up our walkthrough on leveraging Backstage Software Templates in the realm of Platform Engineering. If you weren’t a believer before, I hope you are now. These templates are not just bells and whistles; they’re the unsung heroes that can supercharge your platform engineering efforts.

Think about it—less boilerplate code, more consistency, and way fewer headaches. That’s what Backstage Software Templates bring to the table. They’re your express ticket to a well-architected, easy-to-navigate platform that makes life a heck of a lot easier for everyone involved.

If you’re thirsty for more, you know where to find us. We’ve got video tutorials to walk you through the how-tos, and our TeKanAid Academy courses are always there to take your learning to the next level.

So, don’t sit on the sidelines. Jump in and get your hands dirty with Backstage Software Templates. Trust me, your future self will thank you. 🚀

Additional Resources

Before you go, check out these resources for further learning. From more blog posts to in-depth courses and YouTube videos, we’ve got you covered.

Scroll to Top