~damien/infrastructure

d7193ddc03eee0bd8e29735f554338d58d9e85a3 — Damien Radtke 2 years ago 55daf21
Use Packer more
M ca/consul-agent-ca.srl => ca/consul-agent-ca.srl +1 -1
@@ 1,1 1,1 @@
2E741F16F5701C92061B3669C7546E4A1AA2C8BF
2E741F16F5701C92061B3669C7546E4A1AA2C8D2

M ca/nomad-agent-ca.srl => ca/nomad-agent-ca.srl +1 -1
@@ 1,1 1,1 @@
3A95C8A7EE198C7858E58366940C5F25842606B6
3A95C8A7EE198C7858E58366940C5F25842606CA

M ca/provision-cert => ca/provision-cert +2 -1
@@ 40,7 40,8 @@ cn="${hostname:-${basename}}"
# the requested hostname if it was provided.
san="IP:${addr},DNS:localhost"
if [[ -n "${hostname:-}" ]]; then
	san="${san},DNS:${hostname}"
	# Support comma-separated hostname list
	san="${san},$(echo "${hostname}" | sed 's/^/DNS:/' | sed 's/,/,DNS:/g')"
fi

# Generate a private key and CSR remotely

M ca/vault-server-ca.srl => ca/vault-server-ca.srl +1 -1
@@ 1,1 1,1 @@
73BA2463646820941EB0EC0FDCDC6DE86EE1426A
73BA2463646820941EB0EC0FDCDC6DE86EE1427D

M jobs/damienradtkecom.nomad.erb => jobs/damienradtkecom.nomad.erb +1 -0
@@ 1,3 1,4 @@
// TODO: use variables: https://www.nomadproject.io/docs/job-specification/hcl2/variables
job "damienradtkecom" {
	region = "global"


D packer/base.pkr.hcl => packer/base.pkr.hcl +0 -39
@@ 1,39 0,0 @@
// TODO: move resources required by packer into this folder?
packer {
  required_plugins {
    linode = {
      version = ">= 0.0.1"
      source  = "github.com/hashicorp/linode"
    }
  }
}

variable "linode_token" {
  type    = string
}

variable "opensuse_version" {
  type    = string
  default = "15.3"
}

locals {
  timestamp = regex_replace(timestamp(), "[- TZ:]", "")
}

source "linode" "cluster-image" {
  image             = "linode/opensuse${var.opensuse_version}"
  image_label       = "testing-cluster-image-${local.timestamp}"
  instance_label    = "cluster-imaging-${local.timestamp}"
  instance_type     = "g6-nanode-1"
  linode_token      = "${var.linode_token}"
  region            = "ca-central"
  ssh_username      = "root"
  swap_size         = 256
}

build {
  sources = ["source.linode.cluster-image"]
}

// vim: set expandtab tabstop=2 shiftwidth=2 autoindent:

A packer/build.pkr.hcl => packer/build.pkr.hcl +636 -0
@@ 0,0 1,636 @@
// TODO: move resources required by packer into this folder?
packer {
  required_plugins {
    linode = {
      version = ">= 1.0.1"
      source  = "github.com/hashicorp/linode"
    }
  }
}

variable "linode_token" {
  type    = string
}

variable "opensuse_version" {
  type    = string
  default = "15.3"
}

variable "consul_version" {
  type    = string
  default = "1.10.3"
}

variable "nomad_version" {
  type    = string
  default = "1.2.0"
}

variable "vault_version" {
  type    = string
  default = "1.8.5"
}

locals {
  instance_type = "g6-nanode-1"
  region = "ca-central"

  zypper_packages = [
    "wget",
    "jq",
    "firewalld",
    "moreutils",
    "git",
  ]

  zypper_patterns = [
    "dhcp_dns_server",
  ]

  timestamp = regex_replace(timestamp(), "[- TZ:]", "")

  shared_setup = [
      "update-ca-certificates --verbose",
      "zypper --non-interactive refresh",
      "zypper --non-interactive install ${join(" ", local.zypper_packages)}",
      "zypper --non-interactive install --type pattern ${join(" ", local.zypper_patterns)}",
      "zypper --non-interactive clean",
  ]

  make_damien = [
      "mkdir /home/damien",
      "mkdir /home/damien/.ssh",
      "touch /home/damien/.bashrc",
      "useradd --home-dir /home/damien damien",
      "chown -R damien:users /home/damien",
      "echo 'damien ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/damien",
  ]

  authorized_keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDtZGPZxwlRQdmXGFhp+gtXBBrXFvis64T9DsQ4EGUcz7F25dxZCtPYpB0DqNlAywfB+O2uwnVgCdtZ7BieHCh1lgeCA62t1WwzSLShxjBq0YWVysqiZTmFyaUbzlhuJUd386gkfraJotL1Em8txTFD/Eys4WLmTMgqpH5ammN7KunKsgudYPya9RQQcZsFQ2MmYkEz42oEqKBWYi25/Lz8SxIXE41mc+z3Y1OPEQdh8YryBHCOeceI5DjYc3lxX8Sk1Ihyho5Vu98COL+Mc195goGmWoRJjfszspnlIMEE5Svgy+CJrWIuE4M0IAGQZvIYsRrMjVijniofZT1wfI+1 damien@damien-laptop"]
}

source "linode" "base" {
  image             = "linode/opensuse${var.opensuse_version}"
  instance_type     = local.instance_type
  linode_token      = var.linode_token
  region            = local.region
  ssh_username      = "root"
  authorized_keys   = local.authorized_keys
  swap_size         = 256
}

build {
  name = "consul-server"
  
  source "linode.base" {
    image_description = <<EOF
openSUSE Leap ${var.opensuse_version}
Consul ${var.consul_version}
EOF
    image_label       = "consul-server-${local.timestamp}"
    instance_label    = "consul-server-${local.timestamp}"
  }

  provisioner "shell" {
    inline = local.shared_setup
  }

  provisioner "shell" {
    inline = [
      "mkdir /etc/ssl/consul-agent",
    ]
  }

  provisioner "file" {
  	destination = "/etc"
    source      = "config/consul.d"
  }

  provisioner "file" {
    destination = "/etc/firewalld/services"
    source      = "firewall/services/"
  }

  provisioner "file" {
    destination = "/etc/firewalld/zones"
    source      = "firewall/zones/"
  }

  provisioner "file" {
    destination = "/etc/systemd/system"
    source      = "services/"
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=consul", "APP_VERSION=${var.consul_version}"]
  }

  provisioner "file" {
    destination = "/etc/ssl/consul-agent/ca.crt"
    source      = "../ca/consul-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/profile.local"
    source      = "config/profile.local"
  }

  provisioner "file" {
    destination = "/etc/named.d/consul.conf"
    source      = "config/dns/consul.conf"
  }

  provisioner "file" {
    destination = "/root/bin/on-startup.sh"
    source      = "scripts/on-startup.sh"
  }

  provisioner "shell" {
    script = "scripts/configure-dns.sh"
  }

  provisioner "shell" {
    inline = local.make_damien
  }

  provisioner "shell" {
    inline = [
      "sudo -u damien /usr/local/bin/consul -autocomplete-install",
      "usermod --append --groups consul damien",
    ]
  }

  provisioner "shell" {
    inline = [
      "systemctl enable firewalld",
      "systemctl enable consul",
    ]
  }
}

build {
  name = "vault-server"

  source "linode.base" {
    image_description = <<EOF
openSUSE Leap ${var.opensuse_version}
Consul ${var.consul_version}
Vault ${var.vault_version}
EOF
    image_label       = "vault-server-${local.timestamp}"
    instance_label    = "vault-server-${local.timestamp}"
  }

  provisioner "shell" {
    inline = local.shared_setup
  }

  provisioner "shell" {
    inline = [
      "mkdir /etc/ssl/consul-agent",
      "mkdir /etc/ssl/vault-server",
    ]
  }

  provisioner "file" {
  	destination = "/etc"
    source      = "config/consul.d"
  }

  provisioner "file" {
    destination = "/etc"
    source      = "config/vault.d"
  }

  provisioner "file" {
    destination = "/etc/firewalld/services"
    source      = "firewall/services/"
  }

  provisioner "file" {
    destination = "/etc/firewalld/zones"
    source      = "firewall/zones/"
  }

  provisioner "file" {
    destination = "/etc/systemd/system"
    source      = "services/"
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=consul", "APP_VERSION=${var.consul_version}"]
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=vault", "APP_VERSION=${var.vault_version}"]
  }

  provisioner "file" {
    destination = "/etc/ssl/consul-agent/ca.crt"
    source      = "../ca/consul-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/vault-server/ca.crt"
    source      = "../ca/vault-server-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/profile.local"
    source      = "config/profile.local"
  }

  provisioner "file" {
    destination = "/etc/named.d/consul.conf"
    source      = "config/dns/consul.conf"
  }

  provisioner "file" {
    destination = "/root/bin/on-startup.sh"
    source      = "scripts/on-startup.sh"
  }

  provisioner "shell" {
    script = "scripts/configure-dns.sh"
  }

  provisioner "shell" {
    inline = local.make_damien
  }

  provisioner "shell" {
    inline = [
      "sudo -u damien /usr/local/bin/consul -autocomplete-install",
      "sudo -u damien /usr/local/bin/vault -autocomplete-install",
      "usermod --append --groups consul,vault damien",
    ]
  }

  provisioner "shell" {
    inline = [
      "systemctl enable firewalld",
      "systemctl enable consul",
      "systemctl enable vault",
    ]
  }
}

build {
  name = "nomad-server"
  source "linode.base" {
    image_description = <<EOF
openSUSE Leap ${var.opensuse_version}
Consul ${var.consul_version}
Nomad ${var.nomad_version}
EOF
    image_label       = "nomad-server-${local.timestamp}"
    instance_label    = "nomad-server-${local.timestamp}"
  }

  provisioner "shell" {
    inline = local.shared_setup
  }

  provisioner "shell" {
    inline = [
      "mkdir /etc/ssl/consul-agent",
      "mkdir /etc/ssl/nomad-agent",
      "mkdir /etc/ssl/vault-server",
    ]
  }

  provisioner "file" {
  	destination = "/etc"
    source      = "config/consul.d"
  }

  provisioner "file" {
    destination = "/etc"
    source      = "config/nomad.d"
  }

  provisioner "file" {
    destination = "/etc/firewalld/services"
    source      = "firewall/services/"
  }

  provisioner "file" {
    destination = "/etc/firewalld/zones"
    source      = "firewall/zones/"
  }

  provisioner "file" {
    destination = "/etc/systemd/system"
    source      = "services/"
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=consul", "APP_VERSION=${var.consul_version}"]
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=nomad", "APP_VERSION=${var.nomad_version}"]
  }

  provisioner "file" {
    destination = "/etc/ssl/consul-agent/ca.crt"
    source      = "../ca/consul-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/nomad-agent/ca.crt"
    source      = "../ca/nomad-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/vault-server/ca.crt"
    source      = "../ca/vault-server-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/profile.local"
    source      = "config/profile.local"
  }

  provisioner "file" {
    destination = "/etc/named.d/consul.conf"
    source      = "config/dns/consul.conf"
  }

  provisioner "file" {
    destination = "/root/bin/on-startup.sh"
    source      = "scripts/on-startup.sh"
  }

  provisioner "shell" {
    script = "scripts/configure-dns.sh"
  }

  provisioner "shell" {
    inline = local.make_damien
  }

  provisioner "shell" {
    inline = [
      "sudo -u damien /usr/local/bin/consul -autocomplete-install",
      "sudo -u damien /usr/local/bin/nomad -autocomplete-install",
      "usermod --append --groups consul,nomad damien",
    ]
  }

  provisioner "shell" {
    inline = [
      "systemctl enable firewalld",
      "systemctl enable consul",
      "systemctl enable nomad",
    ]
  }
}

build {
  name = "nomad-client"
  source "linode.base" {
    image_description = <<EOF
openSUSE Leap ${var.opensuse_version}
Consul ${var.consul_version}
Nomad ${var.nomad_version}
EOF
    image_label       = "nomad-client-${local.timestamp}"
    instance_label    = "nomad-client-${local.timestamp}"
  }

  provisioner "shell" {
    inline = local.shared_setup
  }

  provisioner "shell" {
    inline = [
      "mkdir /etc/ssl/consul-agent",
      "mkdir /etc/ssl/nomad-agent",
      "mkdir /etc/ssl/vault-server",
    ]
  }

  provisioner "file" {
  	destination = "/etc"
    source      = "config/consul.d"
  }

  provisioner "file" {
    destination = "/etc"
    source      = "config/nomad.d"
  }

  provisioner "file" {
    destination = "/etc/firewalld/services"
    source      = "firewall/services/"
  }

  provisioner "file" {
    destination = "/etc/firewalld/zones"
    source      = "firewall/zones/"
  }

  provisioner "file" {
    destination = "/etc/systemd/system"
    source      = "services/"
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=consul", "APP_VERSION=${var.consul_version}"]
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=nomad", "APP_VERSION=${var.nomad_version}"]
  }

  provisioner "file" {
    destination = "/etc/ssl/consul-agent/ca.crt"
    source      = "../ca/consul-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/nomad-agent/ca.crt"
    source      = "../ca/nomad-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/vault-server/ca.crt"
    source      = "../ca/vault-server-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/profile.local"
    source      = "config/profile.local"
  }

  provisioner "file" {
    destination = "/etc/named.d/consul.conf"
    source      = "config/dns/consul.conf"
  }

  provisioner "file" {
    destination = "/root/bin/on-startup.sh"
    source      = "scripts/on-startup.sh"
  }

  provisioner "shell" {
    script = "scripts/configure-dns.sh"
  }

  provisioner "shell" {
    inline = local.make_damien
  }

  provisioner "shell" {
    inline = [
      "sudo -u damien /usr/local/bin/consul -autocomplete-install",
      "sudo -u damien /usr/local/bin/nomad -autocomplete-install",
      "usermod --append --groups consul,nomad damien",
    ]
  }

  provisioner "shell" {
    inline = [
      "systemctl enable firewalld",
      "systemctl enable consul",
      "systemctl enable nomad",
    ]
  }
}

build {
  name = "nomad-client-ingress"
  source "linode.base" {
    image_description = <<EOF
openSUSE Leap ${var.opensuse_version}
Consul ${var.consul_version}
Nomad ${var.nomad_version}
EOF
    image_label       = "nomad-client-ingress-${local.timestamp}"
    instance_label    = "nomad-client-ingress-${local.timestamp}"
  }

  provisioner "shell" {
    inline = local.shared_setup
  }

  provisioner "shell" {
    inline = [
      "mkdir /etc/ssl/consul-agent",
      "mkdir /etc/ssl/nomad-agent",
      "mkdir /etc/ssl/vault-server",
    ]
  }

  provisioner "file" {
  	destination = "/etc"
    source      = "config/consul.d"
  }

  provisioner "file" {
    destination = "/etc"
    source      = "config/nomad.d"
  }

  provisioner "file" {
    destination = "/etc/firewalld/services"
    source      = "firewall/services/"
  }

  provisioner "file" {
    destination = "/etc/firewalld/zones"
    source      = "firewall/zones/"
  }

  provisioner "file" {
    destination = "/etc/systemd/system"
    source      = "services/"
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=consul", "APP_VERSION=${var.consul_version}"]
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=nomad", "APP_VERSION=${var.nomad_version}"]
  }

  provisioner "file" {
    destination = "/etc/ssl/consul-agent/ca.crt"
    source      = "../ca/consul-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/nomad-agent/ca.crt"
    source      = "../ca/nomad-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/vault-server/ca.crt"
    source      = "../ca/vault-server-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/profile.local"
    source      = "config/profile.local"
  }

  provisioner "file" {
    destination = "/etc/named.d/consul.conf"
    source      = "config/dns/consul.conf"
  }

  provisioner "file" {
    destination = "/root/bin/on-startup.sh"
    source      = "scripts/on-startup.sh"
  }

  provisioner "shell" {
    script = "scripts/configure-dns.sh"
  }

  provisioner "shell" {
    inline = local.make_damien
  }

  provisioner "shell" {
    inline = [
      "sudo -u damien /usr/local/bin/consul -autocomplete-install",
      "sudo -u damien /usr/local/bin/nomad -autocomplete-install",
      "usermod --append --groups consul,nomad damien",
    ]
  }

  provisioner "shell" {
    inline = [
      "systemctl enable firewalld",
      "systemctl enable consul",
      "systemctl enable nomad",
    ]
  }

  provisioner "shell" {
    inline = [
      "groupadd fabio",
      "useradd --gid fabio fabio",
      "mkdir -p --mode=0500 /etc/ssl/fabio",
      "chown fabio:fabio /etc/ssl/fabio",
      "service firewalld start",
      "firewall-cmd --zone=public --add-service=fabio --permanent",
      "firewall-cmd --zone=public --add-service=web --permanent",
    ]
  }
}

// vim: set expandtab tabstop=2 shiftwidth=2 autoindent:

D packer/image.pkr.hcl => packer/image.pkr.hcl +0 -179
@@ 1,179 0,0 @@
// TODO: move resources required by packer into this folder?
packer {
  required_plugins {
    linode = {
      version = ">= 0.0.1"
      source  = "github.com/hashicorp/linode"
    }
  }
}

variable "linode_token" {
  type    = string
}

variable "opensuse_version" {
  type    = string
  default = "15.3"
}

variable "consul_version" {
  type    = string
  default = "1.10.3"
}

variable "nomad_version" {
  type    = string
  default = "1.2.0"
}

variable "vault_version" {
  type    = string
  default = "1.8.5"
}

locals {
  zypper_packages = [
    "wget",
    "jq",
    "firewalld",
    "moreutils",
    "git",
  ]
  zypper_patterns = [
    "dhcp_dns_server",
  ]
  timestamp = regex_replace(timestamp(), "[- TZ:]", "")
}

source "linode" "cluster-image" {
  image             = "linode/opensuse${var.opensuse_version}"
  image_description = <<EOF
openSUSE Leap ${var.opensuse_version}
Consul ${var.consul_version}
Nomad ${var.nomad_version}
Vault ${var.vault_version}
EOF
  image_label       = "cluster-image-${local.timestamp}"
  instance_label    = "cluster-imaging-${local.timestamp}"
  instance_type     = "g6-nanode-1"
  linode_token      = "${var.linode_token}"
  region            = "ca-central"
  ssh_username      = "root"
  swap_size         = 256
}

build {
  sources = ["source.linode.cluster-image"]

  provisioner "shell" {
    inline = [
      "zypper --non-interactive refresh",
      "zypper --non-interactive install ${join(" ", local.zypper_packages)}",
      "zypper --non-interactive install --type pattern ${join(" ", local.zypper_patterns)}",
      "zypper --non-interactive clean",
      "echo Updating CA certificates",
      "update-ca-certificates --verbose",
      "echo Making directories",
      "mkdir /etc/ssl/consul-agent",
      "mkdir /etc/ssl/nomad-agent",
      "mkdir /etc/ssl/vault-server",
    ]
  }

  provisioner "file" {
  	destination = "/etc"
    source      = "config/consul.d"
  }

  provisioner "file" {
    destination = "/etc"
    source      = "config/nomad.d"
  }

  provisioner "file" {
    destination = "/etc"
    source      = "config/vault.d"
  }

  provisioner "file" {
    destination = "/etc/firewalld/services"
    source      = "firewall/services/"
  }

  provisioner "file" {
    destination = "/etc/firewalld/zones"
    source      = "firewall/zones/"
  }

  provisioner "file" {
    destination = "/etc/systemd/system"
    source      = "services/"
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=consul", "APP_VERSION=${var.consul_version}"]
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=nomad", "APP_VERSION=${var.nomad_version}"]
  }

  provisioner "shell" {
    script = "scripts/install-hashicorp.sh"
    environment_vars = ["APP_NAME=vault", "APP_VERSION=${var.vault_version}"]
  }

  provisioner "file" {
    destination = "/etc/ssl/consul-agent/ca.crt"
    source      = "../ca/consul-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/nomad-agent/ca.crt"
    source      = "../ca/nomad-agent-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/ssl/vault-server/ca.crt"
    source      = "../ca/vault-server-ca.crt"
  }

  provisioner "file" {
    destination = "/etc/profile.local"
    source      = "config/profile.local"
  }

  provisioner "file" {
    destination = "/etc/named.d/consul.conf"
    source      = "config/dns/consul.conf"
  }

  provisioner "file" {
    destination = "/root/bin/on-startup.sh"
    source      = "scripts/on-startup.sh"
  }

  provisioner "shell" {
    script = "scripts/configure-dns.sh"
  }

  provisioner "shell" {
    inline = [
      "mkdir /home/damien",
      "mkdir /home/damien/.ssh",
      "touch /home/damien/.bashrc",
      "useradd --home-dir /home/damien damien",
      "chown -R damien:users /home/damien",
      "echo 'damien ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/damien",
      "sudo -u damien /usr/local/bin/consul -autocomplete-install",
      "sudo -u damien /usr/local/bin/nomad -autocomplete-install",
      "sudo -u damien /usr/local/bin/vault -autocomplete-install",
      "usermod --append --groups consul,vault,nomad damien",
    ]
  }
}

// vim: set expandtab tabstop=2 shiftwidth=2 autoindent:

M terraform/consul-server/main.tf => terraform/consul-server/main.tf +5 -14
@@ 7,10 7,6 @@ terraform {
  }
}

locals {
  addrs = [for ipv6 in linode_instance.servers.*.ipv6 : split("/", ipv6)[0]]
}

resource "linode_instance" "servers" {
  count            = var.servers
  label            = "consul-${random_id.servers[count.index].keepers.datacenter}-${random_id.servers[count.index].hex}"


@@ 32,10 28,6 @@ resource "linode_instance" "servers" {
    command = "ssh-keygen -R '${split("/", self.ipv6)[0]}' && ssh-keyscan -v '${split("/", self.ipv6)[0]}' >> ~/.ssh/known_hosts"
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca consul-agent --hostname server.${self.region}.consul --owner consul:consul --outdir /etc/ssl/consul-agent --basename consul"
  }

  provisioner "file" {
    connection { host = split("/", self.ipv6)[0] }
    destination = "/etc/consul.d/server.hcl"


@@ 47,18 39,17 @@ resource "linode_instance" "servers" {
    EOT
  }

  // start services
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["systemctl enable consul && service consul start"]
  }

  // set hostname
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["hostnamectl set-hostname '${self.label}'"]
  }

  // provision certs
  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca consul-agent --hostname client.${self.region}.consul --owner consul:consul --outdir /etc/ssl/consul-agent --basename consul"
  }

  // disable further root ssh
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }

R terraform/domain-address/variables.tf => terraform/domain/input.tf +6 -2
@@ 9,9 9,13 @@ variable name {

variable instances {
  type = list(object({
    ip_address = string
    ipv6       = string
    ip = string
    ipv4 = string
  }))
}

variable live_workspace {
  type = string
}

// vim: set expandtab shiftwidth=2 tabstop=2:

R terraform/domain-address/main.tf => terraform/domain/main.tf +11 -2
@@ 1,3 1,12 @@
terraform {
  required_providers {
    linode = {
      source  = "linode/linode"
      version = "~> 1.19.1"
    }
  }
}

data "linode_domain" "d" {
  domain = var.domain
}


@@ 5,7 14,7 @@ data "linode_domain" "d" {
// Domains should only be applied in the default workspace to avoid clobbering DNS records in test deployments.

resource "linode_domain_record" "a" {
  for_each    = toset(terraform.workspace == "default" ? var.instances[*].ip_address : [])
  for_each    = toset(terraform.workspace == var.live_workspace ? var.instances[*].ipv4 : [])
  domain_id   = data.linode_domain.d.id
  name        = var.name
  record_type = "A"


@@ 13,7 22,7 @@ resource "linode_domain_record" "a" {
}

resource "linode_domain_record" "aaaa" {
  for_each    = toset(terraform.workspace == "default" ? [for ip in var.instances[*].ipv6 : split("/", ip)[0]] : [])
  for_each    = toset(terraform.workspace == var.live_workspace ? var.instances[*].ip : [])
  domain_id   = data.linode_domain.d.id
  name        = var.name
  record_type = "AAAA"

A terraform/input.tf => terraform/input.tf +16 -0
@@ 0,0 1,16 @@
variable linode_token { type = string }

variable bootstrap {
  type = string
  default = false
}

variable vault_token {
  type = string
  default = ""
}

variable live_workspace {
  type = string
  default = "default"
}

M terraform/main.tf => terraform/main.tf +15 -16
@@ 18,16 18,6 @@ provider "linode" {
  token = var.linode_token
}

variable "linode_token" { type = string }
variable "bootstrap" {
  type = string
  default = false
}
variable "vault_token" {
  type = string
  default = ""
}

data "linode_profile" "me" {}

module "consul-server" {


@@ 36,7 26,7 @@ module "consul-server" {
  servers        = 1

  datacenter       = local.datacenter
  image            = local.image
  image            = "private/16175270"
  instance_type    = local.instance_type
  authorized_users = local.authorized_users
  bootstrap        = var.bootstrap


@@ 54,7 44,7 @@ module "nomad-server" {
  consul_server_ips = module.consul-server.instances[*].ip

  datacenter       = local.datacenter
  image            = "private/15446344"
  image            = "private/16176373"
  instance_type    = local.instance_type
  authorized_users = local.authorized_users
  vault_token      = var.vault_token


@@ 73,7 63,7 @@ module "nomad-client" {
  consul_server_ips = module.consul-server.instances[*].ip

  datacenter       = local.datacenter
  image            = "private/15446344"
  image            = "private/16182279"
  instance_type    = local.instance_type
  authorized_users = local.authorized_users
}


@@ 84,14 74,14 @@ output "nomad-clients" {
}

module "nomad-client-ingress" {
  source = "./nomad-client"
  source = "./nomad-client-ingress"

  clients           = 1
  node_class        = "ingress"
  consul_server_ips = module.consul-server.instances[*].ip

  datacenter       = local.datacenter
  image            = "private/15446344"
  image            = "private/16182548"
  instance_type    = local.instance_type
  authorized_users = local.authorized_users
}


@@ 108,7 98,7 @@ module "vault-server" {
  consul_server_ips = module.consul-server.instances[*].ip

  datacenter       = local.datacenter
  image            = local.image
  image            = "private/16175603"
  instance_type    = local.instance_type
  authorized_users = local.authorized_users
  bootstrap        = var.bootstrap


@@ 118,3 108,12 @@ output "vault-servers" {
  description = "Vault servers"
  value       = module.vault-server.instances
}
/*

module "module-damienradtkecom" {
  source = "./domain"
  domain = "damienradtke.com"
  instances = module.nomad-client-ingress.instances
  live_workspace = var.live_workspace
}
  */

A terraform/nomad-client-ingress/main.tf => terraform/nomad-client-ingress/main.tf +155 -0
@@ 0,0 1,155 @@
terraform {
  required_providers {
    linode = {
      source  = "linode/linode"
      version = "~> 1.19.1"
    }
  }
}

resource "linode_instance" "clients" {
  count            = var.clients
  label            = "nomad-client-${random_id.clients[count.index].keepers.datacenter}-${random_id.clients[count.index].hex}"
  region           = random_id.clients[count.index].keepers.datacenter
  type             = random_id.clients[count.index].keepers.instance_type
  group            = terraform.workspace
  tags             = [terraform.workspace]

  disk {
    label = "boot"
    size = 20480 // 20G
    image = random_id.clients[count.index].keepers.image
    authorized_users = var.authorized_users
  }

  config {
    label = "boot_config"
    kernel = "linode/grub2"
    devices {
      sda {
        disk_label = "boot"
      }
    }
  }

  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["echo SSH is up"]
  }

  // Recognize the new server
  // This isn't _ideal_, but it's better than disabling host key checking for every SSH command.
  provisioner "local-exec" {
    command = "ssh-keygen -R '${split("/", self.ipv6)[0]}' && ssh-keyscan -v '${split("/", self.ipv6)[0]}' >> ~/.ssh/known_hosts"
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca consul-agent --hostname client.${self.region}.consul --owner consul:consul --outdir /etc/ssl/consul-agent --basename consul"
  }

  provisioner "file" {
    connection { host = split("/", self.ipv6)[0] }
    destination = "/etc/consul.d/client.hcl"
    content     = <<-EOT
      node_name        = "${self.label}"
      datacenter       = "${var.datacenter}"
      server           = false
    EOT
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca nomad-agent --hostname client.global.nomad --owner nomad:nomad --outdir /etc/ssl/nomad-agent --basename nomad"
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca nomad-agent --owner damien:nobody --outdir /etc/ssl/nomad-agent --basename cli"
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca vault-server --hostname client.global.nomad --owner nomad:nomad --outdir /etc/ssl/nomad-agent --basename vault"
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca consul-agent --owner fabio:fabio --outdir /etc/ssl/fabio --basename consul"
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca vault-server --owner fabio:fabio --outdir /etc/ssl/fabio --basename vault"
  }

  provisioner "file" {
    connection { host = split("/", self.ipv6)[0] }
    destination = "/etc/nomad.d/client.hcl"
    content     = <<-EOT
      name = "${self.label}"
      datacenter = "${var.datacenter}"
      client {
        enabled = true
        node_class = "${var.node_class}"
      }
      plugin "raw_exec" {
        config {
          enabled = true
        }
      }
    EOT
  }

  // restart services
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["service consul restart && service nomad restart"]
  }

  // set hostname
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["hostnamectl set-hostname '${self.label}'"]
  }

  // disable further root ssh
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = [
      "cp /root/.ssh/authorized_keys /home/damien/.ssh/",
      "chown -R damien:users /home/damien/.ssh/",
      // TODO: re-disable root, but only after null resource provisioners have also run
      //"sed -i 's/PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config",
      //"service sshd reload",
    ]
  }
}

resource "random_id" "clients" {
  count = var.clients
  keepers = {
    datacenter     = var.datacenter
    image          = var.image
    instance_type  = var.instance_type
  }
  byte_length = 4
}

resource "null_resource" "cluster" {
  triggers = {
    ips = "${join(",", var.consul_server_ips)}"
  }

  count = length(linode_instance.clients.*.id)
  connection {
    host = split("/", linode_instance.clients[count.index].ipv6)[0]
  }

  provisioner "file" {
    destination = "/etc/consul.d/join.hcl"
    content = <<EOF
retry_join = [${join(", ", [for ip in var.consul_server_ips : format("\"%s\"", ip)])}]
EOF
  }

  provisioner "remote-exec" {
    inline = ["service consul restart"]
  }
}

// vim: set expandtab shiftwidth=2 tabstop=2:

A terraform/nomad-client-ingress/outputs.tf => terraform/nomad-client-ingress/outputs.tf +9 -0
@@ 0,0 1,9 @@
output "instances" {
  description = "Nomad client instances"
  value       = [for instance in linode_instance.clients[*] : {
    ip = split("/", instance.ipv6)[0]
    ipv4 = one(instance.ipv4)
  }]
}

// vim: set expandtab shiftwidth=2 tabstop=2:

A terraform/nomad-client-ingress/variables.tf => terraform/nomad-client-ingress/variables.tf +19 -0
@@ 0,0 1,19 @@
variable clients { type = number }

variable datacenter { type = string }
variable image { type = string }
variable instance_type { type = string }
variable authorized_users { type = list(string) }
variable consul_server_ips { type = list(string) }

variable meta {
  type    = map(string)
  default = {}
}

variable node_class {
  type    = string
  default = ""
}

// vim: set expandtab shiftwidth=2 tabstop=2:

M terraform/nomad-client/main.tf => terraform/nomad-client/main.tf +3 -22
@@ 7,32 7,13 @@ terraform {
  }
}

// TODO: use this
locals {
  extra_provisions_for_class = lookup({
    "load-balancer" = [
      "groupadd fabio",
      "useradd --gid fabio fabio",
      "mkdir -p --mode=0500 /etc/ssl/fabio",
      "chown fabio:fabio /etc/ssl/fabio",
      "/usr/local/bin/issue-cert.sh --user fabio --ca consul --name consul",
      "/usr/local/bin/issue-cert.sh --user fabio --ca vault --name vault",
      "firewall-cmd --zone=public --add-service=fabio --permanent",
      "firewall-cmd --zone=public --add-service=web --permanent",
      "firewall-cmd --reload",
    ]
  }, var.node_class, [])
}

resource "linode_instance" "clients" {
  count            = var.clients
  label            = "nomad-client-${random_id.clients[count.index].keepers.datacenter}-${random_id.clients[count.index].hex}"
  region           = random_id.clients[count.index].keepers.datacenter
  //image            = random_id.clients[count.index].keepers.image
  type             = random_id.clients[count.index].keepers.instance_type
  //authorized_users = var.authorized_users
  group            = terraform.workspace
  tags            = [terraform.workspace]
  tags             = [terraform.workspace]

  disk {
    label = "boot"


@@ 106,10 87,10 @@ resource "linode_instance" "clients" {
    EOT
  }

  // start services
  // restart services
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["systemctl enable consul && service consul start && systemctl enable nomad && service nomad start"]
    inline = ["service consul restart && service nomad restart"]
  }

  // set hostname

M terraform/nomad-client/outputs.tf => terraform/nomad-client/outputs.tf +1 -0
@@ 2,6 2,7 @@ output "instances" {
  description = "Nomad client instances"
  value       = [for instance in linode_instance.clients[*] : {
    ip = split("/", instance.ipv6)[0]
    ipv4 = one(instance.ipv4)
  }]
}


M terraform/nomad-server/main.tf => terraform/nomad-server/main.tf +2 -2
@@ 82,10 82,10 @@ resource "linode_instance" "servers" {
    inline = ["chmod 0600 /etc/nomad.d/vault.hcl"]
  }

  // start services
  // restart services
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["systemctl enable consul && service consul start && systemctl enable nomad && service nomad start"]
    inline = ["service consul restart && service nomad restart"]
  }

  // set hostname

M terraform/vault-server/main.tf => terraform/vault-server/main.tf +6 -3
@@ 43,7 43,10 @@ resource "linode_instance" "servers" {
  }

  provisioner "local-exec" {
    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca vault-server --hostname server.${self.region}.vault --owner vault:vault --outdir /etc/ssl/vault-server --basename vault"
    // See the list of domain names here: https://www.vaultproject.io/docs/configuration/service-registration/consul
    // active and standby are not included because of this error: 140339863930688:error:0D07A097:asn1 encoding routines:ASN1_mbstring_ncopy:string too long:crypto/asn1/a_mbstr.c:107:maxsize=64

    command = "../ca/provision-cert --addr ${split("/", self.ipv6)[0]} --ca vault-server --hostname server.${self.region}.vault,vault.service.consul --owner vault:vault --outdir /etc/ssl/vault-server --basename vault"
  }

  provisioner "local-exec" {


@@ 62,10 65,10 @@ resource "linode_instance" "servers" {
    EOT
  }

  // start services
  // restart services
  provisioner "remote-exec" {
    connection { host = split("/", self.ipv6)[0] }
    inline = ["systemctl enable consul && service consul start && systemctl enable vault && service vault start"]
    inline = ["service consul restart && service vault restart"]
  }

  // set hostname