← Volver a proyectos

Portal de empleados

Un portal interno para la gestión diaria de una empresa: autenticación, permisos por rol y los paneles que usa el equipo cada día. Lo diseñé y desplegué de punta a punta yo solo — backend, frontend e infraestructura en AWS. No puedo compartir código ni capturas por un acuerdo de confidencialidad.

Cuándo
2026 · Encargo profesional
Rol
De punta a punta, yo solo: backend, frontend e infraestructura en AWS
Stack
  • Java
  • Spring Boot
  • React
  • AWS
  • Terraform
  • Docker

Qué es

Arquitectura

Por dentro, el frontend se sirve desde una CDN, la API y las automatizaciones comparten un servidor y la base de datos vive en una red privada. Toda la infraestructura está definida con Terraform.

Desliza el esquema hacia los lados para verlo entero.

AWS VPC Subred pública Subred privada GitHub Servidor EC2 web API URL firmada OIDC imagen Usuariosnavegador WAFfiltro de tráfico CloudFrontCDN con HTTPS S3web estática Caddyproxy HTTPS n8nautomatizaciones APISpring Boot PostgreSQLRDS, cifrada S3ficheros SSMsin SSH Budgetsfreno de costes Secrets Managercredenciales Actionstests y despliegue GHCRimagen Docker
Esquema simplificado: sin dominios, regiones ni tamaños reales.
Usuarios
El equipo entra al portal desde el navegador. Todo el tráfico viaja cifrado por HTTPS, tanto hacia la web como hacia la API.
WAF
Cortafuegos de aplicación delante de CloudFront: filtra el tráfico malicioso antes de que llegue a la web.
CloudFront
Sirve el frontend desde la red de distribución de AWS, con HTTPS y caché. Tras cada despliegue se invalida la caché para que nadie vea una versión antigua.
S3 (web)
Guarda el frontend en React ya compilado. El bucket es privado y solo CloudFront puede leerlo, así que no hay forma de saltarse el WAF.
Servidor EC2
Un único servidor con Docker Compose que ejecuta Caddy, la API y n8n. Solo abre los puertos web y exige IMDSv2, que impide que un fallo de tipo SSRF robe sus credenciales de AWS.
Caddy
Proxy inverso: recibe todo el tráfico HTTPS del servidor y lo reparte entre la API y n8n. Emite y renueva los certificados solo.
API
Spring Boot con Java 21, organizada por capas. Se encarga de la autenticación, los permisos por rol, el cifrado de datos personales y el límite de peticiones.
n8n
Automatizaciones del equipo. Procesa datos que llegan de fuera y los envía a la API por webhook; la API comprueba tamaño y formato antes de aceptarlos.
PostgreSQL (RDS)
Base de datos cifrada, con backups diarios, en una subred privada sin salida a internet. Solo acepta conexiones del servidor de la API, sin reglas por IP. Por qué no hay NAT Gateway
S3 (ficheros)
Avatares, documentos y vídeos. La API firma URLs temporales y el navegador sube y descarga directamente, sin que los ficheros pasen por el servidor.
Secrets Manager
Guarda la contraseña de la base de datos, gestionada por AWS, y la clave de cifrado de n8n. Ninguna está en el código ni en la configuración.
SSM
Administración y despliegues sin puerto 22: cada sesión pasa por IAM y queda registrada. Para desplegar, ordena al servidor descargar la nueva imagen. Por qué no hay SSH
Budgets + Lambda
Avisos por email cuando el gasto se acerca al presupuesto. Si se dispara, una Lambda para el servidor sola, sin borrar nada.
GitHub Actions
Cada cambio pasa los tests. Al integrarlo, construye la imagen de la API y publica el frontend en S3 con credenciales temporales (OIDC), sin claves de AWS guardadas en GitHub.
GHCR
Registro de GitHub donde se publica la imagen Docker de la API. El servidor la descarga en cada despliegue.

Decisiones técnicas

Cada decisión de arquitectura quedó documentada con las alternativas que descarté y por qué.

Sin NAT Gateway
La base de datos vive en una subred privada sin salida a internet: no la necesita, y evita un coste recurrente injustificado a esta escala.
Sin SSH abierto
La administración del servidor va por AWS SSM (IAM + registro de auditoría) en vez de un puerto 22 con claves que mantener.