Home

Awesome

Atlantis on AWS Fargate Terraform Module

SWUbanner

Atlantis is tool which provides unified workflow for collaborating on Terraform through GitHub, GitLab and Bitbucket Cloud.

Before using Atlantis and the code in this repository, please make sure that you have read and understood the security implications described in the official Atlantis documentation.

Usage

GitHub is shown below in usage examples; however, any git provider supported by Atlantis can be used by simply using the correct Atlantis environment variables and configuring the respective webhook for the given git provider.

See the Supplemental Docs for additional details on integrating with git providers.

GitHub Complete

The Atlantis module creates all resources required to run Atlantis on AWS Fargate.

module "atlantis" {
  source  = "terraform-aws-modules/atlantis/aws"

  name = "atlantis"

  # ECS Container Definition
  atlantis = {
    environment = [
      {
        name  = "ATLANTIS_GH_USER"
        value = "myuser"
      },
      {
        name  = "ATLANTIS_REPO_ALLOWLIST"
        value = "github.com/terraform-aws-modules/*"
      },
    ]
    secrets = [
      {
        name      = "ATLANTIS_GH_TOKEN"
        valueFrom = "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes256-7g8H9i"
      },
      {
        name      = "ATLANTIS_GH_WEBHOOK_SECRET"
        valueFrom = "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes192-4D5e6F"
      },
    ]
  }

  # ECS Service
  service = {
    task_exec_secret_arns = [
      "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes256-7g8H9i",
      "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes192-4D5e6F",
    ]
    # Provide Atlantis permission necessary to create/destroy resources
    tasks_iam_role_policies = {
      AdministratorAccess = "arn:aws:iam::aws:policy/AdministratorAccess"
    }
  }
  service_subnets = ["subnet-xyzde987", "subnet-slkjf456", "subnet-qeiru789"]
  vpc_id          = "vpc-1234556abcdef"

  # ALB
  alb_subnets             = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
  certificate_domain_name = "example.com"
  route53_zone_id         = "Z2ES7B9AZ6SHAE"

  tags = {
    Environment = "dev"
    Terraform   = "true"
  }
}

GitHub Separate

The Atlantis module creates most of resources required to run Atlantis on AWS Fargate, except for the ECS Cluster and ALB. This allows you to integrate Atlantis with your existing AWS infrastructure.

module "atlantis" {
  source  = "terraform-aws-modules/atlantis/aws"

  name = "atlantis"

  # Existing cluster
  create_cluster = false
  cluster_arn    = "arn:aws:ecs:eu-west-1:123456789012:cluster/default"

  # Existing ALB
  create_alb            = false
  alb_target_group_arn  = "arn:aws:elasticloadbalancing:eu-west-1:1234567890:targetgroup/bluegreentarget1/209a844cd01825a4"
  alb_security_group_id = "sg-12345678"

  # ECS Container Definition
  atlantis = {
    environment = [
      {
        name  = "ATLANTIS_GH_USER"
        value = "myuser"
      },
      {
        name  = "ATLANTIS_REPO_ALLOWLIST"
        value = "github.com/terraform-aws-modules/*"
      },
    ]
    secrets = [
      {
        name      = "ATLANTIS_GH_TOKEN"
        valueFrom = "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes256-7g8H9i"
      },
      {
        name      = "ATLANTIS_GH_WEBHOOK_SECRET"
        valueFrom = "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes192-4D5e6F"
      },
    ]
  }

  # ECS Service
  service = {
    task_exec_secret_arns = [
      "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes256-7g8H9i",
      "arn:aws:secretsmanager:eu-west-1:111122223333:secret:aes192-4D5e6F",
    ]
    # Provide Atlantis permission necessary to create/destroy resources
    tasks_iam_role_policies = {
      AdministratorAccess = "arn:aws:iam::aws:policy/AdministratorAccess"
    }
  }
  service_subnets = ["subnet-xyzde987", "subnet-slkjf456", "subnet-qeiru789"]
  vpc_id          = "vpc-1234556abcdef"

  tags = {
    Environment = "dev"
    Terraform   = "true"
  }
}

Utilize EFS for Persistent Storage

You can enable EFS to ensure that any plan outputs are persisted to EFS in the event that the Atlantis Task is replaced:

```hcl
module "atlantis" {
  source  = "terraform-aws-modules/atlantis/aws"

  # Truncated for brevity ...

  # EFS
  enable_efs = true
  efs = {
    mount_targets = {
      "eu-west-1a" = {
        subnet_id = "subnet-xyzde987"
      }
      "eu-west-1b" = {
        subnet_id = "subnet-slkjf456"
      }
      "eu-west-1c" = {
        subnet_id = "subnet-qeiru789"
      }
    }
  }
}

Supply Atlantis server configuration

server-atlantis.yaml

repos:
  - id: /.*/
    allow_custom_workflows: true
    allowed_overrides:
      - apply_requirements
      - workflow
    apply_requirements:
      - approved
    workflow: default

main.tf

module "atlantis" {
  source  = "terraform-aws-modules/atlantis/aws"

  # ...

  atlantis = {
    environment = [
      {
        name : "ATLANTIS_REPO_CONFIG_JSON",
        value : jsonencode(yamldecode(file("${path.module}/server-atlantis.yaml"))),
      },
    ]
  }
}

Examples

<!-- BEGIN_TF_DOCS -->

Requirements

NameVersion
<a name="requirement_terraform"></a> terraform>= 1.0

Providers

No providers.

Modules

NameSourceVersion
<a name="module_acm"></a> acmterraform-aws-modules/acm/aws5.0.0
<a name="module_alb"></a> albterraform-aws-modules/alb/aws9.1.0
<a name="module_ecs_cluster"></a> ecs_clusterterraform-aws-modules/ecs/aws//modules/cluster5.11.0
<a name="module_ecs_service"></a> ecs_serviceterraform-aws-modules/ecs/aws//modules/service5.11.0
<a name="module_efs"></a> efsterraform-aws-modules/efs/aws1.3.1

Resources

No resources.

Inputs

NameDescriptionTypeDefaultRequired
<a name="input_alb"></a> albMap of values passed to ALB module definition. See the ALB module for full list of arguments supportedany{}no
<a name="input_alb_https_default_action"></a> alb_https_default_actionDefault action for the ALB https listenerany<pre>{<br/> "forward": {<br/> "target_group_key": "atlantis"<br/> }<br/>}</pre>no
<a name="input_alb_security_group_id"></a> alb_security_group_idID of an existing security group that will be used by ALB. Required if create_alb is falsestring""no
<a name="input_alb_subnets"></a> alb_subnetsList of subnets to place ALB in. Required if create_alb is truelist(string)[]no
<a name="input_alb_target_group_arn"></a> alb_target_group_arnARN of an existing ALB target group that will be used to route traffic to the Atlantis service. Required if create_alb is falsestring""no
<a name="input_atlantis"></a> atlantisMap of values passed to Atlantis container definition. See the ECS container definition module for full list of arguments supportedany{}no
<a name="input_atlantis_gid"></a> atlantis_gidGID of the atlantis usernumber1000no
<a name="input_atlantis_uid"></a> atlantis_uidUID of the atlantis usernumber100no
<a name="input_certificate_arn"></a> certificate_arnARN of certificate issued by AWS ACM. If empty, a new ACM certificate will be created and validated using Route53 DNSstring""no
<a name="input_certificate_domain_name"></a> certificate_domain_nameRoute53 domain name to use for ACM certificate. Route53 zone for this domain should be created in advance. Specify if it is different from value in route53_zone_namestring""no
<a name="input_cluster"></a> clusterMap of values passed to ECS cluster module definition. See the ECS cluster module for full list of arguments supportedany{}no
<a name="input_cluster_arn"></a> cluster_arnARN of an existing ECS cluster where resources will be created. Required when create_cluster is falsestring""no
<a name="input_create"></a> createControls if resources should be created (affects nearly all resources)booltrueno
<a name="input_create_alb"></a> create_albDetermines whether to create an ALB or notbooltrueno
<a name="input_create_certificate"></a> create_certificateDetermines whether to create an ACM certificate or not. If false, certificate_arn must be providedbooltrueno
<a name="input_create_cluster"></a> create_clusterWhether to create an ECS cluster or notbooltrueno
<a name="input_create_route53_records"></a> create_route53_recordsDetermines whether to create Route53 A and AAAA records for the loadbalancerbooltrueno
<a name="input_efs"></a> efsMap of values passed to EFS module definition. See the EFS module for full list of arguments supportedany{}no
<a name="input_enable_efs"></a> enable_efsDetermines whether to create and utilize an EFS filesystemboolfalseno
<a name="input_name"></a> nameCommon name to use on all resources created unless a more specific name is providedstring"atlantis"no
<a name="input_route53_record_name"></a> route53_record_nameName of Route53 record to create ACM certificate in and main A-record. If null is specified, var.name is used instead. Provide empty string to point root domain name to ALB.stringnullno
<a name="input_route53_zone_id"></a> route53_zone_idRoute53 zone ID to use for ACM certificate and Route53 recordsstring""no
<a name="input_service"></a> serviceMap of values passed to ECS service module definition. See the ECS service module for full list of arguments supportedany{}no
<a name="input_service_subnets"></a> service_subnetsList of subnets to place ECS service withinlist(string)[]no
<a name="input_tags"></a> tagsA map of tags to add to all resourcesmap(string){}no
<a name="input_validate_certificate"></a> validate_certificateDetermines whether to validate ACM certificate using Route53 DNS. If false, certificate will be created but not validatedbooltrueno
<a name="input_vpc_id"></a> vpc_idID of the VPC where the resources will be provisionedstring""no

Outputs

NameDescription
<a name="output_alb"></a> albALB created and all of its associated outputs
<a name="output_cluster"></a> clusterECS cluster created and all of its associated outputs
<a name="output_efs"></a> efsEFS created and all of its associated outputs
<a name="output_service"></a> serviceECS service created and all of its associated outputs
<a name="output_url"></a> urlURL of Atlantis
<!-- END_TF_DOCS -->

Authors

Module is maintained by Anton Babenko with help from these awesome contributors.

License

Apache 2 Licensed. See LICENSE for full details.

Additional information for users from Russia and Belarus