HashiCorp Learn
Infrastructure
  • TerraformTerraformLearn terraformDocs
  • PackerPackerLearn packerDocs
  • VagrantVagrantLearn vagrantDocs
Security
  • VaultVaultLearn vaultDocs
  • BoundaryBoundaryLearn boundaryDocs
Networking
  • ConsulConsulLearn consulDocs
Applications
  • NomadNomadLearn nomadDocs
  • WaypointWaypointLearn waypointDocs
  • HashiCorp Cloud Platform (HCP) LogoHashiCorp Cloud Platform (HCP)HashiCorp Cloud Platform (HCP)Docs
Type '/' to Search
Loading account...
  • Bookmarks
  • Manage Account
  • Overview
  • Prerequisites
  • Analyze a CircleCI configuration
  • Setup the CircleCI UI
  • Create a remote backend
  • Define your Terraform variables
  • Trigger CircleCI workflow
  • Next Steps
DocsForum
Back to terraform
Automate TerraformView Collection
    Running Terraform in AutomationDeploy Terraform infrastructure with CircleCIAutomate Terraform with GitHub ActionsAutomate Terraform Cloud Workflows

Deploy Terraform infrastructure with CircleCI

  • 9 min
  • Products Usedterraform

CircleCI is a continuous integration tool to automate software builds, tests, and deployments. The continuous integration workflow enables development teams to automate, self-test, quickly build, clone, and deploy software. Terraform deploys infrastructure repeatably. By adding Terraform into a CircleCI workflow, you can deploy your infrastructure alongside software in the same pipeline.

In this tutorial, you will use CircleCI to deploy an S3 backed web application. Your deployment process will be controlled by the CircleCI workflow to run your Terraform configuration in automation. CircleCI will be able to access your state file with an S3 remote backend for future deployments.

»Prerequisites

This tutorial assumes you have the following:

  • A GitHub account
  • A CircleCI account. Sign up with your GitHub account so CircleCI can build and deploy from your GitHub repositories. Review the CircleCI getting started guide for an introduction to the workflow if you are unfamiliar.
  • An AWS account

Fork the demo code from GitHub. Once you have forked the repository, clone the demo code to your machine. You will need to edit the command below to include your GitHub username.

$ git clone https://github.com/YOUR-USER-NAME/learn-terraform-circleci

»Analyze a CircleCI configuration

Change directories to your forked repository.

$ cd learn-terraform-circleci/.circleci

Open the config.yml file in your file editor. This configuration defines the jobs for each step in your deployment.

There will be a total of four jobs in this workflow: plan-apply, apply, plan-destroy, and destroy. You will then use these jobs to define the automated Terraform workflow.

»Review the plan-apply job

Jobs are collections of steps CircleCI performs. Each job must declare an executor, an operating system which will launch and perform the actions you define, and a series of steps. You will use the docker executor in this tutorial to perform jobs to initialize, plan, apply, and destroy your Terraform configuration.

The plan job uses the hashicorp/terraform:light image which contains the Terraform binary. This job checkouts your repository, runs terraform init to initialize your configuration, and generates a plan file named tfapply by running terraform plan -out.

Finally, the persist_to_workspace step saves the initialized configuration and your environment variables for use in the following jobs. persist_to_workspace allows you to run this initialized Terraform configuration throughout the rest of the jobs in the workflow as if they are running on the same machine.

version: 2

jobs:
  plan-apply:
    working_directory: /tmp/project
    docker:
      - image: hashicorp/terraform:light
    steps:
      - checkout
      - run:
          name: terraform init & plan
          command: |
            terraform init -input=false
            terraform plan -out tfapply -var-file variables.tfvars
      - persist_to_workspace:
          root: .
          paths:
            - .

The steps in this configuration are actions that CircleCI takes in the workflow to perform your job. Steps are a collection of executable commands. For example, the checkout step checks out the source code for a job over SSH. The steps in this job run CLI commands terraform init and terraform plan -out with your defined variables.

»Review the apply job

The next job in this config is the apply job. The attach_workspace step in the apply job loads the previously persisted workspace in the plan job. The apply job runs terraform apply using the execution plan generated from the previous job.

apply:
  docker:
    - image: hashicorp/terraform:light
  steps:
    - attach_workspace:
        at: .
    - run:
        name: terraform
        command: |
          terraform apply -auto-approve tfapply
    - persist_to_workspace:
        root: .
        paths:
          - .

»Review the plan-destroy and destroy jobs

The plan-destroy job creates an execution plan and the destroy job executes that with terraform apply tfdestroy job to remove all of the infrastructure you created.

plan-destroy:
  docker:
    - image: hashicorp/terraform:light
  steps:
    - attach_workspace:
        at: .
    - run:
        name: terraform create destroy plan
        command: |
          terraform plan -destroy -out tfdestroy -var-file variables.tfvars
    - persist_to_workspace:
        root: .
        paths:
          - .

destroy:
  docker:
    - image: hashicorp/terraform:light
  steps:
    - attach_workspace:
        at: .
    - run:
        name: terraform destroy
        command: |
          terraform apply -auto-approve tfdestroy

You should not run these jobs unattended because it may lead to disruptions in your infrastructure. In the next section, your CircleCI configuration defines the order of operations for these jobs in a workflow.

»Review the workflow

Finally, the last block in the configuration is the workflows. Workflow defines order, precedence, and requirements to perform the jobs within the pipeline. This workflow runs the jobs detailed throughout the config and details the order in which those jobs run as well as the dependencies of each job. The plan_approve_apply workflow runs through all of the steps in order and creates the application.

workflows:
  version: 2
  plan_approve_apply:
    jobs:
      - plan-apply
      - hold-apply:
          type: approval
          requires:
            - plan-apply
      - apply:
          requires:
            - hold-apply
      - plan-destroy:
          requires:
            - apply
      - hold-destroy:
          type: approval
          requires:
            - plan-destroy
      - destroy:
          requires:
            - hold-destroy

Notice that hold-apply and hold-destroy have type: approval in this workflow. This means that for every run, CircleCI will generate a plan and wait for approval before running the apply job. CircleCI will also generate a plan to destroy the infrastructure and wait for approval before running the destroy job.

»Setup the CircleCI UI

In order to pass this configuration to the CircleCI jobs, you have to setup your CirleCI project.

In the CircleCI web UI, choose the Projects icon from the left. Search for the repo you forked and choose Set Up Project.

Set up your project in the CircleCI UI

Choose "Hello World" as the language and choose the "Use Existing Config" option.

Create a generic project in the CircleCI UI

Choose "Start Building" and you should be presented with a popup confirming you have created config.yml file.

Use your existing config.yaml file to build your project

CircleCI will automatically attempt to run the job and fail because the project needs your AWS credentials.

In the right-hand corner of this page, go the Project Settings and navigate to Environment Variables.

The two environment variables for this project are AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY. These are variables that CircleCI uses to inject data into the .config.yml file.

  1. AWS_ACCESS_KEY_ID is the generated keys for the AWS user running this job. To generate an access key and secret access key file, log in to your AWS account and create them in IAM.
  2. AWS_SECRET_ACCESS_KEY is bundled with the access key above.

Add and save these variables in your CircleCI Build Settings.

Create two environment variables in the CircleCI UI

»Create a remote backend

You need to save the Terraform state file for future runs. In this workflow, your remote state storage will be in an S3 bucket backend.

In your terminal, change into the s3_backend directory of the learn-terraform-circleci repository.

$ cd s3_backend

Initialize and apply the backend configuration. You will be prompted to choose an AWS region for your S3 bucket.

$ terraform init && terraform apply

Save the output of the random bucket name. This is the encrypted bucket for your remote state storage.

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

s3_bucket_name = 5092f11c-xxxx-xxxx-xxxx-xxxxxxx-backend

Change into the root directory of the learn-terraform-circleci local repository.

$ cd ..

Open the main.tf file and add the backend configuration with your unique bucket ID and region.

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
+  backend "s3" {
+    bucket = "YOUR-UNIQUE-BUCKET-ID"
+    key    = "terraform/webapp/terraform.tfstate"
+    region = "us-east-1"
+ }
}

Save this file.

»Define your Terraform variables

In your file editor, make an edit to the variables.tfvars file to define variables for your deployment.

region = "us-east-1"
label  = "hashicorp.fun"
app    = "terramino"
user   = "circleci-user"

Replace the region variable with an AWS region closest to you and save the file.

Note: Your webapp region does not have to match your remote backend bucket region.

»Trigger CircleCI workflow

Prepare to add your changes to your GitHub repository.

$ git add main.tf variables.tfvars

Commit these changes with a message.

$ git commit -m "Add remote backend and variable definitions"

Finally, push these changes to your forked repositories master branch to kick off a CircleCI run.

$ git push

The CircleCI web UI should indicate that your build has started. The steps for this deployment will initialize your Terraform directory, plan the Terraform deployment, and wait for your approval to apply the planned changes.

CircleCI web UI project build beginning

Approve the apply step.

Approve the apply step in CircleCI

Review that job by navigating to the workflows for plan_approve_apply. In each job in the workflow, you can click on each step to expand the output.

Once the deployment job is complete, your workflow will be on hold. The hold in your configuration is the step before destruction. The output in the job displays your webapp address. Navigate to that address and verify your app deployed correctly.

Job output in CircleCI web UI

Any changes to your GitHub repo will trigger another run of this workflow. As with any Terraform deployment, some resources will be destroyed or updated in place depending on the configuration and the cloud provider you are using in the future.

»Generate the destroy plan

The plan-destroy step in the workflow will prevent CircleCI from continuing to the next job in your workflow. hold-destroy is a manual gate step which allows you to decide when to move to the final step in the configuration. Click on the hold step and then choose "approve" to move on to the destroy job in this workflow.

Approve the destroy job.

Navigate to the plan-destroy job in the CircleCI web UI to observe the output in the "terraform destroy" drop down.

»Destroy your state S3 bucket

When you have completed this tutorial, you should destroy the S3 bucket you created for your state file.

In your local repository, navigate to the s3_bucket directory.

$ cd s3_bucket

Run terraform destroy to destroy the S3 bucket.

$ terraform destroy

Type yes to approve the destroy job.

»Next Steps

In this tutorial, you deployed a hosted webpage in S3 by integrating Terraform with your CircleCI workflow. If you would like to learn more about CircleCI or automated Terraform workflow best practices, consider these resources:

  • Deploy your Terraform infrastructure with the official CircleCI Terraform Orb
  • Running Terraform in Automation
  • CircleCI Configuration reference
  • Automate Your Infrastructure with GitOps, Terraform & CircleCI


Back to Collection
HashiCorp
  • System Status
  • Terms of Use
  • Security
  • Privacy
stdin: is not a tty