This weekend I started working on revamping my website. I decided to use Terraform's DigitalOcean Provider to generate a new droplet, import my domain name, and implement new DNS records and a firewall. First up, the provider (providers.tf) along with the variable to feed in the token (variables.tf).

        
    provider "digitalocean" {
        token = var.do_token
    }

    terraform {
        required_providers {
            digitalocean = {
                source = "digitalocean/digitalocean"
            }
        }
    }
        
    
        
    variable "do_token" {
        type      = string
    }
        
    
You see where the token is injected allowing us to talk to DigitalOcean's API. This allows us to create our droplet, as shown below (main.tf). Note the ssh_keys argument is the ID of the one I already set up on my DigitalOcean account.
        
    resource "digitalocean_droplet" "web" {
        image  = "ubuntu-20-04-x64"
        name   = "bakey-us"
        region = "nyc3"
        size   = "s-1vcpu-1gb"
        ssh_keys = [
            13895248
        ]
    }
        
    
And what good is a server with no DNS record? We'll create that and some CAA records for LetsEncrypt (dns.tf).
            
    resource "digitalocean_domain" "bakey-us" {
        name       = "bakey.us"
    }
    
    # Add an A record to the domain for www.bakey.us
    resource "digitalocean_record" "www" {
        domain = digitalocean_domain.bakey-us.name
        type   = "A"
        name   = "www"
        value  = digitalocean_droplet.web.ipv4_address
    }
    
    resource "digitalocean_record" "caa-wild" {
        domain = digitalocean_domain.bakey-us.name
        type   = "CAA"
        name   = "*.bakey.us."
        value  = "letsencrypt.org."
        tag = "issuewild"
        flags = 0
    }
    
    resource "digitalocean_record" "caa" {
        domain = digitalocean_domain.bakey-us.name
        type   = "CAA"
        name   = "www.bakey.us."
        value  = "letsencrypt.org."
        tag = "issue"
        flags = 0
    }
            
        
Last we'll make sure our firewall is set up appropriately to allow web and ssh traffic inbound, as well as all traffic outbound (firewall.tf).
            
    resource "digitalocean_firewall" "www" {
        name = "www-bakey-us"
        droplet_ids = [ digitalocean_droplet.web.id ]
        
        inbound_rule {
            protocol         = "tcp"
            port_range       = "22"
            source_addresses = ["0.0.0.0/0", "::/0"]
        }
        
        inbound_rule {
            protocol         = "tcp"
            port_range       = "80"
            source_addresses = ["0.0.0.0/0", "::/0"]
        }
        
        inbound_rule {
            protocol         = "tcp"
            port_range       = "443"
            source_addresses = ["0.0.0.0/0", "::/0"]
        }
        
        inbound_rule {
            protocol         = "icmp"
            source_addresses = ["0.0.0.0/0", "::/0"]
        }
        
        outbound_rule {
            protocol              = "tcp"
            port_range            = "1-65535"
            destination_addresses = ["0.0.0.0/0", "::/0"]
        }
        
        outbound_rule {
            protocol              = "udp"
            port_range            = "1-65535"
            destination_addresses = ["0.0.0.0/0", "::/0"]
        }
        
        outbound_rule {
            protocol              = "icmp"
            destination_addresses = ["0.0.0.0/0", "::/0"]
        }
    }
            
        
All these get checked into GitHub and connected to a Terraform workspace at app.terrafrom.io. This takes me from an empty slate to a running machine I can SSH into using a key I've already provided. This is important for part 2 coming next - configuring this droplet for LetsEncrypt (certbot), Docker, and a GitHub runner using Ansible.

Posted 2021-01-31

📬 Posts | 🏠 Home | 👋 About