Taking on new clients for Elixir and web development.
Mike Zornek

Terraform on Linode Notes

Posted on

Over vacation I worked through a small project to use Terraform on Linode to provision a new webserver for my personal website. The following is a collection of notes and resources from the experience.

Project Goals / Areas of Improvement:

  • Since the addition of the guildflow.com static website, anyone who was attempting to load a HTTPS version of mikezornek.com would be met with a security warning as the browser was attempting to load the SSL cert for guildflow.com when serving up mikezornek.com.
  • The lack of SSL to mikezornek.com has historically been intentional.
  • The Linode serving my static sites uses Ubuntu 16.04 LTS, which is going to be EOL on April 30, 2021 and so it’d be good to get one a new LTS version.
  • This is a good excuse to experiment with Terraform, which is something I’ve been learning in support of some possible Guildflow infrastructure updates.

Quick Review of the MikeZornek.com Infrastructure and Deployment

  • MikeZornek is a static site. I like static sites as they are cheaper to serve and easier to keep secure. I have used WordPress in the distant pass but I was lazy at keeping it updated and eventually it was hacked.
  • Hugo is used to help build the static site.
  • The git repo is public and hosted on GitHub.
  • I’ve setup CircleCI to detect changes on the repo’s master branch and deploy any changes.
  • The deploy is pretty basic but there are a few HTML/link checks.
  • Once generated, the static files are copied to my Linode using rsync.
  • The historic Linode was hand crafted and used Apache as it’s web server.

Learning Terraform Resources

My Terraform Script

provider "linode" {
  # API Token
  token = "abc123"
}

resource "linode_sshkey" "mikezornek_linode_ssh_key" {
  label = "mikezornek_linode_ssh_key"
  ssh_key = chomp(file("~/.ssh/id_rsa_linode_mikezornek.pub"))
}

resource "linode_stackscript" "setup_mikezornek_prod" {
  label = "setup_mikezornek_prod"
  description = "setups nginx and certbot for mikezornek"
  script = file("files/setup.sh")
  images = ["linode/ubuntu20.04"]
  is_public = false
}

resource "linode_instance" "mikezornek_prod" {
  image = "linode/ubuntu20.04"
  label = "mikezornek_prod"
  group = "mikezornek"
  region = "us-east"
  type = "g6-nanode-1"
  authorized_keys = [linode_sshkey.mikezornek_linode_ssh_key.ssh_key]
  # Leave the root password unset if want to keep it random
  root_pass = "abc123"
  backups_enabled = true
  stackscript_id = linode_stackscript.setup_mikezornek_prod.id
}

output "server_ip" {
  value = linode_instance.mikezornek_prod.ip_address
}

The output is useful if you want to ssh into your new linode instance right away with:

$ ssh root@(terraform output server_ip)

My setup bash script

#!/bin/bash

# strict mode
set -xeo pipefail

exec > >(tee -i /var/log/stackscript.log)

FQDN=mikezornek.com

echo Setting hostname to ${FQDN}
hostnamectl set-hostname ${FQDN}

echo Running apt-get update and upgrade
apt update && apt upgrade -y

echo Installing nginx
apt install -y nginx

echo Prep snap
snap install core; snap refresh core

echo Install certbot
snap install --classic certbot

# echo Setup certbot for nginx for the domain ${FQDN}
# we will do this manually after setup since the
# domain should be pointing at this machine at the time of setup
# certbot --nginx --agree-tos -m zorn@zornlabs.com --verbose -d mikezornek.com

echo Starting nginx
sudo service nginx start

echo ALL DONE!

Observe the log file on your new server with:

$ tail -f /var/log/stackscript.log

About the Author. Mike Zornek is a developer and teacher focusing on product design and development with a heavy focus on Elixir and LiveView. In between his projects, Mike helps other teams through consulting. During off hours, he enjoyed watching Phillies baseball and playing relaxing video games.

Hopefully, you found interest in my scribbles. If you have commentary or a response, I'd love to hear it.