Buenas prácticas: .env.example, rotación y entornos
La disciplina que sostiene todo lo anterior: mantener un .env.example versionado como mapa de variables sin secretos, ignorar los archivos reales para no commitear credenciales nunca, separar los secretos por entorno con el mínimo privilegio, y rotar las claves de forma periódica y de urgencia cuando se filtran, diseñando siempre para contener el daño y no solo para prevenirlo.
.env.example: el mapa que sí se comparte
Los archivos .env con valores reales no se versionan, pero el equipo necesita saber qué variables existen para poner en marcha el proyecto. Ese hueco lo llena .env.example: una plantilla versionada que lista cada nombre de variable con un valor de relleno o vacío, sin un solo secreto de verdad. Es a la vez documentación de arranque y contrato social sobre qué configuración espera el proyecto.
# .env.example -> se versiona, no lleva secretos realesPUBLIC_API_URL=https://api.ejemplo.comPORT=8787API_SECRET=pon-aqui-tu-claveDATABASE_URL=postgres://usuario:clave@localhost/dbQuien clona el proyecto copia .env.example a .env, rellena los valores reales y arranca. El ejemplo debe mantenerse sincronizado con el esquema de astro:env: cada vez que añades una variable al esquema, añádela también aquí. Así el .env.example y el esquema se refuerzan mutuamente —uno enumera los nombres para un humano que empieza, el otro los valida para la máquina— y juntos forman una descripción completa de la superficie de configuración del proyecto.
Nunca commitear un secreto, y qué hacer si pasó
La regla es absoluta: los archivos con valores reales quedan fuera del control de versiones. Tu .gitignore debe cubrir el .env y sus variantes locales, mientras deja pasar la plantilla de ejemplo, que es justo lo que sí quieres compartir.
# .gitignore.env.env.local.env.*.local# .env.example NO se ignora: es la plantilla publicaAun con esa red, un secreto se cuela alguna vez —un git add con comodín, un archivo mal nombrado—. Cuando ocurre, hay una verdad que asumir sin negociar: el secreto está comprometido. Borrarlo del último commit no basta, y reescribir el historial tampoco lo salva, porque en el intervalo en que estuvo publicado cualquiera pudo copiarlo, y los rastreadores automáticos que peinan los repositorios lo hacen en segundos. La única respuesta correcta es rotar: invalidar de inmediato la credencial filtrada y emitir una nueva. Limpiar el historial es higiene posterior; rotar es la cura.
Separar, rotar y verificar
Un solo secreto compartido por desarrollo, pruebas y producción es una bomba de radio amplio: si se filtra el de un becario en su portátil, cae producción entera. La práctica sana es lo contrario. Cada entorno tiene sus propias credenciales, y cada credencial lleva el mínimo privilegio que su tarea exige. La clave de desarrollo apunta a recursos de desarrollo y no puede tocar los datos reales; la de producción vive solo en el almacén de producción y jamás baja a la máquina de nadie.
La rotación tiene dos ritmos. El periódico es preventivo: renuevas las claves cada cierto tiempo aunque nada haya pasado, porque una credencial que lleva años viva ha tenido años de oportunidades para filtrarse por vías que ni sospechas. El de urgencia es reactivo: en cuanto hay indicio de exposición, revocas y reemplazas sin dudar. Que rotar sea posible sin dolor es, precisamente, el fruto de todo lo que construimos en la lección anterior: como el secreto vive en el entorno y no en el artefacto, cambiarlo es actualizar un almacén, no reconstruir y redesplegar el mundo. La higiene se apoya en la arquitectura.
Y a esa detección automática conviene sumar la comprobación deliberada, porque la disciplina se sostiene mejor cuando se verifica que cuando se confía en el proceso. Dos verificaciones baratas atrapan la mayoría de los descuidos antes de que lleguen lejos. La primera mira el artefacto: tras construir, rastrea la carpeta de cliente en busca de fragmentos de tus secretos, y si alguno aparece, tienes una fuga que corregir antes de desplegar.
# Busca en el build de cliente cualquier rastro de un secreto conocidogrep -r "fragmento-del-secreto" dist/client/ && echo "FUGA" || echo "limpio"La segunda mira el repositorio: revisa qué archivos rastrea git y confirma que ningún .env con valores reales está entre ellos. Estas comprobaciones no sustituyen a los mecanismos de fondo —el prefijo, el esquema, el .gitignore—, pero los cierran con una mirada empírica que convierte creo que no filtro en he mirado y no filtro. En seguridad, esa distancia entre creer y haber comprobado es casi todo.
Menos secretos, y de vida más corta
La mejor forma de proteger un secreto es no tener que guardarlo. Cada credencial estática de larga vida es un pasivo permanente: existe, hay que custodiarla y su probabilidad de filtrarse solo crece con el tiempo. Por eso la dirección en la que se mueve la industria es reducir su número y acortar su vida. Donde la plataforma lo permita, prefiere una identidad gestionada o un token efímero a una clave fija guardada a mano: en vez de un secreto eterno que copias entre entornos, el runtime obtiene una credencial de corta duración justo cuando la necesita y la descarta enseguida.
Este principio se combina con todo lo anterior en una jerarquía clara de preferencias. Lo ideal es no necesitar un secreto, resolviendo la autenticación con una identidad que la plataforma gestiona. Si hace falta un secreto, que sea de vida corta y ámbito estrecho. Y si ha de ser estático y duradero, que viva cifrado en el almacén del entorno, separado por entorno y rotado con disciplina. Cada escalón que subes en esa jerarquía añade una capa de contención, y ninguna sustituye a las demás: se acumulan.
Con esto cierra el nivel. Empezaste con un prefijo que Vite sustituye en el build, seguiste con un esquema que tipa y valida, aprendiste a leerlo desde los dos lados y a inyectar secretos en cada plataforma, y terminas con los hábitos que lo sostienen. El hilo que une las cinco lecciones es uno solo: la configuración es una frontera, y una frontera se cuida decidiendo temprano qué la cruza, tipando lo que entra, aislando lo sensible y asumiendo, con humildad, que algún día algo se escapará.