Terraform Atlantis with Terragrunt: Complete Integration Guide 2025

Streamline Terraform with Atlantis & Terragrunt: step-by-step setup, best practices, CI/CD integration, security hardening and scaling tips.

Atlantis automates Terraform workflows through pull requests, while Terragrunt keeps your infrastructure code DRY. Together, they create a streamlined, collaborative approach to infrastructure management that scales from small teams to large enterprises.

Why combine Atlantis with Terragrunt

The integration of Atlantis and Terragrunt delivers substantial benefits for infrastructure automation while introducing some technical challenges that require careful consideration.

Key benefits drive adoption across organizations

Enhanced workflow automation transforms how teams collaborate on infrastructure changes. With pull request-based workflows, infrastructure modifications become visible, reviewable, and auditable. Custom Terragrunt workflows in Atlantis adapt to specific team processes, while pre-workflow hooks enable validation and compliance checks before executing changes.

True DRY implementation extends beyond code to your CI/CD process. Terragrunt's centralized configuration patterns allow teams to define remote backend configuration, provider settings, and common variables once, then reuse them across modules. Dependency management becomes explicit through Terragrunt dependency blocks, ensuring Atlantis understands relationships between modules.

Advanced automation capabilities make complex infrastructures manageable. Parallel execution runs Terragrunt plans and applies concurrently using workspaces, while dependency-aware automation ensures correct execution order. Support for Terragrunt's run-all command allows operations across multiple modules simultaneously when properly configured.

Technical challenges require thoughtful solutions

Integration complexity demands careful configuration. Setting up Atlantis with Terragrunt requires custom workflow definitions, binary path management, and potentially complex configuration file management for large monorepos.

Performance considerations emerge at scale. Atlantis operates in a single-threaded manner by default, which becomes a bottleneck for large infrastructures. Parallel execution increases resource consumption as each workspace requires its own repository clone.

Security implications require attention to credential management, command injection risks, and proper state file security. Both tools need access to cloud provider credentials, making secure secret management essential.

Setting up Atlantis for Terragrunt projects

Creating a proper foundation for Atlantis with Terragrunt requires careful server setup and project structure planning.

Server installation and configuration

The default Atlantis image doesn't include Terragrunt, so you'll need to create a custom Docker image:

FROM ghcr.io/runatlantis/atlantis:latest

# Install Terragrunt
ARG TERRAGRUNT_VERSION=v0.55.0
RUN curl -Lo /usr/local/bin/terragrunt "https://github.com/gruntwork-io/terragrunt/releases/download/${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" && \
    chmod +x /usr/local/bin/terragrunt

Configure your Atlantis server with appropriate flags:

atlantis server \
  --repo-allowlist="github.com/your-org/*" \
  --atlantis-url="https://your-atlantis-server.com" \
  --gh-user="your-github-user" \
  --gh-token="your-github-token" \
  --gh-webhook-secret="your-webhook-secret" \
  --repo-config="repos.yaml" \
  --autoplan-file-list="**/*.tf,**/*.tfvars,**/*.tfvars.json,**/terragrunt.hcl,**/.terraform.lock.hcl"

Terragrunt-Atlantis-Config setup

The terragrunt-atlantis-config tool automatically generates atlantis.yaml configurations based on Terragrunt dependency structures. This tool has become the de facto standard for managing Atlantis configuration in Terragrunt projects:

# Install terragrunt-atlantis-config
TERRAGRUNT_ATLANTIS_CONFIG_VERSION="1.20.0"
wget https://github.com/transcend-io/terragrunt-atlantis-config/releases/download/v${TERRAGRUNT_ATLANTIS_CONFIG_VERSION}/terragrunt-atlantis-config_${TERRAGRUNT_ATLANTIS_CONFIG_VERSION}_linux_amd64.tar.gz
tar xf terragrunt-atlantis-config_${TERRAGRUNT_ATLANTIS_CONFIG_VERSION}_linux_amd64.tar.gz
sudo install terragrunt-atlantis-config_${TERRAGRUNT_ATLANTIS_CONFIG_VERSION}_linux_amd64/terragrunt-atlantis-config /usr/local/bin

Add a pre-workflow hook to your server's repo configuration:

// repos.yaml
{
  "repos": [
    {
      "id": "github.com/your-org/your-repo",
      "workflow": "terragrunt",
      "allowed_overrides": ["workflow"],
      "allow_custom_workflows": true,
      "pre_workflow_hooks": [
        {
          "run": "terragrunt-atlantis-config generate --output atlantis.yaml --autoplan --parallel --create-workspace",
          "description": "Generate Atlantis config for Terragrunt projects"
        }
      ]
    }
  ]
}

Project structure recommendations

Optimal project structure for Terragrunt projects with Atlantis follows a hierarchical pattern:

.
├── terragrunt.hcl                  # Root configuration
├── environments
│   ├── dev
│   │   ├── terragrunt.hcl          # Environment config
│   │   ├── region1
│   │   │   ├── terragrunt.hcl      # Region config
│   │   │   ├── vpc
│   │   │   │   └── terragrunt.hcl  # Module config
│   │   │   ├── rds
│   │   │   │   └── terragrunt.hcl
│   │   │   └── eks
│   │   │       └── terragrunt.hcl
│   │   └── region2
│   │       └── ...
│   ├── staging
│   │   └── ...
│   └── prod
│       └── ...
└── modules                         # Optional: Include modules
    ├── vpc
    ├── rds
    └── eks

Root terragrunt.hcl should contain common configuration like remote state and provider settings:

# terragrunt.hcl
remote_state {
  backend = "s3"
  config = {
    bucket         = "my-terraform-state"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "my-terraform-locks"
  }
}

generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "aws" {
  region = "us-west-2"
}
EOF
}

Configuring atlantis.yaml for Terragrunt

Atlantis configuration for Terragrunt projects requires special attention to workflows, dependencies, and automation.

Basic atlantis.yaml configuration

While manually creating this file is possible, using terragrunt-atlantis-config is recommended. A basic manual configuration looks like:

version: 3
projects:
- dir: environments/dev/region1/vpc
  workflow: terragrunt
- dir: environments/dev/region1/rds
  workflow: terragrunt
- dir: environments/dev/region1/eks
  workflow: terragrunt
# ... other projects

workflows:
  terragrunt:
    plan:
      steps:
      - env:
          name: TERRAGRUNT_TFPATH
          command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
      - env:
          name: TF_IN_AUTOMATION
          value: 'true'
      - run: terragrunt plan -input=false -no-color -out=$PLANFILE
        output: strip_refreshing
    apply:
      steps:
      - env:
          name: TERRAGRUNT_TFPATH
          command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
      - env:
          name: TF_IN_AUTOMATION
          value: 'true'
      - run: terragrunt apply $PLANFILE

Using terragrunt run-all

For multi-module operations using Terragrunt's run-all feature:

workflows:
  terragrunt-run-all:
    plan:
      steps:
      - env:
          name: TERRAGRUNT_TFPATH
          command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
      - env:
          name: TF_IN_AUTOMATION
          value: 'true'
      - run: cd $DIR && terragrunt run-all plan -out atlantis.tfplan
    apply:
      steps:
      - env:
          name: TERRAGRUNT_TFPATH
          command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
      - env:
          name: TF_IN_AUTOMATION
          value: 'true'
      - run: cd $DIR && terragrunt run-all apply atlantis.tfplan

Note: When using run-all, use a relative path for the plan file instead of $PLANFILE to ensure proper plan location and application.

Project-level autoplan configuration

Control when plans automatically run with detailed autoplan configuration:

projects:
- dir: environments/dev/region1/vpc
  autoplan:
    enabled: true
    when_modified:
    - "*.hcl"
    - "*.tf*"
    - "../../../modules/vpc/**/*.tf*"
  workflow: terragrunt

Managing Terragrunt dependencies in Atlantis

Terragrunt's dependency blocks create relationships between modules that Atlantis must understand for proper execution.

How dependency blocks work with Atlantis

Terragrunt dependency blocks allow modules to reference outputs from other modules. When integrating with Atlantis, these dependencies require special handling because Atlantis primarily operates on individual directories.

The most effective approach uses terragrunt-atlantis-config to generate Atlantis configuration based on Terragrunt dependency blocks:

terragrunt-atlantis-config generate --output atlantis.yaml --autoplan --parallel --create-workspace

This scans your repository, analyzes Terragrunt dependency blocks, and generates an atlantis.yaml file that correctly maps the dependency tree to Atlantis projects.

Strategies for proper dependency resolution

Several strategies ensure proper dependency resolution in Atlantis workflows:

  1. Cascade dependencies: Use the --cascade-dependencies flag with terragrunt-atlantis-config to ensure a module depends on direct and transitive dependencies.
  2. Workspace isolation: The --create-workspace flag generates unique workspaces for each project based on their path, enabling parallel execution while maintaining dependency isolation.
  3. Custom workflow with run-all: For complex dependency chains, configure a custom workflow using Terragrunt's run-all command:
workflows:
  terragrunt:
    plan:
      steps:
        - run: terragrunt run-all plan --terragrunt-non-interactive -out "$PLANFILE"
    apply:
      steps:
        - run: terragrunt run-all apply --terragrunt-non-interactive "$PLANFILE"
  1. Extra dependencies: For dependencies on files not automatically detected by Terragrunt, use the extra_atlantis_dependencies local:
locals {
  extra_atlantis_dependencies = [
    "some_extra_dep",
    find_in_parent_folders(".gitignore")
  ]
}

Handling mock outputs

When using mock outputs in dependency blocks, Atlantis may apply modules with mock values rather than actual outputs from dependencies. The run-all command helps ensure Terragrunt applies resources in the correct dependency order:

dependency "vpc" {
  config_path = "../vpc"
  
  mock_outputs = {
    vpc_id = "mock-vpc-id"
  }
  mock_outputs_allowed_terraform_commands = ["plan", "validate"]
}

Example atlantis.yaml for multi-account/multi-region setup

A detailed atlantis.yaml example for a multi-account/multi-region setup demonstrates how to structure complex infrastructures:

version: 3
automerge: false
parallel_apply: true
parallel_plan: true
projects:
  # Dev Account - US East Region
  - name: dev_us_east_vpc
    dir: dev/us-east-1/vpc
    workflow: terragrunt
    autoplan:
      enabled: true
      when_modified:
        - "*.hcl"
        - "*.tf*"
        - "../../../common/*.hcl"
    workspace: dev_us_east_vpc
  
  - name: dev_us_east_rds
    dir: dev/us-east-1/rds
    workflow: terragrunt
    depends_on:
      - dev_us_east_vpc
    autoplan:
      enabled: true
      when_modified:
        - "*.hcl"
        - "*.tf*"
        - "../../../common/*.hcl"
    workspace: dev_us_east_rds
  
  # Prod Account - EU West Region
  - name: prod_eu_west_vpc
    dir: prod/eu-west-1/vpc
    workflow: terragrunt
    autoplan:
      enabled: true
      when_modified:
        - "*.hcl"
        - "*.tf*"
        - "../../../common/*.hcl"
    workspace: prod_eu_west_vpc
  
  - name: prod_eu_west_rds
    dir: prod/eu-west-1/rds
    workflow: terragrunt
    depends_on:
      - prod_eu_west_vpc
    autoplan:
      enabled: true
      when_modified:
        - "*.hcl"
        - "*.tf*"
        - "../../../common/*.hcl"
    workspace: prod_eu_west_rds

workflows:
  terragrunt:
    plan:
      steps:
        - env:
            name: TERRAGRUNT_TFPATH
            command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
        - env:
            name: TF_IN_AUTOMATION
            value: 'true'
        - run: terragrunt plan -input=false -no-color -out=$PLANFILE
    apply:
      steps:
        - env:
            name: TERRAGRUNT_TFPATH
            command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
        - env:
            name: TF_IN_AUTOMATION
            value: 'true'
        - run: terragrunt apply -input=false $PLANFILE

For real-world implementations, generate this configuration automatically:

terragrunt-atlantis-config generate --output atlantis.yaml \
  --autoplan --create-workspace --parallel \
  --cascade-dependencies

Troubleshooting Atlantis with Terragrunt

Even with careful configuration, issues can arise when integrating these complex tools.

Configuration errors

Error: "Repo config not allowed to set 'workflow' key"

Add allowed_overrides to your server-side config:

repos:
  - id: "github.com/your-org/*"
    allowed_overrides: [workflow]
    allowed_workflows: [terragrunt]
    allow_custom_workflows: true

Error: "terragrunt: command not found"

Create a custom Atlantis Docker image with Terragrunt installed:

FROM ghcr.io/runatlantis/atlantis:v0.27.0
USER root
RUN curl -L https://github.com/gruntwork-io/terragrunt/releases/download/v${TG_VERSION}/terragrunt_linux_amd64 -o /usr/local/bin/terragrunt \
    && chmod +x /usr/local/bin/terragrunt
USER atlantis

Dependency resolution errors

Error: "Failed to parse HCL: Invalid expression..."

Use mock_outputs for dependencies that haven't been applied yet:

dependency "vpc" {
  config_path = "../vpc"
  mock_outputs = {
    vpc_id = "mock-vpc-id"
  }
  mock_outputs_allowed_terraform_commands = ["plan", "validate"]
}

Performance issues

Slow plan and apply operations

Enable parallel execution with --parallel and --create-workspace flags:

terragrunt-atlantis-config generate --output atlantis.yaml --parallel --create-workspace

Set parallel_plan and parallel_apply in atlantis.yaml:

version: 3
automerge: false
parallel_apply: true
parallel_plan: true

Autoplan problems

Changes to HCL files don't trigger Atlantis plans

Configure the autoplan section in atlantis.yaml with correct file patterns:

autoplan:
  enabled: true
  when_modified:
    - "*.tf"
    - "*.tfvars"
    - "*.hcl"
    - "../*.hcl"  # parent terragrunt files

Set the server-side --autoplan-file-list flag:

--autoplan-file-list="**/*.tf,**/*.tfvars,**/*.tfvars.json,**/terragrunt.hcl,**/.terraform.lock.hcl"

Best practices for production implementations

Based on real-world implementations and community recommendations, follow these best practices:

  1. Automate configuration generation using terragrunt-atlantis-config with appropriate flags:
terragrunt-atlantis-config generate --output atlantis.yaml \
  --autoplan --workflow terragrunt --create-workspace \
  --parallel --cascade-dependencies
  1. Use mock outputs for initial planning to prevent dependency issues:
dependency "vpc" {
  config_path = "../vpc"
  mock_outputs = {
    vpc_id = "mock-vpc-id"
  }
  mock_outputs_allowed_terraform_commands = ["plan", "validate"]
}
  1. Optimize dependency resolution with performance optimizations:
    • Enable --dependency-fetch-output-from-state to fetch outputs directly from state
    • Use parallel execution with separate workspaces
    • Consider minimizing dependency chain depth when possible
  2. Maintain clearly defined boundaries:
    • Organize modules by account/region/environment
    • Use consistent naming conventions
    • Implement custom locals to manage workflow assignments
  3. Leverage extra dependencies for non-Terragrunt files:
locals {
  extra_atlantis_dependencies = [
    "../../../modules/shared/variables.tf",
    find_in_parent_folders("common_vars.yaml")
  ]
}

Conclusion

Integrating Terraform Atlantis with Terragrunt delivers a powerful infrastructure automation solution that enhances collaboration, enforces best practices, and maintains DRY principles. The combination's benefits—workflow automation, improved collaboration, and advanced automation capabilities—outweigh the technical challenges of integration complexity and performance considerations.

The key to success lies in proper configuration, especially around dependency management. Using tools like terragrunt-atlantis-config to automate configuration generation makes implementing this integration significantly easier, while following established patterns for repository structure and workflow definition ensures a smooth experience.

As both tools continue to evolve, this integration represents the state of the art in infrastructure automation, enabling teams to collaborate effectively on infrastructure changes while maintaining the highest standards of consistency and reliability.