From f872d2199b947a89af4a1bf94b5a15455773c9bd Mon Sep 17 00:00:00 2001 From: Tobias Reisinger Date: Wed, 25 Sep 2024 13:23:52 +0200 Subject: [PATCH] Migrate opentofu part --- .gitignore | 3 + .terraform.lock.hcl | 119 +++++++++++++++++++++++++++++++ hcloud.tf | 63 ++++++++++++++++ hosts.auto.tfvars | 24 +++++++ main.tf | 63 ++++++++++++++++ output.tf | 20 ++++++ ovh.tf | 74 +++++++++++++++++++ scaleway.tf | 77 ++++++++++++++++++++ service_buckets.auto.tfvars | 14 ++++ tailscale.tf | 11 +++ tf-templates/cloud-init.yaml.tpl | 40 +++++++++++ variables.tf | 88 +++++++++++++++++++++++ 12 files changed, 596 insertions(+) create mode 100644 .terraform.lock.hcl create mode 100644 hcloud.tf create mode 100644 hosts.auto.tfvars create mode 100644 main.tf create mode 100644 output.tf create mode 100644 ovh.tf create mode 100644 scaleway.tf create mode 100644 service_buckets.auto.tfvars create mode 100644 tailscale.tf create mode 100644 tf-templates/cloud-init.yaml.tpl create mode 100644 variables.tf diff --git a/.gitignore b/.gitignore index 19594fd..f12db07 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ types-dnscontrol.d.ts dns/hosts.json + +secrets.auto.tfvars +.terraform diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..e7e7ec1 --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,119 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/hashicorp/template" { + version = "2.2.0" + hashes = [ + "h1:tdS0otiAtvUV8uLJWJNfcqOPo3llj7FyRzExw6X1srY=", + "zh:374c28bafc43cd65e578cb209efc9eee4c1cec7618f451528e928db98059e8c8", + "zh:6a2982e70fbc2ab2668d624c648ef2eb32243c1a1185246b03991a7a21326db9", + "zh:af83169c21bb13f141510a349e1f70cf7d893247a269bd71cad74dd22f1df0f5", + "zh:b81a5bedc91a1a81b938c393247248d6c3d1bd8ea685541f9c858908c0afb6b3", + "zh:de15486244af2d29d44d510d647cd6e0b1408e89952261013c572b7c9bfd744b", + ] +} + +provider "registry.opentofu.org/hashicorp/time" { + version = "0.12.0" + hashes = [ + "h1:Om7xF0GgRkBsAjKis3RAFXQJKmHgnO04C+PEScF/xTM=", + "zh:01b7ac8203eb7ed712a356215e44f8851b96ddcfdf63b13ff9f870f799667059", + "zh:06c4420bdb964209eb119f1740575df7b8ac44a3b5d71631dae2962a155f58b7", + "zh:2534d1d04ca934e25426ab5bb0b29a57a95c676f70b154bfb382d58bf1e6f6c9", + "zh:340de6c71a1090f13ab5c429ca2134c12189e8b86c2b104859e82eb30eea9772", + "zh:561a2780f7fb1b0a9092c59c4eb3e3d8c3ec9cecddc9214ae92fdc941c3bd2e7", + "zh:65b1a982617375123bc3a1dcd44d61264cabac6b3d83378e7079ee0655ec6679", + "zh:9ae9f6c9609c5ed9e35a702068629ef5adfb131f957a571fc39ce0127c782ca4", + "zh:ad7f066c5db340683cb5a3a29ced3a2ece13c5b84c46d6b3d30815444a6c78ee", + "zh:f532d2c33c2303a970e9ee813e37d208eb65321aec489da14786b7f04ea66105", + "zh:fb269e2425a4b996fef79665eaeec8f40a388bf7ac7bf8ce2c108fb83c4b10ca", + ] +} + +provider "registry.opentofu.org/hetznercloud/hcloud" { + version = "1.48.1" + constraints = "~> 1.45" + hashes = [ + "h1:fa9fxdSV9DG+HDcXyRbcGfb6Dk94SBP3TamHb1yOYiI=", + "zh:086cce10cb005f25f85183c59e639d6675e91e919934c80f660ca1cc4b9bc09b", + "zh:111d185707168b90c7ed3d245b522b2bd508f0bd4275496a1acdc9c0adaa85f2", + "zh:1acba3f30150282d283c46cd7ce25e9afb8b027fd2f594d41de9131d25a42b27", + "zh:1f8858aa81f93d52550502a11c7ea4e9370316ab098f6b75a09ffe75da6129ee", + "zh:20e01e6e6f99f57b3c1ef2a9de5d617c0139d3f3934eeb5e6c5976ae8b831a48", + "zh:2a8489a586a7bdadc42bbc9e3cb7b9deaefdf8020e3f2caba2678877d5d64d52", + "zh:31d8017529b0429bc9e873ec5d358ab9b75af2ba0ae24f21abcd4d09f36b7ee9", + "zh:407b4d7f1407e7e4a51b6f4dcdb0c7fbf81f2f1e25a7275f34054009419125a2", + "zh:42cf7cf867d199054713d4e6060e4b578eff16f0f537e9aaa5fd990c3eab8bc6", + "zh:460ac856ff952c5d41525949b93cfb7ee642f900594eff965494f11999d7496b", + "zh:d09e527d23f62564c82bc24e286cf2cb8cb0ed6cdc6f4c66adf2145cfa62adac", + "zh:d465356710444ac70dea4883252efc429b73e79fc6dc94f075662b838476680e", + "zh:d476c8eca307e30a20eed54c0735b062a6f3066b4ac63eebecd38ab8f40c16f4", + "zh:e0e9b2f6d5e28dbd01fa1ec3147aa88062d6223c5146532a3dcd1d3bb827e1e9", + ] +} + +provider "registry.opentofu.org/ovh/ovh" { + version = "0.48.0" + constraints = "~> 0.48" + hashes = [ + "h1:dOwImR7DGX4FHt9IpY6S7z8z62fyhTOiLm0kgSA+MfE=", + "zh:64ae6a94f86115d6a0cf54e62de16f3751f2f511c7c133a58734b623ecd83133", + "zh:808c0dfc35f0cdde84fff2b772ef52aef57363e2f496ae8e5b5d191ae2482db3", + "zh:91427314fe73ee5bb3cc0fdcc88c15416709ff049751573674cb56a17ebf137f", + "zh:97a60491d8a50900c83365ab86343f59ae39a6a8d0ecbf2229be389143c584af", + "zh:a2be10afc172ea844706217143b003c21dd502fcfe429fa61f5cebdbd2c38c55", + "zh:a6e0e5978a6b1247a110e1bf2461771e3bf1b3c974cc83b56ae3255cdc5123d3", + "zh:b6cac2ddd451cb783faab09ec90a54be222a2bc9ef59eaaec309980b46a8650c", + "zh:d767fc3a8c992fa01be52a86ba92204d5ac7ea238a2ebce5e313eaf56e4ae3ac", + "zh:ed2f82995fbe92d7a750a9560cb325d6dbee1b031898dba4ab74447c6043c878", + "zh:ef20c721c5349f03106aa3514752b1df3583ce96a0e704a4b45d9b4b455ca57b", + "zh:f33f42bca65d40097033f0e64e45ad113107804be2198a2279d5561bb1122b34", + "zh:f922c6d3d73f8c252beb91dc9f97eb96643781ad3e7192018be47d4df2e4d0e3", + "zh:f93577ad688f449c03c4087a19cea3cc37bc30c94519eee4710323099bf501ad", + "zh:ff33c4b2543030a82935551631d209df87adf981b4661a4ab60406e704fe7485", + ] +} + +provider "registry.opentofu.org/scaleway/scaleway" { + version = "2.44.0" + constraints = "~> 2.43" + hashes = [ + "h1:VRA4GE/N4YaxrsDi4VtCvTa2F2VMz6cHvig+uXx95Ys=", + "zh:07626890d5417058f5999675304f039036253a2b17eb1b658cb4d8a9dd783cdd", + "zh:153fb6d63f7e7203cbadd35f0ec46f8a1ce2bee16817a3f7c2b7f908d833fe9e", + "zh:2d535d419d2c44810d538e06769afc02ca529f59d4340f563d4ca040f6c43f35", + "zh:3097ffad52ea5102dfd1c0693e86f812634a029dd1a98fb8a448154daa6063fc", + "zh:562477ee7953c836a1133e20158911ff3d831167689a691b58ce7f6954e636b5", + "zh:71c4168c400b421fa1edaee1970473b6f3abe3f76d2ea5c2ef2292df9f909bcb", + "zh:82c6c6c81a5dd911f33f5363d777f0009689a83fb7bf219e958717e4d9ed0e23", + "zh:88daeb4b398e7806a1c94afce439238bf2abcb290e8c65eb3ea7e0c42c1442b1", + "zh:a1e83eda0c66140d86239b3830a258fa98f2e964bd52f2a8f3cc97aca2390166", + "zh:d7d7e37de2a66d5048e19797edd59358c357f26ac03beab9fec36c1838969ad2", + "zh:dc0692b3378057e18354a1f7aa87e64f7b84ed8e9c005b9ad69bf01638f88246", + "zh:e32409c6dfd397c297dfb702f8dff0ae3c9592c017a24148fec8379c1a67e50c", + "zh:e4aa8b3bbfbe1b5bc9a06b32a68e30def2af91c886e6008a5d4b7d6a5e18f46f", + "zh:ef08071c2c4a398c6c287a26e2255831afe5b2049416d7e7c23117f199687676", + ] +} + +provider "registry.opentofu.org/tailscale/tailscale" { + version = "0.16.2" + constraints = "~> 0.16" + hashes = [ + "h1:m8r5+K4JWe+tdT4IyryZkAQ7d38GVPtoQ9mzp+5Scaw=", + "zh:2a37ef43b88ad8e26ecad79e6b34a896769be2b7d18140f855f6063775367841", + "zh:3867d3331b59c8281dd8a742260b22e18750ae84a9bd2009e8f9d90412d2c044", + "zh:5e5e5ee08e0ecefa08a0ce7a9281a858f9b3a2a66bc9c06802b1624a1cb3eae0", + "zh:6298e8ed55bccd5513060e0d357d055919b3a22146fcfb6c34881efd49ec33f8", + "zh:6ce0ab6564fbbc673ab98ce4b7db7d64258a916394436a005d14b25c3ea58ad1", + "zh:6fdc1fb66074d2af5124a6988f81efdc77011b185e710629140e87ffb8624956", + "zh:7ff7888d77a17b18c9bdc9dfc1bf1e7f98f512410c29d1a8c2e6c21c8fe2a5c4", + "zh:9cafb8660daffd5c9c490d4529c7ba3d691fee5e4093b55e73f188b17e34cead", + "zh:b11e0e1b6c8485eb832336a69be02dfae151b71350e25288ec7bf0637df35485", + "zh:c7371d0dcde253fcd1808f86be2fcfc6e0b6ec82aa714e5dc6b533ba10007d48", + "zh:dcddd847b8a03a3b7c9288d68e781d65a3b911ef9cc96df9502a2d069195ae42", + "zh:dfd37ec661fe5b1520b595dcb93cca65f716270edc173a393a600c85b3f842d7", + "zh:e3b623167859344ed93f4125e97d24c5793246ccb329e4d82b2d9d8e5c356380", + "zh:f4d38ec08191ae70ef05ffd3943df1c27e2b11192a02e1979498a59ea1881ee3", + ] +} diff --git a/hcloud.tf b/hcloud.tf new file mode 100644 index 0000000..97f74b0 --- /dev/null +++ b/hcloud.tf @@ -0,0 +1,63 @@ +resource "hcloud_ssh_key" "openpgp_0xAB920993" { + name = "openpgp:0xAB920993" + public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCkmWZmum4cVeDy5+9N1HdUzfnjEHSJ900ucD8F0wAy4MV1cdPYnZ4u5PFv5XMfmvA9SJ+VFsr0lhYlr+GQBG9aCCAdMJVVmEz3SccT6dp6ZYywT158RNshzfCe9ylWKK80+W7XnDXhdkec7aK+BQn5wOER3A3mUqRR0JDXWga9jyakH1K6OwXmQOO419bJWs2uCT1ZEgndHxKJEt2pEvoSz7z8p1SS2zyro+R3YtvL9WiDo3+0yPFYficNDr7s39yF5IJE+KTqAlCn5R2+kJ54lRmzB8oNS2jGwK2Q6wtph4AmfnlJTMODG2U2RjUltH2MIDXIYe2epATWL8qhkI4LTr38C7QR3DeJQsel/yTWdYqGakvU6Ge/xkbsaWOrSDTV3bPgKHzlL+dIKaGpV+5usZN4fpOLOb/nmYy3ekLpobzxza7rBRT2CxXS72DoPFaRE1ye7SxhcsLBNwre9YQFE4VvUZwJYkWz2V7eqGrk8VYnmQmT/bnUnMnVwMpeDc7pFKAFndIUxifoOj77c98Tdy3ncdS7SOd7+zRbLG+7k0UU1k89o1+tfREAddUJYR4RvB6g0kCyjpwOf1Pt4zhJR3y/zpsCCc5UnzK9X2kEo/8TSyvTr+GBiFVp5yLYgwCPJSNna33YX7+c3oLRM1QGgtqZk9qnGX9hgP8qpF8Akw== openpgp:0xAB920993" +} + +data "template_file" "cloud_init" { + template = "${file("./tf-templates/cloud-init.yaml.tpl")}" + + vars = { + tailscale_authkey = "${tailscale_tailnet_key.cloud_init_key.key}" + } +} + +locals { + hetzner_hosts = {for key, val in var.hosts : key => val if val.provider == "hetzner"} +} + +resource "hcloud_primary_ip" "node_ipv4_addresses" { + for_each = local.hetzner_hosts + name = "primary_ipv4_${each.value.hostname}" + datacenter = each.value.datacenter + type = "ipv4" + assignee_type = "server" + auto_delete = false +} + +resource "hcloud_primary_ip" "node_ipv6_addresses" { + for_each = local.hetzner_hosts + name = "primary_ipv6_${each.value.hostname}" + datacenter = each.value.datacenter + type = "ipv6" + assignee_type = "server" + auto_delete = false +} + +# Create a server +resource "hcloud_server" "nodes" { + for_each = local.hetzner_hosts + name = each.value.hostname + datacenter = each.value.datacenter + image = each.value.image + server_type = each.value.server_type + ssh_keys = [hcloud_ssh_key.openpgp_0xAB920993.id] + user_data = "${data.template_file.cloud_init.rendered}" + public_net { + ipv4 = hcloud_primary_ip.node_ipv4_addresses[each.key].id + ipv6 = hcloud_primary_ip.node_ipv6_addresses[each.key].id + } + lifecycle { + ignore_changes = [ + ssh_keys, + user_data + ] + prevent_destroy = true + } +} + +resource "hcloud_rdns" "nodes_rdns" { + for_each = local.hetzner_hosts + server_id = hcloud_server.nodes[each.key].id + ip_address = hcloud_server.nodes[each.key].ipv4_address + dns_ptr = each.value.rdns +} diff --git a/hosts.auto.tfvars b/hosts.auto.tfvars new file mode 100644 index 0000000..7e062bc --- /dev/null +++ b/hosts.auto.tfvars @@ -0,0 +1,24 @@ +hosts = { + "node001" = { + hostname = "node001" + rdns = "node001.serguzim.net" + provider = "contabo" + ipv4_address = "144.91.106.67", + ipv6_address = "2a02:c207:2051:6620::1" + }, + "node002" = { + hostname = "node002" + rdns = "node002.serguzim.net" + provider = "contabo" + ipv4_address = "62.171.181.192", + ipv6_address = "2a02:c207:2036:6681::1" + }, + "node003" = { + hostname = "node003" + rdns = "mail.serguzim.me" + provider = "hetzner" + image = "debian-12" + server_type = "cx32" + datacenter = "fsn1-dc14" + }, +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..17e0ce6 --- /dev/null +++ b/main.tf @@ -0,0 +1,63 @@ +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + version = "~> 1.45" + } + ovh = { + source = "ovh/ovh" + version = "~> 0.48" + } + scaleway = { + source = "scaleway/scaleway" + version = "~> 2.43" + } + tailscale = { + source = "tailscale/tailscale" + version = "~> 0.16" + } + } + + backend "s3" { + bucket = var.backend_bucket + access_key = var.backend_access_key + secret_key = var.backend_secret_key + key = "terraform.tfstate" + region = var.backend_region + encrypt = true + endpoints = { + s3 = var.backend_endpoint + } + + # Disable AWS-specific features + skip_credentials_validation = true + skip_region_validation = true + skip_requesting_account_id = true + skip_s3_checksum = true + } +} + +provider "hcloud" { + token = "${var.hcloud_token}" +} + +provider "ovh" { + endpoint = "ovh-eu" + application_key = "${var.ovh_application_key}" + application_secret = "${var.ovh_application_secret}" + consumer_key = "${var.ovh_consumer_key}" +} + +provider "scaleway" { + organization_id = "${var.scaleway_organization_id}" + project_id = "${var.scaleway_project_id}" + access_key = "${var.scaleway_access_key}" + secret_key = "${var.scaleway_secret_key}" + region = "nl-ams" + zone = "nl-ams-1" +} + +provider "tailscale" { + api_key = "${var.tailscale_api_key}" + tailnet = "${var.tailscale_tailnet}" +} diff --git a/output.tf b/output.tf new file mode 100644 index 0000000..e07d0ee --- /dev/null +++ b/output.tf @@ -0,0 +1,20 @@ +output "hosts" { + value = { + for subdomain in distinct([for record in ovh_domain_zone_record.server_records : record.subdomain]) : + subdomain => { + "ipv4_address" = try( + ovh_domain_zone_record.server_records["${subdomain}:ipv4"].target, + null + ) + "ipv6_address" = try( + ovh_domain_zone_record.server_records["${subdomain}:ipv6"].target, + null + ) + } + } +} + +output "scaleway_service_keys" { + value = scaleway_iam_api_key.service_keys + sensitive = true +} diff --git a/ovh.tf b/ovh.tf new file mode 100644 index 0000000..65f0d2a --- /dev/null +++ b/ovh.tf @@ -0,0 +1,74 @@ +locals { + contabo_hosts = {for key, val in var.hosts : key => val if val.provider == "contabo"} + server_addresses = flatten([ + [ + for host in local.contabo_hosts : [ + { + hostname = host.hostname + ipv4_address = host.ipv4_address + ipv6_address = host.ipv6_address + }, + ] + ], + [ + for host in hcloud_server.nodes : [ + { + hostname = host.name + ipv4_address = host.ipv4_address + ipv6_address = host.ipv6_address + }, + ] + ] + ]) + + server_addresses_separated = flatten([ + for host in local.server_addresses : [ + { + hostname = host.hostname + key = "${host.hostname}:ipv4" + address = host.ipv4_address + }, + { + hostname = host.hostname + key = "${host.hostname}:ipv6" + address = host.ipv6_address + }, + ] + ]) + + tailscale_host_addresses = flatten([ + for host in data.tailscale_devices.nodes.devices : [ + for index, address in host.addresses : { + hostname = host.hostname + key = "${host.hostname}:${index}" + address = address + } + ] + ]) +} + +resource "ovh_domain_zone_record" "server_records" { + for_each = { for entry in local.server_addresses_separated: entry.key => entry } + zone = "serguzim.net" + subdomain = each.value.hostname + fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A" + ttl = 3600 + target = each.value.address +} + +resource "ovh_domain_zone_record" "tailscale_vpn" { + for_each = { for entry in local.tailscale_host_addresses: entry.key => entry } + zone = "serguzim.net" + subdomain = "${each.value.hostname}.vpn" + fieldtype = strcontains(each.value.address, ":") ? "AAAA" : "A" + ttl = 600 + target = each.value.address +} + +resource "ovh_domain_zone_record" "status_page_cname" { + zone = "serguzim.net" + subdomain = "status" + fieldtype = "CNAME" + ttl = 3600 + target = "status.serguzim.me." +} diff --git a/scaleway.tf b/scaleway.tf new file mode 100644 index 0000000..5ff13cf --- /dev/null +++ b/scaleway.tf @@ -0,0 +1,77 @@ +data "scaleway_account_project" "project" { + project_id = "${var.scaleway_project_id}" +} + +resource "scaleway_account_ssh_key" "openpgp_0xAB920993" { + name = "openpgp:0xAB920993" + public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCkmWZmum4cVeDy5+9N1HdUzfnjEHSJ900ucD8F0wAy4MV1cdPYnZ4u5PFv5XMfmvA9SJ+VFsr0lhYlr+GQBG9aCCAdMJVVmEz3SccT6dp6ZYywT158RNshzfCe9ylWKK80+W7XnDXhdkec7aK+BQn5wOER3A3mUqRR0JDXWga9jyakH1K6OwXmQOO419bJWs2uCT1ZEgndHxKJEt2pEvoSz7z8p1SS2zyro+R3YtvL9WiDo3+0yPFYficNDr7s39yF5IJE+KTqAlCn5R2+kJ54lRmzB8oNS2jGwK2Q6wtph4AmfnlJTMODG2U2RjUltH2MIDXIYe2epATWL8qhkI4LTr38C7QR3DeJQsel/yTWdYqGakvU6Ge/xkbsaWOrSDTV3bPgKHzlL+dIKaGpV+5usZN4fpOLOb/nmYy3ekLpobzxza7rBRT2CxXS72DoPFaRE1ye7SxhcsLBNwre9YQFE4VvUZwJYkWz2V7eqGrk8VYnmQmT/bnUnMnVwMpeDc7pFKAFndIUxifoOj77c98Tdy3ncdS7SOd7+zRbLG+7k0UU1k89o1+tfREAddUJYR4RvB6g0kCyjpwOf1Pt4zhJR3y/zpsCCc5UnzK9X2kEo/8TSyvTr+GBiFVp5yLYgwCPJSNna33YX7+c3oLRM1QGgtqZk9qnGX9hgP8qpF8Akw== openpgp:0xAB920993" +} + +resource "scaleway_iam_application" "service_applications" { + for_each = var.service_buckets + name = each.value.name +} + +resource "scaleway_iam_policy" "service_storage_policies" { + for_each = var.service_buckets + name = "${each.key}_storage_policy" + application_id = scaleway_iam_application.service_applications[each.key].id + rule { + project_ids = [data.scaleway_account_project.project.id] + permission_set_names = ["ObjectStorageFullAccess"] + } +} + +resource "scaleway_object_bucket" "service_buckets" { + for_each = var.service_buckets + name = "${each.value.name}.serguzim.me" + lifecycle { + prevent_destroy = true + } +} + +resource "scaleway_object_bucket_policy" "service_bucket_policies" { + for_each = var.service_buckets + bucket = scaleway_object_bucket.service_buckets[each.key].id + policy = jsonencode({ + Version = "2023-04-17", + Id = "${each.key}_bucket_policy", + Statement = [ + { + Sid = "Scaleway secure statement" + Effect = "Allow" + Action = "*" + Principal = { + SCW = "user_id:${var.scaleway_user_id}" + } + Resource = [ + "${scaleway_object_bucket.service_buckets[each.key].name}", + "${scaleway_object_bucket.service_buckets[each.key].name}/*", + ] + }, + { + Sid = "${each.key} statement" + Effect = "Allow" + Action = "*" + Principal = { + SCW = "application_id:${scaleway_iam_application.service_applications[each.key].id}" + } + Resource = [ + "${scaleway_object_bucket.service_buckets[each.key].name}", + "${scaleway_object_bucket.service_buckets[each.key].name}/*", + ] + }, + ] + }) +} + +resource "time_rotating" "rotate_after_a_year" { + rotation_years = 1 +} + +resource "scaleway_iam_api_key" "service_keys" { + for_each = var.service_buckets + description = "Service key for ${each.key}" + application_id = scaleway_iam_application.service_applications[each.key].id + expires_at = time_rotating.rotate_after_a_year.rotation_rfc3339 +} diff --git a/service_buckets.auto.tfvars b/service_buckets.auto.tfvars new file mode 100644 index 0000000..5a8d391 --- /dev/null +++ b/service_buckets.auto.tfvars @@ -0,0 +1,14 @@ +service_buckets = { + "linkwarden" = { + name = "linkwarden" + bucket = "linkwarden.serguzim.me" + }, + "harbor" = { + name = "harbor" + bucket = "harbor.serguzim.me" + } + "forgejo" = { + name = "forgejo" + bucket = "forgejo.serguzim.me" + } +} diff --git a/tailscale.tf b/tailscale.tf new file mode 100644 index 0000000..0f0a99e --- /dev/null +++ b/tailscale.tf @@ -0,0 +1,11 @@ +resource "tailscale_tailnet_key" "cloud_init_key" { + reusable = true + ephemeral = false + preauthorized = true + expiry = 3600 + description = "Cloud-init key used by opentofu" +} + +data "tailscale_devices" "nodes" { + name_prefix = "node" +} diff --git a/tf-templates/cloud-init.yaml.tpl b/tf-templates/cloud-init.yaml.tpl new file mode 100644 index 0000000..8ecab22 --- /dev/null +++ b/tf-templates/cloud-init.yaml.tpl @@ -0,0 +1,40 @@ +#cloud-config + +users: + - name: serguzim + gecos: Serguzim + groups: users,admin,wheel + sudo: "ALL=(ALL) ALL" + shell: /bin/bash + lock_passwd: false + ssh_authorized_keys: + - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCkmWZmum4cVeDy5+9N1HdUzfnjEHSJ900ucD8F0wAy4MV1cdPYnZ4u5PFv5XMfmvA9SJ+VFsr0lhYlr+GQBG9aCCAdMJVVmEz3SccT6dp6ZYywT158RNshzfCe9ylWKK80+W7XnDXhdkec7aK+BQn5wOER3A3mUqRR0JDXWga9jyakH1K6OwXmQOO419bJWs2uCT1ZEgndHxKJEt2pEvoSz7z8p1SS2zyro+R3YtvL9WiDo3+0yPFYficNDr7s39yF5IJE+KTqAlCn5R2+kJ54lRmzB8oNS2jGwK2Q6wtph4AmfnlJTMODG2U2RjUltH2MIDXIYe2epATWL8qhkI4LTr38C7QR3DeJQsel/yTWdYqGakvU6Ge/xkbsaWOrSDTV3bPgKHzlL+dIKaGpV+5usZN4fpOLOb/nmYy3ekLpobzxza7rBRT2CxXS72DoPFaRE1ye7SxhcsLBNwre9YQFE4VvUZwJYkWz2V7eqGrk8VYnmQmT/bnUnMnVwMpeDc7pFKAFndIUxifoOj77c98Tdy3ncdS7SOd7+zRbLG+7k0UU1k89o1+tfREAddUJYR4RvB6g0kCyjpwOf1Pt4zhJR3y/zpsCCc5UnzK9X2kEo/8TSyvTr+GBiFVp5yLYgwCPJSNna33YX7+c3oLRM1QGgtqZk9qnGX9hgP8qpF8Akw== openpgp:0xAB920993" + - name: ansible + gecos: Ansible User + groups: users,admin,wheel + sudo: "ALL=(ALL) NOPASSWD:ALL" + shell: /bin/bash + lock_passwd: true + ssh_authorized_keys: + - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCkmWZmum4cVeDy5+9N1HdUzfnjEHSJ900ucD8F0wAy4MV1cdPYnZ4u5PFv5XMfmvA9SJ+VFsr0lhYlr+GQBG9aCCAdMJVVmEz3SccT6dp6ZYywT158RNshzfCe9ylWKK80+W7XnDXhdkec7aK+BQn5wOER3A3mUqRR0JDXWga9jyakH1K6OwXmQOO419bJWs2uCT1ZEgndHxKJEt2pEvoSz7z8p1SS2zyro+R3YtvL9WiDo3+0yPFYficNDr7s39yF5IJE+KTqAlCn5R2+kJ54lRmzB8oNS2jGwK2Q6wtph4AmfnlJTMODG2U2RjUltH2MIDXIYe2epATWL8qhkI4LTr38C7QR3DeJQsel/yTWdYqGakvU6Ge/xkbsaWOrSDTV3bPgKHzlL+dIKaGpV+5usZN4fpOLOb/nmYy3ekLpobzxza7rBRT2CxXS72DoPFaRE1ye7SxhcsLBNwre9YQFE4VvUZwJYkWz2V7eqGrk8VYnmQmT/bnUnMnVwMpeDc7pFKAFndIUxifoOj77c98Tdy3ncdS7SOd7+zRbLG+7k0UU1k89o1+tfREAddUJYR4RvB6g0kCyjpwOf1Pt4zhJR3y/zpsCCc5UnzK9X2kEo/8TSyvTr+GBiFVp5yLYgwCPJSNna33YX7+c3oLRM1QGgtqZk9qnGX9hgP8qpF8Akw== openpgp:0xAB920993" + +packages: + - git + - vim + +runcmd: + ############################################################ + ### Configure sshd ### Configure sshd ### Configure sshd ### + ############################################################ + - sed -i 's/\#\?Port .\+/Port 17/' /etc/ssh/sshd_config + - sed -i 's/\#\?PasswordAuthentication .\+/PasswordAuthentication no/' /etc/ssh/sshd_config + - sed -i 's/\#\?PermitRootLogin .\+/PermitRootLogin no/' /etc/ssh/sshd_config + - systemctl restart sshd + + ##################################################################### + ### Install tailscale ### Install tailscale ### Install tailscale ### + ##################################################################### + # One-command install, from https://tailscale.com/download/ + - ['sh', '-c', 'curl -fsSL https://tailscale.com/install.sh | sh'] + - ['tailscale', 'up', '--authkey=${tailscale_authkey}'] + diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..88da41b --- /dev/null +++ b/variables.tf @@ -0,0 +1,88 @@ +variable "backend_access_key" { + sensitive = true +} + +variable "backend_secret_key" { + sensitive = true +} + +variable "backend_endpoint" { + sensitive = false +} + +variable "backend_region" { + sensitive = false +} + +variable "backend_bucket" { + sensitive = false +} + + +variable "hcloud_token" { + sensitive = true +} + + +variable "ovh_application_key" { + sensitive = true +} + +variable "ovh_application_secret" { + sensitive = true +} + +variable "ovh_consumer_key" { + sensitive = true +} + + +variable "scaleway_user_id" { + sensitive = true +} + +variable "scaleway_organization_id" { + sensitive = true +} + +variable "scaleway_project_id" { + sensitive = true +} + +variable "scaleway_access_key" { + sensitive = true +} + +variable "scaleway_secret_key" { + sensitive = true +} + + +variable "tailscale_api_key" { + sensitive = true +} + +variable "tailscale_tailnet" { + sensitive = false +} + + +variable "service_buckets" { + type = map(object({ + name = string + bucket = string + })) +} + +variable "hosts" { + type = map(object({ + hostname = string + rdns = string + provider = string + ipv4_address = optional(string) + ipv6_address = optional(string) + image = optional(string) + server_type = optional(string) + datacenter = optional(string) + })) +}