View on GitHub

Povio Engineering Guidelines

These are guidelines for the technologies we are using.

Terraform

Terraform is an infrastructure as code tool that provides a cli workflow to mange cloud services. The configurations are defined as declarative and idempotent text files. The state can be managed in shared state files along with concurrency protection.

To allow for easier development, we also use Terragrunt. Terragrunt is a thin wrapper around terraform that provides:

Getting started

The Povio Terraform Template has examples for several platforms to get you started.

Requirements

Install terraform and terragrunt

OR

Use docker-compose to have a pinned local version of terraform/terragrunt

version: '3'

services:
  terragrunt:
    image: alpine/terragrunt:0.15.0
    command: bash
    environment:
      # Use .gitignore-d .env instead of this
      #AWS_ACCESS_KEY_ID=
      #AWS_SECRET_ACCESS_KEY=
      #AWS_DEFAULT_REGION=
      #AWS_PROFILE=
    volumes:
      - ./:/apps
      # Use environment instead of this
      #- ${HOME}/.aws:/root/.aws
      #- ${HOME}/.ssh:/root/.ssh
   

Prepare IAM users

Add a new IAM user with programmatic access and full AdministratorAccess and name it something like myapp-terraform.

This used should not be shared or used in CI.

Populate ./aws/config (aws-cli config) with credentials using the profile myapp

[myapp]
region = us-east-1
aws_access_key_id = []
aws_secret_access_key = []

Init Terragrunt for AWS

# /infrastructure/terragrunt.hcl

# default backend
remote_state {
  backend = "s3"
  config = {
    # the AWS local profile
    profile = "myapp"

    # the bucket to store the state in
    bucket = "myapp-terraform-state"

    key = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true

    # the dynamodb table for state locking
    dynamodb_table = "myapp-terraform-lock"
  }
}

# default provider config
generate "provider" {
  path = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents = <<EOF
provider "aws" {
  # only allow deployment on this accountId for safety reason
  allowed_account_ids = ["000000000000"]
  region = "us-east-1"
  profile = "myapp"
}
terraform {
  backend "s3" {}
}
EOF
}

At the time of writing, the S3 bucket created by terragrunt will not enable versioning in the myapp-terraform-state bucket - it is advised to do so manually.

Read more about managing Terragrunt code here.

.gitignore

While .terraform.lock.hcl needs to be versioned, .terragrunt-cache is reproducible and .terraform/ should be handled by terragrunt.

*.auto.tfvars
.terraform/
.terragrunt-cache