
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-filepara 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.