General

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.sh para subir a S3 (aws s3 sync) en lugar de rsync a EC2
  • Verificar que https://d14d3oowx2gsjh.cloudfront.net sirva el landing correctamente
  • Verificar que https://d14d3oowx2gsjh.cloudfront.net/api/health llegue 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.html desde S3
    • Rutas Angular dinámicas → servir /index.original.html (o index.html raíz)
    • Sin esta función, las rutas prerenderizadas no funcionarán igual que en nginx

Paso 3 — Certificado SSL para postea.la en CloudFront

  • Crear certificado ACM en us-east-1 (obligatorio para CloudFront) para postea.la y www.postea.la
  • Asociar certificado a la distribución
  • Agregar CNAME alias postea.la a la distribución

Paso 4 — Cambio de DNS (momento del corte)

  • Cambiar registro DNS de postea.la de 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.html y HTMLs prerenderizados NO tienen hash — deben tener Cache-Control: no-cache o 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