Quickstart
In this guide, you will learn how to get started with Terramate from scratch by building a basic Terramate project that manages Terraform or OpenTofu in stacks using the most essential Terramate features, such as stacks, code generation, orchestration, and change detection.
Terramate Community Discord Server
Join the Terramate Community on Discord, the best place to ask questions and get answers about Terramate and its ecosystem. Come aboard ⛵️🏴☠️
Introduction
For a quick example of how Terramate works, this guide takes you through the following steps:
- Creating a new Terramate project.
- Adding stacks using Terramate CLI.
- Generating a Terraform local backend configuration in all stacks using code generation.
- Orchestrating commands such as
terraform plan
andterraform apply
using orchestration and change detection. - Syncing all stacks to Terramate Cloud.
Prerequisites
To start using Terramate, let's quickly run through some steps to ensure the correct setup of your environment.
Install Terramate
brew install terramate
# Add the Terramate repo to your sources
echo "deb [trusted=yes] https://repo.terramate.io/apt/ /" \
| sudo tee /etc/apt/sources.list.d/terramate.list
apt update
apt install terramate
# Add the Terramate repo to your sources
sudo tee /etc/yum.repos.d/terramate.repo <<EOF
[terramate]
name=Terramate Repository
baseurl=https://repo.terramate.io/yum/
enabled=1
gpgcheck=0
EOF
dnf install terramate
# Download the binary from
https://github.com/terramate-io/terramate/releases
Other installation options are available. When the installation is complete, you can test it out by reading the current version:
$ terramate version
Install Terraform or OpenTofu
Next, install Terraform or OpenTofu:
Create a new project
Terramate requires a git repository, and every git repository is a project in Terramate.
Let's create a new repository terramate-quickstart
to set up your first Terramate project.
$ git init -b main terramate-quickstart
$ cd terramate-quickstart
New git repositories are empty per default and don't contain any commits. The change detection in Terramate works by detecting changes between at least two commits. Let's add an initial, empty commit to the repository:
$ git commit --allow-empty -m "Initial empty commit"
Create stacks
Now that the repository is ready, you can create your first stack. Stacks in Terramate are a collection of infrastructure resources that you configure, provision, and manage as a unit.
We will give the stack an optional name
and description
upon creation to track the purpose and details of a stack.
Terramate will ensure that on creation, each stack gets an id
set automatically if not defined by the user.
$ terramate create \
--name "Alice" \
--description "Alice's first stack" \
stacks/alice
The terramate create
command creates a file stack.tm.hcl
containing a stack {}
block to configure the stack, which will look something like this.
$ cat stacks/alice/stack.tm.hcl
stack {
name = "Alice"
description = "Alice's first stack"
id = "5b33e1c4-a3b0-477d-b0f1-add5918f764d"
}
How does Terramate detect stacks?
Stacks in Terramate are identified by a directory that includes a *.tm.hcl
file, which contains a stack {}
block. The file can have any name but the terramate create command always creates a file named stack.tm.hcl
Next, let's check in our newly created stack to the repository:
$ git add stacks/alice/stack.tm.hcl
$ git commit -m "Create a first stack with Terramate"
To verify that Terramate is aware of the new stack, you can run terramate list
, which returns a list of all stacks available in your project.
$ terramate list
stacks/alice
To create a second stack, we follow the same commands. First, we create the stack:
$ terramate create \
--name "Bob" \
--description "Bob's first stack" \
stacks/bob
Next, we add the second stack to our repository:
$ git add stacks/bob/stack.tm.hcl
$ git commit -m "Create a second stack with Terramate"
To verify that Terramate is aware of both stacks, we can run terramate list
again.
$ terramate list
stacks/alice
stacks/bob
Change detection in action
Since we created our stacks step by step and created a git commit per stack, we can leverage change detection to see what changes we introduced in our latest commit.
$ terramate list --changed
stacks/bob
By running the command mentioned above, you will see only the second stack is listed now, as we newly introduced the second stack without changing the first stack. Terramate’s change detection is based on a Git integration but also supports more integrations like Terraform to detect affected stacks using a local Terraform Module that has been updated outside of the stack.
Code generation
Empty stacks are of not much use. One of Terramate’s primary use cases is orchestrating IaC tools such as Terraform and generating code for it - but Terramate is not limited to Terraform and can also be used with other tooling such as OpenTofu, Terragrunt, Kubernetes, Helm, CloudFormation, etc.
Every Terraform stack will need a backend configuration. For the sake of this guide, we will use the Terraform local backend.
To generate backend code we create a file called stacks/backend.tm.hcl
:
$ cat <<EOF >stacks/backend.tm.hcl
generate_hcl "backend.tf" {
content {
terraform {
backend "local" {}
}
}
}
EOF
$ cat <<EOF >stacks/backend.tm.hcl
generate_hcl "backend.tf" {
content {
terraform {
backend "local" {}
}
}
}
EOF
This configures Terramate to generate a backend.tf
file in every stack it can reach within the stacks/
directory. In this case, it applies to our alice
and bob
stacks.
To trigger the code generation we need to run the terramate generate
command:
$ terramate generate
Code generation report
Successes:
- /stacks/alice
[+] backend.tf
- /stacks/bob
[+] backend.tf
Hint: '+', '~' and '-' mean the file was created, changed and deleted, respectively.
The generation report will report any changes in the generated code.
Let’s commit the changes and generated code:
$ git add stacks
$ git commit -m 'Add a backend configuration to all stacks'
TIP
It's a recommended best practice to check in generated code to your repository. For details, please see code generation best practices.
Orchestration in action
The stacks created in the previous sections represent isolated environments, often referred to as "root modules" in Terraform and OpenTofu. To make them functional, we must run terraform init
or tofu init
in both. Terramate allows you to orchestrate any command in stacks using the terramate run command.
But before we can start, we need to prepare git to ignore temporary Terraform files by adding a .gitignore
file, which is located in the root directory of our repository:
# NOTE:
# You might not want to add state and lock file here
# This is just convenient when running the quickstart guide
$ cat <<EOF >.gitignore
.terraform
.terraform.lock.hcl
*.tfstate
terraform.tfstate
terraform.tfstate.backup
*.tfplan
EOF
$ git add .gitignore
$ git commit -m 'Add .gitignore'
Now let’s initialize our stacks:
$ terramate run terraform init
$ terramate run tofu init
And run a Terraform plan:
$ terramate run terraform plan
$ terramate run tofu plan
Add Terraform resources
In this section, we create a Terraform null resource for demonstration. Null Resources do not need to configure any cloud credentials as they do not create real resources but only virtual ones.
This example will show:
- You can use plain Terraform config in any stack without using code generation.
- Running only on changed stacks can save us time running and reviewing.
$ cat <<EOF >stacks/bob/null.tf
resource "null_resource" "quickstart" {
}
EOF
$ git add stacks/bob/null.tf
$ git commit -m "Add a null resource"
$ cat <<EOF >stacks/bob/null.tf
resource "null_resource" "quickstart" {
}
EOF
$ git add stacks/bob/null.tf
$ git commit -m "Add a null resource"
To apply the changes, re-initialize Terraform and run terraform apply
in the updated stacks. As we only added the resource to the bob
stack, we can leverage change detection to run in the changed stack only.
Running commands only in stacks containing changes allows us to keep execution run times fast and blast radius small.
Re-initialize Terraform to download the null provider:
$ terramate run --changed terraform init
$ terramate run --changed tofu init
Preview a plan:
terramate run --changed terraform plan
terramate run --changed tofu plan
After reviewing the plan, we can apply the changes:
terramate run --changed terraform apply -auto-approve
terramate run --changed tofu apply -auto-approve
When running the terraform plan
again, we expect no changes to be planned anymore:
terramate run --changed terraform plan
terramate run --changed tofu plan
Connecting Terramate Cloud
Now that you have created your first Terramate project, let's connect it to Terramate Cloud and learn how we can enable observability, CI/CD, drift detection, and more! Terramate CLI and Terramate Cloud work in tandem to deliver a reliable experience. Terramate Cloud is free for individual use, with features available for teams.
Create a cloud account
To start using the cloud, you need to sign up for a free cloud account and create an organization.
- Sign in and Sign up to cloud.terramate.io and
- Create your Organization. You can edit GitHub Trust settings to establish a trust relationship with GitHub Actions, which is required to sync data from GitHub, and specify whether to sync the entire organization or a specific repository with Terramate Cloud. Similarly, GitLab Trust settings can be configured to sync data from GitLab.
Remember the organization's short name that you set for accessing the organization on Terramate Cloud to configure your Terramate CLI in the next steps.
Configure your repository
Configure your Terramate project to sync data to your Terramate Cloud organization after creating it.
$ cat <<EOF >terramate.tm.hcl
terramate {
config {
cloud {
organization = "organization-short-name" # TODO: fill in your org short name
}
}
}
EOF
$ git add terramate.tm.hcl
$ git commit -m "Add Terramate Cloud configuration"
Create a GitHub repository
Terramate Cloud requires a GitHub, GitLab, or BitBucket repository to work properly. We will use GitHub in this guide. Let's start by creating a new repository in your personal GitHub account or an organization. We'll name the repository terramate-quickstart
and create it as a private repository.
Once the repository is created on GitHub, you can add it to your local repository and push your data to GitHub. Don't forget to replace your-account
with your GitHub account or organization handle.
$ git remote add origin git@github.com:your-account/terramate-quickstart.git
$ git branch -M main
$ git push -u origin main
Login from CLI
To synchronize data from your local machine, you will need to login
to Terramate Cloud from the CLI. Terramate CLI will store a session on your machine after a successful login.
Use the following command to initiate the login.
$ terramate cloud login
If you want to login with GitHub instead, use:
$ terramate cloud login --github
Sync stacks to Terramate Cloud
After setting up your GitHub repository and Terramate Cloud organization, let's sync the stacks configured in our Terramate project to Terramate Cloud. The easiest to sync your stacks is to run a drift detection workflow in all stacks and sync the result to Terramate Cloud:
$ terramate run \
--sync-drift-status \
--terraform-plan-file=drift.tfplan \
--continue-on-error \
-- \
terraform plan -detailed-exitcode -out drift.tfplan
$ terramate run \
--sync-drift-status \
--tofu-plan-file=drift.tfplan \
--continue-on-error \
-- \
tofu plan -detailed-exitcode -out drift.tfplan
In a nutshell, the command above runs a terraform plan
or tofu plan
in all your stacks and sends the result to Terramate Cloud. Since the plans don't detect any changes, Terramate Cloud won't mark those stacks as drifted but only adds them to your inventory of stacks.
Trigger a deployment
As a final step of this guide, we will change one of our stacks and trigger a new deployment. For that, let's add another null resource to our bob
stack.
$ cat <<EOF >>stacks/bob/null.tf
resource "null_resource" "quickstart2" {
}
EOF
$ git add stacks/bob/null.tf
$ git commit -m "Add another null resource"
$ cat <<EOF >>stacks/bob/null.tf
resource "null_resource" "quickstart2" {
}
EOF
$ git add stacks/bob/null.tf
$ git commit -m "Add another null resource"
$ git push origin main
Next, plan and apply the changes. The following command will create a plan in all changed stacks and apply the generated plan files and sync the result as a deployment to Terramate Cloud.
$ terramate run \
--changed \
-- \
terraform plan -lock-timeout=5m -out deploy.tfplan
$ terramate run \
--changed \
--sync-deployment \
--terraform-plan-file=deploy.tfplan \
-- \
terraform apply -input=false -auto-approve -lock-timeout=5m deploy.tfplan
$ terramate run \
--changed \
-- \
tofu plan -lock-timeout=5m -out deploy.tfplan
$ terramate run \
--changed \
--sync-deployment \
--tofu-plan-file=deploy.tfplan \
-- \
tofu apply -input=false -auto-approve -lock-timeout=5m deploy.tfplan
A new deployment has started in Terramate Cloud. Check out the Deployments section to see it.
Summary
We hope this tutorial has helped you grasp the basics of Terramate. Here's a summary of what we learned:
- How to initialize a Terramate Project in a Git repository.
- How to create stacks.
- How to leverage change detection when managing stacks or running commands.
- How to generate code in all stacks to keep the configuration DRY.
- How to deploy Terraform and OpenTofu using a local backend and null resources as an example.
- How to create a Terramate Cloud account and connect it to your project.
Those examples hopefully give you a starting point and help you get insights into the capabilities of Terramate. This quickstart is just the tip of the iceberg. Running code generation and change detection can help you save a lot of time when maintaining or running Terraform.
Next steps
- Configure CI/CD workflows for pull request previews, deployment, drift detection and reconciliation using GitHub Actions, GitLab, BitBucket pipeline or any other CI/CD platform.
- Configure Slack Notifications.
- Invite your team members to your organization.
Join the community
If you have questions or feature requests regarding Terramate, we encourage you to join our Discord Community where we host regular events such as weekly Office hours. It's an excellent place to contact our team and fellow community members if you have questions regarding Terramate. Alternatively, you can also create an issue in the Github repository.