Atlantis on Ubuntu 24.04 on Azure User Guide
Overview
Atlantis is an open-source self-hosted server that automates Terraform through your pull requests. It listens for webhooks from GitHub, GitLab, Bitbucket or Azure DevOps and, when someone opens a pull request, runs terraform plan and posts the plan output back to the PR as a comment. A reviewer types atlantis apply in the PR and Atlantis runs terraform apply, locking the workspace so two pull requests can never modify the same state concurrently. The cloudimg image installs Atlantis 0.44.0 as a single Go binary at /usr/local/bin/atlantis, runs it as a dedicated atlantis system user, fronts its web UI with an nginx reverse proxy on TCP 80 with HTTP Basic auth, bundles a base Terraform 1.15.6 binary, and generates a unique web password on the first boot of every VM. Backed by 24/7 cloudimg support.
What is included:
- Atlantis 0.44.0 at
/usr/local/bin/atlantis - Terraform 1.15.6 at
/usr/local/bin/terraform(Atlantis can also manage per-project Terraform versions on demand) - The Atlantis web UI (the locks and jobs dashboard), fronted by nginx on
:80 - nginx HTTP Basic auth with a per-VM password in a root-only file, plus an unauthenticated
/healthzliveness endpoint - A ready-to-edit
/etc/atlantis/atlantis.envso you connect your own VCS provider, webhook secret and repo-allowlist atlantis.service+nginx.serviceas systemd units, enabled and active- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point; scale up for larger Terraform states and more concurrent plans. NSG inbound: allow 22/tcp from your management network and 80/tcp so your VCS provider's webhook delivery and your browser can reach the server (front with TLS for public exposure — see Enabling HTTPS). You also need a Git repository (GitHub is used in the examples below) and permission to add a webhook and a bot access token to it.
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Atlantis by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create → Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name atlantis \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name atlantis --port 80 --priority 1010
Step 3 — Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 — Confirm the services are running
systemctl is-active atlantis.service nginx.service
Both services report active. Atlantis starts in seconds; until you connect a repository it runs with a deny-all repo-allowlist and acts on nothing.
Step 5 — Retrieve your web password
The web password is generated uniquely on the first boot of your VM and written to a root-only file:
sudo cat /root/atlantis-credentials.txt
This file contains ATLANTIS_WEB_USER (admin) and ATLANTIS_WEB_PASSWORD, plus the URLs for the web UI, the /healthz liveness endpoint and the /events webhook endpoint. Store the password somewhere safe.
Step 6 — Check the health endpoints
nginx serves an unauthenticated static health endpoint for load balancers, and proxies Atlantis's own /healthz liveness endpoint without authentication:
curl -s http://localhost/health
curl -s http://localhost/healthz
/health returns ok and /healthz returns {"status":"ok"}.

Step 7 — Open the web UI
Browse to http://<vm-public-ip>/ and sign in as admin with the password from Step 5. The Atlantis dashboard lists active workspace Locks and recent Jobs, and lets you enable or disable apply commands globally. Before you connect a repository both sections read "No locks found" and "No jobs found" — this is the expected empty state of a fresh server.

Step 8 — Confirm the bundled binaries
The image ships both Atlantis and a base Terraform so the server is ready to run plans the moment you connect a repository:
sudo /usr/local/bin/atlantis version
/usr/local/bin/terraform version
These report Atlantis 0.44.0 and Terraform v1.15.6.

Step 9 — Connect your GitHub repository
Atlantis needs three things to act on a repository: a bot user and access token so it can read the repo and write PR comments, a shared webhook secret so it can verify incoming webhooks, and a repo-allowlist that names which repositories it is permitted to touch. The image ships these as placeholders in /etc/atlantis/atlantis.env; you replace them with your own.

First, on GitHub, create a Personal Access Token (classic) for a bot user with the repo scope, and decide on a random webhook secret string. Then, on the VM, edit the environment file:
sudo nano /etc/atlantis/atlantis.env
Set these four values (use your own bot user, token, secret and organisation):
ATLANTIS_REPO_ALLOWLIST=github.com/your-org/*
ATLANTIS_GH_USER=your-github-bot-user
ATLANTIS_GH_TOKEN=ghp_your_real_token
ATLANTIS_GH_WEBHOOK_SECRET=your-shared-webhook-secret
Restart Atlantis to apply the change:
sudo systemctl restart atlantis
The repo-allowlist supports wildcards: github.com/your-org/* allows every repository in your organisation, github.com/your-org/infra allows a single repository. Atlantis will refuse any pull request from a repository that does not match the allowlist.
Step 10 — Add the webhook to your repository
In your GitHub repository, open Settings → Webhooks → Add webhook and configure:
- Payload URL:
http://<vm-public-ip>/events - Content type:
application/json - Secret: the same value you set for
ATLANTIS_GH_WEBHOOK_SECRET - Events: select Let me select individual events, then tick Pull requests, Pushes and Issue comments
Save the webhook. GitHub sends a ping that Atlantis verifies against the shared secret. The /events endpoint is intentionally served without HTTP Basic auth because the webhook secret is its authentication — GitHub cannot send Basic-auth credentials.
Step 11 — Try it on a pull request
Add a Terraform configuration to your repository, open a pull request that changes it, and Atlantis automatically comments with the terraform plan output. The workspace is now Locked, which you can see in the web UI's Locks section. Comment atlantis apply on the pull request to run terraform apply; comment atlantis unlock (or merge the PR) to release the lock. The startup log confirms Atlantis is listening and which VCS host it supports:

GitLab, Bitbucket and Azure DevOps work the same way — set the corresponding ATLANTIS_GITLAB_*, ATLANTIS_BITBUCKET_* or ATLANTIS_AZUREDEVOPS_* variables instead of the ATLANTIS_GH_* ones, and point that provider's webhook at /events.
Enabling HTTPS
The nginx reverse proxy terminates plain HTTP on port 80. Because webhooks carry your repository contents and plan output, you should put TLS in front of Atlantis for any non-trivial use. Add a DNS name for the VM and use the companion cloudimg nginx-ssl-certbot image as a TLS reverse proxy, or install certbot and extend the existing nginx site with a listen 443 ssl; server block and your certificate paths. After adding TLS, set your webhook Payload URL to the https:// address and update ATLANTIS_ATLANTIS_URL in /etc/atlantis/atlantis.env to match.
Maintenance
- Configuration: all Atlantis server flags live in
/etc/atlantis/atlantis.envasATLANTIS_-prefixed variables. Edit it andsudo systemctl restart atlantisto apply changes. - Repository config: commit an
atlantis.yamlto your repository to control workspaces, the Terraform version per project, and apply requirements (for example requiring PR approval before apply). - Upgrades: replace
/usr/local/bin/atlantisor/usr/local/bin/terraformwith a newer release and restart the service. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.
Atlantis and the Atlantis logo are projects of the runatlantis open-source community. Terraform is a registered trademark of HashiCorp, Inc. This image is produced by cloudimg and is not affiliated with or endorsed by the Atlantis project or HashiCorp. Atlantis is distributed under the Apache License 2.0.