Migración Frontend → CloudFront + S3
**Fecha inicio:** 7 agosto 2026
Migración Frontend → CloudFront + S3
Fecha inicio: 7 agosto 2026
Estado: 🔄 En progreso — distribución creada, pendiente subir archivos y probar
Objetivo: Mover el frontend estático (Angular + prerender) de nginx/EC2 a S3 + CloudFront, sin tocar el backend
Arquitectura actual
Usuario
└── postea.la (DNS → EC2 sa-east-1)
└── nginx (EC2 ec2-56-125-136-223.sa-east-1.compute.amazonaws.com)
├── / y rutas estáticas → /usr/share/nginx/html (Angular prerenderizado)
└── /api/* → localhost:8081 (Spring Boot)
Arquitectura objetivo
Usuario
└── postea.la (DNS → CloudFront)
├── /* (frontend) → S3 bucket posteala-frontend (us-east-1)
└── /api/* → EC2 ec2-56-125-136-223.sa-east-1.compute.amazonaws.com:443
El backend (Spring Boot en EC2) no se toca. nginx en EC2 se mantiene igual por ahora — solo se deja de usar para el frontend cuando el DNS apunte a CloudFront.
Recursos AWS creados
| Recurso | ID / Valor |
|---|---|
| S3 Bucket | posteala-frontend — región us-east-1 |
| S3 ARN | arn:aws:s3:::posteala-frontend |
| Acceso bucket | Privado — solo CloudFront via OAC |
| OAC (Origin Access Control) | E14J0R87SBABHD — nombre posteala-frontend-oac |
| CloudFront Distribution ID | E391AO5VCCAQBO |
| CloudFront ARN | arn:aws:cloudfront::287526491030:distribution/E391AO5VCCAQBO |
| CloudFront URL temporal | https://d14d3oowx2gsjh.cloudfront.net |
| AWS Account | 287526491030 |
| PriceClass | PriceClass_100 (US, Europa, Asia) |
Orígenes de la distribución
| Origen | ID | Dominio | Protocolo |
|---|---|---|---|
| S3 frontend | S3-posteala-frontend |
posteala-frontend.s3.us-east-1.amazonaws.com |
OAC (sigv4) |
| EC2 backend | EC2-backend |
ec2-56-125-136-223.sa-east-1.compute.amazonaws.com |
HTTPS only (TLS 1.2) |
Comportamientos de caché (Cache Behaviors)
| Path | Origen | Cache Policy | Métodos |
|---|---|---|---|
/api/* |
EC2-backend | 4135ea2d (CachingDisabled) |
GET HEAD OPTIONS PUT POST PATCH DELETE |
/* (default) |
S3-posteala-frontend | 658327ea (CachingOptimized) |
GET HEAD |
Custom Error Responses
| Error | Respuesta | Código HTTP devuelto | TTL |
|---|---|---|---|
| 403 (S3 objeto no encontrado) | /index.html |
200 | 0s |
Esto hace que rutas de Angular (/event/xxx, /admin, etc.) devuelvan el shell index.html en lugar de un error 403.
Bucket policy aplicada
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowCloudFrontOAC",
"Effect": "Allow",
"Principal": {"Service": "cloudfront.amazonaws.com"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::posteala-frontend/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::287526491030:distribution/E391AO5VCCAQBO"
}
}
}]
}
Estado actual del routing en nginx (EC2) — NO se toca por ahora
# Rutas prerenderizadas (landing, blog, docs, planes...)
location ~ ^/(planes|pricing|...|donde-poner-qr-boda)(/.*)?$ {
try_files $uri $uri/index.html /index.original.html;
}
# Rutas dinámicas Angular
location / {
try_files $uri $uri/ /index.original.html;
}
# API backend
location /api/ {
proxy_pass http://localhost:8081/api/;
}
En CloudFront esta lógica se replicará con una CloudFront Function en el evento viewer-request — pendiente de implementar.
Plan de migración — pasos pendientes
✅ Completado
- Crear bucket S3
posteala-frontend(privado) - Crear OAC
E14J0R87SBABHD - Crear distribución CloudFront
E391AO5VCCAQBO - Configurar origen S3 + origen EC2 backend
- Cache behavior
/api/*→ EC2 sin caché - Custom error response 403 → index.html
- Bucket policy para OAC
🔄 Pendiente
Paso 1 — Subir frontend al bucket y probar URL temporal
- Adaptar
deploy-frontend.shpara subir a S3 (aws s3 sync) en lugar de rsync a EC2 - Verificar que
https://d14d3oowx2gsjh.cloudfront.netsirva el landing correctamente - Verificar que
https://d14d3oowx2gsjh.cloudfront.net/api/healthllegue al backend
Paso 2 — CloudFront Function para routing
- Replicar la lógica de nginx en una CloudFront Function (viewer-request):
- Rutas prerenderizadas → servir
/{slug}/index.htmldesde S3 - Rutas Angular dinámicas → servir
/index.original.html(oindex.htmlraíz) - Sin esta función, las rutas prerenderizadas no funcionarán igual que en nginx
- Rutas prerenderizadas → servir
Paso 3 — Certificado SSL para postea.la en CloudFront
- Crear certificado ACM en us-east-1 (obligatorio para CloudFront) para
postea.laywww.postea.la - Asociar certificado a la distribución
- Agregar CNAME alias
postea.laa la distribución
Paso 4 — Cambio de DNS (momento del corte)
- Cambiar registro DNS de
postea.lade EC2 IP → CloudFront domain (d14d3oowx2gsjh.cloudfront.net) - Verificar que todo funcione con el dominio real
- El backend en EC2 sigue corriendo sin cambios
Paso 5 — Limpieza (opcional, después de validar)
- Simplificar nginx en EC2 — solo necesita servir
/api/ - Cancelar el certificado Let's Encrypt si ACM lo reemplaza completamente
Consideraciones importantes
CORS en el backend
Cuando el frontend se sirva desde CloudFront, el origen de las requests cambia. Verificar que Spring Boot tenga CORS configurado para aceptar https://postea.la y https://d14d3oowx2gsjh.cloudfront.net durante la prueba.
Cache invalidation
Cada deploy nuevo requiere invalidar la caché de CloudFront para que los archivos JS/CSS con hash nuevo sean visibles inmediatamente. Agregar al script de deploy:
aws cloudfront create-invalidation --distribution-id E391AO5VCCAQBO --paths "/*"
Archivos con hash vs sin hash
- JS/CSS de Angular tienen hash en el nombre (
main.d4cad70d.js) — se cachean agresivamente (1 año), correcto index.htmly HTMLs prerenderizados NO tienen hash — deben tenerCache-Control: no-cacheo TTL corto en CloudFront
PriceClass_100
La distribución usa PriceClass_100 (edge nodes en US + Europa + Israel). Para incluir São Paulo y otros nodos latinoamericanos usar PriceClass_All — más caro pero mejor latencia para usuarios peruanos.
Comandos útiles
# Ver estado de la distribución
aws cloudfront get-distribution --id E391AO5VCCAQBO --query 'Distribution.Status'
# Subir frontend a S3
aws s3 sync dist/postea-la/browser/ s3://posteala-frontend/ --delete
# Invalidar caché completo
aws cloudfront create-invalidation --distribution-id E391AO5VCCAQBO --paths "/*"
# Ver distribución completa
aws cloudfront get-distribution --id E391AO5VCCAQBO