aboutsummaryrefslogtreecommitdiff
path: root/terraform
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2018-10-22 04:02:44 -0700
committerJakob Odersky <jakob@odersky.com>2018-10-22 04:02:44 -0700
commit4d7a93c535ceeb720dc1873bfa61531099b611cb (patch)
tree5aa2c02bf756f72fecb5d7bf695a98edfdb417b2 /terraform
downloadinfra-4d7a93c535ceeb720dc1873bfa61531099b611cb.tar.gz
infra-4d7a93c535ceeb720dc1873bfa61531099b611cb.tar.bz2
infra-4d7a93c535ceeb720dc1873bfa61531099b611cb.zip
Initial commit
Diffstat (limited to 'terraform')
-rw-r--r--terraform/.gitignore22
-rw-r--r--terraform/main.tf57
-rw-r--r--terraform/role/README.md4
-rw-r--r--terraform/role/main.tf91
-rw-r--r--terraform/stdvps/README.md2
-rw-r--r--terraform/stdvps/main.tf54
-rwxr-xr-xterraform/tf3
-rw-r--r--terraform/volume/main.tf68
8 files changed, 301 insertions, 0 deletions
diff --git a/terraform/.gitignore b/terraform/.gitignore
new file mode 100644
index 0000000..4aa60fc
--- /dev/null
+++ b/terraform/.gitignore
@@ -0,0 +1,22 @@
+# Local .terraform directories
+**/.terraform/*
+terraform.d/
+
+# .tfstate files
+*.tfstate
+*.tfstate.*
+
+# Crash log files
+crash.log
+
+# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
+# .tfvars files are managed as part of configuration and so should be included in
+# version control.
+#
+# example.tfvars
+
+# Ignore override files as they are usually used to override ressources locally
+override.tf
+override.tf.json
+*_override.tf
+*_override.tf.json \ No newline at end of file
diff --git a/terraform/main.tf b/terraform/main.tf
new file mode 100644
index 0000000..8a5e599
--- /dev/null
+++ b/terraform/main.tf
@@ -0,0 +1,57 @@
+variable "secret_hcloud_token" {
+ type = "string"
+}
+
+variable "secret_cloudflare_token" {
+ type = "string"
+}
+
+provider "hcloud" {
+ token = "${var.secret_hcloud_token}"
+}
+
+provider "cloudflare" {
+ email = "jakob@odersky.com"
+ token = "${var.secret_cloudflare_token}"
+}
+
+provider "acme" {
+ #server_url = "https://acme-staging-v02.api.letsencrypt.org/directory"
+ server_url = "https://acme-v02.api.letsencrypt.org/directory"
+}
+
+################################################################################
+
+# Main ssh key
+resource "hcloud_ssh_key" "root" {
+ name = "root"
+ public_key = "${file("~/.ssh/id_rsa.pub")}"
+}
+
+module "vps" {
+ source = "./stdvps"
+ location = "nbg1"
+ ssh_key_name = "${hcloud_ssh_key.root.name}"
+}
+
+module "volume" {
+ source = "./volume"
+ server_id = "${module.vps.id}"
+ server_fqdn = "${module.vps.fqdn}"
+}
+
+module "roles" {
+ source = "./role"
+ secret_cloudflare_token = "${var.secret_cloudflare_token}"
+ host = "${module.vps.fqdn}"
+ id = "${module.volume.server_id}"
+ roles = ["ip", "git"]
+}
+
+output "vps_address" {
+ value = "${module.vps.fqdn}"
+}
+
+output "vps_roles" {
+ value = "${join(" ", module.roles.roles)}"
+}
diff --git a/terraform/role/README.md b/terraform/role/README.md
new file mode 100644
index 0000000..11e2e21
--- /dev/null
+++ b/terraform/role/README.md
@@ -0,0 +1,4 @@
+# Role-based configuration for standalone hosts.
+
+Applying a role to a host will install corresponding config packages
+and create a role CNAME record to the host.
diff --git a/terraform/role/main.tf b/terraform/role/main.tf
new file mode 100644
index 0000000..e85fd3b
--- /dev/null
+++ b/terraform/role/main.tf
@@ -0,0 +1,91 @@
+variable "host" {
+ type = "string"
+}
+
+variable "id" {
+ type = "string"
+}
+
+variable "roles" {
+ type = "list"
+}
+
+variable "secret_cloudflare_token" {
+ type = "string"
+}
+
+resource "tls_private_key" "private_key" {
+ algorithm = "RSA"
+}
+
+resource "acme_registration" "reg" {
+ account_key_pem = "${tls_private_key.private_key.private_key_pem}"
+ email_address = "jakob@odersky.com"
+}
+
+resource "acme_certificate" "certificate" {
+ account_key_pem = "${acme_registration.reg.account_key_pem}"
+ common_name = "${var.host}"
+ subject_alternative_names = "${formatlist("%s.crashbox.io", var.roles)}"
+
+ dns_challenge {
+ provider = "cloudflare"
+
+ config {
+ CLOUDFLARE_EMAIL = "jakob@odersky.com"
+ CLOUDFLARE_API_KEY = "${var.secret_cloudflare_token}"
+ }
+ }
+}
+
+resource "cloudflare_record" "role_cname" {
+ count = "${length(var.roles)}"
+
+ domain = "crashbox.io"
+ name = "${element(var.roles, count.index)}"
+ value = "${var.host}"
+ type = "CNAME"
+}
+
+resource "null_resource" "role_config" {
+ triggers = {
+ host_id = "${var.id}"
+ config_packages = "${join(" ", sort(formatlist("crashbox-%s-config", var.roles)))}"
+ }
+
+ connection {
+ host = "${var.host}"
+ }
+
+ provisioner "file" {
+ content = "${acme_certificate.certificate.certificate_pem}"
+ destination = "/etc/ssl/server.cert.pem"
+ }
+
+ provisioner "file" {
+ content = "${acme_certificate.certificate.issuer_pem}"
+ destination = "/etc/ssl/issuer.cert.pem"
+ }
+
+ provisioner "file" {
+ content = "${acme_certificate.certificate.private_key_pem}"
+ destination = "/etc/ssl/private/server.key.pem"
+ }
+
+ provisioner "file" {
+ source = "${path.root}/../packages/target/archive"
+ destination = "/usr/local/share/"
+ }
+
+ provisioner "remote-exec" {
+ inline = [
+ "echo deb [trusted=yes] file:/usr/local/share/archive ./ > /etc/apt/sources.list.d/local-archive.list",
+ "apt update --quiet=2",
+ "apt install --quiet=2 --yes ${null_resource.role_config.triggers.config_packages}",
+ ]
+ }
+}
+
+output "roles" {
+ value = "${var.roles}"
+}
diff --git a/terraform/stdvps/README.md b/terraform/stdvps/README.md
new file mode 100644
index 0000000..316641c
--- /dev/null
+++ b/terraform/stdvps/README.md
@@ -0,0 +1,2 @@
+# stdvps
+A basic cloud virtual machine.
diff --git a/terraform/stdvps/main.tf b/terraform/stdvps/main.tf
new file mode 100644
index 0000000..2328bb1
--- /dev/null
+++ b/terraform/stdvps/main.tf
@@ -0,0 +1,54 @@
+variable "ssh_key_name" {
+ type = "string"
+}
+
+variable "location" {
+ type = "string"
+}
+
+resource "random_id" "server" {
+ prefix = "peter-"
+ byte_length = 2
+}
+
+resource "hcloud_server" "server" {
+ name = "${random_id.server.hex}.crashbox.io"
+ image = "debian-9"
+ server_type = "cx11"
+ location = "${var.location}"
+ ssh_keys = ["${var.ssh_key_name}"]
+}
+
+resource "cloudflare_record" "record_a" {
+ domain = "crashbox.io"
+ name = "${hcloud_server.server.name}"
+ value = "${hcloud_server.server.ipv4_address}"
+ type = "A"
+}
+
+resource "cloudflare_record" "record_aaaa" {
+ domain = "crashbox.io"
+ name = "${hcloud_server.server.name}"
+ value = "${hcloud_server.server.ipv6_address}1"
+ type = "AAAA"
+}
+
+output "ipv4" {
+ value = "${hcloud_server.server.ipv4_address}"
+}
+
+output "ipv6" {
+ value = "${hcloud_server.server.ipv6_address}"
+}
+
+output "fqdn" {
+ value = "${cloudflare_record.record_aaaa.hostname}"
+}
+
+output "id" {
+ value = "${hcloud_server.server.id}"
+}
+
+output "name" {
+ value = "${hcloud_server.server.name}"
+}
diff --git a/terraform/tf b/terraform/tf
new file mode 100755
index 0000000..888e681
--- /dev/null
+++ b/terraform/tf
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exec terraform "$@" -var-file=<(pass infra/terraform) \ No newline at end of file
diff --git a/terraform/volume/main.tf b/terraform/volume/main.tf
new file mode 100644
index 0000000..828d85d
--- /dev/null
+++ b/terraform/volume/main.tf
@@ -0,0 +1,68 @@
+variable "server_fqdn" {
+ type = "string"
+}
+
+variable "server_id" {
+ type = "string"
+}
+
+resource "hcloud_volume" "master" {
+ name = "master"
+ size = 50
+ server_id = "${var.server_id}"
+}
+
+# this is only run once if the volume id changes
+resource "null_resource" "volume_format" {
+ triggers = {
+ volume_id = "${hcloud_volume.master.id}"
+ }
+
+ connection {
+ host = "${var.server_fqdn}"
+ }
+
+ provisioner "remote-exec" {
+ inline = [
+ "mkfs.ext4 ${hcloud_volume.master.linux_device}",
+ ]
+ }
+}
+
+resource "null_resource" "volume_mount" {
+ triggers = {
+ server_id = "${var.server_id}"
+ volume_id = "${hcloud_volume.master.id}"
+ }
+
+ connection {
+ host = "${var.server_fqdn}"
+ }
+
+ provisioner "file" {
+ content = <<EOF
+[Unit]
+Description=Mount /srv directory
+
+[Mount]
+What=${hcloud_volume.master.linux_device}
+Where=/srv
+Type=ext4
+Options=defaults
+EOF
+
+ destination = "/etc/systemd/system/srv.mount"
+ }
+
+ provisioner "remote-exec" {
+ inline = [
+ "systemctl daemon-reload",
+ "systemctl enable srv.mount",
+ "systemctl start srv.mount",
+ ]
+ }
+}
+
+output "server_id" {
+ value = "${var.server_id}"
+}