Terraforming my blog

I’ve just pushed a first step for managing my infrastructure via Hashicorps Terraform. In this article I want to speak about this first step and I want to give a glimpse into the future for it.

My infrastructure is hosted in Hetzner Cloud (there is luckily a terraform provider for it). DNS will be talked about in a later blog article.

I usually store my passwords in a gopass password store, hence I’ve wanted to let Terraform retrieve the Hetzner Cloud API key magically.

The solution is the use of the external Terraform module:

data "external" "hetzner_cloud_api_key" {
	program = ["${path.module}/fetch-key.sh"]
}

This snippet will call a wrapper script called fetch-key.sh, that basically just calls gopass and translates the output to a JSON structure:

#!/bin/bash

hetzner_cloud_api_key=$(gopass api/hetzner.com/motoko)
echo "{ \"hetzner_cloud_api_key\": \"${hetzner_cloud_api_key}\" }"

It’s important to use the key hetzner_cloud_api_key here! In the next part I am going to set the hetzner_cloud_api_key and call the hcloud provider (this is going to download a go binary):

provider "hcloud" {
  token = data.external.hetzner_cloud_api_key.result.hetzner_cloud_api_key
}

Then we are setting the actual server resource and an rdns entry for the server:

resource "hcloud_server" "kurisu" {
  name        = "kurisu"
  server_type = "cx11-ceph"
  location    = "fsn1"
  image       = "fedora-31"
  lifecycle {
    ignore_changes = [image]
  }
}

resource "hcloud_rdns" "kurisu" {
  server_id  = hcloud_server.kurisu.id
  ip_address = hcloud_server.kurisu.ipv4_address
  dns_ptr    = "kurisu.shibumi.dev"
}

Interesting is the last part of the hcloud_server resource:

  image       = "fedora-31"
  lifecycle {
    ignore_changes = [image]
  }
}

The image variable is actually never used. I have created my server with Fedora-28 years ago. When Hetzner introduces a new Fedora image the last one gets deprecated and the Hetzner Cloud API links that value against null or No Image. Therefore any import of an existing server will fail, because you can’t set the null value to the image variable (it’s a requirement for the hcloud_server resource). And if you set any other string, the Hetzner Cloud API will think it’s a valid image value and will try to destroy your image and create a new one. To go around this issue, just add a lifecycle for it and set ignore_changes = [image]. This will ignore any changes to the image variable on Hetzner Cloud API side.

If you want to have a look on all files go and checkout:

https://github.com/shibumi/infra

I will definitely work further on this. On my todo list are:

  • DNS via inwx.de
  • rDNS entries for IPv6
  • Provisioning of the actual image (not sure if I will use Ansible or rely on this for Terraform too).