Environments

Configure and manage multiple environments with isolated state and independent deployments.


Overview

The starter kit supports multiple isolated environments (staging, production, etc.) with independent state management and deployment workflows. Each environment lives in its own directory under environments/.

Note: All environment files and GitHub Actions workflows are automatically generated by the make setup command. See the Install guide.

Environment structure

Each environment directory contains:

environments/
└── staging/
    ├── backend.tf           # Terraform and S3 backend configuration
    ├── main.tf              # Provider and module configuration
    ├── variables.tf         # Input variable definitions
    ├── outputs.tf           # Output values from the OIDC module
    └── terraform.tfvars     # Variable values for OIDC configuration

backend.tf

Configures Terraform version, required providers, and S3 backend:

terraform {
  required_version = ">= 1.10"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket       = "terraform-state-123456789012-eu-west-1"
    key          = "environments/staging/terraform.tfstate"
    region       = "eu-west-1"
    encrypt      = true
    use_lockfile = true
  }
}

Key features:

  • State encryption - encrypt = true enables AES-256 server-side encryption
  • Native state locking - use_lockfile = true enables Terraform 1.10+ locking with .tflock files (see Terraform S3 Backend docs)
  • Unique state key - Each environment uses its own path

main.tf

Configures the AWS provider and calls the OIDC module:

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      Environment = "staging"
      ManagedBy   = "terraform"
      Repository  = "your-org/your-repo"
    }
  }
}

module "oidc_provider" {
  source = "../../modules/oidc-provider"

  use_existing_oidc_provider = var.use_existing_oidc_provider
  github_repo                = var.github_repo
  role_name                  = var.role_name
  managed_policy_arns        = var.managed_policy_arns
}

Key features:

  • Default tags - Automatically applied to all resources
  • Module-based - Uses the oidc-provider module from modules/
  • Configurable OIDC - Can create or reuse existing OIDC providers

variables.tf

Defines all input variables with defaults:

variable "aws_region" {
  description = "AWS region for resources"
  type        = string
  default     = "eu-west-1"
}

variable "use_existing_oidc_provider" {
  description = "Whether to use an existing OIDC provider"
  type        = bool
  default     = true
}

variable "github_repo" {
  description = "GitHub repository name (format: owner/repo)"
  type        = string
  default     = "your-org/your-repo"
}

variable "role_name" {
  description = "Name of the IAM role for GitHub Actions"
  type        = string
  default     = "GitHubActionsServiceRole-Terraform"
}

variable "managed_policy_arns" {
  description = "List of IAM policy ARNs to attach"
  type        = list(string)
  default = [
    "arn:aws:iam::aws:policy/AdministratorAccess"
  ]
}
VariableDescription
aws_regionAWS region for deploying resources
use_existing_oidc_providerSet true for multiple environments in same account
github_repoYour GitHub repository in owner/repo format
role_nameIAM role name for GitHub Actions
managed_policy_arnsAWS managed policies attached to the role

outputs.tf

Exports values from the OIDC module:

output "oidc_provider_arn" {
  description = "ARN of the GitHub OIDC provider"
  value       = module.oidc_provider.oidc_provider_arn
}

output "role_arn" {
  description = "ARN of the GitHub Actions IAM role"
  value       = module.oidc_provider.role_arn
}

output "role_name" {
  description = "Name of the GitHub Actions IAM role"
  value       = module.oidc_provider.role_name
}

Adding a new environment

Use the setup wizard:

make setup

The wizard:

  1. Detects existing backend (reuses S3 bucket)
  2. Prompts for environment name
  3. Generates all necessary files
  4. Checks for existing OIDC provider
  5. Deploys OIDC infrastructure
  6. Displays IAM role ARN

Multi-account setup: Switch AWS credentials before running make setup:

assume production-account
make setup  # Select: production

See Install for detailed setup options.

Multi-account vs. single-account

Single-account deployment

When deploying multiple environments to the same AWS account, the OIDC provider can only exist once:

  • First environment: use_existing_oidc_provider = false
  • Additional environments: use_existing_oidc_provider = true

Multi-account deployment

When deploying to separate AWS accounts, each account needs its own OIDC provider:

  • Each environment: use_existing_oidc_provider = false

This provides complete isolation with separate IAM configurations.

Default tags

The default_tags block applies tags to all resources:

default_tags {
  tags = {
    Environment = "staging"
    ManagedBy   = "terraform"
    Repository  = "your-org/your-repo"
  }
}

No need to repeat tag blocks on individual resources.

IAM role permissions

The managed_policy_arns variable controls GitHub Actions permissions:

managed_policy_arns = [
  "arn:aws:iam::aws:policy/AdministratorAccess"
]

For production, consider more restrictive policies based on your infrastructure needs.

Next steps