Post

Self Hosting Atlantis

I’ve been interacting with Atlantis at work. But I am not responsible for its deployment or configuration, it was a bit of a magic black box.

Considering I use some terraform for managing my personal Cloudflare DNS settings, I figured I may as well try and get Atlantis setup for my own use!

Not every step will be documented here, this is not intended to be a full walkthrough.
I will attempt to link the relevant documentation I used.

The problem

So there were a few requirements I had to meet before setting this into the wild.

  1. I must self host the Atlantis service
  2. GitHub is my go to repo host, it must be able to reach Atlantis
  3. No exposing Atlantis completely to the entire internet

Attempt one

I attempted to first try using Tailscale Funnel and mapping atlantis to Tailscale in docker from this example

This worked great, I self hosted Atlantis and can access it externally! ✅

Unfortunately as much as Tailscale is awesome the ACLs do not support controlled access to services hosted with funnel. ❌

Attempt Two (Success)

Revisiting the toolbox of poking safe holes through my firewall, and since I am already using Cloudflare for my DNS, I looked at their Cloudflare Tunnel offering.

After creating a tunnel I was quickly able to access to Atlantis over the open internet. ✅

Thankfully unlike Tailscale, Cloudflare does have a WAF that works alongside the tunnel to control access. ✅

Grabbing the webhook CIDR blocks from GitHub Meta API I quickly put together a WAF rule to block access:

1
(not ip.src in {192.30.252.0/22 185.199.108.0/22 140.82.112.0/20 143.55.64.0/20} and http.host eq "atlantis.domain.ca")

Putting it together

Following the Atlantis GitHub app docs I was able to meet all my personal requirements.

I ended up with the following docker-compose.yml that binds the Atlantis containers networking to the cloudflared container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---
version: "2.2"
services:
  atlantis:
    image: ghcr.io/runatlantis/atlantis:latest
    restart: unless-stopped
    volumes:
      - ${PWD}/config:/config
      - ${PWD}/data:/data
    environment:
      ATLANTIS_CONFIG: /config/atlantis.yml
      ATLANTIS_DATA_DIR: /data
      AWS_ACCESS_KEY_ID: <Access Key ID>
      AWS_SECRET_ACCESS_KEY: <Secret Key>
      AWS_REGION: us-west-2
      CLOUDFLARE_API_TOKEN: <Cloudflare Access Token>
    networks:
      - atlantis

  tunnel:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=<Your CF Tunnel Token>
    networks:
      - atlantis

volumes:
  tailscale-data-atlantis:

networks:
  atlantis:

Most importantly, I can now safely access the Atlantis UI locally, and the webhooks from GitHub work great! Now I can atlantis plan and atlantis apply on my terraform PRs for my personal cloud infrastructure! ✅

Atlantis The Atlantis UI is safely accessible

GitHub GitHub interactions are automated and work great!

Extra notes

My terraform code is private, so I will not be sharing that. Additionally Atlantis specifically calls out not to use public repos. Setting up terraform is an exercise for the reader.

This post is licensed under CC BY 4.0 by the author.