| name | atlantis |
| description | Atlantis — automated Terraform/OpenTofu pull request workflow with plan and apply via PR comments. Use this skill whenever the user needs to automate Terraform plan/apply on PRs, enforce code review before infrastructure changes, set up GitOps for infrastructure, configure Atlantis server with repo-level workflow overrides, or prevent unapproved Terraform applies. Trigger for "atlantis terraform", "atlantis plan", "atlantis apply", "terraform pr automation", "infrastructure gitops atlantis", or "terraform code review workflow". |
Atlantis — Terraform Pull Request Automation
Overview
Atlantis is a self-hosted application that listens for GitHub/GitLab/Bitbucket webhook events and runs terraform plan and terraform apply automatically when pull requests touch Terraform or OpenTofu code. Engineers comment atlantis plan on a PR to see the plan output, and atlantis apply to apply after approval. Atlantis enforces that every infrastructure change is reviewed, planned, and applied via version control — eliminating one-off manual applies from engineers' laptops. It runs as a single stateless binary or Kubernetes Deployment.
When to Use
- Enforcing peer review for all infrastructure changes (Terraform/OpenTofu)
- Getting plan output visible in PRs without granting engineers direct Terraform access
- Preventing unreviewed
terraform apply from engineer laptops
- Setting up GitOps for infrastructure (apply on merge to main)
- Workspace-per-PR workflows with parallel plan/apply across multiple environments
- CI/CD integration for infrastructure with mandatory approvals
Installation
brew install atlantis
atlantis server \
--atlantis-url="https://atlantis.mycompany.com" \
--gh-user="atlantis-bot" \
--gh-token="$GITHUB_TOKEN" \
--gh-webhook-secret="$WEBHOOK_SECRET" \
--repo-allowlist="github.com/myorg/*"
Key Patterns
Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: atlantis
namespace: atlantis
spec:
replicas: 1
selector:
matchLabels:
app: atlantis
template:
metadata:
labels:
app: atlantis
spec:
serviceAccountName: atlantis
containers:
- name: atlantis
image: ghcr.io/runatlantis/atlantis:v0.29.0
args:
- server
env:
- name: ATLANTIS_ATLANTIS_URL
value: "https://atlantis.mycompany.com"
- name: ATLANTIS_REPO_ALLOWLIST
value: "github.com/myorg/*"
- name: ATLANTIS_GH_USER
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: gh-user
- name: ATLANTIS_GH_TOKEN
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: gh-token
- name: ATLANTIS_GH_WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: webhook-secret
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: aws-access-key-id
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: aws-secret-access-key
ports:
- containerPort: 4141
volumeMounts:
- name: atlantis-data
mountPath: /atlantis
- name: repo-config
mountPath: /etc/atlantis
volumes:
- name: atlantis-data
persistentVolumeClaim:
claimName: atlantis-data
- name: repo-config
configMap:
name: atlantis-repo-config
---
apiVersion: v1
kind: Service
metadata:
name: atlantis
namespace: atlantis
spec:
ports:
- port: 80
targetPort: 4141
selector:
app: atlantis
Server-Side Config — repos.yaml
repos:
- id: "github.com/myorg/.*"
apply_requirements:
- approved
- mergeable
allowed_overrides:
- apply_requirements
- workflow
- delete_source_branch_on_merge
allow_custom_workflows: true
workflows:
default:
plan:
steps:
- init
- plan
apply:
steps:
- apply
production:
plan:
steps:
- init
- run: echo "Planning production infrastructure..."
- plan:
extra_args: ["-detailed-exitcode"]
apply:
steps:
- run: echo "Applying production infrastructure - be careful!"
- apply
Repo-Level Config — atlantis.yaml
version: 3
automerge: false
delete_source_branch_on_merge: false
projects:
- name: "networking-dev"
dir: infrastructure/networking
workspace: dev
terraform_version: v1.9.0
workflow: default
apply_requirements:
- approved
- name: "networking-prod"
dir: infrastructure/networking
workspace: prod
workflow: production
apply_requirements:
- approved
- mergeable
branch: main
- name: "app-cluster-dev"
dir: infrastructure/eks
workspace: dev
autoplan:
when_modified:
- "*.tf"
- "../modules/**/*.tf"
enabled: true
- name: "app-cluster-prod"
dir: infrastructure/eks
workspace: prod
autoplan:
enabled: false
GitHub Webhook Setup
PR Workflow — Commands
# In a GitHub PR comment:
atlantis help # show available commands
atlantis plan # run terraform plan on all modified projects
atlantis plan -p networking-prod # plan a specific project
atlantis apply # apply all projects that have been planned and approved
atlantis apply -p networking-prod # apply a specific project
atlantis unlock # unlock the workspace (if a plan lock is stuck)
# Approval flow:
# 1. Engineer opens PR with Terraform changes
# 2. Atlantis auto-comments the plan output (if autoplan enabled)
# 3. Reviewer approves PR on GitHub
# 4. Engineer comments "atlantis apply"
# 5. Atlantis applies and comments with the output
IRSA — AWS Credentials Without Static Keys (EKS)
apiVersion: v1
kind: ServiceAccount
metadata:
name: atlantis
namespace: atlantis
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/AtlantisRole
Custom Workflow — Terraform with Vault Secrets
workflows:
vault-backed:
plan:
steps:
- run: vault login -method=aws role=atlantis
- run: eval $(vault kv get -format=json secret/tf/aws | jq -r '.data.data | to_entries[] | "export \(.key)=\(.value)"')
- init
- plan
apply:
steps:
- run: vault login -method=aws role=atlantis
- run: eval $(vault kv get -format=json secret/tf/aws | jq -r '.data.data | to_entries[] | "export \(.key)=\(.value)"')
- apply
Common Commands
atlantis server --help
atlantis testdrive
atlantis version
Pitfalls
- Atlantis holds workspace locks: while a plan or apply is running, the workspace is locked — if a plan fails or an engineer abandons a PR, others cannot plan/apply the same workspace; use
atlantis unlock to release
- Only one replica: Atlantis uses a local filesystem lock mechanism and cannot scale horizontally — run exactly one replica; for HA, use the webhook queue or a managed Atlantis (e.g., Spacelift)
autoplan triggers on any .tf change: if modules are shared across many projects, a change to modules/vpc/main.tf may trigger plans for all projects that include "../modules/**/*.tf" — size your server accordingly
- GitHub token permissions: the bot token needs
repo scope (or at minimum: repo:status, public_repo or repo, read:org for org-level webhooks) — scoping too tightly causes silent failures where Atlantis can't comment on PRs
- Plan files are ephemeral: Atlantis saves plan files to disk between
plan and apply; if the pod restarts between the two commands, the plan file is lost and the engineer must re-plan
Related Skills
opentofu — Atlantis works equally well with OpenTofu via terraform_version or custom workflow
argocd — complementary GitOps for application deployments (Atlantis for infra, ArgoCD for apps)
hashicorp-vault — inject Vault secrets into Atlantis workflows
flux-cd — alternative GitOps approach for Kubernetes infra
github-actions-ci-workflow — complement Atlantis with CI for terraform validate and lint
GitNexus Index
Index path: /Users/localuser/.claude/skills/atlantis/.gitnexus
Created: 2026-05-24