-
-
Notifications
You must be signed in to change notification settings - Fork 213
Feature/iac scaffolding : Foundational Network Module #2310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ional structure and documentation for the new Terraform-based IaC
In this commit I introduced the initial, production-grade Terraform module for the core AWS network infrastructure. Key features of this module include: - Creates a new VPC with public and private subnets across multiple Availability Zones for high availability. - Implements a single, cost-effective, and resilient NAT Gateway for private subnet egress. - Provisions a public Application Load Balancer (ALB) with a secure default configuration and an HTTPS redirect. - Establishes a secure-by-default posture with a locked-down ALB security group.
Summary by CodeRabbit
WalkthroughAdds a Terraform network module (VPC, subnets, NAT, ALB with HTTP→HTTPS redirect and HTTPS listener), its variables and outputs. Introduces an operational guide for Terraform workflows. Updates pre-commit config to include Terraform format/validate/lint/security scanning hooks. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (6)
.pre-commit-config.yaml (1)
90-100
: Add terraform_docs and prefer types-based matching over regex.
- Add the terraform_docs hook to keep variables/outputs documented and in sync.
- Prefer types_or: [terraform] over files regex to catch all Terraform sources consistently (including nested paths).
Apply this diff:
- repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.92.0 + rev: v1.92.0 hooks: + - id: terraform_docs + args: + - --hook-config=--create-file-if-not-exist=true - id: terraform_fmt - files: \.tf$ + types_or: + - terraform - id: terraform_validate - files: \.tf$ + types_or: + - terraform - id: terraform_tflint - files: \.tf$ + types_or: + - terraform - id: terraform_trivy - files: \.tf$ + types_or: + - terraformTerraform/Operational-Guide.md (1)
18-21
: Fix module path to match repository structure.Doc lists modules/network but the added code resides under modules/01-Network. Align the path or rename for consistency.
Terraform/modules/01-Network/variables.tf (3)
19-23
: Validate vpc_cidr format.Add a simple CIDR validation to catch typos early.
variable "vpc_cidr" { description = "The CIDR block for the VPC." type = string default = "10.0.0.0/16" + validation { + condition = can(cidrhost(var.vpc_cidr, 0)) + error_message = "vpc_cidr must be a valid IPv4 CIDR block." + } }
25-28
: Ensure at least one AZ provided.Add length check to avoid empty lists.
variable "availability_zones" { description = "A list of Availability Zones to deploy resources into. Must match the number of subnets. e.g., [\"us-east-1a\", \"us-east-1b\"]" type = list(string) + validation { + condition = length(var.availability_zones) > 0 + error_message = "At least one availability zone must be provided." + } }
48-52
: Optionally add a toggle for per‑AZ NAT gateways.Expose a boolean to support HA NAT as an opt-in later.
variable "enable_multi_az_nat_gateways" { description = "If true, create a NAT Gateway in each public subnet (higher availability, higher cost)." type = bool default = false }Terraform/modules/01-Network/main.tf (1)
65-73
: Allocate the EIP in VPC scope explicitly.Set domain = "vpc" to ensure correct allocation context for the NAT.
resource "aws_eip" "nat" { - # Only one EIP is needed for the single NAT Gateway. + domain = "vpc" # Ensure EIP is allocated in the VPC scope + # Only one EIP is needed for the single NAT Gateway. tags = merge(
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.pre-commit-config.yaml
(1 hunks)Terraform/Operational-Guide.md
(1 hunks)Terraform/modules/01-Network/main.tf
(1 hunks)Terraform/modules/01-Network/outputs.tf
(1 hunks)Terraform/modules/01-Network/variables.tf
(1 hunks)
🧰 Additional context used
🪛 Checkov (3.2.334)
Terraform/modules/01-Network/main.tf
[medium] 179-195: Ensure that ALB drops HTTP headers
(CKV_AWS_131)
[high] 212-227: Ensure that load balancer is using at least TLS 1.2
(CKV_AWS_103)
🔇 Additional comments (1)
Terraform/modules/01-Network/outputs.tf (1)
1-29
: Outputs look good.Clear and minimal set to enable composition by downstream modules.
resource "aws_eip" "nat" { | ||
# Only one EIP is needed for the single NAT Gateway. | ||
tags = merge( | ||
var.tags, | ||
{ | ||
Name = "${var.project_prefix}-${var.environment}-nat-eip" | ||
} | ||
) | ||
} | ||
|
||
resource "aws_nat_gateway" "main" { | ||
# Only one NAT Gateway, placed in the first public subnet for simplicity. | ||
# As AWS automatically handles failover at the infrastructure level. | ||
allocation_id = aws_eip.nat.id | ||
subnet_id = aws_subnet.public[0].id | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix misleading NAT failover comment and note SPOF risk.
AWS does not auto-failover a single NAT Gateway across AZs; placing it in one AZ is an egress SPOF for all private subnets if that AZ or the NAT fails. Keep single NAT if cost-optimized, but document the trade-off (or add an opt-in for per‑AZ NAT).
Apply this diff to correct the comment:
resource "aws_nat_gateway" "main" {
- # Only one NAT Gateway, placed in the first public subnet for simplicity.
- # As AWS automatically handles failover at the infrastructure level.
+ # Cost-optimized: a single NAT Gateway in the first public subnet.
+ # NOTE: This is a single-AZ SPOF for egress. Consider a per-AZ NAT option for higher availability.
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public[0].id
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
resource "aws_eip" "nat" { | |
# Only one EIP is needed for the single NAT Gateway. | |
tags = merge( | |
var.tags, | |
{ | |
Name = "${var.project_prefix}-${var.environment}-nat-eip" | |
} | |
) | |
} | |
resource "aws_nat_gateway" "main" { | |
# Only one NAT Gateway, placed in the first public subnet for simplicity. | |
# As AWS automatically handles failover at the infrastructure level. | |
allocation_id = aws_eip.nat.id | |
subnet_id = aws_subnet.public[0].id | |
resource "aws_eip" "nat" { | |
# Only one EIP is needed for the single NAT Gateway. | |
tags = merge( | |
var.tags, | |
{ | |
Name = "${var.project_prefix}-${var.environment}-nat-eip" | |
} | |
) | |
} | |
resource "aws_nat_gateway" "main" { | |
# Cost-optimized: a single NAT Gateway in the first public subnet. | |
# NOTE: This is a single-AZ SPOF for egress. Consider a per-AZ NAT option for higher availability. | |
allocation_id = aws_eip.nat.id | |
subnet_id = aws_subnet.public[0].id |
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 65 to 80, the existing
comment wrongly implies AWS auto-fails over a single NAT Gateway; update the
comment to state that a single NAT Gateway is placed in the first public subnet
and that AWS does not provide cross‑AZ automatic failover, making this an egress
single point of failure for private subnets in that AZ; then either document
this trade‑off (cost vs availability) and suggest adding an opt‑in variable to
create per‑AZ NAT Gateways for high availability.
resource "aws_lb" "main" { | ||
name = "${var.project_prefix}-${var.environment}-alb" | ||
internal = false | ||
load_balancer_type = "application" | ||
security_groups = [aws_security_group.alb.id] | ||
subnets = aws_subnet.public[*].id | ||
|
||
# Deletion protection should be enabled via a variable for production. | ||
enable_deletion_protection = var.environment == "prod" ? true : false | ||
|
||
tags = merge( | ||
var.tags, | ||
{ | ||
Name = "${var.project_prefix}-${var.environment}-alb" | ||
} | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Harden ALB: drop invalid headers.
Satisfies CKV_AWS_131 and improves security posture.
resource "aws_lb" "main" {
name = "${var.project_prefix}-${var.environment}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
+ drop_invalid_header_fields = true
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
resource "aws_lb" "main" { | |
name = "${var.project_prefix}-${var.environment}-alb" | |
internal = false | |
load_balancer_type = "application" | |
security_groups = [aws_security_group.alb.id] | |
subnets = aws_subnet.public[*].id | |
# Deletion protection should be enabled via a variable for production. | |
enable_deletion_protection = var.environment == "prod" ? true : false | |
tags = merge( | |
var.tags, | |
{ | |
Name = "${var.project_prefix}-${var.environment}-alb" | |
} | |
) | |
} | |
resource "aws_lb" "main" { | |
name = "${var.project_prefix}-${var.environment}-alb" | |
internal = false | |
load_balancer_type = "application" | |
security_groups = [aws_security_group.alb.id] | |
subnets = aws_subnet.public[*].id | |
drop_invalid_header_fields = true | |
# Deletion protection should be enabled via a variable for production. | |
enable_deletion_protection = var.environment == "prod" ? true : false | |
tags = merge( | |
var.tags, | |
{ | |
Name = "${var.project_prefix}-${var.environment}-alb" | |
} | |
) | |
} |
🧰 Tools
🪛 Checkov (3.2.334)
[medium] 179-195: Ensure that ALB drops HTTP headers
(CKV_AWS_131)
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 179 to 195, the ALB
resource needs the HTTP attribute to drop invalid headers to satisfy
CKV_AWS_131; add a load_balancer_attributes block to aws_lb.main with the
attribute "routing.http.drop_invalid_header_fields.enabled" set to "true" (as a
string) so the ALB will drop invalid header fields, keeping existing fields and
tags unchanged.
resource "aws_lb_listener" "https" { | ||
load_balancer_arn = aws_lb.main.arn | ||
port = 443 | ||
protocol = "HTTPS" | ||
ssl_policy = "ELBSecurityPolicy-2016-08" | ||
certificate_arn = var.acm_certificate_arn | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enforce TLS 1.2+ on HTTPS listener.
Current policy ELBSecurityPolicy-2016-08 allows TLS 1.0/1.1. Use a TLS 1.2/1.3 policy (e.g., TLS13-1-2-2021-06).
- ssl_policy = "ELBSecurityPolicy-2016-08"
+ ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
resource "aws_lb_listener" "https" { | |
load_balancer_arn = aws_lb.main.arn | |
port = 443 | |
protocol = "HTTPS" | |
ssl_policy = "ELBSecurityPolicy-2016-08" | |
certificate_arn = var.acm_certificate_arn | |
resource "aws_lb_listener" "https" { | |
load_balancer_arn = aws_lb.main.arn | |
port = 443 | |
protocol = "HTTPS" | |
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06" | |
certificate_arn = var.acm_certificate_arn |
🧰 Tools
🪛 Checkov (3.2.334)
[high] 212-227: Ensure that load balancer is using at least TLS 1.2
(CKV_AWS_103)
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 212 to 218, the
aws_lb_listener uses ssl_policy "ELBSecurityPolicy-2016-08" which permits TLS
1.0/1.1; update the ssl_policy to a modern TLS 1.2+ policy such as
"TLS13-1-2-2021-06" (or another AWS-managed TLS1.2/1.3 policy) to enforce TLS
1.2+; optionally make the policy configurable via a variable (e.g.,
var.ssl_policy with a sensible default) and validate that the ACM certificate
supports the chosen policy.
variable "public_subnet_cidrs" { | ||
description = "A list of CIDR blocks for the public subnets. The number of CIDRs must match the number of availability_zones." | ||
type = list(string) | ||
validation { | ||
condition = length(var.public_subnet_cidrs) > 0 | ||
error_message = "At least one public subnet CIDR must be provided." | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Validate count matches availability_zones for public subnets.
Prevent index-out-of-range errors when AZs and CIDRs differ.
validation {
- condition = length(var.public_subnet_cidrs) > 0
- error_message = "At least one public subnet CIDR must be provided."
+ condition = length(var.public_subnet_cidrs) > 0 && length(var.public_subnet_cidrs) == length(var.availability_zones)
+ error_message = "Provide at least one public subnet CIDR, and ensure its count matches availability_zones."
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
variable "public_subnet_cidrs" { | |
description = "A list of CIDR blocks for the public subnets. The number of CIDRs must match the number of availability_zones." | |
type = list(string) | |
validation { | |
condition = length(var.public_subnet_cidrs) > 0 | |
error_message = "At least one public subnet CIDR must be provided." | |
} | |
} | |
variable "public_subnet_cidrs" { | |
description = "A list of CIDR blocks for the public subnets. The number of CIDRs must match the number of availability_zones." | |
type = list(string) | |
validation { | |
condition = length(var.public_subnet_cidrs) > 0 && length(var.public_subnet_cidrs) == length(var.availability_zones) | |
error_message = "Provide at least one public subnet CIDR, and ensure its count matches availability_zones." | |
} | |
} |
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/variables.tf around lines 30 to 37, the
validation for public_subnet_cidrs only checks for non-empty list but must also
ensure the number of CIDRs matches the number of availability_zones to avoid
index-out-of-range errors; update the validation.condition to require
length(var.public_subnet_cidrs) == length(var.availability_zones) (or explicitly
compare to var.availability_zones length expression used in this module) and
change the validation.error_message to something like "public_subnet_cidrs must
have the same number of entries as availability_zones."
variable "private_subnet_cidrs" { | ||
description = "A list of CIDR blocks for the private subnets. The number of CIDRs must match the number of availability_zones." | ||
type = list(string) | ||
validation { | ||
condition = length(var.private_subnet_cidrs) > 0 | ||
error_message = "At least one private subnet CIDR must be provided." | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Validate count matches availability_zones for private subnets.
Same rationale as public subnets.
validation {
- condition = length(var.private_subnet_cidrs) > 0
- error_message = "At least one private subnet CIDR must be provided."
+ condition = length(var.private_subnet_cidrs) > 0 && length(var.private_subnet_cidrs) == length(var.availability_zones)
+ error_message = "Provide at least one private subnet CIDR, and ensure its count matches availability_zones."
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
variable "private_subnet_cidrs" { | |
description = "A list of CIDR blocks for the private subnets. The number of CIDRs must match the number of availability_zones." | |
type = list(string) | |
validation { | |
condition = length(var.private_subnet_cidrs) > 0 | |
error_message = "At least one private subnet CIDR must be provided." | |
} | |
} | |
variable "private_subnet_cidrs" { | |
description = "A list of CIDR blocks for the private subnets. The number of CIDRs must match the number of availability_zones." | |
type = list(string) | |
validation { | |
condition = length(var.private_subnet_cidrs) > 0 && length(var.private_subnet_cidrs) == length(var.availability_zones) | |
error_message = "Provide at least one private subnet CIDR, and ensure its count matches availability_zones." | |
} | |
} |
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/variables.tf around lines 39 to 46, the variable
private_subnet_cidrs currently only validates that at least one CIDR is
provided; add a validation to ensure the number of CIDRs equals the number of
availability_zones (same as public subnets) by updating the validation block to
check length(var.private_subnet_cidrs) == length(var.availability_zones) and
provide an appropriate error_message indicating the counts must match.
aws s3api create-bucket \ | ||
--bucket ${TF_STATE_BUCKET} \ | ||
--region ${AWS_REGION} \ | ||
--create-bucket-configuration LocationConstraint=${AWS_REGION} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle us-east-1 S3 create-bucket special case.
In us-east-1, omit --create-bucket-configuration; otherwise the command fails.
Suggested note:
-aws s3api create-bucket \
- --bucket ${TF_STATE_BUCKET} \
- --region ${AWS_REGION} \
- --create-bucket-configuration LocationConstraint=${AWS_REGION}
+if [ "${AWS_REGION}" = "us-east-1" ]; then
+ aws s3api create-bucket --bucket "${TF_STATE_BUCKET}" --region "${AWS_REGION}"
+else
+ aws s3api create-bucket \
+ --bucket "${TF_STATE_BUCKET}" \
+ --region "${AWS_REGION}" \
+ --create-bucket-configuration LocationConstraint=${AWS_REGION}
+fi
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
aws s3api create-bucket \ | |
--bucket ${TF_STATE_BUCKET} \ | |
--region ${AWS_REGION} \ | |
--create-bucket-configuration LocationConstraint=${AWS_REGION} | |
if [ "${AWS_REGION}" = "us-east-1" ]; then | |
aws s3api create-bucket --bucket "${TF_STATE_BUCKET}" --region "${AWS_REGION}" | |
else | |
aws s3api create-bucket \ | |
--bucket "${TF_STATE_BUCKET}" \ | |
--region "${AWS_REGION}" \ | |
--create-bucket-configuration LocationConstraint=${AWS_REGION} | |
fi |
🤖 Prompt for AI Agents
In Terraform/Operational-Guide.md around lines 49 to 53, the S3 create-bucket
example always includes the --create-bucket-configuration flag which breaks in
us-east-1; update the guidance to mention the us-east-1 special case and show
two variants (one with --create-bucket-configuration for other regions and one
without it for us-east-1) or explain to conditionally omit that flag when
AWS_REGION is us-east-1.
aws s3api put-bucket-versioning \ | ||
--bucket ${TF_STATE_BUCKET} \ | ||
--versioning-configuration Status=Enabled | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enable encryption and block public access on the state bucket.
Add SSE and public access block to meet security best practices for Terraform state.
Add after versioning:
aws s3api put-public-access-block \
--bucket "${TF_STATE_BUCKET}" \
--public-access-block-configuration 'BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true'
aws s3api put-bucket-encryption \
--bucket "${TF_STATE_BUCKET}" \
--server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
🤖 Prompt for AI Agents
In Terraform/Operational-Guide.md around lines 54 to 57, the state bucket
configuration only enables versioning but omits public access blocking and
server-side encryption; update the guide to add commands after the versioning
block that call aws s3api put-public-access-block with BlockPublicAcls=true,
IgnorePublicAcls=true, BlockPublicPolicy=true, RestrictPublicBuckets=true for
the TF_STATE_BUCKET and then call aws s3api put-bucket-encryption to enable
server-side encryption (AES256) for the same bucket so the state bucket is
encrypted and not publicly accessible.
cd terraform/environments/dev | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify environment directory path/casing.
Doc uses terraform/environments/dev, while repo paths appear under Terraform/. Ensure the path exists and matches case-sensitive filesystems.
🏁 Script executed:
#!/bin/bash
# Discover environment and module paths (case-insensitive) in repo
fd -i -t d '^environments$' -d 4
fd -i -t d '01-Network' -d 6
Length of output: 53
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Listing Terraform/environments =="
ls -la Terraform/environments || true
echo
echo "== Searching for 'dev' directories under Terraform =="
fd -t d -i dev Terraform -d 4 || true
echo
echo "== Showing Operational-Guide.md around lines 100-120 =="
sed -n '100,120p' Terraform/Operational-Guide.md || true
Length of output: 991
Fix path casing and missing dev
environment in docs
Terraform/Operational-Guide.md (lines 111–113) shows cd terraform/environments/dev
, but the repo has Terraform/environments/
(only .gitkeep
— no dev
directory). Update the doc to use the correct path/casing (e.g., cd Terraform/environments/<env>
) and either document creating the environment directory or add Terraform/environments/dev/
to the repo.
🤖 Prompt for AI Agents
In Terraform/Operational-Guide.md around lines 111 to 113, the documented path
uses the wrong casing and references a non-existent dev directory; update the
path to use the actual repo casing and a placeholder (e.g., cd
Terraform/environments/<env>) and either add a short step that instructs users
to create the environment directory (mkdir -p Terraform/environments/dev &&
touch Terraform/environments/dev/.gitkeep) or add Terraform/environments/dev/ to
the repository so the example works as written; ensure the text matches the
repository layout and casing consistently.
I'm reviewing all the suggestions now and will push up a new commit with the fixes shortly. |
|
Proposed change
This is the first major PR for the IaC PoC as discussed in Resolves #2215. It establishes the foundational, production-grade network infrastructure for the Nest application on AWS.
This PR introduces the first reusable Terraform module:
modules/01-Network
.Key Architectural Features:
variables.tf
andoutputs.tf
) and is ready to be consumed by other modules (likecompute
anddatabase
).Next Steps:
Once this foundational network is approved and merged, I will proceed with the
database
andstorage
modules as planned.Looking forward to your feedback!
Checklist
make check-test
locally; all checks and tests passed.