Módulo 5 · Arquitectura y código mantenible

Lección 27 — Configuración por entorno (12-factor)

Secretos y settings por entorno: la misma imagen, tres despliegues.

Publicada
En esta lección
  1. Ejercicio 1 — Auditoría de configuración
  2. Ejercicio 2 — settings.py 12-factor
  3. Ejercicio 3 — Rotación dual
  4. Ejercicio 4 — Fail-fast
  5. Ejercicio 5 — Config por feature flag
  6. Entrega

Migra los settings de TicketFlow al entorno. Sin solutions.md hasta entregar.

Ejercicio 1 — Auditoría de configuración

  1. Lista TODA la config de tu proyecto: la que está en settings.py como literal, la que lee de env vars, la que hay en código de vistas/servicios (un requests.get("https://...") con URL hardcodeada es config escondida).
  2. Clasifica cada una: código (no varía), config sensible (secreto), config no sensible (varía pero no es secreto), y bad config (literal que DEBE variar y está clavada).
  3. Mueve las bad config al entorno con defaults seguros. El test: git grep -n "https://" -- '*.py' devuelve solo URLs de documentación.

Ejercicio 2 — settings.py 12-factor

  1. Convierte tu settings.py a un solo módulo con django-environ (o pydantic-settings): SECRET_KEY/DEBUG/ALLOWED_HOSTS/DATABASE_URL/REDIS_URL del entorno, defaults seguros.
  2. Escribe el .env.example (sin valores reales) y el .env de dev (gitignored). Un compañero debe poder clonar y arrancar solo con cp.env.example.env + valores locales.
  3. La prueba de la misma imagen: escribe el Dockerfile (40 lo profundiza) con UNA imagen y arranca 3 contenedores con 3.env. Mismo hash de imagen, tres configs.

Ejercicio 3 — Rotación dual

  1. Implementa SECRET_KEYS (lista con nueva + vieja opcional) y haz que el validador de tokens/simplejwt acepte cualquiera de la lista.
  2. Escribe la secuencia de rotación como checklist de 5 pasos con la ventana de tiempo entre el paso 2 (deploy dual) y el 5 (retirar la vieja). ¿Qué pasa con los tokens emitidos con la clave vieja durante la ventana?
  3. Haz lo mismo para WEBHOOK_SECRET de la 17 (verificación HMAC acepta clave nueva y vieja).

Ejercicio 4 — Fail-fast

  1. Añade las validaciones de arranque (SECRET_KEY, ALLOWED_HOSTS, DATABASE_URL obligatorios fuera de DEBUG) con ImproperlyConfigured y mensajes que digan QUÉ variable falta y DÓNDE se documenta.
  2. Test de humo: manage.py check --deploy con entorno de prod fake (vars seteadas en el test) pasa; con DJANGO_DEBUG=true en prod fake, falla con error claro.
  3. Documenta en el README el "triage de arranque": las 3 variables más comunes que faltan y su síntoma exacto al arrancar.

Ejercicio 5 — Config por feature flag

  1. Añade FEATURE_WEBHOOKS (bool) y FEATURE_SAGA_V2 (bool) como flags de config (no de código): leídos del entorno, default false, usados con if settings.FEATURE_WEBHOOKS: en el servicio.
  2. Escribe el test que corre la misma prueba con flag on y off. ¿Qué gana esto frente a un branch de git por entorno?

Entrega

Pega el settings.py, el.env.example, la checklist de rotación y el test de humo. Después: Lección 28 — Refactorizar sin romper nada.