Free Preview

The Infrastructure Launch Kit gives technical founders everything they need to go from zero to a production-grade AWS deployment in a single afternoon. Instead of stitching together blog posts and out-of-date tutorials, you get 8 battle-tested deliverables covering networking, containers, load balancing, CI/CD, monitoring, and secrets management — all wired together and ready to terraform apply.

Below is one sample from the kit: the core main.tf Terraform configuration that provisions a VPC, ECS Fargate cluster, Application Load Balancer, and all supporting resources. The full kit includes parameterized modules, environment configs, and a step-by-step deployment guide.

Full Kit — 8 Deliverables Included

Terraform configs (VPC, ECS, ALB)
CI/CD pipeline (GitHub Actions)
Docker multi-stage Dockerfile
Secrets management setup (SSM)
CloudWatch monitoring & alarms
Auto-scaling policies
SSL/TLS certificate automation
Step-by-step deployment guide

Sample Deliverable

1 of 8

This Terraform configuration provisions the core infrastructure stack on AWS. It creates an isolated VPC with public and private subnets, an ECS Fargate cluster for running containers, an Application Load Balancer for traffic distribution, and the security groups to lock it all down.

main.tf
HCL / Terraform
 1# ============================================================
 2# Infrastructure Launch Kit — main.tf
 3# Production-grade AWS ECS Fargate with ALB
 4# Founder Stack © 2026
 5# ============================================================
 6
 7terraform {
 8  required_version = ">= 1.5.0"
 9
10  required_providers {
11    aws = {
12      source  = "hashicorp/aws"
13      version = "~> 5.30"
14    }
15  }
16
17  backend "s3" {
18    bucket         = "myapp-terraform-state"
19    key            = "prod/infrastructure.tfstate"
20    region         = "us-east-1"
21    encrypt        = true
22    dynamodb_table = "terraform-lock"
23  }
24}
25
26provider "aws" {
27  region = var.aws_region
28
29  default_tags {
30    tags = {
31      Project     = var.project_name
32      Environment = var.environment
33      ManagedBy   = "terraform"
34    }
35  }
36}
37
38# -----------------------------------------------
39# Variables
40# -----------------------------------------------
41
42variable "aws_region" {
43  description = "AWS region for all resources"
44  type        = string
45  default     = "us-east-1"
46}
47
48variable "project_name" {
49  description = "Name prefix for all resources"
50  type        = string
51  default     = "myapp"
52}
53
54variable "environment" {
55  description = "Deployment environment (prod, staging, dev)"
56  type        = string
57  default     = "prod"
58}
59
60variable "container_port" {
61  description = "Port the container listens on"
62  type        = number
63  default     = 3000
64}
65
66variable "container_image" {
67  description = "Docker image URI (ECR or Docker Hub)"
68  type        = string
69}
70
71# -----------------------------------------------
72# Data Sources
73# -----------------------------------------------
74
75data "aws_availability_zones" "available" {
76  state = "available"
77}
78
79# -----------------------------------------------
80# VPC & Networking
81# -----------------------------------------------
82
83resource "aws_vpc" "main" {
84  cidr_block           = "10.0.0.0/16"
85  enable_dns_hostnames = true
86  enable_dns_support   = true
87
88  tags = {
89    Name = "${var.project_name}-${var.environment}-vpc"
90  }
91}
92
93resource "aws_subnet" "public" {
94  count                   = 2
95  vpc_id                  = aws_vpc.main.id
96  cidr_block              = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
97  availability_zone       = data.aws_availability_zones.available.names[count.index]
98  map_public_ip_on_launch = true
99
100  tags = {
101    Name = "${var.project_name}-public-${count.index + 1}"
102  }
103}
104
105resource "aws_subnet" "private" {
106  count             = 2
107  vpc_id            = aws_vpc.main.id
108  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 10)
109  availability_zone = data.aws_availability_zones.available.names[count.index]
110
111  tags = {
112    Name = "${var.project_name}-private-${count.index + 1}"
113  }
114}
115
116resource "aws_internet_gateway" "main" {
117  vpc_id = aws_vpc.main.id
118
119  tags = {
120    Name = "${var.project_name}-igw"
121  }
122}
123
124resource "aws_route_table" "public" {
125  vpc_id = aws_vpc.main.id
126
127  route {
128    cidr_block = "0.0.0.0/0"
129    gateway_id = aws_internet_gateway.main.id
130  }
131
132  tags = {
133    Name = "${var.project_name}-public-rt"
134  }
135}
136
137resource "aws_route_table_association" "public" {
138  count          = 2
139  subnet_id      = aws_subnet.public[count.index].id
140  route_table_id = aws_route_table.public.id
141}
142
143# -----------------------------------------------
144# Security Groups
145# -----------------------------------------------
146
147resource "aws_security_group" "alb" {
148  name        = "${var.project_name}-alb-sg"
149  description = "Allow inbound HTTP/HTTPS to ALB"
150  vpc_id      = aws_vpc.main.id
151
152  ingress {
153    description = "HTTP"
154    from_port   = 80
155    to_port     = 80
156    protocol    = "tcp"
157    cidr_blocks = ["0.0.0.0/0"]
158  }
159
160  ingress {
161    description = "HTTPS"
162    from_port   = 443
163    to_port     = 443
164    protocol    = "tcp"
165    cidr_blocks = ["0.0.0.0/0"]
166  }
167
168  egress {
169    from_port   = 0
170    to_port     = 0
171    protocol    = "-1"
172    cidr_blocks = ["0.0.0.0/0"]
173  }
174
175  tags = {
176    Name = "${var.project_name}-alb-sg"
177  }
178}
179
180resource "aws_security_group" "ecs_tasks" {
181  name        = "${var.project_name}-ecs-tasks-sg"
182  description = "Allow inbound from ALB only"
183  vpc_id      = aws_vpc.main.id
184
185  ingress {
186    description     = "Allow traffic from ALB"
187    from_port       = var.container_port
188    to_port         = var.container_port
189    protocol        = "tcp"
190    security_groups = [aws_security_group.alb.id]
191  }
192
193  egress {
194    from_port   = 0
195    to_port     = 0
196    protocol    = "-1"
197    cidr_blocks = ["0.0.0.0/0"]
198  }
199
200  tags = {
201    Name = "${var.project_name}-ecs-tasks-sg"
202  }
203}
204
205# -----------------------------------------------
206# Application Load Balancer
207# -----------------------------------------------
208
209resource "aws_lb" "main" {
210  name               = "${var.project_name}-alb"
211  internal           = false
212  load_balancer_type = "application"
213  security_groups    = [aws_security_group.alb.id]
214  subnets            = aws_subnet.public[*].id
215
216  enable_deletion_protection = false
217
218  tags = {
219    Name = "${var.project_name}-alb"
220  }
221}
222
223resource "aws_lb_target_group" "app" {
224  name        = "${var.project_name}-tg"
225  port        = var.container_port
226  protocol    = "HTTP"
227  vpc_id      = aws_vpc.main.id
228  target_type = "ip"
229
230  health_check {
231    enabled             = true
232    healthy_threshold   = 3
233    unhealthy_threshold = 3
234    timeout             = 10
235    interval            = 30
236    path                = "/health"
237    protocol            = "HTTP"
238    matcher             = "200"
239  }
240}
241
242resource "aws_lb_listener" "http" {
243  load_balancer_arn = aws_lb.main.arn
244  port             = 80
245  protocol         = "HTTP"
246
247  default_action {
248    type             = "forward"
249    target_group_arn = aws_lb_target_group.app.arn
250  }
251}
252
253# -----------------------------------------------
254# ECS Cluster & Fargate Service
255# -----------------------------------------------
256
257resource "aws_ecs_cluster" "main" {
258  name = "${var.project_name}-${var.environment}"
259
260  setting {
261    name  = "containerInsights"
262    value = "enabled"
263  }
264}
265
266resource "aws_ecs_task_definition" "app" {
267  family                   = "${var.project_name}-app"
268  network_mode             = "awsvpc"
269  requires_compatibilities = ["FARGATE"]
270  cpu                      = "512"
271  memory                   = "1024"
272  execution_role_arn       = aws_iam_role.ecs_execution.arn
273  task_role_arn            = aws_iam_role.ecs_task.arn
274
275  container_definitions = jsonencode([{
276    name      = "app"
277    image     = var.container_image
278    essential = true
279
280    portMappings = [{
281      containerPort = var.container_port
282      protocol      = "tcp"
283    }]
284
285    logConfiguration = {
286      logDriver = "awslogs"
287      options   = {
288        "awslogs-group"         = aws_cloudwatch_log_group.app.name
289        "awslogs-region"        = var.aws_region
290        "awslogs-stream-prefix" = "ecs"
291      }
292    }
293
294    environment = [
295      { name = "NODE_ENV",    value = var.environment },
296      { name = "PORT",        value = tostring(var.container_port) },
297    ]
298  }])
299}
300
301resource "aws_cloudwatch_log_group" "app" {
302  name              = "/ecs/${var.project_name}"
303  retention_in_days = 30
304}
305
306resource "aws_ecs_service" "app" {
307  name            = "${var.project_name}-service"
308  cluster         = aws_ecs_cluster.main.id
309  task_definition = aws_ecs_task_definition.app.arn
310  desired_count   = 2
311  launch_type     = "FARGATE"
312
313  network_configuration {
314    subnets          = aws_subnet.private[*].id
315    security_groups  = [aws_security_group.ecs_tasks.id]
316    assign_public_ip = false
317  }
318
319  load_balancer {
320    target_group_arn = aws_lb_target_group.app.arn
321    container_name  = "app"
322    container_port  = var.container_port
323  }
324
325  depends_on = [aws_lb_listener.http]
326}
327
328# -----------------------------------------------
329# IAM Roles for ECS
330# -----------------------------------------------
331
332resource "aws_iam_role" "ecs_execution" {
333  name = "${var.project_name}-ecs-execution-role"
334
335  assume_role_policy = jsonencode({
336    Version = "2012-10-17"
337    Statement = [{
338      Action    = "sts:AssumeRole"
339      Effect    = "Allow"
340      Principal = { Service = "ecs-tasks.amazonaws.com" }
341    }]
342  })
343}
344
345resource "aws_iam_role_policy_attachment" "ecs_execution" {
346  role       = aws_iam_role.ecs_execution.name
347  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
348}
349
350resource "aws_iam_role" "ecs_task" {
351  name = "${var.project_name}-ecs-task-role"
352
353  assume_role_policy = jsonencode({
354    Version = "2012-10-17"
355    Statement = [{
356      Action    = "sts:AssumeRole"
357      Effect    = "Allow"
358      Principal = { Service = "ecs-tasks.amazonaws.com" }
359    }]
360  })
361}
362
363# -----------------------------------------------
364# Outputs
365# -----------------------------------------------
366
367output "alb_dns_name" {
368  description = "DNS name of the Application Load Balancer"
369  value       = aws_lb.main.dns_name
370}
371
372output "ecs_cluster_name" {
373  description = "Name of the ECS cluster"
374  value       = aws_ecs_cluster.main.name
375}
376
377output "ecs_service_name" {
378  description = "Name of the ECS service"
379  value       = aws_ecs_service.app.name
380}
381
382output "vpc_id" {
383  description = "ID of the VPC"
384  value       = aws_vpc.main.id
385}

Ready to ship your infrastructure?

Get all 8 production-ready deliverables. Stop guessing at AWS configs
and deploy with confidence on day one.

Get the full Infrastructure Launch Kit — $49 One-time purchase. Instant download. Lifetime updates.

Production-Ready

Battle-tested configs used in real SaaS deployments, not toy examples.

Deploy in Hours

Step-by-step guide takes you from zero to production in one afternoon.

Security-First

Proper VPC isolation, least-privilege IAM, and encrypted state management.