Skip to content

Step 4. Add AWS site account

Now that we've created our service account, we can create an AWS account for a specific site (or; MACH stack).

Setup site-specific

For this account we will create:

  1. Terraform state backend
  2. deploy IAM role for MACH composer to manage your resources

1. Create AWS account

  • In your AWS console, go to My Organization and choose Add accounts
  • For your new account choose a name like your-project-tst
  • As IAM role name enter admin

2. Setup your Terraform configuration

Within your mach-account directory 1 create the following files:

variable "aws_account_id" {
    type = string

variable "name" {
    type = string

variable "region" {
  default = "eu-central-1"

locals {
  role_arn            = "arn:aws:iam::${var.aws_account_id}:role/admin"
  tfstate_bucket_name = "${}-tfstate"

terraform {
  # We will uncomment this later
  # backend "s3" {}

provider "aws" {
  region = var.region

  assume_role {
    role_arn = local.role_arn

module "tfstate-backend" {
  source  = "cloudposse/tfstate-backend/aws"
  version = "0.33.0"

  s3_bucket_name = local.tfstate_bucket_name
  role_arn       = local.role_arn

module "mach_account" {
  source               = "git::"
  aws_account_alias    =
  code_repository_name = "your-project-lambdas"  # Replace with the actual name given to the S3 bucket
  deploy_principle_identifiers = [
    "arn:aws:iam::000000000000:user/admin" # Specify your root account here


We specify our root account here, so it makes it easier for this tutorial to set up credentials to be able to deploy using MACH.

The terraform-aws-mach-account module will create the necessary IAM policies that allows the mach deploy user to deploy the necessary resources.

The Terraform state backend must also be used by MACH composer, so we need to create the necessary policies that allows the mach user to read/write to that state backend:

data "aws_iam_policy_document" "terraform_state" {

  statement {
    actions = [
    resources = [
  statement {
    actions = [

    resources = [

  statement {
    actions = [

    resources = [

resource "aws_iam_policy" "terraform_state" {
  name        = "terraform-state-policy"
  path        = "/"
  description = "Policy to access terraform state"

  policy = data.aws_iam_policy_document.terraform_state.json

resource "aws_iam_role_policy" "apigateway" {
  name   = "terraform-state-policy"
  role   = module.mach_account.mach_role_id
  policy = data.aws_iam_policy_document.terraform_state.json

resource "aws_iam_user_policy_attachment" "mach_user_terraform_state" {
  user       = module.mach_account.mach_user_name
  policy_arn = aws_iam_policy.terraform_state.arn

3. Create the first environment configuration

Create a directory called mach-account/envs/ and create a new file tst.tfvars:

aws_account_id = "<your-account-id>"
name           = "your-project-tst"

4. Terraform roll-out

Within your mach-account directory, run the following commands:

$ terraform init -var-file=envs/tst.tfvars
$ terraform apply -var-file=envs/tst.tfvars

5. Configure state backend

Terraform has now created the Terraform state backend.

We are going to store that information in a site-specific backend configuration file. This way, several backends for multiple sites can live side-by-side in the same infra repo.

  1. Create a new directory mach-account/backend-configs and create a new file tst.conf:
    region         = "eu-central-1"
    bucket         = "your-project-tst-tfstate"
    key            = "terraform.tfstate"
    dynamodb_table = "lock"
    role_arn       = "arn:aws:iam::<account-id>:role/admin"
    encrypt        = "true"
  2. Uncomment the # backend "s3" {} line in
  3. Perform the following command:
    $ terraform init -force-copy -var-file=envs/tst.tfvars  -backend-config=backend-configs/tst.conf
    Now the state is stored in the S3 bucket, and the DynamoDB table will be used to lock the state to prevent concurrent modification.

6. Grant access to service account

The last step is to allow the new AWS account to access resources from the service account.

In service/ add the allow_code_repo_read_access variable to the shared-config module:

module "shared-config" {
  source = "git::"
  allow_code_repo_read_access = [
      "arn:aws:iam::<test-aws-account-id>:user/mach", # test env
      "arn:aws:iam::<test-aws-account-id>:role/mach", # test env

This will make sure that this AWS account is able to read the contents of the component repository bucket.

Run terraform apply to apply these changes.

Next: step 5

Next we'll create our first MACH component.

  1. Refer to the previous step to see how we organize the two different AWS accounts