Guia de implantação do AWS EC2 para aplicativos da Web
O EC2 continua sendo a opção de computação mais flexível na AWS para aplicações web que precisam de desempenho consistente, pilhas de software personalizadas e preços previsíveis. Embora ECS, EKS e Lambda recebam mais atenção no mundo nativo da nuvem, o EC2 oferece um servidor que você controla completamente — sem complexidade de orquestração de contêineres, sem latência de inicialização a frio, sem custos de invocação surpresa.
Este guia aborda a implantação de um aplicativo web Node.js de produção no EC2: seleção de instância, configuração de grupo de segurança, implantação de aplicativo, proxy reverso Nginx, SSL com Cloudflare, monitoramento com CloudWatch e os padrões de manutenção contínua que mantêm uma implantação EC2 saudável.
Principais conclusões
- t3.large é o ponto de partida certo para uma implantação full-stack de Node.js + PostgreSQL
- Use Ubuntu 24.04 LTS — com suporte até 2029, amplamente documentado, excelente disponibilidade de pacotes
- Elastic IP é obrigatório — seu IP do EC2 muda a cada parada/início sem ele
- Os grupos de segurança têm estado — você só precisa de regras de entrada; a saída normalmente é permitida para todos
- Armazene sua chave SSH de implantação em um arquivo
.pemseparado; nunca comprometa com o git- Use conexão de instância EC2 ou Session Manager em vez de SSH direto quando possível (gerenciamento de chave zero)
- O agente CloudWatch fornece métricas de memória e disco (não disponíveis por padrão)
- Instâncias reservadas ou planos de economia reduzem os custos do EC2 em 40-60% em comparação com sob demanda
Seleção de instância
O tipo de instância correto depende da sua carga de trabalho:
| Carga de trabalho | Instância recomendada | vCPU | memória RAM | Custo/mês |
|---|---|---|---|---|
| Light (blog, pequeno aplicativo) | t3.pequeno | 2 | 2 GB | ~$18 |
| Médio (aplicativo full stack) | t3.médio | 2 | 4 GB | ~$35 |
| Produção (multisserviço) | t3.grande | 2 | 8 GB | ~$70 |
| Pesado (API de alto tráfego) | c6i.xlarge | 4 | 8 GB | ~$140 |
| Muita memória (ML/cache) | r6i.grande | 2 | 16 GB | ~$120 |
Para um monorepo com 5 aplicativos Node.js (Next.js, NestJS, Docusaurus, 2 sites de marca) mais infraestrutura Docker (PostgreSQL, Redis, Authentik), um t3.large é a configuração mínima viável. A família t3 usa desempenho "expansível" — o desempenho é excelente durante a operação normal, mas a alta sustentação da CPU aciona o afogamento.
Para cargas de trabalho de CPU consistentemente altas (processamento de vídeo, inferência de ML, criptografia pesada), use instâncias c6i (otimizadas para computação).
Configuração inicial do servidor
Depois de iniciar sua instância EC2 com Ubuntu 24.04:
# Connect via SSH
ssh -i your-key.pem [email protected]
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install essential tools
sudo apt install -y \
git curl wget unzip \
build-essential \
nginx \
certbot python3-certbot-nginx \
docker.io docker-compose-plugin \
htop ncdu iotop
# Install Node.js via NVM (allows easy version management)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 22
nvm use 22
nvm alias default 22
# Install pnpm
curl -fsSL https://get.pnpm.io/install.sh | sh -
source ~/.bashrc
# Install PM2 globally
npm install -g pm2
# Install PM2 log rotation immediately
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7
pm2 set pm2-logrotate:compress true
Configuração do grupo de segurança
O grupo de segurança é o firewall da sua instância EC2. Configure-o com cuidado:
Inbound Rules:
┌─────────┬──────────┬─────────────┬──────────────────────────────────┐
│ Type │ Protocol │ Port Range │ Source │
├─────────┼──────────┼─────────────┼──────────────────────────────────┤
│ SSH │ TCP │ 22 │ Your IP only (not 0.0.0.0/0!) │
│ HTTP │ TCP │ 80 │ 0.0.0.0/0 (Cloudflare IPs only) │
│ HTTPS │ TCP │ 443 │ 0.0.0.0/0 (Cloudflare IPs only) │
└─────────┴──────────┴─────────────┴──────────────────────────────────┘
Note: Internal app ports (3000, 3001, 3002, etc.) should NOT be
in the security group — traffic goes through Nginx only
Para domínios com proxy da Cloudflare, restrinja HTTP/HTTPS aos intervalos de IP da Cloudflare:
# Cloudflare IPv4 ranges — restrict port 80/443 source to these
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
104.16.0.0/13
104.24.0.0/14
108.162.192.0/18
131.0.72.0/22
141.101.64.0/18
162.158.0.0/15
172.64.0.0/13
173.245.48.0/20
188.114.96.0/20
190.93.240.0/20
197.234.240.0/22
198.41.128.0/17
Isso impede o acesso direto ao seu servidor, ignorando a proteção WAF e DDoS da Cloudflare.
Implantação de aplicativos
# Create application directory
sudo mkdir -p /opt/ecosire/app
sudo chown ubuntu:ubuntu /opt/ecosire/app
# Clone the repository
git clone https://github.com/your-org/your-repo.git /opt/ecosire/app
cd /opt/ecosire/app
# Create .env.local from template
cp .env.example .env.local
# Edit with production values
nano .env.local
# Install dependencies
pnpm install --frozen-lockfile
# Build everything
npx turbo run build
# Run database migrations
pnpm --filter @ecosire/db db:migrate
# Start infrastructure (PostgreSQL, Redis, Authentik)
docker compose -f infrastructure/docker-compose.dev.yml up -d
# Wait for services to be healthy
sleep 30
# Start Node.js applications
pm2 start ecosystem.config.cjs
# Save process list for reboot persistence
pm2 save
# Configure PM2 to start on system boot
pm2 startup
# Run the command it outputs
IP elástico e DNS
O IP público de uma instância do EC2 muda sempre que você a interrompe e inicia. Elastic IP fornece um IP permanente:
# In AWS Console:
# 1. EC2 > Network & Security > Elastic IPs
# 2. Allocate Elastic IP address
# 3. Associate it with your instance
# Your IP is now permanent — update Cloudflare DNS to point to it
# A record: ecosire.com → 13.223.116.181 (your Elastic IP)
# A record: api.ecosire.com → 13.223.116.181
# A record: auth.ecosire.com → 13.223.116.181
Na Cloudflare, defina esses registros como “Proxied” (nuvem laranja) para tráfego da web. O proxy Cloudflare oculta seu IP EC2 real, fornecendo proteção DDoS.
Armazenamento: gerenciamento de volume EBS
As instâncias EC2 incluem um volume EBS raiz. Para produção, você precisa de espaço suficiente para construir artefatos, logs e dados do Docker:
# Check current disk usage
df -h
# Check which directories are consuming space
ncdu /
# Typical space requirements for a 5-app monorepo:
# - /opt/ecosire/app: ~2GB (code + node_modules + .next builds)
# - Docker data (/var/lib/docker): ~5GB
# - PM2 logs (/var/log/pm2): ~1GB (with rotation)
# - System: ~5GB
# Total: ~13GB minimum, recommend 30GB+ root volume
# If you need to resize an EBS volume (no downtime needed):
# 1. In AWS Console: EC2 > Volumes > Modify Volume
# 2. After resize completes, grow the filesystem:
sudo growpart /dev/xvda 1
sudo resize2fs /dev/xvda1
Monitoramento CloudWatch
O EC2 fornece métricas básicas de CPU e rede por padrão. Para métricas de memória e disco, instale o agente CloudWatch:
# Download and install CloudWatch agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i amazon-cloudwatch-agent.deb
# Create configuration
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
// /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "cwagent"
},
"metrics": {
"append_dimensions": {
"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
"ImageId": "${aws:ImageId}",
"InstanceId": "${aws:InstanceId}",
"InstanceType": "${aws:InstanceType}"
},
"metrics_collected": {
"mem": {
"measurement": ["mem_used_percent"],
"metrics_collection_interval": 60
},
"disk": {
"measurement": ["used_percent"],
"metrics_collection_interval": 60,
"resources": ["/", "/opt/ecosire"]
}
}
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/pm2/ecosire-api.err.log",
"log_group_name": "/ec2/ecosire/api-errors",
"log_stream_name": "{instance_id}"
},
{
"file_path": "/var/log/nginx/ecosire-error.log",
"log_group_name": "/ec2/ecosire/nginx-errors",
"log_stream_name": "{instance_id}"
}
]
}
}
}
}
# Start the agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config \
-m ec2 \
-c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json \
-s
Backups automatizados
Configure backups automatizados do PostgreSQL para S3:
# Create backup script
cat > /opt/ecosire/scripts/backup-db.sh << 'EOF'
#!/bin/bash
set -e
DATE=$(date +%Y-%m-%d-%H%M%S)
BACKUP_FILE="/tmp/ecosire-db-${DATE}.sql.gz"
S3_BUCKET="s3://your-backups-bucket/postgres"
# Dump the database (connects via Docker network)
docker exec ecosire-postgres pg_dump \
-U ecosire \
-d ecosire_dev \
--no-owner \
--no-privileges \
| gzip > "$BACKUP_FILE"
# Upload to S3
aws s3 cp "$BACKUP_FILE" "$S3_BUCKET/"
# Clean up local file
rm "$BACKUP_FILE"
# Delete backups older than 30 days from S3
aws s3 ls "$S3_BUCKET/" \
| awk '{print $4}' \
| sort \
| head -n -30 \
| xargs -I {} aws s3 rm "$S3_BUCKET/{}" 2>/dev/null || true
echo "Backup complete: ${DATE}"
EOF
chmod +x /opt/ecosire/scripts/backup-db.sh
# Schedule daily backups at 3 AM UTC
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/ecosire/scripts/backup-db.sh >> /var/log/db-backup.log 2>&1") | crontab -
Configuração de função IAM
Anexe uma função IAM à sua instância EC2 para acesso ao serviço AWS (S3, CloudWatch, SES):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::your-products-bucket",
"arn:aws:s3:::your-products-bucket/*",
"arn:aws:s3:::your-backups-bucket",
"arn:aws:s3:::your-backups-bucket/*"
]
},
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricData",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
Com a função do IAM anexada à sua instância, as chamadas do AWS SDK usam credenciais de instância automaticamente, sem necessidade de chave de acesso/chave secreta nas variáveis de ambiente.
Armadilhas e soluções comuns
Armadilha 1: Sem Elastic IP – alterações de IP na reinicialização
Interromper e iniciar (não reinicializar) uma instância do EC2 atribui um novo IP público. Sem um Elastic IP, seu DNS quebra. Aloque e associe um Elastic IP imediatamente após iniciar sua instância.
Armadilha 2: acesso SSH bloqueado
Se você perder sua chave SSH ou se bloquear configurando incorretamente grupos de segurança, use o EC2 Instance Connect (SSH baseado em navegador) no console AWS ou o Session Manager (requer o agente SSM instalado, que vem com o Ubuntu por padrão). Como último recurso, desconecte o volume raiz do EBS, anexe-o a outra instância, corrija o arquivoauthorized_keys e reconecte.
Armadilha 3: Ficar sem espaço em disco durante a implantação
O cache de compilação .next e node_modules crescem substancialmente durante o desenvolvimento. Monitore o uso do disco com df -h e defina um alarme do CloudWatch em disk_used_percent > 80%. O comando ncdu (ncdu /) identifica quais diretórios estão consumindo espaço.
Armadilha 4: Esgotamento de memória do Node.js OOM
O Node.js tem um limite de memória padrão (1,4 GB em 64 bits) que pode causar travamentos de OOM em aplicativos grandes. Defina node_args: '--max-old-space-size=1024' em seu arquivo do ecossistema PM2 para limitar explicitamente o uso de memória. Defina max_memory_restart um pouco acima para reiniciar automaticamente se for excedido.
Armadilha 5: Aceleração da CPU T3 sob carga sustentada
As instâncias T3 usam "créditos de CPU" para desempenho expansível. Operações estendidas de alta CPU (construções grandes, consultas pesadas ao banco de dados) esgotam os créditos, causando limitação no desempenho da "linha de base". Monitore CPUCreditBalance no CloudWatch. Se os créditos se esgotarem consistentemente, atualize para uma instância c6i ou ative o modo "ilimitado" (custo adicional por hora de CPU acima da linha de base).
Perguntas frequentes
Devo usar o EC2 ou um serviço gerenciado como o AWS Elastic Beanstalk?
O EC2 oferece controle total: a versão exata do Node.js, acesso ao sistema de arquivos, capacidade de executar contêineres secundários do Docker e configuração personalizada do Nginx. O Elastic Beanstalk gerencia a infraestrutura subjacente, mas restringe suas opções e adiciona complexidade à solução de problemas. Para uma equipe confortável com o gerenciamento de servidores Linux, o EC2 com PM2 + Nginx é mais simples e previsível do que as plataformas gerenciadas. Use o Beanstalk se quiser que a plataforma lide com o dimensionamento e o gerenciamento de integridade automaticamente.
Como lidar com implantações com tempo de inatividade zero no EC2?
O comando PM2 pm2 reload fornece tempo de inatividade zero para processos em modo cluster (API NestJS). Para Next.js (modo fork), crie primeiro a nova versão e depois recarregue o PM2. Durante os poucos segundos que o PM2 leva para alternar processos, o Nginx enfileira as solicitações recebidas (com um pequeno tempo limite). Para um tempo de inatividade verdadeiramente zero, use duas instâncias EC2 atrás de um ALB (Application Load Balancer) e implante em uma enquanto a outra atende o tráfego.
Quando devo usar o escalonamento automático?
O escalonamento automático adiciona complexidade operacional significativa — verificações de integridade, modelos de inicialização, balanceadores de carga e considerações de afinidade de sessão. Para aplicações com tráfego previsível, uma instância EC2 de tamanho adequado com escalonamento vertical (tipo de instância maior) é mais simples e geralmente mais barata do que o escalonamento automático horizontal. Considere o escalonamento automático quando você tiver picos de tráfego superiores a 5 vezes a linha de base e o custo de execução de uma instância permanentemente maior exceder a complexidade do escalonamento automático.
Como faço para migrar do EC2 para contêineres posteriormente?
Comece conteinerizando seu aplicativo com Docker (escreva um Dockerfile para cada aplicativo). Teste-o localmente com Docker Compose. Em seguida, escolha entre ECS Fargate (contêineres sem servidor, mais simples) ou EKS (Kubernetes, mais poderoso, porém complexo). A migração não causa interrupções se você conteinerizar de forma incremental – execute a versão em contêiner atrás da mesma configuração Nginx/Cloudflare, verifique o comportamento e, em seguida, faça a transição.
Qual é a maneira mais econômica de executar o EC2 em produção?
Compre uma instância reservada de 1 ano (sem adiantamento ou adiantamento parcial) para sua instância de linha de base — 40% mais barata do que sob demanda. Para obter capacidade adicional durante picos de tráfego, use instâncias spot (até 90% mais baratas) se seu aplicativo puder lidar com interrupções. Configure um alarme de faturamento do CloudWatch em 80% do seu orçamento mensal para que aumentos inesperados de custos sejam detectados antecipadamente. Para aplicativos Web de produção, as Instâncias Reservadas oferecem o melhor equilíbrio entre custo e confiabilidade.
Próximas etapas
A execução de uma aplicação web de produção no EC2 requer atenção operacional contínua – patches de segurança, gerenciamento de disco, monitoramento de desempenho e automação de implantação. ECOSIRE executa uma instância de produção EC2 t3.large que atende 5 aplicativos em vários domínios, com backups automatizados, monitoramento CloudWatch e implantações PM2 com tempo de inatividade zero.
Se você precisa de consultoria de infraestrutura AWS, configuração de implantação EC2 ou suporte completo de DevOps para seu aplicativo Node.js, explore nossos serviços para ver como podemos ajudar.
Escrito por
ECOSIRE Research and Development Team
Construindo produtos digitais de nível empresarial na ECOSIRE. Compartilhando insights sobre integrações Odoo, automação de e-commerce e soluções de negócios com IA.
Artigos Relacionados
Cloud Hosting for ERP: AWS vs Azure vs Google Cloud
A detailed comparison of AWS, Azure, and Google Cloud for ERP hosting in 2026. Covers performance, cost, regional availability, managed services, and ERP-specific recommendations.
Cloud vs On-Premise ERP in 2026: The Definitive Guide
Cloud vs on-premise ERP in 2026: total cost analysis, security comparison, scalability, compliance, and the right deployment model for your business.
Docker Compose for Development: Local Infrastructure
Docker Compose for local development: PostgreSQL, Redis, Authentik, networking, health checks, volume management, and environment-specific configurations for TypeScript monorepos.