From 021df5e059e9d3fc09d6dfea13ce984f71548355 Mon Sep 17 00:00:00 2001 From: Sheogorath <sheogorath@shivering-isles.com> Date: Sat, 3 Dec 2022 23:51:38 +0000 Subject: [PATCH] feat(terraform): Add initial Terrafrom setup for gateway This patch finally upstreams the currently used terraform setup for the gateway machine at Hetzner. This should provide better insights into the infrastructure and help people to learn from the setup. It also helps to keep the automation level high and using terraform more actively to keep these servers running. The gateway server is the frontend reverse proxy for all web-originating traffic and provides a simple setup, that runs a L4 HAProxy to forward all traffic to the Kubernetes cluster, where it's terminated and handled. This allows to keep the cloud server stupid and not being able to compromise a connection (at least not more than any other middlebox). This keeps the trust away from the cloud provider. --- images/koolbox/Dockerfile | 10 +- terraform/k8s01/.terraform.lock.hcl | 122 ++++++++++++++++++ terraform/k8s01/firewall.tf | 88 +++++++++++++ terraform/k8s01/main.tf | 19 +++ terraform/k8s01/network.tf | 11 ++ terraform/k8s01/output.tf | 3 + terraform/k8s01/provider.tf | 14 ++ terraform/k8s01/ssh.tf | 2 + terraform/k8s01/templates/cloud-init.tpl | 79 ++++++++++++ terraform/k8s01/variables.tf | 33 +++++ terraform/k8s01/versions.tf | 1 + terraform/modules/hcloud_instance/main.tf | 71 ++++++++++ terraform/modules/hcloud_instance/network.tf | 5 + terraform/modules/hcloud_instance/output.tf | 30 +++++ .../modules/hcloud_instance/variables.tf | 111 ++++++++++++++++ terraform/modules/hcloud_instance/versions.tf | 1 + terraform/modules/hcloud_instance/volumes.tf | 19 +++ terraform/versions.tf | 21 +++ 18 files changed, 636 insertions(+), 4 deletions(-) create mode 100644 terraform/k8s01/.terraform.lock.hcl create mode 100644 terraform/k8s01/firewall.tf create mode 100644 terraform/k8s01/main.tf create mode 100644 terraform/k8s01/network.tf create mode 100644 terraform/k8s01/output.tf create mode 100644 terraform/k8s01/provider.tf create mode 100644 terraform/k8s01/ssh.tf create mode 100644 terraform/k8s01/templates/cloud-init.tpl create mode 100644 terraform/k8s01/variables.tf create mode 120000 terraform/k8s01/versions.tf create mode 100644 terraform/modules/hcloud_instance/main.tf create mode 100644 terraform/modules/hcloud_instance/network.tf create mode 100644 terraform/modules/hcloud_instance/output.tf create mode 100644 terraform/modules/hcloud_instance/variables.tf create mode 120000 terraform/modules/hcloud_instance/versions.tf create mode 100644 terraform/modules/hcloud_instance/volumes.tf create mode 100644 terraform/versions.tf diff --git a/images/koolbox/Dockerfile b/images/koolbox/Dockerfile index 9de6088fd..16e126f0e 100644 --- a/images/koolbox/Dockerfile +++ b/images/koolbox/Dockerfile @@ -127,7 +127,8 @@ ENV MDBOOK_VERSION=${MDBOOK_VERSION} RUN curl -L "https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz" | tar xvzf - mdbook \ && install -o root -g root -m 0755 mdbook /usr/local/bin/mdbook - +# Terraform CLI +FROM FROM docker.io/hashicorp/terraform:1.3.6 AS terraform # Actual start of container build FROM quay.io/fedora/fedora:36 @@ -177,6 +178,7 @@ COPY --from=mdbook /usr/local/bin/mdbook /usr/local/bin/mdbook COPY --from=release-cli /usr/local/bin/release-cli /usr/local/bin/release-cli COPY --from=git-chglog /usr/local/bin/git-chglog /usr/local/bin/git-chglog COPY --from=svu /usr/local/bin/svu /usr/local/bin/svu +COPY --from=terraform /bin/terraform /usr/local/bin/terraform RUN true \ && echo "command -v kubectl-krew >/dev/null && export PATH=\"${KREW_ROOT:-$HOME/.krew}/bin:$PATH\"" >> /root/.bashrc \ @@ -188,9 +190,9 @@ RUN true \ && true RUN true \ - && kubectl krew install cyclonus \ - && kubectl krew install outdated \ - && kubectl krew install access-matrix \ + && /usr/local/bin/kubectl krew install cyclonus \ + && /usr/local/bin/kubectl krew install outdated \ + && /usr/local/bin/kubectl krew install access-matrix \ && true # Create workspace diff --git a/terraform/k8s01/.terraform.lock.hcl b/terraform/k8s01/.terraform.lock.hcl new file mode 100644 index 000000000..a400b7eb0 --- /dev/null +++ b/terraform/k8s01/.terraform.lock.hcl @@ -0,0 +1,122 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/cloudflare/cloudflare" { + version = "3.29.0" + constraints = "3.29.0" + hashes = [ + "h1:iGDvVJ6kdlopyhR3ONeoh8gZWZg8+M/seP7VM7gOp1I=", + "zh:0947f7f9e0234aaeb6b5f344de4148a6379d05370937e1c255872697803c17cc", + "zh:17abb230abd852e0e4ed9921cd9aaf03336ad4a13a25b1040ed86cdbddf05123", + "zh:2ddf550dbdf5c58bbb8d14de6b2dc76627bb92787b99328300fb312c51e12d1f", + "zh:4645758bdefe52c1aa260368522aff6fcb4e508c918e9b2c263c9debd7d71684", + "zh:6047320a05d07045f7fb4b24c2540600473a94fc15a24ef99339a6690ab47dfe", + "zh:6db2d4e4bc3ab8b6107aec80a8041388c2a7722472c5efa6caf8435a453b1f33", + "zh:8b6b75a75567ae44a788128aebcbb59cebd9a9dbc4ddc1b05f4455734363d55a", + "zh:90c51deb4e96690ed73d8b8498d5ab2d7bb78597861bbef23fab18764371deb0", + "zh:9b0f89952afb5d00e31fb745f1ebb4ef677591ca62c002c744d23bcaa0d51e9a", + "zh:9cfe38d8ef5515d164f59b5f4ddc14bb8817051ea4efed54cb7834c66492dd79", + "zh:acf89e44b8643d52186ef5155c8889845681471abb60a933017cda9bc38d86ef", + "zh:c09205c6f1e39994c2f707cce0758a2cd16949b33566a724644593d2a616ea41", + "zh:c5412f2868592db091b91361b7a85fa3a1a97282e9e6e1c5883dd5f6b5f2e86c", + "zh:ff93702ca9a99863914718ae4214acffa1a72d481c8e1d3254ccf5930a2d7e10", + ] +} + +provider "registry.terraform.io/hashicorp/http" { + version = "3.2.1" + hashes = [ + "h1:DfxMa1zM/0NCFWN5PAxivSHJMNkOAFZvDYQkO72ZQmw=", + "zh:088b3b3128034485e11dff8da16e857d316fbefeaaf5bef24cceda34c6980641", + "zh:09ed1f2462ea4590b112e048c4af556f0b6eafc7cf2c75bb2ac21cd87ca59377", + "zh:39c6b0b4d3f0f65e783c467d3f634e2394820b8aef907fcc24493f21dcf73ca3", + "zh:47aab45327daecd33158a36c1a36004180a518bf1620cdd5cfc5e1fe77d5a86f", + "zh:4d70a990aa48116ab6f194eef393082c21cf58bece933b63575c63c1d2b66818", + "zh:65470c43fda950c7e9ac89417303c470146de984201fff6ef84299ea29e02d30", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:842b4dd63e438f5cd5fdfba1c09b8fdf268e8766e6690988ee24e8b25bfd9e8d", + "zh:a167a057f7e2d80c78d4b4057538588131fceb983d5c93b07675ad9eb1aa5790", + "zh:d0ba69b62b6db788cfe3cf8f7dc6e9a0eabe2927dc119d7fe3fe6573ee559e66", + "zh:e28d24c1d5ff24b1d1cc6f0074a1f41a6974f473f4ff7a37e55c7b6dca68308a", + "zh:fde8a50554960e5366fd0e1ca330a7c1d24ae6bbb2888137a5c83d83ce14fd18", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "1.4.0" + constraints = "1.4.0" + hashes = [ + "h1:P3mtBQSRp/KhVLJgwdHZRTWaYsT6A9nSwrmKrRZwsW8=", + "zh:1b265fcfdce8cc3ccb51969c6d7a61531bf8a6e1218d95c1a74c40f25595c74b", + "zh:2ea6d8c503a1119b80a273eacd187516347c00a54990c47d130235e2ad53d163", + "zh:38bcc4a224d2c0745015564b0803a368b2bd08d1a3e349783bc4c09c68fde24b", + "zh:3fada9c646bf57bcdd6844d7c30153407a2a8100811daa69fc0d674fb39a9d18", + "zh:74ccb372e752188ba4ff1b1280222d6fd61bdf29dcf474edb8ea63178897912c", + "zh:7a323f05ccd7caa1450301af1bb7cac25e2d6ac799eb581219c2c663e5d9ae3f", + "zh:7ef13da7e8ae7129fae8a9c72845d52d4586db496359228ed435aeab2f44aea8", + "zh:9df7edb284f5548918b839b18204c6a78ac33b4df070d4e4a5c264bb11152e9c", + "zh:b062919beaca2e06fd3b333b700dae664828fe734479e51c2c28b8219286e0fc", + "zh:ca9fe963f261236b3f3308f8b4979cdd95dd68281b00c1c18a6d17db07519ac8", + "zh:e125e4a7d838e231a88e0efc1e727f5a1807db5c0cad5e1cbaf1b52c560b47c7", + "zh:f3c3bbab3785f00433135538bdb697d516bc43f102c1b128a0c1419b172e88f6", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.4.3" + hashes = [ + "h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=", + "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752", + "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b", + "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3", + "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5", + "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda", + "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6", + "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1", + "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d", + "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8", + "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93", + ] +} + +provider "registry.terraform.io/hashicorp/template" { + version = "2.2.0" + constraints = "2.2.0" + hashes = [ + "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", + "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386", + "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53", + "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603", + "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16", + "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776", + "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451", + "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae", + "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde", + "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d", + "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2", + ] +} + +provider "registry.terraform.io/hetznercloud/hcloud" { + version = "1.36.1" + constraints = "1.36.1" + hashes = [ + "h1:xZSvxx6aUo0oZp2uqNxi/+wqnCNEBBuu8y7GeXIO9qA=", + "zh:16558b25c7f92f187278e94e951b0ab687882b06acff5b1387f3293f27939f8c", + "zh:28fc79ac2189ff0f5e6c9535ada8f57552b6e21c978b59dc78e086c27b9e4b23", + "zh:373907f9f7f2cefa94e2d5638bf5bef3d3b17e7655dc84dd6089346c6f4f9096", + "zh:394716cd877de682a0772d660f1bdb3838c5d751eca2211105d5ede248c48c39", + "zh:3c438c6590fcc8ac65a10039b2f5ba9ee379a734cb93a59c6cf74f385d891e87", + "zh:3f777a460a62fd23b283c269f1533b3887bf0c5564581e1e96cf294e077f5a8a", + "zh:4f62967553d7ce81ec14db7685306b625970ba6640b5764dc0137675ab97af0b", + "zh:56da08f8d75f596d6f9da4f0fd16bd60d1733cabcc260e885e1d7a711d6d3d8b", + "zh:62776c885bfa8e715dba6662f1744b5251f4cdd523dd4d1e4ccb2e25489593e9", + "zh:64cbb68139aa65f95ab3e654d872f9d34ef991fbf667fc30e0f29b96b5e8b4ed", + "zh:75a4b7a73ff0a537214d12d820438b7ae7a33d660e5d793f4ae0ebe3152bff00", + "zh:7b59d72538772ada7d51eaa50c905285200b1889ab29948b533412ccdf4d18de", + "zh:b84eeaa82bf765c6dd945ae83f1a9271fa5fad53b861b18b09cb8deda67dae13", + "zh:e81c3ea971e32a6ca3fdb0cd9e644614308ab2cf2a19482dd8a109d67fe3fb6f", + ] +} diff --git a/terraform/k8s01/firewall.tf b/terraform/k8s01/firewall.tf new file mode 100644 index 000000000..cc6a4efdb --- /dev/null +++ b/terraform/k8s01/firewall.tf @@ -0,0 +1,88 @@ +resource "hcloud_firewall" "ingress-web" { + name = "ingress-web" + apply_to { + label_selector = "firewall.hetzner.si-infra.de/web=true" + } + + # ICMP is always a good idea + # + # Network reachability tests + rule { + direction = "in" + protocol = "icmp" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } + + # Allow HTTP and HTTPS traffic in + rule { + direction = "in" + protocol = "tcp" + port = "80" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } + rule { + direction = "in" + protocol = "tcp" + port = "443" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } +} + +resource "hcloud_firewall" "ingress-email" { + name = "ingress-email" + apply_to { + label_selector = "firewall.hetzner.si-infra.de/email=true" + } + + # ICMP is always a good idea + # + # Network reachability tests + rule { + direction = "in" + protocol = "icmp" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } + + # Allow HTTP and HTTPS traffic in + rule { + direction = "in" + protocol = "tcp" + port = "25" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } + + rule { + direction = "in" + protocol = "tcp" + port = "465" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } + + rule { + direction = "in" + protocol = "tcp" + port = "993" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } +} diff --git a/terraform/k8s01/main.tf b/terraform/k8s01/main.tf new file mode 100644 index 000000000..11c35d3c4 --- /dev/null +++ b/terraform/k8s01/main.tf @@ -0,0 +1,19 @@ +module "gw" { + source = "../modules/hcloud_instance" + instance_count = 1 + location = var.location + name = "gw" + dns_domain = var.dns_domain + dns_zone_id = var.dns_zone_id + dns_record_aaaa = false + image = "fedora-36" + user_data = templatefile("templates/cloud-init.tpl", {netbird_key = "${var.netbird_key}"}) + ssh_keys = data.hcloud_ssh_keys.all_keys.ssh_keys.*.name + server_type = "cx11" + labels = { + "cluster.kubernetes.io/k8s01" = "owner", + "firewall.hetzner.si-infra.de/web" = "true", + "firewall.hetzner.si-infra.de/email" = "true" + } + subnet = hcloud_network_subnet.subnet.id +} diff --git a/terraform/k8s01/network.tf b/terraform/k8s01/network.tf new file mode 100644 index 000000000..62cc1e08f --- /dev/null +++ b/terraform/k8s01/network.tf @@ -0,0 +1,11 @@ +resource "hcloud_network" "network" { + name = "hetzner-network" + ip_range = var.network_cidr +} + +resource "hcloud_network_subnet" "subnet" { + network_id = hcloud_network.network.id + type = "server" + network_zone = "eu-central" + ip_range = var.subnet_cidr +} diff --git a/terraform/k8s01/output.tf b/terraform/k8s01/output.tf new file mode 100644 index 000000000..6e469dafd --- /dev/null +++ b/terraform/k8s01/output.tf @@ -0,0 +1,3 @@ +output "gw" { + value = module.gw +} diff --git a/terraform/k8s01/provider.tf b/terraform/k8s01/provider.tf new file mode 100644 index 000000000..eac840f08 --- /dev/null +++ b/terraform/k8s01/provider.tf @@ -0,0 +1,14 @@ +provider "cloudflare" { +} + +provider "hcloud" { +} + +provider "template" { +} + +provider "local" { +} + +provider "random" { +} diff --git a/terraform/k8s01/ssh.tf b/terraform/k8s01/ssh.tf new file mode 100644 index 000000000..db794f29d --- /dev/null +++ b/terraform/k8s01/ssh.tf @@ -0,0 +1,2 @@ +data "hcloud_ssh_keys" "all_keys" { +} diff --git a/terraform/k8s01/templates/cloud-init.tpl b/terraform/k8s01/templates/cloud-init.tpl new file mode 100644 index 000000000..387868af4 --- /dev/null +++ b/terraform/k8s01/templates/cloud-init.tpl @@ -0,0 +1,79 @@ +#!/bin/bash + +set -e + +dnf upgrade -y + +cat <<EOF | tee /etc/yum.repos.d/wiretrustee.repo +[Wiretrustee] +name=Wiretrustee +baseurl=https://pkgs.wiretrustee.com/yum/ +enabled=1 +gpgcheck=0 +gpgkey=https://pkgs.wiretrustee.com/yum/repodata/repomd.xml.key +repo_gpgcheck=1 +EOF + +dnf install -y netbird + +netbird up --setup-key ${netbird_key} + +# Install and configure HAProxy +dnf install -y haproxy + +mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig + +cat <<EOF | tee /etc/haproxy/haproxy.cfg +listen smtp + bind 0.0.0.0:25 + bind :::25 + mode tcp + option tcplog + log stdout format short daemon info + timeout connect 7s + timeout client 1m + timeout server 1m + server srv1-smtp mail.k8s01.si-infra.de:10025 send-proxy-v2 +listen l1 + bind 0.0.0.0:80 + bind :::80 + mode tcp + timeout connect 4s + timeout client 180s + timeout server 180s + server srv1-http ingress.k8s01.si-infra.de:80 check inter 5s +listen l2 + bind 0.0.0.0:443 + bind :::443 + mode tcp + timeout connect 4s + timeout client 180s + timeout server 180s + server srv1-https ingress.k8s01.si-infra.de:443 check inter 5s +listen submissions + bind 0.0.0.0:465 + bind :::465 + mode tcp + timeout connect 4s + timeout client 180s + timeout server 180s + server srv1-submissions mail.k8s01.si-infra.de:465 +listen imaps + bind 0.0.0.0:993 + bind :::993 + mode tcp + timeout connect 4s + timeout client 180s + timeout server 180s + server srv1-imaps mail.k8s01.si-infra.de:993 check inter 5s + +EOF + +systemctl enable --now haproxy.service + +# Enable automatic updates +dnf install -y dnf-automatic + +systemctl enable --now dnf-automatic-install.timer + +reboot diff --git a/terraform/k8s01/variables.tf b/terraform/k8s01/variables.tf new file mode 100644 index 000000000..a11edbaeb --- /dev/null +++ b/terraform/k8s01/variables.tf @@ -0,0 +1,33 @@ +variable "dns_domain" { + type = string + description = "Name of the Cloudflare domain" +} + +variable "dns_zone_id" { + type = string + description = "Zone ID of the Cloudflare domain" +} + +variable "network_cidr" { + type = string + description = "CIDR for the network" + default = "10.2.0.0/24" +} + +variable "subnet_cidr" { + type = string + description = "CIDR for the subnet" + default = "10.2.0.0/28" +} + +variable "location" { + type = string + description = "Region" + default = "nbg1" +} + + +variable "netbird_key" { + type = string + description = "NetBird activation key" +} \ No newline at end of file diff --git a/terraform/k8s01/versions.tf b/terraform/k8s01/versions.tf new file mode 120000 index 000000000..8bd0ff140 --- /dev/null +++ b/terraform/k8s01/versions.tf @@ -0,0 +1 @@ +../versions.tf \ No newline at end of file diff --git a/terraform/modules/hcloud_instance/main.tf b/terraform/modules/hcloud_instance/main.tf new file mode 100644 index 000000000..72ea024b2 --- /dev/null +++ b/terraform/modules/hcloud_instance/main.tf @@ -0,0 +1,71 @@ +# The MIT License (MIT) +# +# Copyright 2021 Simon Lauger +# Copyright 2022 Christoph (Sheogorath) Kern +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +resource "hcloud_server" "server" { + count = var.instance_count + name = "${format("${var.name}%02d", count.index + 1)}.${var.dns_domain}" + image = var.image + server_type = var.server_type + keep_disk = var.keep_disk + ssh_keys = var.ssh_keys + user_data = var.user_data + labels = var.labels + datacenter = var.datacenter + backups = var.backups + public_net { + ipv4 = element(hcloud_primary_ip.main.*.id, count.index) + } + lifecycle { + ignore_changes = [firewall_ids] + } +} + +resource "hcloud_primary_ip" "main" { + count = var.instance_count + name = "${format("${var.name}%02d", count.index + 1)}.${var.dns_domain}" + datacenter = var.datacenter + type = "ipv4" + assignee_type = "server" + auto_delete = false +} + +resource "cloudflare_record" "dns-a" { + count = var.instance_count + zone_id = var.dns_zone_id + name = element(hcloud_server.server.*.name, count.index) + value = element(hcloud_server.server.*.ipv4_address, count.index) + type = "A" + ttl = 1800 +} + +resource "cloudflare_record" "dns-aaaa" { + count = var.dns_record_aaaa ? var.instance_count : "0" + zone_id = var.dns_zone_id + name = element(hcloud_server.server.*.name, count.index) + value = "${element(hcloud_server.server.*.ipv6_address, count.index)}1" + type = "AAAA" + ttl = 120 +} + +resource "hcloud_rdns" "dns-ptr-ipv4" { + count = var.instance_count + server_id = element(hcloud_server.server.*.id, count.index) + ip_address = element(hcloud_server.server.*.ipv4_address, count.index) + dns_ptr = element(hcloud_server.server.*.name, count.index) +} + +resource "hcloud_rdns" "dns-ptr-ipv6" { + count = var.instance_count + server_id = element(hcloud_server.server.*.id, count.index) + ip_address = "${element(hcloud_server.server.*.ipv6_address, count.index)}1" + dns_ptr = element(hcloud_server.server.*.name, count.index) +} diff --git a/terraform/modules/hcloud_instance/network.tf b/terraform/modules/hcloud_instance/network.tf new file mode 100644 index 000000000..bebdd1153 --- /dev/null +++ b/terraform/modules/hcloud_instance/network.tf @@ -0,0 +1,5 @@ +#resource "hcloud_server_network" "server_network" { +# server_id = element(hcloud_server.server.*.id, count.index) +# subnet_id = var.subnet +# count = length(hcloud_server.server.*.id) +#} diff --git a/terraform/modules/hcloud_instance/output.tf b/terraform/modules/hcloud_instance/output.tf new file mode 100644 index 000000000..5e0805a6b --- /dev/null +++ b/terraform/modules/hcloud_instance/output.tf @@ -0,0 +1,30 @@ +# The MIT License (MIT) +# +# Copyright 2021 Simon Lauger +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +output "server_ids" { + value = hcloud_server.server.*.id +} + +output "server_names" { + value = hcloud_server.server.*.name +} + +#output "internal_ipv4_addresses" { +# value = hcloud_server_network.server_network.*.ip +#} + +output "ipv4_addresses" { + value = hcloud_server.server.*.ipv4_address +} + +output "ipv6_addresses" { + value = hcloud_server.server.*.ipv6_address +} diff --git a/terraform/modules/hcloud_instance/variables.tf b/terraform/modules/hcloud_instance/variables.tf new file mode 100644 index 000000000..953cdced5 --- /dev/null +++ b/terraform/modules/hcloud_instance/variables.tf @@ -0,0 +1,111 @@ +# The MIT License (MIT) +# +# Copyright 2021 Simon Lauger +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +variable "name" { + type = string + description = "Instance name" +} + +variable "dns_domain" { + type = string + description = "DNS domain" +} + +variable "dns_zone_id" { + description = "Zone ID" + default = null +} + +variable "dns_internal_ip" { + description = "Point DNS record to internal ip" + default = false +} + +variable "dns_record_aaaa" { + description = "Create AAAA record" + default = true +} + +variable "instance_count" { + type = number + description = "Number of instances to deploy" + default = 1 +} + +variable "server_type" { + type = string + description = "Hetzner Cloud instance type" + default = "cx11" +} + +variable "image" { + type = string + description = "Hetzner Cloud system image" + default = "ubuntu-18.04" +} + +variable "user_data" { + description = "Cloud-Init user data to use during server creation" + default = null +} + +variable "ssh_keys" { + type = list(any) + description = "SSH key IDs or names which should be injected into the server at creation time" + default = [] +} + +variable "keep_disk" { + type = bool + description = "If true, do not upgrade the disk. This allows downgrading the server type later." + default = true +} + +variable "labels" { + type = map(string) + description = "Labels that the instance is tagged with." + default = {} +} + +variable "location" { + type = string + description = "The location name to create the server in. nbg1, fsn1 or hel1" + default = "nbg1" +} + +variable "datacenter" { + type = string + description = "The location name to create the server in. nbg1, fsn1 or hel1" + default = "nbg1-dc3" +} + +variable "backups" { + type = bool + description = "Enable or disable backups" + default = false +} + +variable "volume" { + type = bool + description = "Enable or disable an additional volume" + default = false +} + +variable "volume_size" { + type = number + description = "Size of the additional data volume" + default = 20 +} + +variable "subnet" { + type = string + description = "Id of the additional internal network" +} diff --git a/terraform/modules/hcloud_instance/versions.tf b/terraform/modules/hcloud_instance/versions.tf new file mode 120000 index 000000000..b7707ec81 --- /dev/null +++ b/terraform/modules/hcloud_instance/versions.tf @@ -0,0 +1 @@ +../../versions.tf \ No newline at end of file diff --git a/terraform/modules/hcloud_instance/volumes.tf b/terraform/modules/hcloud_instance/volumes.tf new file mode 100644 index 000000000..eef1db274 --- /dev/null +++ b/terraform/modules/hcloud_instance/volumes.tf @@ -0,0 +1,19 @@ +# The MIT License (MIT) +# +# Copyright 2021 Simon Lauger +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +resource "hcloud_volume" "volumes" { + name = "${element(hcloud_server.server.*.name, count.index)}-data" + size = var.volume_size + format = "xfs" + automount = false + server_id = element(hcloud_server.server.*.id, count.index) + count = var.volume == true ? var.instance_count : 0 +} diff --git a/terraform/versions.tf b/terraform/versions.tf new file mode 100644 index 000000000..396d4216f --- /dev/null +++ b/terraform/versions.tf @@ -0,0 +1,21 @@ +terraform { + required_providers { + cloudflare = { + source = "cloudflare/cloudflare" + version = "3.29.0" + } + hcloud = { + source = "hetznercloud/hcloud" + version = "1.36.1" + } + template = { + source = "hashicorp/template" + version = "2.2.0" + } + local = { + source = "hashicorp/local" + version = "1.4.0" + } + } + required_version = ">= 0.14" +} -- GitLab