diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0b8690c..13779cf 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.2 - name: Setup Terraform uses: hashicorp/setup-terraform@v3.1.2 diff --git a/.modules/service/module.tf b/.modules/service/module.tf index 6759f5e..98a4f36 100644 --- a/.modules/service/module.tf +++ b/.modules/service/module.tf @@ -1,4 +1,6 @@ data "tfe_outputs" "infrastructure" { organization = "home_assistant" workspace = "infrastructure" -} \ No newline at end of file +} + +data "aws_region" "current" {} diff --git a/.modules/service/policy.tf b/.modules/service/policy.tf index cdbf186..4728dc0 100644 --- a/.modules/service/policy.tf +++ b/.modules/service/policy.tf @@ -10,7 +10,7 @@ data "aws_iam_policy_document" "ecs-role-policy" { } resource "aws_iam_role" "ecs-execution" { - name = "${var.service_name}-ExecutionRole-role" + name = "${var.service_name}-${data.aws_region.current.name}-ExecutionRole-role" assume_role_policy = data.aws_iam_policy_document.ecs-role-policy.json } @@ -46,11 +46,11 @@ data "aws_iam_policy_document" "task-assume-role" { } resource "aws_iam_role" "task-execution" { - name = "${var.service_name}-TaskRole-role" + name = "${var.service_name}-${data.aws_region.current.name}-TaskRole-role" assume_role_policy = data.aws_iam_policy_document.task-assume-role.json } resource "aws_iam_role_policy" "task-role" { policy = data.aws_iam_policy_document.task-policy.json role = aws_iam_role.task-execution.id -} \ No newline at end of file +} diff --git a/assist/main.tf b/assist/main.tf index 226618b..b6a380e 100644 --- a/assist/main.tf +++ b/assist/main.tf @@ -7,11 +7,12 @@ terraform { } } + required_version = "= 1.9.8" required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "~> 4" + version = "~> 4.0" } } } diff --git a/cas_validator/main.tf b/cas_validator/main.tf deleted file mode 100644 index adb6e0d..0000000 --- a/cas_validator/main.tf +++ /dev/null @@ -1,46 +0,0 @@ -terraform { - cloud { - organization = "home_assistant" - - workspaces { - name = "cas_validator" - } - } - - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 4.0" - } - - cloudflare = { - source = "cloudflare/cloudflare" - version = "~> 3.0" - } - } -} - -provider "aws" { - region = "us-east-1" -} - -module "webservice_cas_validator" { - source = "../.modules/webservice" - - service_name = "CAS-Validator" - subdomain = "cas-validator" - container_image = "codenotary/immuproof" - container_version = "v0.0.11" - port = 8091 - - container_definitions = { - environment : [ - { name : "IMMUPROOF_HOST", value : "cas.codenotary.com" }, - { name : "IMMUPROOF_PORT", value : "443" }, - { name : "IMMUPROOF_API_KEY", value : var.cas_api_key }, - { name : "IMMUPROOF_WEB_TITLE_TEXT", value : "Home Assistant service validator" }, - { name : "IMMUPROOF_WEB_HOSTED_BY_TEXT", value : "Home Assistant Community" }, - { name : "IMMUPROOF_WEB_HOSTED_BY_LOGO_URL", value : "https://www.home-assistant.io/images/home-assistant-logo.svg" } - ] - } -} diff --git a/cas_validator/variables.tf b/cas_validator/variables.tf deleted file mode 100644 index 879e5e2..0000000 --- a/cas_validator/variables.tf +++ /dev/null @@ -1,4 +0,0 @@ -variable "cas_api_key" { - description = "CAS Key for monitoring the immodb" - type = string -} diff --git a/community/dns.tf b/community/dns.tf index 137e53b..1f45d03 100644 --- a/community/dns.tf +++ b/community/dns.tf @@ -5,7 +5,7 @@ data "cloudflare_zone" "dns_zone" { resource "cloudflare_record" "community" { zone_id = data.cloudflare_zone.dns_zone.id name = "community" - value = aws_eip.discourse.public_ip + content = aws_eip.discourse.public_ip type = "A" proxied = true } diff --git a/community/ec2.tf b/community/ec2.tf index 622f618..fd7a805 100644 --- a/community/ec2.tf +++ b/community/ec2.tf @@ -9,5 +9,5 @@ resource "aws_instance" "discourse" { resource "aws_eip" "discourse" { instance = aws_instance.discourse.id - vpc = true + domain = "vpc" } diff --git a/community/main.tf b/community/main.tf index 2b8e605..270242e 100644 --- a/community/main.tf +++ b/community/main.tf @@ -7,15 +7,17 @@ terraform { } } + required_version = "= 1.9.8" + required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.0" } cloudflare = { source = "cloudflare/cloudflare" - version = "~> 3.0" + version = "~> 4.0" } } } diff --git a/infrastructure/certificate.tf b/infrastructure/certificate.tf index c77cb2e..e616c2f 100644 --- a/infrastructure/certificate.tf +++ b/infrastructure/certificate.tf @@ -22,7 +22,7 @@ resource "cloudflare_record" "dns_instance_validation" { zone_id = data.cloudflare_zone.dns_zone.id name = each.value.name - value = trimsuffix(each.value.record, ".") + content = trimsuffix(each.value.record, ".") type = each.value.type ttl = 1 proxied = false diff --git a/infrastructure/region/network.tf b/infrastructure/region/network.tf index 0508b39..a4a97cc 100644 --- a/infrastructure/region/network.tf +++ b/infrastructure/region/network.tf @@ -32,7 +32,7 @@ resource "aws_route_table" "public" { resource "aws_eip" "nat" { count = 2 - vpc = true + domain = "vpc" tags = { Region = data.aws_region.current.name diff --git a/infrastructure/versions.tf b/infrastructure/versions.tf index c238c02..5337068 100644 --- a/infrastructure/versions.tf +++ b/infrastructure/versions.tf @@ -1,14 +1,15 @@ terraform { - required_version = "= 1.7.5" + required_version = "= 1.9.8" + required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.0" } cloudflare = { source = "cloudflare/cloudflare" - version = "~> 3.0" + version = "~> 4.0" } } } diff --git a/ohf-public-assets/bucket.tf b/ohf-public-assets/bucket.tf new file mode 100644 index 0000000..ba506bc --- /dev/null +++ b/ohf-public-assets/bucket.tf @@ -0,0 +1,5 @@ +resource "cloudflare_r2_bucket" "ohf_public_assets" { + account_id = var.CLOUDFLARE_ACCOUNT_ID + name = "ohf-public-assets" + location = "ENAM" +} diff --git a/ohf-public-assets/main.tf b/ohf-public-assets/main.tf new file mode 100644 index 0000000..d39edc6 --- /dev/null +++ b/ohf-public-assets/main.tf @@ -0,0 +1,18 @@ +terraform { + cloud { + organization = "home_assistant" + + workspaces { + name = "ohf-public-assets" + } + } + + required_version = "= 1.10.0" + + required_providers { + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 4.0" + } + } +} diff --git a/ohf-public-assets/variables.tf b/ohf-public-assets/variables.tf new file mode 100644 index 0000000..29eee8e --- /dev/null +++ b/ohf-public-assets/variables.tf @@ -0,0 +1,4 @@ +variable "CLOUDFLARE_ACCOUNT_ID" { + description = "Cloudflare Account Id" + type = string +} 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..d96ff0e --- /dev/null +++ b/stun_server/main.tf @@ -0,0 +1,34 @@ +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" + image_tag = var.image_tag +} + +module "eu_central_1" { + source = "./region" + + region = "eu-central-1" + image_tag = var.image_tag +} + +module "ap_southeast_1" { + source = "./region" + + region = "ap-southeast-1" + image_tag = var.image_tag +} diff --git a/stun_server/outputs.tf b/stun_server/outputs.tf new file mode 100644 index 0000000..89e85a6 --- /dev/null +++ b/stun_server/outputs.tf @@ -0,0 +1,8 @@ +output "endpoints" { + description = "Endpoints of the Stun server" + value = { + "us-east-1" = module.us_east_1.stun_server_endpoint + "eu-central-1" = module.eu_central_1.stun_server_endpoint + "ap-southeast-1" = module.ap_southeast_1.stun_server_endpoint + } +} diff --git a/stun_server/region/ecs.tf b/stun_server/region/ecs.tf new file mode 100644 index 0000000..ac771ff --- /dev/null +++ b/stun_server/region/ecs.tf @@ -0,0 +1,51 @@ +resource "aws_ecs_service" "stun-server-tcp" { + name = "${local.service_name}-tcp" + cluster = local.infrastructure_region_outputs.ecs_cluster + task_definition = module.stun_server_tcp.task_definition + desired_count = 1 + deployment_minimum_healthy_percent = 100 + deployment_maximum_percent = 200 + launch_type = "FARGATE" + depends_on = [aws_lb_listener.stun_80, aws_lb_listener.stun_3478] + + network_configuration { + security_groups = [aws_security_group.stun_sg.id] + subnets = local.infrastructure_region_outputs.private_subnets + } + + load_balancer { + container_name = "${local.service_name}-tcp" + container_port = "3478" + target_group_arn = aws_lb_target_group.stun.arn + } + + tags = { + region = data.aws_region.current.name + } +} + +resource "aws_ecs_service" "stun-server-udp" { + name = "${local.service_name}-udp" + cluster = local.infrastructure_region_outputs.ecs_cluster + task_definition = module.stun_server_udp.task_definition + desired_count = 1 + deployment_minimum_healthy_percent = 100 + deployment_maximum_percent = 200 + launch_type = "FARGATE" + depends_on = [aws_lb_listener.stun_80, aws_lb_listener.stun_3478] + + network_configuration { + security_groups = [aws_security_group.stun_sg.id] + subnets = local.infrastructure_region_outputs.private_subnets + } + + load_balancer { + container_name = "${local.service_name}-udp" + container_port = "3478" + target_group_arn = aws_lb_target_group.stun.arn + } + + tags = { + region = data.aws_region.current.name + } +} diff --git a/stun_server/region/module.tf b/stun_server/region/module.tf new file mode 100644 index 0000000..dcf42bd --- /dev/null +++ b/stun_server/region/module.tf @@ -0,0 +1,57 @@ +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_tcp" { + source = "../../.modules/service" + + service_name = "${local.service_name}-tcp" + 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" + } + ], + } + webservice = true +} + +module "stun_server_udp" { + source = "../../.modules/service" + + service_name = "${local.service_name}-udp" + 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 = "udp" + } + ], + } + webservice = true +} diff --git a/stun_server/region/network.tf b/stun_server/region/network.tf new file mode 100644 index 0000000..5e76d4b --- /dev/null +++ b/stun_server/region/network.tf @@ -0,0 +1,98 @@ +resource "aws_security_group" "stun_sg" { + vpc_id = local.infrastructure_region_outputs.network_id + + tags = { + Region = data.aws_region.current.name + Zone = "public" + } +} + +resource "aws_vpc_security_group_egress_rule" "stun_sg_egress" { + security_group_id = aws_security_group.stun_sg.id + + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" +} + +resource "aws_vpc_security_group_ingress_rule" "stun_sg_ingress_tcp" { + security_group_id = aws_security_group.stun_sg.id + + from_port = 3478 + to_port = 3478 + ip_protocol = "tcp" + cidr_ipv4 = "0.0.0.0/0" +} + +resource "aws_vpc_security_group_ingress_rule" "stun_sg_ingress_udp" { + security_group_id = aws_security_group.stun_sg.id + + from_port = 3478 + to_port = 3478 + ip_protocol = "udp" + cidr_ipv4 = "0.0.0.0/0" +} + +resource "aws_lb" "main" { + name = local.service_name + internal = false + load_balancer_type = "network" + + subnets = local.infrastructure_region_outputs.public_subnets + + tags = { + Region = data.aws_region.current.name + Zone = "public" + } +} + +resource "aws_lb_listener" "stun_80" { + load_balancer_arn = aws_lb.main.arn + port = 80 + protocol = "TCP_UDP" + + default_action { + type = "forward" + target_group_arn = aws_lb_target_group.stun.arn + } + + depends_on = [ + aws_lb_target_group.stun, + aws_lb.main, + ] +} + +resource "aws_lb_listener" "stun_3478" { + load_balancer_arn = aws_lb.main.arn + port = 3478 + protocol = "TCP_UDP" + + default_action { + type = "forward" + target_group_arn = aws_lb_target_group.stun.arn + } + + depends_on = [ + aws_lb_target_group.stun, + aws_lb.main, + ] +} + +resource "aws_lb_target_group" "stun" { + port = 3478 + protocol = "TCP_UDP" + vpc_id = local.infrastructure_region_outputs.network_id + target_type = "ip" + deregistration_delay = 60 + + health_check { + protocol = "TCP" + interval = 10 + unhealthy_threshold = 2 + healthy_threshold = 2 + } + + tags = { + Region = data.aws_region.current.name + Zone = "public" + } +} diff --git a/stun_server/region/outputs.tf b/stun_server/region/outputs.tf new file mode 100644 index 0000000..4b8a672 --- /dev/null +++ b/stun_server/region/outputs.tf @@ -0,0 +1,4 @@ +output "stun_server_endpoint" { + description = "Endpoint of the Stun server" + value = aws_lb.main.dns_name +} diff --git a/stun_server/region/variables.tf b/stun_server/region/variables.tf new file mode 100644 index 0000000..fe4d51d --- /dev/null +++ b/stun_server/region/variables.tf @@ -0,0 +1,9 @@ +variable "region" { + description = "The region to deploy the STUN server to" + 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..f229e66 --- /dev/null +++ b/stun_server/variables.tf @@ -0,0 +1,4 @@ +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" + } + } +}