diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0b8690c..9ed1aa3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Setup Terraform uses: hashicorp/setup-terraform@v3.1.2 diff --git a/os-builds/main.tf b/os-builds/main.tf index 88c48a7..b928965 100644 --- a/os-builds/main.tf +++ b/os-builds/main.tf @@ -7,11 +7,12 @@ terraform { } } + required_version = "= 1.9.6" required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "~> 4" + version = "~> 4.0" } } } diff --git a/static_dns/main.tf b/static_dns/main.tf index a0d8d20..0d0a340 100644 --- a/static_dns/main.tf +++ b/static_dns/main.tf @@ -7,10 +7,12 @@ terraform { } } + required_version = "= 1.9.6" + required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "~> 3.0" + version = "~> 4.0" } } } diff --git a/static_dns/record._checkdns.tf b/static_dns/record._checkdns.tf index ddb4823..555fd13 100644 --- a/static_dns/record._checkdns.tf +++ b/static_dns/record._checkdns.tf @@ -2,7 +2,7 @@ resource "cloudflare_record" "_checkdns" { zone_id = data.cloudflare_zone.dns_zone.id name = "_checkdns" - value = "1.1.1.1" + content = "1.1.1.1" type = "A" ttl = 1 proxied = false diff --git a/stun_server/main.tf b/stun_server/main.tf new file mode 100644 index 0000000..f524393 --- /dev/null +++ b/stun_server/main.tf @@ -0,0 +1,37 @@ +terraform { + cloud { + organization = "home_assistant" + + workspaces { + name = "stun_server" + } + } +} + +provider "aws" { + region = "us-east-1" +} + +module "us_east_1" { + source = "./region" + + region = "us-east-1" + domain_name = var.domain_name + image_tag = var.image_tag +} + +module "eu_central_1" { + source = "./region" + + region = "eu-central-1" + domain_name = var.domain_name + image_tag = var.image_tag +} + +module "ap_southeast_1" { + source = "./region" + + region = "ap-southeast-1" + domain_name = var.domain_name + image_tag = var.image_tag +} diff --git a/stun_server/outputs.tf b/stun_server/outputs.tf new file mode 100644 index 0000000..916ea9a --- /dev/null +++ b/stun_server/outputs.tf @@ -0,0 +1,8 @@ +output "ip" { + description = "The public IP address of the stun server" + value = { + "us-east-1" = module.us_east_1.stun_server_ip + "eu-central-1" = module.eu_central_1.stun_server_ip + "ap-southeast-1" = module.ap_southeast_1.stun_server_ip + } +} diff --git a/stun_server/region/dns.tf b/stun_server/region/dns.tf new file mode 100644 index 0000000..e832e2d --- /dev/null +++ b/stun_server/region/dns.tf @@ -0,0 +1,12 @@ +data "cloudflare_zone" "dns_zone" { + name = var.domain_name +} + +resource "cloudflare_record" "instance_dns" { + zone_id = data.cloudflare_zone.dns_zone.id + name = join("-", ["stun", data.aws_region.current.name]) + content = data.aws_network_interface.stun_server_interface.association[0].public_ip + type = "A" + proxied = true + depends_on = [data.aws_network_interface.stun_server_interface] +} diff --git a/stun_server/region/ecs.tf b/stun_server/region/ecs.tf new file mode 100644 index 0000000..760a9ff --- /dev/null +++ b/stun_server/region/ecs.tf @@ -0,0 +1,32 @@ +resource "aws_ecs_service" "stun-server" { + name = local.service_name + cluster = local.infrastructure_region_outputs.ecs_cluster + task_definition = module.stun_server.task_definition + desired_count = 1 + deployment_minimum_healthy_percent = 100 + deployment_maximum_percent = 200 + health_check_grace_period_seconds = 90 + launch_type = "FARGATE" + + # Required to fetch the public IP address of the ECS service + enable_ecs_managed_tags = true + wait_for_steady_state = true + + network_configuration { + assign_public_ip = true + security_groups = [aws_security_group.stun_sg.id] + subnets = local.infrastructure_region_outputs.public_subnets + } + + tags = { + region = data.aws_region.current.name + } +} + +data "aws_network_interface" "stun_server_interface" { + filter { + name = "tag:aws:ecs:serviceName" + values = [aws_ecs_service.stun-server.name] + } + depends_on = [aws_ecs_service.stun-server] +} diff --git a/stun_server/region/module.tf b/stun_server/region/module.tf new file mode 100644 index 0000000..c6e56f1 --- /dev/null +++ b/stun_server/region/module.tf @@ -0,0 +1,41 @@ +locals { + service_name = "stun-server" + infrastructure_region_outputs = data.tfe_outputs.infrastructure.values[data.aws_region.current.name] +} + +provider "aws" { + region = var.region +} + +data "tfe_outputs" "infrastructure" { + organization = "home_assistant" + workspace = "infrastructure" +} + +data "aws_region" "current" {} + +module "stun_server" { + source = "../../.modules/service" + + service_name = local.service_name + container_image = "ghcr.io/home-assistant/stun" + container_version = var.image_tag + region = data.aws_region.current.name + ecs_cpu = 512 + ecs_memory = 1024 + container_definitions = { + portMappings = [ + { + containerPort = 3478 + hostPort = 3478 + protocol = "tcp" + }, + { + containerPort = 3478 + hostPort = 3478 + protocol = "udp" + } + ], + } + webservice = true +} diff --git a/stun_server/region/network.tf b/stun_server/region/network.tf new file mode 100644 index 0000000..2caa5c5 --- /dev/null +++ b/stun_server/region/network.tf @@ -0,0 +1,30 @@ +resource "aws_security_group" "stun_sg" { + vpc_id = local.infrastructure_region_outputs.network_id + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + description = "Allow STUN traffic TCP" + from_port = 3478 + to_port = 3478 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + description = "Allow STUN traffic UDF" + from_port = 3478 + to_port = 3478 + protocol = "udp" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + region = data.aws_region.current.name + } +} diff --git a/stun_server/region/outputs.tf b/stun_server/region/outputs.tf new file mode 100644 index 0000000..e32a571 --- /dev/null +++ b/stun_server/region/outputs.tf @@ -0,0 +1,4 @@ +output "stun_server_ip" { + description = "The public IP address of the stun server" + value = data.aws_network_interface.stun_server_interface.association[0].public_ip +} diff --git a/stun_server/region/variables.tf b/stun_server/region/variables.tf new file mode 100644 index 0000000..ec10294 --- /dev/null +++ b/stun_server/region/variables.tf @@ -0,0 +1,14 @@ +variable "region" { + description = "The region to deploy the STUN server to" + type = string +} + +variable "domain_name" { + description = "The base domain name" + type = string +} + +variable "image_tag" { + description = "Version of the Stun server to deploy" + type = string +} diff --git a/stun_server/region/versions.tf b/stun_server/region/versions.tf new file mode 100644 index 0000000..d704bc8 --- /dev/null +++ b/stun_server/region/versions.tf @@ -0,0 +1,19 @@ +terraform { + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + + tfe = { + source = "hashicorp/tfe" + version = "~> 0.58.0" + } + + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 4.0" + } + } +} diff --git a/stun_server/variables.tf b/stun_server/variables.tf new file mode 100644 index 0000000..9f49cbe --- /dev/null +++ b/stun_server/variables.tf @@ -0,0 +1,9 @@ +variable "domain_name" { + description = "The base domain name" + type = string +} + +variable "image_tag" { + description = "Version of the Stun server to deploy" + type = string +} diff --git a/stun_server/versions.tf b/stun_server/versions.tf new file mode 100644 index 0000000..a1b2c49 --- /dev/null +++ b/stun_server/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "= 1.9.6" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +}