diff --git a/.github/workflows/terraform-cloudns-iac-apply.yml b/.github/workflows/terraform-cloudns-iac-apply.yml new file mode 100644 index 0000000..6eeca35 --- /dev/null +++ b/.github/workflows/terraform-cloudns-iac-apply.yml @@ -0,0 +1,35 @@ +name: Terraform CLouDNS IAC Apply + +on: + schedule: + - cron: "0 1 * * 0" + push: + branches: + - main + paths: + - "terraform/cloudns-iac/**" +jobs: + opentofu-apply: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup environment + uses: ./.github/actions/setup-env + + - name: Setup OpenTofu environment + uses: ./.github/actions/setup-opentofu-env + + - name: OpenTofu Init and Apply + env: + BW_PROJECT_ID: ${{ secrets.BW_PROJECT_ID }} + BW_ORGANIZATION_ID: ${{ secrets.BW_ORGANIZATION_ID }} + BW_ACCESS_TOKEN: ${{ secrets.BW_ACCESS_TOKEN }} + run: | + cd terraform/cloudns-iac + sectool -f ../../sectool.json exec tofu init + sectool -f ../../sectool.json exec tofu apply --auto-approve diff --git a/.github/workflows/terraform-cloudns-iac-validate-on-pr.yml b/.github/workflows/terraform-cloudns-iac-validate-on-pr.yml new file mode 100644 index 0000000..ac34a20 --- /dev/null +++ b/.github/workflows/terraform-cloudns-iac-validate-on-pr.yml @@ -0,0 +1,39 @@ +name: Terraform ClouDNS IAC Validate on Pull Request + +on: + pull_request: + branches: + - main + paths: + - "terraform/cloudns-iac/**" + types: + - opened + - synchronize + - reopened +jobs: + terraform-validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup environment + uses: ./.github/actions/setup-env + + - name: Setup OpenTofu environment + uses: ./.github/actions/setup-opentofu-env + + - name: OpenTofu Init and Validate + env: + BW_PROJECT_ID: ${{ secrets.BW_PROJECT_ID }} + BW_ORGANIZATION_ID: ${{ secrets.BW_ORGANIZATION_ID }} + BW_ACCESS_TOKEN: ${{ secrets.BW_ACCESS_TOKEN }} + run: | + cd terraform/cloudns-iac + sectool -f ../../sectool.json exec tofu init + sectool -f ../../sectool.json exec tofu validate + sectool -f ../../sectool.json exec tofu fmt -check + sectool -f ../../sectool.json exec tofu plan diff --git a/terraform/cloudns-iac/backend.tf b/terraform/cloudns-iac/backend.tf new file mode 100644 index 0000000..a25aa2d --- /dev/null +++ b/terraform/cloudns-iac/backend.tf @@ -0,0 +1,7 @@ +terraform { + backend "s3" { + bucket = "a13labs.infra.eu" + key = "cloudns.core.infra.tfstate" + region = "eu-west-1" + } +} diff --git a/terraform/cloudns-iac/config.tf b/terraform/cloudns-iac/config.tf new file mode 100644 index 0000000..0562701 --- /dev/null +++ b/terraform/cloudns-iac/config.tf @@ -0,0 +1,197 @@ +locals { + vps_1 = { + id = data.terraform_remote_state.contabo.outputs.instances[0].id + name = data.terraform_remote_state.contabo.outputs.instances[0].name + ip = data.terraform_remote_state.contabo.outputs.instances[0].ip_config[0].v4[0].ip + } + + default_ttl = "3600" + + domains = { + "a13labs.me" = [ + { + type = "A" + value = local.vps_1.ip + }, + { + type = "MX" + priority = "10" + value = "mail-pt.securemail.pro" + }, + { + type = "TXT" + value = "v=spf1 include:_spf.tem.scaleway.com include:spf.webapps.net ~all" + }, + { + name = "imap" + type = "CNAME" + value = "${local.vps_1.name}.a13labs.me" + }, + { + name = "mail" + type = "CNAME" + value = "mail-pt.securemail.pro" + }, + { + name = "smtp" + type = "CNAME" + value = "${local.vps_1.name}.a13labs.me" + }, + { + name = "_dmarc" + type = "TXT" + value = "v=DMARC1; p=none; rua=mailto:admin@a13labs.me" + }, + { + name = "${local.vps_1.name}" + type = "A" + value = local.vps_1.ip + }, + { + name = "_imap._tcp" + type = "SRV" + priority = "0" + weight = "1" + port = "993" + value = "imap.a13labs.me" + }, + { + name = "_smtp._tcp" + type = "SRV" + priority = "0" + weight = "1" + port = "465" + value = "smtp.a13labs.me" + }, + { + name = "${var.scaleway_dkim_key}._domainkey" + type = "TXT" + value = "v=DKIM1; h=sha256; k=rsa; p=${var.a13labs_me_scaleway_dkim_value}" + }, + ], + "alexpires.me" = [ + { + type = "A" + value = local.vps_1.ip + }, + { + name = "" + type = "MX" + priority = "10" + value = "mail-pt.securemail.pro" + }, + { + type = "TXT" + value = "v=spf1 include:_spf.tem.scaleway.com include:spf.webapps.net ~all" + }, + { + name = "tv" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "www" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "blog" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "code" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "imap" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "mail" + type = "CNAME" + value = "mail-pt.securemail.pro" + }, + { + name = "smtp" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "cloud" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "_dmarc" + type = "TXT" + value = "v=DMARC1; p=none; rua=mailto:admin@alexpires.me" + }, + { + name = "prod-01" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "_keybase" + type = "TXT" + value = "keybase-site-verification=${var.keybase_site_verification}" + }, + { + name = "rustdesk" + type = "CNAME" + value = "${local.vps_1.name}.alexpires.me" + }, + { + name = "${local.vps_1.name}" + type = "A" + value = local.vps_1.ip + }, + { + name = "_imap._tcp" + type = "SRV" + priority = "0" + weight = "1" + port = "993" + value = "imap.alexpires.me" + }, + { + name = "_smtp._tcp" + type = "SRV" + priority = "0" + weight = "1" + port = "465" + value = "smtp.alexpires.me" + }, + { + name = "${var.scaleway_dkim_key}._domainkey" + type = "TXT" + value = "v=DKIM1; h=sha256; k=rsa; p=${var.alexpires_me_scaleway_dkim_value}" + }, + ] + } + + records = flatten([for domain, records in local.domains : [ + for record in records : { + name = lookup(record, "name", "") + zone = domain + type = record.type + value = record.value + priority = lookup(record, "priority", null) + weight = lookup(record, "weight", null) + port = lookup(record, "port", null) + } + ]]) +} + +data "terraform_remote_state" "contabo" { + backend = "s3" + config = { + bucket = "a13labs.infra.eu" + key = "contabo.core.infra.tfstate" + region = "eu-west-1" + } +} + diff --git a/terraform/cloudns-iac/import.tf b/terraform/cloudns-iac/import.tf new file mode 100644 index 0000000..3728364 --- /dev/null +++ b/terraform/cloudns-iac/import.tf @@ -0,0 +1,149 @@ +import { + to = cloudns_dns_record.records["0"] + id = "a13labs.me/597135816" +} + +import { + to = cloudns_dns_record.records["1"] + id = "a13labs.me/597135860" +} + +import { + to = cloudns_dns_record.records["2"] + id = "a13labs.me/597135855" +} + +import { + to = cloudns_dns_record.records["3"] + id = "a13labs.me/597135881" +} + +import { + to = cloudns_dns_record.records["4"] + id = "a13labs.me/597135870" +} + +import { + to = cloudns_dns_record.records["5"] + id = "a13labs.me/597135880" +} + +import { + to = cloudns_dns_record.records["6"] + id = "a13labs.me/597135865" +} + +import { + to = cloudns_dns_record.records["7"] + id = "a13labs.me/597135875" +} + +import { + to = cloudns_dns_record.records["8"] + id = "a13labs.me/597135871" +} + +import { + to = cloudns_dns_record.records["9"] + id = "a13labs.me/597135844" +} + +import { + to = cloudns_dns_record.records["10"] + id = "a13labs.me/597135905" +} + +import { + to = cloudns_dns_record.records["11"] + id = "alexpires.me/532518463" +} + +import { + to = cloudns_dns_record.records["12"] + id = "alexpires.me/532672946" +} + +import { + to = cloudns_dns_record.records["13"] + id = "alexpires.me/281520528" +} + +import { + to = cloudns_dns_record.records["14"] + id = "alexpires.me/521232645" +} + +import { + to = cloudns_dns_record.records["15"] + id = "alexpires.me/532517967" +} + +import { + to = cloudns_dns_record.records["16"] + id = "alexpires.me/178650153" +} + +import { + to = cloudns_dns_record.records["17"] + id = "alexpires.me/178650182" +} + +import { + to = cloudns_dns_record.records["18"] + id = "alexpires.me/586324830" +} + +import { + to = cloudns_dns_record.records["19"] + id = "alexpires.me/532672941" +} + +import { + to = cloudns_dns_record.records["20"] + id = "alexpires.me/586324827" +} + +import { + to = cloudns_dns_record.records["21"] + id = "alexpires.me/281519967" +} + +import { + to = cloudns_dns_record.records["22"] + id = "alexpires.me/281718535" +} + +import { + to = cloudns_dns_record.records["23"] + id = "alexpires.me/532611041" +} + +import { + to = cloudns_dns_record.records["24"] + id = "alexpires.me/589272323" +} + +import { + to = cloudns_dns_record.records["25"] + id = "alexpires.me/541490367" +} + +import { + to = cloudns_dns_record.records["26"] + id = "alexpires.me/532517966" +} + +import { + to = cloudns_dns_record.records["27"] + id = "alexpires.me/587082961" +} + +import { + to = cloudns_dns_record.records["28"] + id = "alexpires.me/587082938" +} + +import { + to = cloudns_dns_record.records["29"] + id = "alexpires.me/281520539" +} diff --git a/terraform/cloudns-iac/provider.tf b/terraform/cloudns-iac/provider.tf new file mode 100644 index 0000000..19ccb40 --- /dev/null +++ b/terraform/cloudns-iac/provider.tf @@ -0,0 +1,14 @@ +terraform { + required_version = "~>1.8" + required_providers { + cloudns = { + source = "ClouDNS/cloudns" + version = "~>1.0" + } + } +} + +provider "cloudns" { + auth_id = var.cloudns_auth_id + password = var.cloudns_password +} diff --git a/terraform/cloudns-iac/records.tf b/terraform/cloudns-iac/records.tf new file mode 100644 index 0000000..df00188 --- /dev/null +++ b/terraform/cloudns-iac/records.tf @@ -0,0 +1,26 @@ +resource "cloudns_dns_zone" "zones" { + for_each = local.domains + domain = each.key + type = "master" +} + +import { + for_each = local.domains + to = cloudns_dns_zone.zones[each.key] + id = each.key +} + +resource "cloudns_dns_record" "records" { + for_each = { + for i, record in local.records : + i => record + } + name = each.value.name + zone = each.value.zone + type = each.value.type + value = each.value.value + priority = lookup(each.value, "priority", null) + weight = lookup(each.value, "weight", null) + port = lookup(each.value, "port", null) + ttl = lookup(each.value, "ttl", local.default_ttl) +} diff --git a/terraform/cloudns-iac/sectool.env b/terraform/cloudns-iac/sectool.env new file mode 100644 index 0000000..3d08929 --- /dev/null +++ b/terraform/cloudns-iac/sectool.env @@ -0,0 +1,8 @@ +AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY +AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY +TF_VAR_cloudns_auth_id=$CLOUDNS_AUTH_ID +TF_VAR_cloudns_password=$CLOUDNS_PASSWORD +TF_VAR_scaleway_dkim_key=$SCALEWAY_DKIM_KEY +TF_VAR_alexpires_me_scaleway_dkim_value=$ALEXPIRES_ME_SCALEWAY_DKIM_VALUE +TF_VAR_a13labs_me_scaleway_dkim_value=$A13LABS_ME_SCALEWAY_DKIM_VALUE +TF_VAR_keybase_site_verification=$KEYBASE_SITE_VERIFICATION \ No newline at end of file diff --git a/terraform/cloudns-iac/variables.tf b/terraform/cloudns-iac/variables.tf new file mode 100644 index 0000000..db31934 --- /dev/null +++ b/terraform/cloudns-iac/variables.tf @@ -0,0 +1,36 @@ +variable "cloudns_auth_id" { + description = "Cloudns Auth ID" + type = string + sensitive = true +} + +variable "cloudns_password" { + description = "Cloudns Password" + type = string + sensitive = true +} + +variable "scaleway_dkim_key" { + description = "Scaleway DKIM key" + type = string + sensitive = true +} + +variable "alexpires_me_scaleway_dkim_value" { + description = "Scaleway DKIM value (alexpires.me)" + type = string + sensitive = true +} + +variable "a13labs_me_scaleway_dkim_value" { + description = "Scaleway DKIM value (a13labs.me)" + type = string + sensitive = true +} + +variable "keybase_site_verification" { + description = "Keybase site verification" + type = string + sensitive = true +} +