Developer Tools AWS

Atlantis on AWS User Guide

| Product: Atlantis on AWS

Overview

This image runs Atlantis 0.46 (Apache-2.0), the open source server that automates Terraform and OpenTofu pull request workflows, on Ubuntu 24.04 LTS. Atlantis listens for webhooks from your Git provider and runs plan and apply on your pull requests, posting the plan output back to the pull request as a comment and locking each workspace so two changes cannot touch the same state at once. The single Go binary is run by an unprivileged atlantis system account under a systemd service that starts it on boot and restarts it on failure.

The bundled infrastructure-as-code engine is OpenTofu, not Terraform. OpenTofu 1.12 (Mozilla Public License 2.0) is installed at /usr/local/bin/tofu and Atlantis is configured with ATLANTIS_DEFAULT_TF_DISTRIBUTION=opentofu so it drives OpenTofu. OpenTofu is a fully open source, drop-in replacement for Terraform; Terraform itself moved to the Business Source License in version 1.6, so this image deliberately ships OpenTofu. If you prefer to run your own Terraform, you can install it and repoint the engine.

Atlantis serves its web UI (the locks and jobs dashboard) on the loopback address 127.0.0.1:4141 - the atlantis server process has no bind-address flag, so port 4141 is never opened in the security group. nginx fronts the application on port 80 and enforces HTTP Basic authentication for the dashboard, which is the only intended access path. On the first boot of every deployed instance a one-shot service generates a fresh per-instance web password, writes it into the nginx htpasswd file and to /root/atlantis-credentials.txt (mode 0600, root only), and sets the Atlantis base URL to the instance's public IP. Two instances launched from the same AMI never share a password, and no default password ships in the image.

Atlantis orchestrates nothing until you connect your own version control. The image ships with non-functional placeholder VCS credentials and a deny-all repository allowlist so the server starts and serves its dashboard, but it acts on no repository until you add your own GitHub, GitLab, Bitbucket or Azure DevOps credentials, webhook secret and allowlist (Step 7). Nothing is automated behind your back.

The default security group for this listing opens port 22 (SSH) and port 80 (HTTP) only.

Prerequisites

  • An AWS account subscribed to this product in AWS Marketplace.
  • An EC2 key pair in your target region for SSH access.
  • A security group allowing inbound TCP 22 (SSH) from your IP and TCP 80 (HTTP) from your users (and from your Git provider's webhook egress, if you connect a repository).
  • Recommended instance type: m5.large or larger.

Connecting to your instance

SSH in as the default login user for your operating system variant, using the key pair you launched with.

OS variant Login user Example
Ubuntu 24.04 ubuntu ssh -i your-key.pem ubuntu@<instance-public-ip>

Step 1 - Launch from the AWS Marketplace console

  1. Open the product page in AWS Marketplace and choose Continue to Subscribe, then Continue to Configuration.
  2. Select the software version and your AWS Region, then choose Continue to Launch.
  3. Choose an instance type (m5.large or larger), your VPC subnet, the security group described above, and your EC2 key pair.
  4. Launch the instance and wait for it to reach the running state with status checks passed.

Step 2 - Launch from the AWS CLI (alternative)

Replace the AMI id, key name, security group and subnet with your own values:

aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --instance-type m5.large \
  --key-name your-key \
  --security-group-ids sg-xxxxxxxx \
  --subnet-id subnet-xxxxxxxx \
  --metadata-options "HttpTokens=required" \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=atlantis}]'

Step 3 - Retrieve the per-instance web password

SSH to the instance and read the credentials file written on first boot. It is mode 0600 and owned by root, so read it with sudo:

sudo cat /root/atlantis-credentials.txt

You will see the unique URL and web password generated for this instance:

# Atlantis - generated on first boot by atlantis-firstboot.service
# This password is unique to this instance. Store it somewhere safe.

ATLANTIS_URL=http://203.0.113.10/
ATLANTIS_WEB_USER=admin
ATLANTIS_WEB_PASSWORD=... (unique per instance)

Step 4 - Sign in to the Atlantis dashboard

Browse to http://<instance-public-ip>/ and sign in with user admin and the password from Step 3. The dashboard shows the workspace Locks and running Jobs - both empty until you connect a repository - and the apply-lock controls.

The Atlantis locks and jobs dashboard served behind the authenticated nginx reverse proxy on port 80, showing the apply-lock control, an empty Locks section, an empty Jobs section, and the Atlantis 0.46.0 version footer

Step 5 - Verify the service and the OpenTofu engine

On the instance, confirm both services are active and check the Atlantis and OpenTofu versions. The unauthenticated liveness endpoint returns {"status":"ok"}:

systemctl is-active atlantis nginx
atlantis version
tofu version | head -1
curl -s http://127.0.0.1/healthz

Terminal output showing atlantis 0.46.0 and OpenTofu 1.12.4 (Mozilla Public License 2.0), the atlantis and nginx services both active, and the healthz endpoint returning status ok

The liveness endpoint is also reachable in a browser at http://<instance-public-ip>/healthz (no authentication - so load balancers and probes can hit it directly):

The Atlantis liveness endpoint rendered in a browser, returning the JSON object status ok

The dashboard itself refuses unauthenticated requests and accepts the per-instance password (substitute the password from Step 3):

# Without credentials the dashboard is refused (401)
curl -s -o /dev/null -w 'no-auth: %{http_code}\n' http://127.0.0.1/
# With the per-instance admin password it succeeds (200)
curl -s -o /dev/null -w 'auth:    %{http_code}\n' -u admin:YOUR_PASSWORD http://127.0.0.1/

Step 6 - Run the bundled OpenTofu plan round-trip self-test

Every instance ships a small self-test that runs a real OpenTofu plan through the same engine Atlantis drives, proving the plan machinery executes end to end before you connect any repository. Run it as the atlantis service user:

sudo -u atlantis bash /opt/cloudimg/atlantis-selftest/plan-proof.sh

It runs tofu init, tofu plan and tofu show against a tiny bundled configuration and asserts that the known resource is planned for creation and the known value appears in the saved plan, printing PLAN_PROOF_OK. You can inspect the plan yourself by copying /opt/cloudimg/atlantis-selftest/main.tf into a working directory owned by the atlantis user and running tofu init then tofu plan - the plan reports one resource to add:

  # terraform_data.cloudimg_plan_probe will be created
  + resource "terraform_data" "cloudimg_plan_probe" {
      + input  = "cloudimg-atlantis-plan-proof"
    }
Plan: 1 to add, 0 to change, 0 to destroy.

Terminal output of the OpenTofu plan round-trip self-test showing the resource terraform_data.cloudimg_plan_probe will be created, Plan 1 to add, and PLAN_PROOF_OK - real plan content, not merely an HTTP 200

Step 7 - Connect your Git provider and webhook

Atlantis does nothing until you connect it to your own version control. Edit the environment file and replace the placeholder values:

sudo nano /etc/atlantis/atlantis.env

Set your VCS credentials and replace the deny-all allowlist with your own repositories. For GitHub:

ATLANTIS_GH_USER=your-github-user
ATLANTIS_GH_TOKEN=your-personal-access-token
ATLANTIS_GH_WEBHOOK_SECRET=a-long-random-secret
ATLANTIS_REPO_ALLOWLIST=github.com/your-org/*

GitLab, Bitbucket and Azure DevOps are supported with the equivalent ATLANTIS_GITLAB_*, ATLANTIS_BITBUCKET_* and ATLANTIS_AZUREDEVOPS_* variables. Restart Atlantis to apply:

sudo systemctl restart atlantis

Then add a webhook in your repository pointing at your instance:

  • Payload URL: http://<instance-public-ip>/events
  • Content type: application/json
  • Secret: the same value as ATLANTIS_GH_WEBHOOK_SECRET
  • Events: Pull requests, Pushes, Issue comments

Open a pull request and comment atlantis plan - Atlantis clones the repository, runs the OpenTofu plan and posts the result back on the pull request.

Step 8 - Enable HTTPS (recommended)

A continuous-delivery server that can run apply against your cloud is a high-value target, so run it over TLS. Terminate HTTPS at an upstream AWS Application Load Balancer or CloudFront, or install a certificate directly on the instance with Let's Encrypt:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

Point your webhook at the https:// URL once TLS is in place.

Step 9 - Maintenance

  • Configuration: /etc/atlantis/atlantis.env (server flags, VCS credentials, allowlist).
  • Service management: sudo systemctl status atlantis and sudo systemctl status nginx.
  • Web password: stored in /root/atlantis-credentials.txt; rotate it by editing the nginx htpasswd with sudo htpasswd /etc/nginx/.htpasswd admin and reloading nginx.
  • Logs: sudo journalctl -u atlantis -f.
  • Data: ephemeral repository clones and plan working directories live under /var/lib/atlantis; durable infrastructure state lives in your own OpenTofu/Terraform backend, not on this instance.

Support

cloudimg provides 24/7 technical support for this product by email and live chat, with a one-hour average response for critical issues. Our engineers help with deployment, connecting Git providers and webhooks, repository allowlists, workflow customization, OpenTofu, TLS termination and upgrades.