Configuración de variables de entorno para aplicaciones Twelve-Factor

Las variables de entorno son la columna vertebral de la configuración en aplicaciones que siguen la metodología Twelve-Factor. Este artículo explica por qué deben usarse, cómo gestionarlas con seguridad y ejemplos prácticos en entornos reales (Docker, systemd, Kubernetes). Incluye buenas prácticas, errores comunes y enlaces a referencias técnicas.

Qué establece el principio de configuración del Twelve-Factor

El factor de configuración del Twelve-Factor recomienda almacenar toda la configuración que varía entre despliegues (credenciales, URIs, claves API, modos de depuración) en el entorno del proceso. Para una explicación técnica del enfoque Twelve-Factor, consulta la página de Twelve-Factor App en Wikipedia.

Ventajas de usar variables de entorno

  • Separación clara entre código y configuración: el mismo artefacto funciona en varios entornos.
  • Despliegue más seguro: evita secretos en repositorios y reduce superficies de error.
  • Compatibilidad con sistemas de orquestación y CI/CD: la mayoría acepta configuración por entorno.
  • Simplicidad operacional: variables legibles por el proceso sin parsing complejo en el código.

Buenas prácticas para variables de entorno

Aplicar buenas prácticas no es opcional en producción. Estas recomendaciones son prácticas, técnicas y probadas en infraestructuras de hosting y servidores.

Nombres claros y consistentes

  • Usa mayúsculas y guiones bajos: DATABASE_URL, REDIS_HOST, SMTP_AUTH.
  • Prefija variables por componente o servicio cuando convenga: PAYMENTS_STRIPE_KEY, PAYMENTS_STRIPE_ENV.
  • Evita usar caracteres especiales o espacios; limítate a ASCII y guiones bajos.

Tipos y normalización

Las variables de entorno son cadenas. Normaliza y valida en el arranque de la aplicación: parsea enteros, booleans y fechas con control de errores. Implementa una rutina de validación que falle rápido si falta una variable crítica.

Gestión de secretos

  • No guardar secretos en repositorios ni en archivos de configuración versionados.
  • Usar gestores de secretos o servicios nativos del proveedor para inyectar variables en tiempo de ejecución.
  • Rotar claves periódicamente y tener procesos automatizados de rotación y despliegue.

Para principios de seguridad sobre manejo de secretos y riesgos comunes, revisa las recomendaciones de OWASP.

Longitud y límites

Algunos sistemas o shells imponen límites de longitud; evita values excesivamente largos en una sola variable. Para secretos muy largos usa almacenamiento seguro (vaults) y referencias en lugar de inyectar el valor completo como variable.

Entornos locales vs producción

  • Para desarrollo local usa archivos .env o herramientas de entornos locales, pero nunca los versionees.
  • En CI/CD define variables en la configuración del pipeline o el sistema de secretos del proveedor.

Ejemplos prácticos

Estos snippets muestran cómo inyectar variables en distintos entornos operativos. Siempre valida y maneja errores en arranque.

Bash / entorno Unix

export DATABASE_URL="postgres://user:pass@db:5432/appdb"
export DEBUG=false
# Iniciar la aplicación
./start-server

Systemd (servicio Linux)

[Service]
Environment="DATABASE_URL=postgres://user:pass@db:5432/appdb"
Environment="REDIS_HOST=redis.internal"
ExecStart=/opt/app/bin/start

Usa archivos de unidad con EnvironmentFile=/etc/app/env si necesitas separar configuración, y protege permisos del archivo de entorno.

Docker

Evita componer secrets en Dockerfile. Ejemplos:

  • Ejecutar con variables: docker run -e DATABASE_URL="..." myimage
  • Usar --env-file para evitar variables en la línea de comandos (pero no versionar el archivo).

Docker Compose (advertencia sobre .env)

Docker Compose lee un archivo .env local; no lo subas a control de versiones. Para producción, inyecta variables desde el entorno del host o usa herramientas de orquestación.

Kubernetes (ConfigMap y Secret)

En Kubernetes separa configuración no sensible (ConfigMap) de secretos sensibles (Secret). Ejemplo simplificado de Secret:

apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
data:
  DATABASE_PASSWORD: cGFzc3dvcmQ=
---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: app
        image: myrepo/app:latest
        env:
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: DATABASE_PASSWORD

Evita imprimir secretos en logs y limita el acceso RBAC al Secret.

Lectura desde el código

Ejemplo en PHP usando getenv:

$dbUrl = getenv('DATABASE_URL') ?: throw new Exception('DATABASE_URL no definido');

Consulta la función getenv en PHP.net para comportamientos específicos del SAPI.

Validación, fallback y testing

  • Valida variables en el arranque: si faltan valores críticos, la aplicación debe fallar con una excepción clara.
  • Proporciona valores por defecto solo para variables no críticas y con cuidado (ej. LOG_LEVEL=info).
  • Automatiza tests que simulen entornos con variables distintas para detectar dependencia oculta en la configuración.

Errores comunes y cómo evitarlos

  • Cometer .env en git: siempre excluir con .gitignore y usar vaults o secretos del CI.
  • Exponer variables en logs o dumps: enmascara valores sensibles en logs y métricas.
  • No validar tipos: provoca bugs difíciles de reproducir. Implementa validadores de esquema.
  • Depender de herramientas locales: documenta cómo inyectar variables en cada entorno (dev, staging, prod).

Checklist de implementación Twelve-Factor

  • Separar configuración del código: ningún valor específico del entorno en el repo.
  • Gestionar secrets mediante sistemas dedicados o mecanismos seguros del proveedor.
  • Validar y documentar variables requeridas para despliegue.
  • Auditar y rotar claves regularmente.
  • Probar despliegues con variables simuladas y flujos de rollback.

Conclusión

Adoptar variables de entorno conforme al Twelve-Factor mejora portabilidad, seguridad y operatividad de tus aplicaciones. La clave no es solo usar variables, sino gestionarlas con disciplina: nombres consistentes, validación temprana, separación entre secretos y configuración pública, y uso de herramientas de orquestación para inyección segura. Implementa validación en el arranque, evita almacenar secretos en repositorios y automatiza rotaciones y pruebas. Para profundizar en seguridad y riesgos revisa las guías de OWASP y, para detalles de implementación en tu lenguaje, consulta la documentación oficial como PHP.net. El resultado será una plataforma más robusta, reproducible y preparada para producción.