💼 Experiencia
- Liderar la migración de Apigee a Apigee Hybrid, diseñando una arquitectura escalable, segura y altamente disponible que abarca entornos on-premise y cloud.
- Administrar y operar Apigee Hybrid sobre EKS, gestionando componentes de runtime, upgrades y configuración de clúster para garantizar la fiabilidad y disponibilidad de la plataforma.
- Desarrollar herramientas de observabilidad potenciadas con LLMs mediante Amazon Bedrock para analizar métricas de plataforma, detectar anomalías de latencia y generar insights accionables en sistemas distribuidos.
- Desarrollar capacidades de platform engineering para monitorizar y optimizar el rendimiento de cargas de trabajo LLM, trazando throughput de tokens, latencia de respuesta, precios por token y eficiencia de coste a escala.
- Despliegue de aplicaciones contenerizadas en clústeres EKS usando manifiestos de Kubernetes, Helm charts o pipelines CI/CD.
- Evaluación y configuración de servicios AWS con Terraform para cumplir requisitos de proyecto e integrarlos en la arquitectura cloud.
- Diseño de arquitecturas cloud y diagramas de infraestructura con servicios AWS, implementados con Terraform.
- Creación de módulos Terraform reutilizables para encapsular patrones y buenas prácticas de infraestructura en AWS.
- Liderazgo técnico y mentoría a un equipo DevOps, supervisando su trabajo y fomentando un entorno colaborativo y de alto rendimiento.
- Diseño, implementación y mantenimiento de sistemas automatizados de build, despliegue y gestión de configuración.
- Dockerización de aplicaciones para crear contenedores portables y escalables que funcionen en cualquier entorno.
- Implementación y mantenimiento de soluciones de monitorización y logging.
- Evaluación de proveedores cloud (AWS, Azure, Google Cloud) y selección de servicios adecuados para cada proyecto.
- Despliegue de apps iOS y Android mediante pipelines de Azure DevOps.
- Monitorización, mantenimiento y resolución de incidencias de software, hardware y red.
- Desarrollo de procesos automatizados para administración de sistemas y software.
- Uso de AWS ECS para autoescalar aplicaciones docker según métricas de CPU.
- Resolución de incidencias en puestos de usuario y red.
🚀 Proyectos
Portfolio bilingüe en Python (FastAPI · Docker · Terraform · AWS · Caddy TLS · SQLite · GitHub Actions)
Descripción general
Portfolio bilingüe en producción construido con FastAPI y servido con HTTPS en AWS. Objetivo: simplicidad, seguridad y automatización completa (infra + despliegue).
Funcionalidades visibles
- Enrutado bilingüe (EN/ES): portada
/y CV en/cv - Páginas de proyecto en Markdown (incluida esta) con código y listas
- Tarjetas colapsables, diseño limpio y centrado, y botones activables/desactivables desde configuración
- Sección de certificaciones donde cada elemento enlaza a su Credly (nombre y badge clicables)
- Página de freelance en
/freelancecon calendario/horas y tarifa; “Reservar” pre‑rellena el flujo de contacto
Disponibilidad y reservas
- Horario semanal aplicado en cliente y servidor:
- Lun–Jue 18–23, Vie 15–23, Sáb/Dom 0–23 (configurable en YAML)
- Fechas/horas pasadas deshabilitadas (cliente) y filtradas en servidor
- Fechas bloqueadas configurables en YAML y respetadas de extremo a extremo
- Prevención de doble reserva con tabla
slots(clave única fecha+hora) - Creación atómica: inserta reserva + slots en una transacción; en conflicto devuelve 409
Panel de administración (/admin)
- Protegido con Basic Auth (variables de entorno ADMINUSER/ADMINPASS)
- Reservas:
- Listar/filtrar/buscar; actualizar estado (new/contacted/confirmed/cancelled)
- Exportar CSV; exportación ICS por reserva (calendario)
- Editor de configuración (/admin/config):
- Visibilidad de secciones
- Botones del hero: activar/desactivar y URL por botón (escribe en el YAML origen correcto)
- Certificaciones: activar/desactivar y URL de Credly por elemento
- Panel de diagnóstico: muestra archivos de config detectados, origen por botón, archivo de certificaciones y metadatos de build (imagen, SHA, hora)
Modelo de configuración (YAML, “último gana”)
- Fusión de
python/config.yamlconpython/config.d/*.yaml - Claves:
sections.*— alterna visibilidad de UIhero_buttons.*— activar/URL/etiquetas por botón (contact/freelance/github/linkedin/certifications/CV)certifications[]—name,badge,url,enabled,orderfreelance.*— tarifa, horario y fechas bloqueadas- El panel administra y escribe en el YAML de origen (seguimiento por clave), así los cambios persisten como fuente de verdad
Persistencia de datos
- Base de datos SQLite con dos tablas:
bookings— datos de la reserva + selecciones serializadasslots— una fila por (fecha, hora) reservada, PK (date,hour)- El directorio de datos se resuelve automáticamente; en producción se usa
/datamontado desde el host
Arquitectura
- App: FastAPI + Uvicorn (puerto 8000 dentro del contenedor)
- Proxy inverso: Caddy publica 80/443, termina TLS (Let’s Encrypt), redirige
www→ apex, añade HSTS y proxifica a la app - Contenerización: una imagen para la app; Caddy como contenedor separado en la misma red Docker
Infraestructura (Terraform)
- EC2 (Amazon Linux 2023) en VPC por defecto
- Elastic IP asociada a la instancia
- Security Group con 22/80/443
- Route 53 zona hospedada para
adrianmagarola.com: - A (apex) → Elastic IP
wwwCNAME → apex- Backend de estado remoto: S3 (+ bloqueo DynamoDB)
Estado de Terraform (boceto)
terraform {
backend "s3" {}
}
resource "aws_instance" "web" { /* Amazon Linux 2023, key pair, SG */ }
resource "aws_eip" "web" { instance = aws_instance.web.id }
resource "aws_route53_zone" "primary" { name = var.domain_name }
resource "aws_route53_record" "root_a" { /* apex A → EIP */ }
resource "aws_route53_record" "www" { /* CNAME www → apex */ }CI/CD (GitHub Actions)
- Provisionar EC2 (Terraform): inicializa backend y aplica infra
- Build y despliegue a EC2 (Docker): build/push de la imagen y despliegue por SSH
- Limpieza de contenedores/imagenes/cache para evitar falta de disco
- Caddyfile enviado en base64 para evitar problemas de shell/SSH
- Montajes en el host EC2:
/opt/portfolio/data→ contenedor/dataconPORTFOLIODATADIR=/data(SQLite persistente)/opt/portfolio/config.d→ contenedor/app/python/config.d(config persistente)- Seedeo de archivos de config que falten desde la imagen; sincronización forzada de
50‑certifications.yaml(con backup) para alinear URLs/estructura - Metadatos de build expuestos:
APPBUILDSHA,APPBUILDIMAGE,APPBUILDTIME(visibles en Diagnóstico)
Caddyfile (esencial)
{
email admin@adrianmagarola.com
}
www.adrianmagarola.com {
redir https://adrianmagarola.com{uri} 301
}
adrianmagarola.com {
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
}
reverse_proxy portfolio:8000
}Seguridad y operabilidad
- TLS automático (Let’s Encrypt)
- HSTS y redirección
www→ apex - Admin con Basic Auth (definir
ADMINUSER/ADMINPASS) - La app corre sin privilegios; Caddy gestiona 80/443
- Limpieza de disco en despliegues para mayor previsibilidad
Endpoints (selección)
GET /— portada (EN/ES)GET /cv— CV; certificaciones con enlaces a CredlyGET /freelance— UI de reservasPOST /api/bookings— reserva atómica (cumple horario, bloqueos y pasado)
Resultado
- Live: https://adrianmagarola.com
- Repo: https://github.com/amagarola/portfolio
Terraform Yaml-Config
Infraestructura Terraform con YAML Configs
📌 Descripción
Este proyecto proporciona un módulo de configuración centralizado para gestionar infraestructura multi-entorno usando plantillas YAML.
En lugar de codificar parámetros en múltiples módulos de Terraform, todas las configuraciones se definen en un único módulo yaml-config que otros módulos pueden referenciar.
Concepto clave: El sistema usa una estrategia de fusión jerárquica donde las configuraciones base se definen una vez, y cada entorno (dev, qa, pre, prod) solo sobrescribe lo diferente. Esto elimina duplicación y mantiene las definiciones DRY.
🗂️ Estructura del Proyecto
terraform/
├── yaml-config/ # Módulo de configuración central
│ ├── main.tf # Punto de entrada
│ ├── outputs.tf # Expone configs jerárquicas
│ ├── variables.tf # Entradas del módulo
│ ├── modules/
│ │ └── yaml-config/ # Lógica de fusión
│ │ ├── main.tf
│ │ └── variables.tf
│ └── config/
│ └── env/
│ ├── ec2.yaml # Config base EC2
│ ├── storage.yaml # Config base S3
│ ├── database.yaml # Config base RDS
│ ├── network.yaml # Config base VPC
│ ├── security.yaml # Config base security groups
│ ├── eks.yaml # Config base EKS
│ ├── dev/ # Sobrescrituras dev
│ ├── qa/ # Sobrescrituras QA
│ ├── pre/ # Sobrescrituras pre-prod
│ └── prod/ # Sobrescrituras producción
│
├── workload-ec2/ # Módulo workload EC2
├── workload-storage/ # Módulo workload S3
├── workload-database/ # Módulo workload RDS
├── workload-network/ # Módulo VPC/networking
├── workload-security/ # Módulo Security Groups
└── workload-eks/ # Módulo cluster EKS---
⚙️ Cómo Funciona
1. Estructura YAML
Cada archivo YAML sigue esta estructura:
context:
environment: "${env}"
terraform:
vars:
storage: # Tipo de recurso
s3_buckets: # Categoría de recurso
first-s3: # Clave del recurso
name: "first-s3-${env}" # Propiedades
versioning: true
encryption: true2. Fusión Jerárquica
- Config base (
config/env/*.yaml) aplica a todos los entornos - Sobrescrituras de entorno (
config/env/{env}/*.yaml) se fusionan encima - Módulo yaml-config usa
templatefile()para interpolar variables - Resultado: Configuración limpia y fusionada por entorno
3. Flujo de Datos
YAML Base + YAML Entorno → yaml-config → Config Fusionada → Módulos Workload → Recursos AWSEjemplo:
storage.yaml + qa/storage.yaml → merge → module.yaml_config.env.qa.storage → for_each → Buckets S3---
🚀 Ejemplo de Uso
En un Módulo Workload
Paso 1: Referenciar yaml-config
module "yaml_config" {
source = "../yaml-config"
environment = var.environment
}Paso 2: Acceder a configuraciones
locals {
s3_buckets = try(
module.yaml_config.env[var.environment].storage.s3_buckets,
{}
)
}Paso 3: Crear recursos dinámicamente
resource "aws_s3_bucket" "this" {
for_each = local.s3_buckets
bucket = each.value.name
# ... otras propiedades del YAML
}Añadir Nuevos Recursos
¡No se requieren cambios en código Terraform!
---
- Editar
config/env/storage.yaml(definición base) - Sobrescribir en
config/env/qa/storage.yamlsi es necesario - Ejecutar
terraform apply -var="environment=qa" - Recursos auto-creados via
for_each✨
✅ Ventajas
- Principio DRY → Definir una vez, sobrescribir solo diferencias
- Centralizado → Única fuente de verdad
- Dinámico → Auto-escalado con
for_each - Tipado seguro → Esquema YAML estructurado
- Flexible → Interpolación de plantillas (
${env}) - Separación clara → Configuración vs. lógica
- Auditoría fácil → Diffs claros en git por entorno


