Managing Infrastructure on Digital Ocean with Terraform
The goal is to provision everything from datacentre to browser in one command using Terraform for infrastructure automation.
Installation
For macOS users, installation uses Homebrew:
brew install terraform
Installation instructions vary by operating system.
Provider Configuration
Before creating resources, configure the Digital Ocean provider:
variable "do_token" {}
provider "digitalocean" {
token = "${var.do_token}"
}
Create a terraform.tfvars file with:
do_token=<YOUR_TOKEN>
Avoid version control for this sensitive file. Run terraform init to download the Digital Ocean package.
SSH Key Setup
Upload public keys to Digital Ocean:
variable "key_path" {}
resource "digitalocean_ssh_key" "markprovan_key" {
name = "Mark Provan Key"
public_key = "${file("${var.key_path}")}"
}
Server Creation
Create tags and a droplet (server):
resource "digitalocean_tag" "blog_tag" {
name = "blog"
}
resource "digitalocean_tag" "personal_tag" {
name = "personal"
}
resource "digitalocean_droplet" "blog" {
image = "coreos-stable"
name = "blog"
region = "lon1"
size = "s-1vcpu-1gb"
tags = [
"${digitalocean_tag.blog_tag.id}",
"${digitalocean_tag.personal_tag.id}"
]
ssh_keys = [
"${digitalocean_ssh_key.markprovan_key.id}"
]
depends_on = ["digitalocean_ssh_key.markprovan_key"]
}
The configuration demonstrates resource interpolation, accessing IDs from other resources. The depends_on attribute ensures the SSH key exists before server creation.
DNS Configuration
Configure Cloudflare DNS records:
variable "cloudflare_email" {}
variable "cloudflare_token" {}
provider "cloudflare" {
email = "${var.cloudflare_email}"
token = "${var.cloudflare_token}"
}
resource "cloudflare_record" "markprovan" {
domain = "markprovan.com"
name = "markprovan.com"
proxied = true
value = "${digitalocean_droplet.blog.ipv4_address}"
type = "A"
}
The DNS record references the droplet’s IP address, demonstrating cross-provider resource dependencies.
Software Provisioning
Deploy Docker containers using provisioners:
resource "digitalocean_droplet" "blog" {
image = "coreos-stable"
name = "blog"
region = "lon1"
size = "s-1vcpu-1gb"
tags = [
"${digitalocean_tag.blog_tag.id}",
"${digitalocean_tag.personal_tag.id}"
]
ssh_keys = [
"${digitalocean_ssh_key.markprovan_key.id}"
]
depends_on = ["digitalocean_ssh_key.markprovan_key"]
provisioner "file" {
source = "docker-compose.yml"
destination = "/home/core/docker-compose.yml"
connection {
type = "ssh"
user = "core"
private_key = "${file("${var.private_key_path}")}"
}
}
provisioner "remote-exec" {
inline = [
"docker-compose up -d"
]
connection {
type = "ssh"
user = "core"
private_key = "${file("${var.private_key_path}")}"
}
}
}
The file provisioner uploads the Docker Compose configuration, followed by remote-exec to start services. These execute sequentially.
Deployment
Execute terraform apply to provision all resources, confirming changes when prompted.
Conclusion
Terraform is a really handy tool for infrastructure automation, and I am excited to continue exploring its capabilities.