

A pull request lands in your repo at 11am. It changes three Terraform modules touching your AWS networking stack. Your team wants to review the plan output before anyone runs apply. Without tooling, that means opening a terminal, assuming the right credentials, running plan locally, pasting the output into a PR comment, and hoping nobody else applies something conflicting while you wait for approval.
That workflow fails at scale. Credentials diverge between engineers. Plans run against different state versions. Someone applies from a feature branch that wasn't reviewed. Atlantis was built specifically to fix this: it moves Terraform execution off local machines and into the pull request itself, making plan output a first-class part of code review.
The part most tutorials skip is the GitHub App setup path. The official docs mention it but don't make clear it's the right default for any team larger than one. That and the production security configuration are where teams most often get tripped up.
Last updated: May 2026.
At a glance Atlantis is an open-source Infrastructure as Code (IaC) workflow tool that runs Terraform, OpenTofu, and Terragrunt operations through Git pull requests. Current version: v0.42.0 (April 21, 2026). License: Apache 2.0. It listens for VCS webhooks from GitHub, GitLab, Bitbucket, or Azure DevOps, runs plan and apply on a dedicated server, and posts results back as PR comments. No SaaS offering. Self-hosted only.
How Atlantis fits into a Terraform workflow
Atlantis is a self-hosted daemon that sits between your Git provider and your Terraform state. When a pull request opens or updates, Atlantis receives a webhook, clones the repo, and runs terraform plan against the affected directories. The plan output shows up in the PR as a comment. Reviewers see exactly what will change in infrastructure before approving. Once a reviewer comments atlantis apply, Atlantis executes the apply and locks the relevant workspace so no other PR can interfere. The merge completes only after the apply succeeds. That loop (plan on open, apply on comment, lock release on merge) is the core contract Atlantis provides.
How the Atlantis workflow runs, end to end
From PR open to merge: the request lifecycle
When a developer opens a pull request against a repo that Atlantis is watching, three things happen in sequence. Atlantis receives the webhook from your VCS, determines which Terraform directories were modified by diffing the changed files against your project configuration, then kicks off a terraform plan for each affected project.
The plan output gets posted directly to the PR as a comment, including the resource additions, changes, and destructions. If you have policy checks configured through OPA or Conftest, those results appear in the same comment thread. Your team reviews the diff and the plan side by side.
To apply, a reviewer with the right permissions posts a comment: atlantis apply. Atlantis picks it up, runs the apply, and posts the result. If the apply succeeds, Atlantis optionally auto-merges the PR. If it fails, the PR stays open and the error appears as a comment so the team can diagnose it inline. After fixing the code, posting atlantis plan again re-runs the plan and clears the stale state.
PR comment quick reference:
| Comment | What it does |
|---|---|
atlantis plan |
Manually triggers a plan (or re-plans after a fix) |
atlantis apply |
Applies the most recent plan for this PR |
atlantis unlock |
Releases the project lock so another PR can proceed |
atlantis cancel |
Cancels any queued operations (added v0.39.0) |
atlantis plan -d <dir> |
Plans a specific directory in the repo |
atlantis plan -p <project> |
Plans a named project from atlantis.yaml |
Locks, plans, and the apply gate
Atlantis serializes access to each Terraform project using a locking mechanism. When a plan runs for a PR, that PR holds the lock on the project until it's either merged or the lock is manually released with atlantis unlock. This prevents two PRs from applying conflicting changes to the same state.
The apply gate is where Atlantis enforces discipline. You can require that a plan has been run and has not become stale (meaning no new commits have been pushed since the last plan), require a minimum number of approvals on the PR, or require that specific status checks pass. These requirements live in your server-side repos.yaml configuration, not in the repo itself, which matters for security. A developer cannot check in an atlantis.yaml that bypasses the approval requirements you defined at the server level.
Starting with v0.39.0, Atlantis added an atlantis cancel command for clearing queued operations that are stuck or no longer relevant, which helps in monorepos where a failed plan can block subsequent work on unrelated directories.
Setting up Atlantis for a real team
Prerequisites
Atlantis v0.42.0 (the current stable release as of April 2026) requires:
- Terraform 1.0+ or OpenTofu 1.6+ installed on the Atlantis server
- A publicly accessible HTTPS endpoint (Atlantis needs to receive webhooks from your VCS)
- Network access from Atlantis to your cloud provider APIs and state backend
- A service account or IAM role for cloud credentials
This guide uses GitHub for VCS setup examples. Atlantis also supports GitLab, Bitbucket, and Azure DevOps — the VCS-specific webhook and credential config differs for each.
For local testing, the Atlantis docs include a test drive guide using ngrok to expose a local server. Production deployments should use a stable URL from a load balancer or reverse proxy.
GitHub App vs Personal Access Token: when to use each
Atlantis supports two authentication methods for GitHub. The choice matters more than the docs suggest.
A Personal Access Token (PAT) works: create a GitHub user, grant the token repo scope, add the credentials to Atlantis. Comments on PRs appear as that user. It's quick to set up and fine for a single team evaluating Atlantis.
For anything running in production, use a GitHub App. The reasons are concrete. A GitHub App authenticates as an installation rather than a user, so it doesn't break when someone's account is deactivated or loses org access. It supports more granular permissions: rather than full repo scope, you grant exactly what Atlantis needs: read/write for pull requests, commit statuses, issues, and contents. You can also share a single GitHub App across multiple Atlantis installations, which matters if you run separate instances for different teams or environments.
To create a GitHub App for Atlantis, open https://<your-atlantis-host>/github-app/setup while Atlantis is running; it walks through the GitHub App creation flow and handles the manifest automatically. The app needs these repository permissions: Administration (read-only), Checks (read and write), Commit statuses (read and write), Contents (read and write), Issues (read and write), Pull requests (read and write).
Webhook configuration and the /events suffix gotcha
The webhook URL is https://your-atlantis-host/events. The /events suffix is required and missing it is the most common setup mistake. Atlantis will appear healthy but silently receive no events.
Configure your webhook with content type application/json. Subscribe to: Pull requests, Issue comments, Pushes, and Pull request reviews. Generate a webhook secret of at least 24 characters and pass it to Atlantis as ATLANTIS_GH_WEBHOOK_SECRET. Atlantis validates the HMAC signature on every incoming webhook, rejecting any that don't match. This is the primary protection against spoofed plan or apply commands.
Running Atlantis: Docker, Helm, and the binary
Atlantis ships as a Docker image (ghcr.io/runatlantis/atlantis:v0.42.0) and as a standalone binary. The official deployment documentation covers AWS ECS, GKE, and bare-metal configurations.
For Kubernetes, the community-maintained Helm chart is the standard path. A minimal production Helm values file looks like this:
atlantis:
orgAllowlist: "github.com/yourorg/*"
githubUser: "atlantis-bot"
githubToken: "<PAT or app token>"
githubWebhookSecret: "<your webhook secret>"
repoConfig: |
repos:
- id: "/.*/"
apply_requirements: [approved, mergeable, undiverged]
delete_source_branch_on_merge: true
environment:
ATLANTIS_WRITE_GIT_CREDS: "true"
AWS_ROLE_ARN: "arn:aws:iam::123456789:role/atlantis-role"
AWS_WEB_IDENTITY_TOKEN_FILE: "/var/run/secrets/eks.amazonaws.com/serviceaccount/token"
Set orgAllowlist to limit which repositories Atlantis accepts webhooks from. Without it, any repo that points to your Atlantis endpoint can trigger plan and apply commands.
Configuring atlantis.yaml for multi-project repos
Repo-level config: the atlantis.yaml file
The atlantis.yaml file lives in the root of each repository and tells Atlantis how to treat the projects inside it. Without this file, Atlantis uses autodetect: it finds every directory containing a .tf file and treats each as a separate project. That works for simple repos, but breaks in monorepos with dozens of modules where you want explicit control.
A typical atlantis.yaml for a repo with separate staging and production environments:
version: 3
projects:
- name: networking-staging
dir: envs/staging/networking
workspace: staging
autoplan:
when_modified: ["*.tf", "../../modules/**/*.tf"]
enabled: true
apply_requirements: [approved]
- name: networking-production
dir: envs/production/networking
workspace: production
autoplan:
when_modified: ["*.tf", "../../modules/**/*.tf"]
enabled: true
apply_requirements: [approved, mergeable]
The when_modified array is glob-matched against the changed files in the PR. Including ../../modules/**/*.tf means a change to a shared module triggers plans for every project that uses it, which is exactly what you want when a module update touches networking, compute, and database stacks simultaneously.
Server-side repos.yaml: the part that actually controls security
The atlantis.yaml in each repo configures projects, but it doesn't control security requirements; developers can modify that file. The repos.yaml on the Atlantis server does, and it cannot be overridden by anything in a repository.
repos:
- id: "github.com/yourorg/.*"
allowed_overrides: [apply_requirements, workflow]
allow_custom_workflows: false
apply_requirements: [approved, mergeable, undiverged]
Setting allow_custom_workflows: false prevents repos from defining their own workflow blocks that could bypass your standard plan/apply commands. The apply_requirements: [undiverged] key, added in v0.42.0 as a targeted requirement, blocks applies when the PR branch has drifted from the base branch, preventing the scenario where two PRs each plan against the current state but the second apply runs against state that the first apply already changed.
Working with Terragrunt and OpenTofu
Atlantis supports Terragrunt through custom workflows. You point Atlantis at the Terragrunt binary rather than Terraform and configure extra_args to pass Terragrunt-specific flags:
workflows:
terragrunt:
plan:
steps:
- run: terragrunt run -- plan -out=$PLANFILE
apply:
steps:
- run: terragrunt run -- apply $PLANFILE
The run -- form is the recommended syntax in Terragrunt 1.0+. The shortcut forms (terragrunt plan, terragrunt apply) remain supported for backward compatibility, but run -- is explicit about which arguments go to Terragrunt and which pass through to the underlying Terraform or OpenTofu binary.
For OpenTofu, Atlantis uses the ATLANTIS_DEFAULT_TF_VERSION environment variable or a atlantis.yaml terraform_version field to select the binary. Point these at an OpenTofu binary installed on your Atlantis server. As of v0.42.0, Atlantis treats OpenTofu and Terraform as interchangeable at the execution layer; the locking, commenting, and approval mechanics work identically.
Related reading: The complete guide to Terragrunt. Covers unit configuration, stack orchestration, and how Terragrunt's dependency graph compares to native Terraform module calls.
Production hardening: security and operations
Webhook secrets and signature verification
Every incoming webhook from GitHub should be verified against a shared HMAC secret. Atlantis does this by default when ATLANTIS_GH_WEBHOOK_SECRET is set. Use a randomly generated secret of at least 24 characters, rotate it periodically, and store it in your secret manager rather than in environment variables baked into your container image.
Beyond the HMAC signature, Atlantis respects the orgAllowlist setting to reject webhooks from unknown repos. Set this to your organization's namespace (github.com/yourorg/*) even if your Atlantis instance is behind a VPN; the defense-in-depth is worth the one-line config.
Cloud credentials: IAM roles vs static keys
Atlantis runs terraform plan and terraform apply with whatever credentials it has. This makes its credential posture critical.
The right approach for AWS is IRSA (IAM Roles for Service Accounts) on EKS or instance profiles on EC2, with no static access keys in the environment. The role needs write access to your state backend (S3, DynamoDB for locking) and whatever permissions your Terraform modules require. Use separate roles for staging and production Atlantis deployments; don't share credentials across environments.
For multi-cloud setups, the same principle applies: workload identity on GKE, Managed Identity on AKS. Atlantis can be configured with per-project credentials using env blocks in workflows, which lets a single Atlantis installation manage workspaces that span cloud providers without sharing a single broad credential set.
Backend state, locking, and high availability
Atlantis itself does not provide high availability. It's a single process, and its built-in locking is in-memory; if the process restarts mid-apply, locks are lost. For most teams, a well-monitored single instance with automatic restart (via Kubernetes) is sufficient.
If you run Terraform with a remote backend that has native locking (S3 + DynamoDB, GCS, Azure Blob Storage, or Terraform Cloud), that locking layer protects you even if Atlantis restarts; the state backend will reject concurrent applies. The Atlantis lock is a coordination mechanism on top, not the only protection.
Related reading: A guide to Terraform state backends. Covers S3, GCS, and Azure state configuration and the tradeoffs between them.
Policy checks and approvals
Atlantis has built-in support for OPA/Conftest policy checking via the conftest binary. When enabled, Atlantis runs your Rego policies against the plan output after terraform plan completes. Policy failures block the apply without requiring you to integrate a separate CI step.
Configure policies in the server-side repos.yaml:
policies:
owners:
users:
- policy-admin
policy_sets:
- name: infra-baseline
path: /etc/atlantis/policies
source: local
The owners section defines who can dismiss a policy failure if a team lead decides to override. Without owners configured, policy failures are hard blocks with no escape hatch.
For teams already using OPA on their CI pipelines, this integration is straightforward. For teams starting with policy as code, the env0 post on Open Policy Agent and infrastructure governance covers the Rego fundamentals before you wire them into Atlantis.
Where Atlantis hits its limits
Atlantis is excellent at the problem it was designed for: running plan and apply through pull requests. But several organizational needs sit outside that scope, and teams run into them in a fairly predictable order as they grow.
Drift is usually the first thing that breaks. Atlantis only acts on PRs, so it has no mechanism to detect when live infrastructure diverges from Terraform state between deployments: a manual change in the cloud console, an incident-response workaround, or a resource deleted outside Terraform. Drift builds silently until it causes an incident. The common workaround is a scheduled CI job running terraform plan against each workspace, but this produces noisy output with no triage layer and doesn't scale past a dozen stacks before someone starts ignoring the alerts.
The second limit teams hit is output verbosity. A plan touching 200 resources produces a comment GitHub truncates. v0.41.0 introduced "intelligent comment splits" to break long output across multiple comments, but 50-module monorepos still generate PR threads that are hard to review efficiently. Setting ATLANTIS_HIDE_UNCHANGED_PLAN_COMMENTS=true reduces noise for unchanged projects, which helps in monorepos where most projects aren't touched by a given PR.
After those two, teams typically run into:
No built-in high availability. One Atlantis server, one in-memory lock table. Teams running mission-critical infrastructure deployments often find themselves building their own restart-and-recovery procedures. We've seen the operational runbook for Atlantis recovery grow longer than the Terraform modules it's running.
No UI for non-engineers. Atlantis is entirely comment-driven. A developer on an application team who needs to spin up a staging environment, or a finance analyst who wants to see what infrastructure exists, has no interface. Everything requires understanding Git and Terraform.
No cost estimation. Atlantis shows you what will change in infrastructure but not what it will cost. Catching a configuration that accidentally provisions a p4d.24xlarge requires a human reviewer who happens to know the pricing.
Scaling friction at the platform level. Managing Atlantis configuration across dozens of teams, enforcing consistent repos.yaml policies, keeping the binary current, and onboarding new teams without a service catalog or self-service layer requires ongoing platform engineering investment that compounds with org size.
When you need more than Atlantis: env zero
The teams that ask us about moving off Atlantis have usually hit drift detection first, then the HA question, then the non-engineer interface problem, in roughly that order. Each one is manageable in isolation. All three at once, across 50+ workspaces and multiple business units, is when Atlantis starts requiring workarounds that cost more to maintain than the tool saves.
env zero runs the same PR comment workflow as Atlantis: plan and apply from pull request comments, applied to Terraform, OpenTofu, Terragrunt, and Pulumi, from a managed control plane. There is no Atlantis server to provision, no repos.yaml to version-control, no webhook secret rotation on your schedule.
The governance layer is where the difference becomes concrete. Continuous drift detection runs against every environment on a configurable schedule and surfaces deviations with cause analysis, not a raw plan diff. Approval policies connect to your identity provider and can require different chains for staging versus production without separate config files per team. Cost estimation is built in: a PR that would increase monthly spend by $4,000 gets flagged before anyone approves the apply. The Service Catalog gives application teams a self-service interface for provisioning approved infrastructure templates without touching Terraform directly.
Adaptavist migrated 700 environments to env zero in five months with zero developer retraining. That number (zero retraining) holds because the PR comment workflow developers already know carries over exactly. For teams already running on Atlantis, env zero can import existing Terraform workspaces and state without affecting running infrastructure. The migration guide covers the state import and PR workflow setup step by step.
Related reading: OpenTofu vs Terraform: a practical guide for enterprise teams. Relevant context if your team is evaluating the move from Terraform to OpenTofu alongside your Atlantis setup.
Try it with env zero
env zero runs the same PR-driven Terraform workflow as Atlantis, without the self-hosted server, in-memory lock management, or drift blind spots. Connect your first repo and the PR comment workflow works on day one, with no server to provision.
Start a free trial or book a demo.
References
- Atlantis documentation: official installation guide, configuration reference, and deployment patterns
- Atlantis v0.42.0 release notes: April 2026; targeted undiverged requirement, GitHub ruleset approval fixes
- Atlantis access credentials documentation: GitHub App vs PAT permissions and setup
- Atlantis repo-level atlantis.yaml reference: project configuration syntax
- Atlantis server-side repo configuration: repos.yaml reference for org-level policy
- Atlantis policy checking: OPA/Conftest integration guide
- Atlantis security documentation: webhook security, network hardening
- env zero PR comment documentation: plan and apply from pull request comments in env zero
Frequently asked questions
Is Atlantis still actively maintained in 2026?
Yes. Atlantis released v0.42.0 in April 2026 and continues to receive regular updates. The project has a healthy contribution history and is widely used in production at organizations of all sizes. It does not have commercial backing, so critical fixes depend on community contributors and pull request reviewers.
Does Atlantis work with OpenTofu?
Yes. Atlantis treats OpenTofu as a drop-in replacement for Terraform at the execution layer. Install the OpenTofu binary on your Atlantis server, set ATLANTIS_DEFAULT_TF_VERSION to point to it (or use the terraform_version field in atlantis.yaml), and plan and apply commands run against OpenTofu. Locking, commenting, and approval mechanics are identical. For a deeper comparison of the two runtimes, see the env zero guide to OpenTofu vs Terraform for enterprise teams.
What's the difference between Atlantis and Terraform Cloud / HCP Terraform?
Atlantis is self-hosted, open-source, and Git-comment-driven. Terraform Cloud (now HCP Terraform) is HashiCorp's managed offering with a web UI, per-seat pricing, private module registry, and Sentinel policy engine. The core automation model differs too: Atlantis runs on PR events and comment triggers; Terraform Cloud runs on pushes to specific branches in addition to API-triggered runs. Atlantis gives you more control over the execution environment; Terraform Cloud abstracts the server management away. The env zero post on Terraform Cloud alternatives covers a detailed breakdown of how these options compare.
GitHub App or Personal Access Token: which should I use?
Use a GitHub App for any production Atlantis deployment. It authenticates as an installation rather than a user account, supports granular permissions (no need for full repo scope), and doesn't break when someone's GitHub account is deactivated or removed from the organization. PATs are fine for local testing or a single-developer evaluation, but they're a maintenance and security risk in shared environments.
How do I run Atlantis with high availability?
Atlantis does not have a built-in HA mode. Its locking is in-memory, so a single process handles all coordination. The practical approach is to run one Atlantis server managed by Kubernetes with automatic restart, and rely on your Terraform remote backend's native locking (S3+DynamoDB, GCS, etc.) as the true concurrency guard. If the Atlantis process restarts mid-apply, the state backend lock guarantees the apply either completes or surfaces a lock error on retry. For organizations that need zero-downtime infrastructure deployment pipelines, this limitation is often what drives the move to a managed platform.
Can env zero replace Atlantis?
Yes. env zero runs the same PR-comment workflow as Atlantis (developers comment plan or apply on a pull request and get results posted back), without the self-hosted server. It adds drift detection, built-in cost estimation, role-based access control, and a self-service portal for non-engineers. Teams that are outgrowing Atlantis typically migrate because they need governance and drift detection that Atlantis doesn't provide, not because the PR workflow model is wrong. The Atlantis to env zero migration guide covers the full transition with state import.

.webp)

![Using Open Policy Agent (OPA) with Terraform: Tutorial and Examples [2026]](https://cdn.prod.website-files.com/63eb9bf7fa9e2724829607c1/69d6a3bde2ffe415812d9782_post_th.png)