diff --git a/.gitignore b/.gitignore index e7f9acb0e1..041927db87 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,8 @@ circuit_js # Reports docs/dead_links_report.txt + +**/.terraform +terraform.tfstate +terraform.tfstate.backup + diff --git a/infra/aggregation_mode/terraform/cloudinit/cloud-init.yaml b/infra/aggregation_mode/terraform/cloudinit/cloud-init.yaml new file mode 100644 index 0000000000..7a52cc3f29 --- /dev/null +++ b/infra/aggregation_mode/terraform/cloudinit/cloud-init.yaml @@ -0,0 +1,56 @@ +#cloud-config +hostname: ${hostname} +fqdn: ${hostname} +manage_etc_hosts: true + +users: + - name: app + shell: /bin/bash + ssh_authorized_keys: + - ${ssh_public_key} + - name: admin + shell: /bin/bash + sudo: ALL=(ALL) NOPASSWD:ALL + ssh_authorized_keys: + - ${ssh_public_key} + +package_update: true +package_upgrade: true + +packages: + - ca-certificates + - curl + - wget + - gnupg + - vim + - git + - zip + - unzip + - openssl + - libssl-dev + - build-essential + - rsyslog + - htop + - rsync + - pkg-config + - locales + - ufw + +write_files: + - path: /etc/environment + content: | + LANG=en_US.UTF-8 + LC_ALL=C + LANGUAGE=en_US.UTF-8 + LC_TYPE=en_US.UTF-8 + LC_CTYPE=en_US.UTF-8 + +runcmd: + - loginctl enable-linger app + # Tailscale installation https://tailscale.com/kb/1293/cloud-init + - curl -fsSL https://tailscale.com/install.sh | sh + - tailscale up --ssh --advertise-tags=tag:server --auth-key=${tailscale_auth_key} + - tailscale set --auto-update + - sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen + - locale-gen + - ufw enable diff --git a/infra/aggregation_mode/terraform/cloudinit/postgres-monitor-cloud-init.yaml b/infra/aggregation_mode/terraform/cloudinit/postgres-monitor-cloud-init.yaml new file mode 100644 index 0000000000..5eb7890d32 --- /dev/null +++ b/infra/aggregation_mode/terraform/cloudinit/postgres-monitor-cloud-init.yaml @@ -0,0 +1,54 @@ +#cloud-config +hostname: ${hostname} +fqdn: ${hostname} +manage_etc_hosts: true + +users: + - name: app + shell: /bin/bash + ssh_authorized_keys: + - ${ssh_public_key} + - name: admin + shell: /bin/bash + sudo: ALL=(ALL) NOPASSWD:ALL + ssh_authorized_keys: + - ${ssh_public_key} + +package_update: true +package_upgrade: true + +packages: + - ca-certificates + - curl + - wget + - gnupg + - vim + - git + - zip + - unzip + - openssl + - libssl-dev + - build-essential + - rsyslog + - htop + - rsync + - pkg-config + - locales + +write_files: + - path: /etc/environment + content: | + LANG=en_US.UTF-8 + LC_ALL=C + LANGUAGE=en_US.UTF-8 + LC_TYPE=en_US.UTF-8 + LC_CTYPE=en_US.UTF-8 + +runcmd: + - loginctl enable-linger app + # Tailscale installation https://tailscale.com/kb/1293/cloud-init + - curl -fsSL https://tailscale.com/install.sh | sh + - tailscale up --ssh --advertise-tags=tag:server --auth-key=${tailscale_auth_key} + - tailscale set --auto-update + - sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen + - locale-gen diff --git a/infra/aggregation_mode/terraform/cloudinit/scaleway-cloud-init.yaml b/infra/aggregation_mode/terraform/cloudinit/scaleway-cloud-init.yaml new file mode 100644 index 0000000000..5eb7890d32 --- /dev/null +++ b/infra/aggregation_mode/terraform/cloudinit/scaleway-cloud-init.yaml @@ -0,0 +1,54 @@ +#cloud-config +hostname: ${hostname} +fqdn: ${hostname} +manage_etc_hosts: true + +users: + - name: app + shell: /bin/bash + ssh_authorized_keys: + - ${ssh_public_key} + - name: admin + shell: /bin/bash + sudo: ALL=(ALL) NOPASSWD:ALL + ssh_authorized_keys: + - ${ssh_public_key} + +package_update: true +package_upgrade: true + +packages: + - ca-certificates + - curl + - wget + - gnupg + - vim + - git + - zip + - unzip + - openssl + - libssl-dev + - build-essential + - rsyslog + - htop + - rsync + - pkg-config + - locales + +write_files: + - path: /etc/environment + content: | + LANG=en_US.UTF-8 + LC_ALL=C + LANGUAGE=en_US.UTF-8 + LC_TYPE=en_US.UTF-8 + LC_CTYPE=en_US.UTF-8 + +runcmd: + - loginctl enable-linger app + # Tailscale installation https://tailscale.com/kb/1293/cloud-init + - curl -fsSL https://tailscale.com/install.sh | sh + - tailscale up --ssh --advertise-tags=tag:server --auth-key=${tailscale_auth_key} + - tailscale set --auto-update + - sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen + - locale-gen diff --git a/infra/aggregation_mode/terraform/environments/hoodi/.terraform.lock.hcl b/infra/aggregation_mode/terraform/environments/hoodi/.terraform.lock.hcl new file mode 100644 index 0000000000..77b6f735a1 --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/.terraform.lock.hcl @@ -0,0 +1,69 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.100.0" + constraints = "~> 5.0" + hashes = [ + "h1:Ijt7pOlB7Tr7maGQIqtsLFbl7pSMIj06TVdkoSBcYOw=", + "zh:054b8dd49f0549c9a7cc27d159e45327b7b65cf404da5e5a20da154b90b8a644", + "zh:0b97bf8d5e03d15d83cc40b0530a1f84b459354939ba6f135a0086c20ebbe6b2", + "zh:1589a2266af699cbd5d80737a0fe02e54ec9cf2ca54e7e00ac51c7359056f274", + "zh:6330766f1d85f01ae6ea90d1b214b8b74cc8c1badc4696b165b36ddd4cc15f7b", + "zh:7c8c2e30d8e55291b86fcb64bdf6c25489d538688545eb48fd74ad622e5d3862", + "zh:99b1003bd9bd32ee323544da897148f46a527f622dc3971af63ea3e251596342", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9f8b909d3ec50ade83c8062290378b1ec553edef6a447c56dadc01a99f4eaa93", + "zh:aaef921ff9aabaf8b1869a86d692ebd24fbd4e12c21205034bb679b9caf883a2", + "zh:ac882313207aba00dd5a76dbd572a0ddc818bb9cbf5c9d61b28fe30efaec951e", + "zh:bb64e8aff37becab373a1a0cc1080990785304141af42ed6aa3dd4913b000421", + "zh:dfe495f6621df5540d9c92ad40b8067376350b005c637ea6efac5dc15028add4", + "zh:f0ddf0eaf052766cfe09dea8200a946519f653c384ab4336e2a4a64fdd6310e9", + "zh:f1b7e684f4c7ae1eed272b6de7d2049bb87a0275cb04dbb7cda6636f600699c9", + "zh:ff461571e3f233699bf690db319dfe46aec75e58726636a0d97dd9ac6e32fb70", + ] +} + +provider "registry.terraform.io/scaleway/scaleway" { + version = "2.64.0" + constraints = "2.64.0" + hashes = [ + "h1:2Hk2k0PTHcbqVHMfMENIJvequcGTlOetqNQcT9imfJo=", + "zh:052399f5e2813f13fbb49a460ec7c7c95dba417c0ecd07fae32143217ab07dbd", + "zh:14dd8252d3c937a190b0256ed8078fcc3b25b609abab0811645cad1e5aa93ef5", + "zh:1ade705c6f1fe1df968a0a09744f829cdcebcd4382d663ee2a50a5ed77ce1780", + "zh:401b622b40b97e00193798959160217b024d4747672ad1c8e71ef7a3623eae27", + "zh:47f7f6d7221db422bc8f8d44025382defcd691550cfd40f4cae879330f4aebc1", + "zh:4e65b651ae3f2c62c62b1b3676cf2c6070b6869d1fddec86e2aa4d736803d634", + "zh:7a67e0c6db4d483ee723bb40340c533cab5540c6ad5a6ba80085b8f9ebb97e85", + "zh:8ea8b3f629bc37b1ed65fa6cd894fd51e27245d0df93974c8137415f13275658", + "zh:a600c544036068a25310e21a5a3dda29158d75311bf726e982ee5deaf76d1d5a", + "zh:a74c67c799fc493ff6faa9b689e4bddb36cc18a2d29ad5d64774eede6ff4e2c3", + "zh:ddfd1432b3dcd57f2a7a6ce07c6ac6d6c942d730390076f0b7ed587fe184e607", + "zh:e3eb4a39ba5e37b9b26eac107c7d954c9d5183d1cb84ffa1b3cf9a28b3519552", + "zh:eb7f7b78abd4555d36275b16dd96bbbfe74fb9ee60a4611c03ce4ae732e0bf0a", + "zh:f7cb5d958814e8ad71c1d9bd66ffc776d969d26c764c97cd01b0d1f8bd00e337", + ] +} + +provider "registry.terraform.io/tailscale/tailscale" { + version = "0.24.0" + constraints = "~> 0.13" + hashes = [ + "h1:F7Jj03acdrWPNit/gV744xsE49CWvfrKssENgeEBlVI=", + "zh:02c232ff3945dc5288fd7e3c9ddcdd5f0aa884b491651271d4fcc083c6293810", + "zh:0de7eb1c45aa50512bf89254c451f442ab17f9f3b9f6a469ad4b3ff105480b1c", + "zh:24ccca014bec2dfb38e2a8d712a5f1d293417ee002f6ddd78a89aee0e6b0a992", + "zh:2b09f56a7380b50784d5692baeb157edea025f8f1d8665d1b5c285040a05b4bc", + "zh:2b12d2be58a97484299c5ae0d43888d75eb131448439d4a319e9295128ff0f31", + "zh:5fd83b0d2cb0fd46aa47e5c43b5c1dbf7acb4114c8073bf62bcf33167091501a", + "zh:64de20614544e3b0bdbc95e9a1819a2a80d36f9561e7d8470ae509b93ab5e348", + "zh:6e388a2eb91512b2e4d2d8a03358fdcfd79a650512f9205fa6857c0e08c56b9e", + "zh:b4867157d854e273dad54e08604989b4c0a495b21f4d5d1aa07af8f888ff1ac3", + "zh:cbb4f14f2e2819b1a7140ee06fd0852cd3471823e6640871581b4632df042828", + "zh:d236bb104c862035224129c36bb8c09b5f26cc2c902309c9f65eaceb3e3e8141", + "zh:f020c98a6e14e14e5a3a98648c0718be8bf890f05c2e823014a01ebc01e1ffc8", + "zh:f0a5580e48d462fa6834f3d38c47a055ce798f564116615cd2703c518be5199d", + "zh:f2b82d084c84b4547a2fa8d358b70eea1fecf383c595361c546ce86eaec316d4", + ] +} diff --git a/infra/aggregation_mode/terraform/environments/hoodi/README.md b/infra/aggregation_mode/terraform/environments/hoodi/README.md new file mode 100644 index 0000000000..d4758109e8 --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/README.md @@ -0,0 +1,22 @@ + +# Init + +```shell +source .env && terraform init -migrate-state \ + -backend-config="bucket=${TFSTATE_BUCKET}" \ + -backend-config="key=${TFSTATE_KEY}" \ + -backend-config="region=${TFSTATE_REGION}" +``` + +# Plan + +```shell +source .env && terraform plan +``` + +# Apply + +```shell +source .env && terraform apply +``` + diff --git a/infra/aggregation_mode/terraform/environments/hoodi/main.tf b/infra/aggregation_mode/terraform/environments/hoodi/main.tf new file mode 100644 index 0000000000..a355bac13c --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/main.tf @@ -0,0 +1,124 @@ +# AWS Provider Configuration +provider "aws" { + region = var.aws_region +} + +# Scaleway Provider Configuration +provider "scaleway" { +} + +# Tailscale Provider Configuration +provider "tailscale" { +} + +# Postgres Monitor (EC2) +module "postgres_monitor" { + source = "../../modules/ec2" + + ec2_instance_name = var.postgres_monitor_instance_name + ec2_hostname = var.postgres_monitor_hostname + ec2_instance_type = var.postgres_monitor_instance_type + ec2_ssh_key_name = var.postgres_monitor_ssh_key_name + ec2_ssh_public_key_path = var.ssh_public_key_path_aws + ec2_cloud_init_template_path = var.postgres_monitor_cloud_init_template_path + ec2_root_volume_size = var.postgres_monitor_root_volume_size + ec2_tailscale_key_expiry = var.tailscale_key_expiry + ec2_tailscale_tags = var.tailscale_tags + + ec2_tags = var.common_tags +} + +# Postgres Primary (Elastic Metal / Scaleway Bare Metal) +module "postgres_primary" { + source = "../../modules/elastic_metal" + + elastic_metal_zone = var.postgres_primary_zone + elastic_metal_offer_name = var.postgres_primary_offer_name + elastic_metal_subscription_period = var.subscription_period + elastic_metal_server_name = var.postgres_primary_server_name + elastic_metal_hostname = var.postgres_primary_hostname + elastic_metal_description = var.postgres_primary_description + elastic_metal_ssh_key_name = var.postgres_primary_ssh_key_name + elastic_metal_ssh_public_key_path = var.ssh_public_key_path_scaleway + elastic_metal_cloud_init_template_path = var.postgres_primary_cloud_init_template_path + elastic_metal_os_id = var.os_id + elastic_metal_tailscale_key_expiry = var.tailscale_key_expiry + elastic_metal_tailscale_tags = var.tailscale_tags + elastic_metal_tags = var.postgres_primary_tags +} + +# Postgres Secondary (Elastic Metal / Scaleway Bare Metal) +module "postgres_secondary" { + source = "../../modules/elastic_metal" + + elastic_metal_zone = var.postgres_secondary_zone + elastic_metal_offer_name = var.postgres_secondary_offer_name + elastic_metal_subscription_period = var.subscription_period + elastic_metal_server_name = var.postgres_secondary_server_name + elastic_metal_hostname = var.postgres_secondary_hostname + elastic_metal_description = var.postgres_secondary_description + elastic_metal_ssh_key_name = var.postgres_secondary_ssh_key_name + elastic_metal_ssh_public_key_path = var.ssh_public_key_path_scaleway + elastic_metal_cloud_init_template_path = var.postgres_secondary_cloud_init_template_path + elastic_metal_os_id = var.os_id + elastic_metal_tailscale_key_expiry = var.tailscale_key_expiry + elastic_metal_tailscale_tags = var.tailscale_tags + elastic_metal_tags = var.postgres_secondary_tags +} + +# Gateway Primary (Elastic Metal / Scaleway Bare Metal) +module "gateway_primary" { + source = "../../modules/elastic_metal" + + elastic_metal_zone = var.gateway_primary_zone + elastic_metal_offer_name = var.gateway_primary_offer_name + elastic_metal_subscription_period = var.subscription_period + elastic_metal_server_name = var.gateway_primary_server_name + elastic_metal_hostname = var.gateway_primary_hostname + elastic_metal_description = var.gateway_primary_description + elastic_metal_ssh_key_name = var.gateway_primary_ssh_key_name + elastic_metal_ssh_public_key_path = var.ssh_public_key_path_scaleway + elastic_metal_cloud_init_template_path = var.gateway_primary_cloud_init_template_path + elastic_metal_os_id = var.os_id + elastic_metal_tailscale_key_expiry = var.tailscale_key_expiry + elastic_metal_tailscale_tags = var.tailscale_tags + elastic_metal_tags = var.gateway_primary_tags +} + +# Gateway Secondary (Elastic Metal / Scaleway Bare Metal) +module "gateway_secondary" { + source = "../../modules/elastic_metal" + + elastic_metal_zone = var.gateway_secondary_zone + elastic_metal_offer_name = var.gateway_secondary_offer_name + elastic_metal_subscription_period = var.subscription_period + elastic_metal_server_name = var.gateway_secondary_server_name + elastic_metal_hostname = var.gateway_secondary_hostname + elastic_metal_description = var.gateway_secondary_description + elastic_metal_ssh_key_name = var.gateway_secondary_ssh_key_name + elastic_metal_ssh_public_key_path = var.ssh_public_key_path_scaleway + elastic_metal_cloud_init_template_path = var.gateway_secondary_cloud_init_template_path + elastic_metal_os_id = var.os_id + elastic_metal_tailscale_key_expiry = var.tailscale_key_expiry + elastic_metal_tailscale_tags = var.tailscale_tags + elastic_metal_tags = var.gateway_secondary_tags +} + +# Metrics Server (Elastic Metal / Scaleway Bare Metal) +module "metrics" { + source = "../../modules/elastic_metal" + + elastic_metal_zone = var.metrics_server_zone + elastic_metal_offer_name = var.metrics_server_offer_name + elastic_metal_subscription_period = var.subscription_period + elastic_metal_server_name = var.metrics_server_name + elastic_metal_hostname = var.metrics_server_hostname + elastic_metal_description = var.metrics_server_description + elastic_metal_ssh_key_name = var.metrics_server_ssh_key_name + elastic_metal_ssh_public_key_path = var.ssh_public_key_path_scaleway + elastic_metal_cloud_init_template_path = var.metrics_server_cloud_init_template_path + elastic_metal_os_id = var.os_id + elastic_metal_tailscale_key_expiry = var.tailscale_key_expiry + elastic_metal_tailscale_tags = var.tailscale_tags + elastic_metal_tags = var.metrics_server_tags +} diff --git a/infra/aggregation_mode/terraform/environments/hoodi/outputs.tf b/infra/aggregation_mode/terraform/environments/hoodi/outputs.tf new file mode 100644 index 0000000000..d2d7e012ce --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/outputs.tf @@ -0,0 +1,95 @@ +# Postgres Monitor Outputs +output "postgres_monitor_name" { + description = "Name of the postgres monitor EC2 instance" + value = var.postgres_monitor_instance_name +} + +output "postgres_monitor_hostname" { + description = "Private DNS name of the postgres monitor EC2 instance" + value = module.postgres_monitor.instance_hostname +} + +output "postgres_monitor_public_ip" { + description = "Public IP address of the postgres monitor EC2 instance" + value = module.postgres_monitor.public_ip +} + +# Postgres Primary Outputs +output "postgres_primary_server_name" { + description = "Name of the postgres primary bare metal server" + value = var.postgres_primary_server_name +} + +output "postgres_primary_server_id" { + description = "ID of the postgres primary bare metal server" + value = module.postgres_primary.server_id +} + +output "postgres_primary_server_ip" { + description = "IP address of the postgres primary bare metal server" + value = module.postgres_primary.server_ip +} + +# Postgres Secondary Outputs +output "postgres_secondary_server_name" { + description = "Name of the postgres secondary bare metal server" + value = var.postgres_secondary_server_name +} + +output "postgres_secondary_server_id" { + description = "ID of the postgres secondary bare metal server" + value = module.postgres_secondary.server_id +} + +output "postgres_secondary_server_ip" { + description = "IP address of the postgres secondary bare metal server" + value = module.postgres_secondary.server_ip +} + +# Gateway Primary Outputs +output "gateway_primary_server_name" { + description = "Name of the gateway primary bare metal server" + value = var.gateway_primary_server_name +} + +output "gateway_primary_server_id" { + description = "ID of the gateway primary bare metal server" + value = module.gateway_primary.server_id +} + +output "gateway_primary_server_ip" { + description = "IP address of the gateway primary bare metal server" + value = module.gateway_primary.server_ip +} + +# Gateway Secondary Outputs +output "gateway_secondary_server_name" { + description = "Name of the gateway secondary bare metal server" + value = var.gateway_secondary_server_name +} + +output "gateway_secondary_server_id" { + description = "ID of the gateway secondary bare metal server" + value = module.gateway_secondary.server_id +} + +output "gateway_secondary_server_ip" { + description = "IP address of the gateway secondary bare metal server" + value = module.gateway_secondary.server_ip +} + +# Metrics Server Outputs +output "metrics_server_name" { + description = "Name of the metrics bare metal server" + value = var.metrics_server_name +} + +output "metrics_server_id" { + description = "ID of the metrics bare metal server" + value = module.metrics.server_id +} + +output "metrics_server_ip" { + description = "IP address of the metrics bare metal server" + value = module.metrics.server_ip +} diff --git a/infra/aggregation_mode/terraform/environments/hoodi/terraform.tf b/infra/aggregation_mode/terraform/environments/hoodi/terraform.tf new file mode 100644 index 0000000000..5da16c740b --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/terraform.tf @@ -0,0 +1,21 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.92" + } + scaleway = { + source = "scaleway/scaleway" + version = "2.64.0" + } + tailscale = { + source = "tailscale/tailscale" + version = "0.24.0" + } + } + + required_version = ">= 1.2" + + backend "s3" { + } +} \ No newline at end of file diff --git a/infra/aggregation_mode/terraform/environments/hoodi/terraform.tfvars b/infra/aggregation_mode/terraform/environments/hoodi/terraform.tfvars new file mode 100644 index 0000000000..1f87741678 --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/terraform.tfvars @@ -0,0 +1,81 @@ +# ============================================ +# Provider Configuration +# ============================================ +aws_region = "us-east-1" +scaleway_zone = "fr-par-2" + +# ============================================ +# Common Configuration +# ============================================ +ssh_public_key_path_aws = "~/.ssh/aws.pub" +ssh_public_key_path_scaleway = "~/.ssh/scaleway.pem.pub" +subscription_period = "monthly" + +# ============================================ +# Postgres Monitor Configuration (EC2) +# ============================================ +postgres_monitor_instance_name = "agg-mode-hoodi-postgres-monitor" +postgres_monitor_hostname = "agg-mode-hoodi-postgres-monitor" +postgres_monitor_instance_type = "t2.micro" +postgres_monitor_ssh_key_name = "agg-mode-hoodi-postgres-monitor-key" +postgres_monitor_cloud_init_template_path = "../../cloudinit/postgres-monitor-cloud-init.yaml" + +# ============================================ +# Postgres Primary Configuration (Elastic Metal) +# ============================================ +postgres_primary_zone = "fr-par-2" +postgres_primary_offer_name = "EM-A610R-NVME" +postgres_primary_server_name = "agg-mode-hoodi-postgres-1" +postgres_primary_hostname = "agg-mode-hoodi-postgres-1" +postgres_primary_description = "PostgreSQL server 1 for hoodi" +postgres_primary_ssh_key_name = "agg-mode-hoodi-postgres-1-key" +postgres_primary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +postgres_primary_tags = ["postgres", "postgres-1", "hoodi"] + +# ============================================ +# Postgres Secondary Configuration (Elastic Metal) +# ============================================ +postgres_secondary_zone = "nl-ams-1" +postgres_secondary_offer_name = "EM-A610R-NVME" +postgres_secondary_server_name = "agg-mode-hoodi-postgres-2" +postgres_secondary_hostname = "agg-mode-hoodi-postgres-2" +postgres_secondary_description = "PostgreSQL server 2 for hoodi" +postgres_secondary_ssh_key_name = "agg-mode-hoodi-postgres-2-key" +postgres_secondary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +postgres_secondary_tags = ["postgres", "postgres-2", "hoodi"] + +# ============================================ +# Gateway Primary Configuration (Elastic Metal) +# ============================================ +gateway_primary_zone = "fr-par-2" +gateway_primary_offer_name = "EM-A610R-NVME" +gateway_primary_server_name = "agg-mode-hoodi-gateway-1" +gateway_primary_hostname = "agg-mode-hoodi-gateway-1" +gateway_primary_description = "Gateway server 1 for hoodi" +gateway_primary_ssh_key_name = "agg-mode-hoodi-gateway-1-key" +gateway_primary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +gateway_primary_tags = ["gateway", "gateway-1", "hoodi"] + +# ============================================ +# Gateway Secondary Configuration (Elastic Metal) +# ============================================ +gateway_secondary_zone = "nl-ams-1" +gateway_secondary_offer_name = "EM-A610R-NVME" +gateway_secondary_server_name = "agg-mode-hoodi-gateway-2" +gateway_secondary_hostname = "agg-mode-hoodi-gateway-2" +gateway_secondary_description = "Gateway server 2 for hoodi" +gateway_secondary_ssh_key_name = "agg-mode-hoodi-gateway-2-key" +gateway_secondary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +gateway_secondary_tags = ["gateway", "gateway-2", "hoodi"] + +# ============================================ +# Metrics Configuration (Elastic Metal) +# ============================================ +metrics_server_zone = "fr-par-2" +metrics_server_offer_name = "EM-A610R-NVME" +metrics_server_name = "agg-mode-hoodi-metrics" +metrics_server_hostname = "agg-mode-hoodi-metrics" +metrics_server_description = "Metrics server for hoodi" +metrics_server_ssh_key_name = "agg-mode-hoodi-metrics-key" +metrics_server_cloud_init_template_path = "../../cloudinit/cloud-init.yaml" +metrics_server_tags = ["metrics", "hoodi"] diff --git a/infra/aggregation_mode/terraform/environments/hoodi/terraform.tfvars.example b/infra/aggregation_mode/terraform/environments/hoodi/terraform.tfvars.example new file mode 100644 index 0000000000..4390ae035a --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/terraform.tfvars.example @@ -0,0 +1,69 @@ +# ============================================ +# Provider Configuration +# ============================================ +aws_region = "us-east-1" +scaleway_zone = "fr-par-2" + +# ============================================ +# Common Configuration +# ============================================ +ssh_public_key_path_aws = "~/.ssh/aws.pub" +ssh_public_key_path_scaleway = "~/.ssh/scaleway.pem.pub" +subscription_period = "monthly" + +# ============================================ +# Postgres Monitor Configuration (EC2) +# ============================================ +postgres_monitor_instance_name = "agg-mode-hoodi-postgres-monitor" +postgres_monitor_hostname = "agg-mode-hoodi-postgres-monitor" +postgres_monitor_instance_type = "t2.micro" +postgres_monitor_ssh_key_name = "agg-mode-hoodi-postgres-monitor-key" +postgres_monitor_cloud_init_template_path = "../../cloudinit/postgres-monitor-cloud-init.yaml" + +# ============================================ +# Postgres Primary Configuration (Elastic Metal) +# ============================================ +postgres_primary_zone = "fr-par-2" +postgres_primary_offer_name = "EM-A610R-NVME" +postgres_primary_server_name = "agg-mode-hoodi-postgres-1" +postgres_primary_hostname = "agg-mode-hoodi-postgres-1" +postgres_primary_description = "PostgreSQL server 1 for hoodi" +postgres_primary_ssh_key_name = "agg-mode-hoodi-postgres-1-key" +postgres_primary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +postgres_primary_tags = ["postgres", "postgres-1", "hoodi"] + +# ============================================ +# Postgres Secondary Configuration (Elastic Metal) +# ============================================ +postgres_secondary_zone = "nl-ams-1" +postgres_secondary_offer_name = "EM-A610R-NVME" +postgres_secondary_server_name = "agg-mode-hoodi-postgres-2" +postgres_secondary_hostname = "agg-mode-hoodi-postgres-2" +postgres_secondary_description = "PostgreSQL server 2 for hoodi" +postgres_secondary_ssh_key_name = "agg-mode-hoodi-postgres-2-key" +postgres_secondary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +postgres_secondary_tags = ["postgres", "postgres-2", "hoodi"] + +# ============================================ +# Gateway Primary Configuration (Elastic Metal) +# ============================================ +gateway_primary_zone = "fr-par-2" +gateway_primary_offer_name = "EM-A610R-NVME" +gateway_primary_server_name = "agg-mode-hoodi-gateway-1" +gateway_primary_hostname = "agg-mode-hoodi-gateway-1" +gateway_primary_description = "Gateway server 1 for hoodi" +gateway_primary_ssh_key_name = "agg-mode-hoodi-gateway-1-key" +gateway_primary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +gateway_primary_tags = ["gateway", "gateway-1", "hoodi"] + +# ============================================ +# Gateway Secondary Configuration (Elastic Metal) +# ============================================ +gateway_secondary_zone = "nl-ams-1" +gateway_secondary_offer_name = "EM-A610R-NVME" +gateway_secondary_server_name = "agg-mode-hoodi-gateway-2" +gateway_secondary_hostname = "agg-mode-hoodi-gateway-2" +gateway_secondary_description = "Gateway server 2 for hoodi" +gateway_secondary_ssh_key_name = "agg-mode-hoodi-gateway-2-key" +gateway_secondary_cloud_init_template_path = "../../cloudinit/scaleway-cloud-init.yaml" +gateway_secondary_tags = ["gateway", "gateway-2", "hoodi"] diff --git a/infra/aggregation_mode/terraform/environments/hoodi/variables.tf b/infra/aggregation_mode/terraform/environments/hoodi/variables.tf new file mode 100644 index 0000000000..d9b01a7953 --- /dev/null +++ b/infra/aggregation_mode/terraform/environments/hoodi/variables.tf @@ -0,0 +1,312 @@ +# ============================================ +# Provider Configuration +# ============================================ + +variable "aws_region" { + description = "AWS region" + type = string +} + +variable "scaleway_zone" { + description = "Default Scaleway zone" + type = string +} + +# ============================================ +# Common Configuration +# ============================================ + +variable "ssh_public_key_path_aws" { + description = "Path to SSH public key for AWS" + type = string +} + +variable "ssh_public_key_path_scaleway" { + description = "Path to SSH public key for Scaleway" + type = string +} + +variable "os_id" { + description = "Scaleway OS ID for Debian 12" + type = string + default = "83640d93-a0b8-45ad-9c9f-30cae48380a4" +} + +variable "subscription_period" { + description = "Subscription period for bare metal servers" + type = string + default = "hourly" +} + +variable "tailscale_key_expiry" { + description = "Tailscale key expiry in seconds" + type = number + default = 3600 +} + +variable "tailscale_tags" { + description = "Tailscale tags" + type = list(string) + default = ["tag:server"] +} + +variable "common_tags" { + description = "Common tags for all resources" + type = map(string) + default = {} +} + +# ============================================ +# Postgres Monitor Configuration (EC2) +# ============================================ + +variable "postgres_monitor_instance_name" { + description = "Name of the postgres monitor EC2 instance" + type = string +} + +variable "postgres_monitor_hostname" { + description = "Hostname for postgres monitor" + type = string +} + +variable "postgres_monitor_instance_type" { + description = "EC2 instance type for postgres monitor" + type = string +} + +variable "postgres_monitor_ssh_key_name" { + description = "SSH key name for postgres monitor" + type = string +} + +variable "postgres_monitor_cloud_init_template_path" { + description = "Path to cloud-init template for postgres monitor" + type = string +} + +variable "postgres_monitor_root_volume_size" { + description = "Root volume size for postgres monitor in GB" + type = number + default = 32 +} + +# ============================================ +# Postgres Primary Configuration (Elastic Metal) +# ============================================ + +variable "postgres_primary_zone" { + description = "Scaleway zone for postgres primary" + type = string +} + +variable "postgres_primary_offer_name" { + description = "Bare metal offer name for postgres primary" + type = string +} + +variable "postgres_primary_server_name" { + description = "Server name for postgres primary" + type = string +} + +variable "postgres_primary_hostname" { + description = "Hostname for postgres primary" + type = string +} + +variable "postgres_primary_description" { + description = "Description for postgres primary" + type = string +} + +variable "postgres_primary_ssh_key_name" { + description = "SSH key name for postgres primary" + type = string +} + +variable "postgres_primary_cloud_init_template_path" { + description = "Path to cloud-init template for postgres primary" + type = string +} + +variable "postgres_primary_tags" { + description = "Tags for postgres primary" + type = list(string) +} + +# ============================================ +# Postgres Secondary Configuration (Elastic Metal) +# ============================================ + +variable "postgres_secondary_zone" { + description = "Scaleway zone for postgres secondary" + type = string +} + +variable "postgres_secondary_offer_name" { + description = "Bare metal offer name for postgres secondary" + type = string +} + +variable "postgres_secondary_server_name" { + description = "Server name for postgres secondary" + type = string +} + +variable "postgres_secondary_hostname" { + description = "Hostname for postgres secondary" + type = string +} + +variable "postgres_secondary_description" { + description = "Description for postgres secondary" + type = string +} + +variable "postgres_secondary_ssh_key_name" { + description = "SSH key name for postgres secondary" + type = string +} + +variable "postgres_secondary_cloud_init_template_path" { + description = "Path to cloud-init template for postgres secondary" + type = string +} + +variable "postgres_secondary_tags" { + description = "Tags for postgres secondary" + type = list(string) +} + +# ============================================ +# Gateway Primary Configuration (Elastic Metal) +# ============================================ + +variable "gateway_primary_zone" { + description = "Scaleway zone for gateway primary" + type = string +} + +variable "gateway_primary_offer_name" { + description = "Bare metal offer name for gateway primary" + type = string +} + +variable "gateway_primary_server_name" { + description = "Server name for gateway primary" + type = string +} + +variable "gateway_primary_hostname" { + description = "Hostname for gateway primary" + type = string +} + +variable "gateway_primary_description" { + description = "Description for gateway primary" + type = string +} + +variable "gateway_primary_ssh_key_name" { + description = "SSH key name for gateway primary" + type = string +} + +variable "gateway_primary_cloud_init_template_path" { + description = "Path to cloud-init template for gateway primary" + type = string +} + +variable "gateway_primary_tags" { + description = "Tags for gateway primary" + type = list(string) +} + +# ============================================ +# Gateway Secondary Configuration (Elastic Metal) +# ============================================ + +variable "gateway_secondary_zone" { + description = "Scaleway zone for gateway secondary" + type = string +} + +variable "gateway_secondary_offer_name" { + description = "Bare metal offer name for gateway secondary" + type = string +} + +variable "gateway_secondary_server_name" { + description = "Server name for gateway secondary" + type = string +} + +variable "gateway_secondary_hostname" { + description = "Hostname for gateway secondary" + type = string +} + +variable "gateway_secondary_description" { + description = "Description for gateway secondary" + type = string +} + +variable "gateway_secondary_ssh_key_name" { + description = "SSH key name for gateway secondary" + type = string +} + +variable "gateway_secondary_cloud_init_template_path" { + description = "Path to cloud-init template for gateway secondary" + type = string +} + +variable "gateway_secondary_tags" { + description = "Tags for gateway secondary" + type = list(string) +} + +# ============================================ +# Metrics Configuration (Elastic Metal) +# ============================================ + +variable "metrics_server_zone" { + description = "Scaleway zone for metrics server" + type = string +} + +variable "metrics_server_offer_name" { + description = "Bare metal offer name for metrics server" + type = string +} + +variable "metrics_server_name" { + description = "Server name for metrics server" + type = string +} + +variable "metrics_server_hostname" { + description = "Hostname for metrics server" + type = string +} + +variable "metrics_server_description" { + description = "Description for metrics server" + type = string +} + +variable "metrics_server_ssh_key_name" { + description = "SSH key name for metrics server" + type = string +} + +variable "metrics_server_cloud_init_template_path" { + description = "Path to cloud-init template for metrics server" + type = string +} + +variable "metrics_server_tags" { + description = "Tags for metrics server" + type = list(string) +} diff --git a/infra/aggregation_mode/terraform/modules/ec2/main.tf b/infra/aggregation_mode/terraform/modules/ec2/main.tf new file mode 100644 index 0000000000..24fe0baa80 --- /dev/null +++ b/infra/aggregation_mode/terraform/modules/ec2/main.tf @@ -0,0 +1,101 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + tailscale = { + source = "tailscale/tailscale" + } + } +} + +# Create Tailscale auth key +resource "tailscale_tailnet_key" "this" { + reusable = false + ephemeral = false + preauthorized = true + expiry = var.ec2_tailscale_key_expiry + description = "Auth key for ${var.ec2_instance_name}" + tags = var.ec2_tailscale_tags +} + +# Upload existing SSH public key to AWS +resource "aws_key_pair" "ssh_key" { + key_name = var.ec2_ssh_key_name + public_key = file(var.ec2_ssh_public_key_path) +} + +# Debian 12 AMI +data "aws_ami" "debian12" { + most_recent = true + + filter { + name = "name" + values = ["debian-12-amd64-*"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } + + owners = ["136693071363"] # https://wiki.debian.org/Cloud/AmazonEC2Image/ +} + +# Security group +resource "aws_security_group" "ssh_access" { + name = "${var.ec2_instance_name}-ssh-access" + description = "Allow SSH inbound traffic for ${var.ec2_instance_name}" + + ingress { + description = "SSH from anywhere" + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + description = "Allow all outbound traffic" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "${var.ec2_instance_name}-ssh-access" + } +} + +# EC2 Instance +resource "aws_instance" "this" { + ami = data.aws_ami.debian12.id + instance_type = var.ec2_instance_type + key_name = var.ec2_ssh_key_name + vpc_security_group_ids = [aws_security_group.ssh_access.id] + + user_data = templatefile(var.ec2_cloud_init_template_path, { + hostname = var.ec2_hostname + ssh_public_key = trimspace(file(var.ec2_ssh_public_key_path)) + tailscale_auth_key = tailscale_tailnet_key.this.key + }) + + user_data_replace_on_change = true + + tags = merge( + { + Name = var.ec2_instance_name + }, + var.ec2_tags + ) + + root_block_device { + volume_size = var.ec2_root_volume_size + } +} diff --git a/infra/aggregation_mode/terraform/modules/ec2/outputs.tf b/infra/aggregation_mode/terraform/modules/ec2/outputs.tf new file mode 100644 index 0000000000..0ca5cdc236 --- /dev/null +++ b/infra/aggregation_mode/terraform/modules/ec2/outputs.tf @@ -0,0 +1,9 @@ +output "instance_hostname" { + description = "Private DNS name of the EC2 instance" + value = aws_instance.this.private_dns +} + +output "public_ip" { + description = "Public IP address of the EC2 instance" + value = aws_instance.this.public_ip +} diff --git a/infra/aggregation_mode/terraform/modules/ec2/variables.tf b/infra/aggregation_mode/terraform/modules/ec2/variables.tf new file mode 100644 index 0000000000..35bcbd4189 --- /dev/null +++ b/infra/aggregation_mode/terraform/modules/ec2/variables.tf @@ -0,0 +1,53 @@ +variable "ec2_instance_name" { + description = "Value of the EC2 instance's Name tag" + type = string +} + +variable "ec2_hostname" { + description = "The hostname to set for the EC2 instance" + type = string +} + +variable "ec2_instance_type" { + description = "The EC2 instance's type" + type = string +} + +variable "ec2_ssh_key_name" { + description = "The name of the SSH key pair to use for the EC2 instance" + type = string +} + +variable "ec2_ssh_public_key_path" { + description = "Path to the SSH public key file to upload to AWS" + type = string +} + +variable "ec2_cloud_init_template_path" { + description = "Path to the cloud-init template file" + type = string +} + +variable "ec2_root_volume_size" { + description = "Size of the root EBS volume in GB" + type = number + default = 32 +} + +variable "ec2_tailscale_key_expiry" { + description = "Expiry time for Tailscale auth key in seconds" + type = number + default = 3600 +} + +variable "ec2_tailscale_tags" { + description = "Tags to apply to the Tailscale key" + type = list(string) + default = ["tag:server"] +} + +variable "ec2_tags" { + description = "Additional tags to apply to the instance" + type = map(string) + default = {} +} diff --git a/infra/aggregation_mode/terraform/modules/elastic_metal/main.tf b/infra/aggregation_mode/terraform/modules/elastic_metal/main.tf new file mode 100644 index 0000000000..43dc58486e --- /dev/null +++ b/infra/aggregation_mode/terraform/modules/elastic_metal/main.tf @@ -0,0 +1,61 @@ +terraform { + required_providers { + scaleway = { + source = "scaleway/scaleway" + } + tailscale = { + source = "tailscale/tailscale" + } + } +} + +# Create Tailscale auth key +resource "tailscale_tailnet_key" "this" { + reusable = false + ephemeral = false + preauthorized = true + expiry = var.elastic_metal_tailscale_key_expiry + description = "Auth key for ${var.elastic_metal_server_name}" + tags = var.elastic_metal_tailscale_tags +} + +# Get available bare metal offer +data "scaleway_baremetal_offer" "offer" { + zone = var.elastic_metal_zone + name = var.elastic_metal_offer_name + subscription_period = var.elastic_metal_subscription_period +} + +# Get Debian 12 OS +data "scaleway_baremetal_os" "debian12" { + os_id = var.elastic_metal_os_id +} + +# Upload SSH key +resource "scaleway_iam_ssh_key" "main" { + name = var.elastic_metal_ssh_key_name + public_key = file(var.elastic_metal_ssh_public_key_path) +} + +# Create bare metal server with hourly billing +resource "scaleway_baremetal_server" "this" { + name = var.elastic_metal_server_name + offer = data.scaleway_baremetal_offer.offer.offer_id + zone = var.elastic_metal_zone + description = var.elastic_metal_description + + # Install OS + os = data.scaleway_baremetal_os.debian12.os_id + + # Attach SSH key + ssh_key_ids = [scaleway_iam_ssh_key.main.id] + + # Cloud-init configuration + cloud_init = templatefile(var.elastic_metal_cloud_init_template_path, { + hostname = var.elastic_metal_hostname + ssh_public_key = trimspace(file(var.elastic_metal_ssh_public_key_path)) + tailscale_auth_key = tailscale_tailnet_key.this.key + }) + + tags = var.elastic_metal_tags +} diff --git a/infra/aggregation_mode/terraform/modules/elastic_metal/outputs.tf b/infra/aggregation_mode/terraform/modules/elastic_metal/outputs.tf new file mode 100644 index 0000000000..ddc34dca88 --- /dev/null +++ b/infra/aggregation_mode/terraform/modules/elastic_metal/outputs.tf @@ -0,0 +1,9 @@ +output "server_id" { + description = "ID of the bare metal server" + value = scaleway_baremetal_server.this.id +} + +output "server_ip" { + description = "IP address of the bare metal server" + value = scaleway_baremetal_server.this.ips[0].address +} diff --git a/infra/aggregation_mode/terraform/modules/elastic_metal/variables.tf b/infra/aggregation_mode/terraform/modules/elastic_metal/variables.tf new file mode 100644 index 0000000000..b4d22b0717 --- /dev/null +++ b/infra/aggregation_mode/terraform/modules/elastic_metal/variables.tf @@ -0,0 +1,69 @@ +variable "elastic_metal_zone" { + description = "Scaleway zone" + type = string +} + +variable "elastic_metal_offer_name" { + description = "Name of the bare metal server offer" + type = string +} + +variable "elastic_metal_subscription_period" { + description = "Subscription period for the bare metal server" + type = string + default = "hourly" +} + +variable "elastic_metal_server_name" { + description = "Name of the bare metal server" + type = string +} + +variable "elastic_metal_hostname" { + description = "Hostname for the server" + type = string +} + +variable "elastic_metal_description" { + description = "Description of the server" + type = string +} + +variable "elastic_metal_ssh_key_name" { + description = "Name for the SSH key in Scaleway" + type = string +} + +variable "elastic_metal_ssh_public_key_path" { + description = "Path to the SSH public key file" + type = string +} + +variable "elastic_metal_cloud_init_template_path" { + description = "Path to the cloud-init template file" + type = string +} + +variable "elastic_metal_os_id" { + description = "Scaleway OS ID" + type = string + default = "83640d93-a0b8-45ad-9c9f-30cae48380a4" +} + +variable "elastic_metal_tailscale_key_expiry" { + description = "Expiry time for Tailscale auth key in seconds" + type = number + default = 3600 +} + +variable "elastic_metal_tailscale_tags" { + description = "Tags to apply to the Tailscale key" + type = list(string) + default = ["tag:server"] +} + +variable "elastic_metal_tags" { + description = "Tags to apply to the server" + type = list(string) + default = [] +}