Desafio 01: VPC + Subnet Pública (Formação AWS Mai/2026)
Como criar uma VPC customizada do zero com Terraform, lançar a aplicação BIA numa EC2 em subnet pública e acessar via SSM, sem abrir a porta 22.
Fonte original: https://hotmart.com/pt-br/club/formacaoaws
// ÍNDICE ▾
TL;DR
Implementei o Desafio 01 (VPC + Subnet Pública) da Mentoria Desafio Labs 2.0 (Formação AWS 5.0, Mai/2026) usando Terraform + módulos reutilizáveis, com 7 tags Well-Architected em todos os recursos, diagrama profissional gerado por código (lib diagrams) e acesso à EC2 via SSM Session Manager, sem expor a porta 22.
Contexto
A trilha de Conectividade e Redes na AWS (Maio/2026) da Formação AWS 5.0 é composta por 6 desafios progressivos. O primeiro é o mais fundamental: entender como a VPC funciona de verdade, criando uma do zero em vez de depender da VPC default que a AWS provisiona automaticamente em toda conta nova.
O objetivo é simples de enunciar, mas cheio de detalhes: criar uma VPC customizada com 2 subnets públicas em AZs diferentes, um Internet Gateway, uma Route Table associada, e lançar a aplicação BIA (Node.js + React + PostgreSQL em Docker) numa EC2 acessível publicamente.
Parece básico. Mas é aqui que a maioria dos engenheiros tem lacunas: “por que preciso de um IGW?”, “qual a diferença entre subnet pública e privada?”, “para que serve a route table?”. Este desafio responde tudo isso na prática.
Arquitetura Adotada
A topologia é intencionalmente simples para este primeiro desafio:
- VPC
desafio-01, CIDR 10.0.0.0/16, DNS habilitado - 2 Subnets públicas, 10.0.1.0/24 (us-east-1a) e 10.0.2.0/24 (us-east-1b)
- Internet Gateway, ponto de entrada/saída da VPC para a internet
- Route Table, rota
0.0.0.0/0 → IGWassociada às duas subnets - EC2 bia-dev, t3.micro em us-east-1a com IP público automático
- Security Group, portas 80 e 3001 abertas; porta 22 propositalmente fechada
Decisões Técnicas
ADR-001: Módulo shared/modules/vpc para toda a rede
Em vez de escrever cada recurso de VPC individualmente, usei o módulo reutilizável do monorepo. Toda a camada de rede (VPC + subnets + IGW + route table + associations) se resume a isso no main.tf:
module "vpc" {
source = "../../shared/modules/vpc"
name = "desafio-01"
cidr_block = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = []
tags = local.common_tags
}
O mesmo módulo será reusado nos 5 desafios seguintes sem modificação.
ADR-002: SG bia-dev recriado na nova VPC
Security Groups são VPC-específicos. Mesmo que exista um SG chamado “bia-dev” em outra VPC, ele não pode ser associado a uma instância na nova VPC. A solução é criar um novo SG com as mesmas regras na VPC correta. O IAM Instance Profile (role-acesso-ssm), por ser global, foi referenciado via data source sem precisar recriar:
data "aws_iam_instance_profile" "ssm" {
name = "role-acesso-ssm"
}
ADR-005: Acesso via SSM, sem porta 22
Com o IAM Instance Profile role-acesso-ssm (que carrega AmazonSSMManagedInstanceCore) e IMDSv2 habilitado, o acesso à instância é feito assim:
aws ssm start-session --target i-0ef9363c5f4d0b985 --region us-east-1
Sem chave .pem no terminal. Sem porta 22 aberta. Tudo auditado pelo CloudTrail.
Implementação em IaC
Estrutura modular do terraform/ deste desafio:
terraform/
├── providers.tf # provider aws com default_tags
├── versions.tf # terraform >= 1.5, aws ~> 5.0
├── locals.tf # common_tags (7 tags Well-Architected)
├── variables.tf # region, challenge_number, ec2_ami, ec2_instance_type
├── data.tf # data sources: AMI AL2023 + IAM profile existente
├── main.tf # module "vpc"
├── ec2.tf # aws_security_group + aws_instance
└── outputs.tf # vpc_id, ec2_public_ip, ssm_connect_cmd, bia_url
O bootstrap da EC2 via user_data instala Docker, clona BIA e sobe os containers:
git clone https://github.com/nilo-lima/bia.git /opt/bia
# Obtém IP público via IMDSv2
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
PUBLIC_IP=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/public-ipv4)
echo "VITE_API_URL=http://${PUBLIC_IP}:3001" > /opt/bia/.env
docker-compose -f /opt/bia/compose.yml up -d
Validação & Custos
Smoke tests executados
| Teste | Resultado |
|---|---|
aws ssm start-session --target i-0ef9363... | ✅ Sessão aberta |
curl http://3.235.128.30:3001 (do PC) | ✅ HTTP 200 |
curl http://3.235.128.30:3001 (da EC2) | ✅ HTTP 200 |
docker ps na instância | ✅ bia-server + postgres:17.1 running |
git -C /opt/bia remote -v | ✅ nilo-lima/bia.git confirmado |
terraform plan pós-apply | ✅ No changes |
Custos reais
| Serviço | Custo USD | Período |
|---|---|---|
| EC2 t3.micro | ~$0.02 | ~2h de execução |
| EBS gp3 20 GB | ~$0.002 | ~2h de execução |
| Transferência | < $0.01 | smoke tests |
| NAT Gateway | $0.00 | Não usado |
| Total | ~$0.03 | sessão única |
Aprendizados-chave
-
Security Groups são VPC-específicos, erro comum de quem vem da VPC default é tentar reutilizar um SG existente em uma nova VPC. Não funciona.
-
IMDSv2 é o padrão correto para acessar metadados, o token com TTL protege contra ataques SSRF que tentam roubar credenciais da EC2 pelo endpoint 169.254.169.254.
-
SSM elimina a necessidade de gerenciar chaves SSH, com o IAM role correto,
aws ssm start-sessioné mais seguro, auditável e conveniente que SSH tradicional. -
Módulos Terraform reduzem erro humano, o módulo
shared/modules/vpcgarante que todos os 6 desafios usem a mesma lógica de rede, testada e padronizada.
Próximos Passos
O Desafio 02 sobe a aposta: a mesma aplicação BIA em ECS Fargate Multi-AZ com um ALB distribuindo carga entre as duas AZs. Saímos de 9 recursos para ~25, e de EC2 para containers gerenciados.
Repositório
Código completo: github.com/nilo-lima/formacao-aws-desafios-conectividade-redes-aws
Este post é parte da série Formação AWS 5.0, Desafio Labs 2.0. Mentor: Henrylle Maia.
// Relacionados