Cuando un secreto tiene que ser un archivo, no una variable de entorno
La mayoría de lo que necesita una app es un simple par KEY=VALUE, y la mayoría de las plataformas PaaS están construidas enteramente sobre esa suposición. Después aparece un JSON de cuenta de servicio de Google Cloud — unos cuantos kilobytes de datos de credenciales estructurados que los propios SDKs de Google esperan encontrar en una ruta de archivo, no dentro de una variable de entorno — y la solución habitual es codificar todo en base64 dentro de una variable y decodificarlo en un script de entrypoint. Funciona, pero es un workaround, no una función.
El mecanismo real
Variables → File secrets recibe un nombre y el contenido directamente — hasta 64 KB, suficiente para un JSON de cuenta de servicio, un certificado de cliente, o credenciales estructuradas similares. Se guarda cifrado, igual que cualquier otro secreto, y se monta como solo lectura dentro del contenedor en /etc/railyard/secrets/<name> — sin ida y vuelta por base64, sin script de entrypoint decodificando una variable antes de que la app pueda arrancar.
La parte que elimina el segundo paso habitual: su ruta también se expone como su propia variable de entorno, RAILYARD_SECRET_FILE_<NAME>. Una librería cliente de Google que espera que GOOGLE_APPLICATION_CREDENTIALS apunte a un archivo simplemente recibe:
GOOGLE_APPLICATION_CREDENTIALS=${RAILYARD_SECRET_FILE_GCP_KEY_JSON}
Ningún paso extra resuelve esa referencia — es el mismo mecanismo de referencia a variables que todo lo demás, apuntando a una ruta en vez de a un valor. Eliminar un secreto de archivo tiene efecto en el siguiente despliegue, igual que cualquier otro cambio de variable.
Dónde queda esto junto a todo lo demás que ya es automático
Los servicios aprovisionados ya inyectan sus propias variables sin que se les pida — DATABASE_URL, los campos individuales DATABASE_HOST/PORT/USER/PASSWORD/NAME, REDIS_URL, claves de almacenamiento, RAILYARD_URL y similares. Las propias variables documentadas de una app (los nombres específicos que declara necesitar, como PGHOST o BIND_ADDRESS) se completan desde esos servicios automáticamente donde los nombres coinciden, y los secretos que la propia app es dueña de generar — SECRET_KEY_BASE, APP_KEY, JWT_SECRET — se generan una sola vez en vez de dejarse en blanco. Lo que ninguno de esos mecanismos hace, deliberadamente, es inventar una credencial de un tercero en tu nombre — una cuenta de servicio de GCP, una clave de Stripe, cualquier cosa que de verdad pertenezca a una cuenta externa. Esas siempre las provees tú, que es exactamente la categoría para la que existen los secretos de archivo.
Referenciar un servicio en vez de fijar un host a mano
La misma sintaxis de referencia ${{...}} usada para rutas de secretos de archivo funciona en general entre servicios: ${{api.RAILYARD_PRIVATE_URL}} se resuelve a la dirección privada de ese servicio dentro del mismo entorno, y ${config.KEY} toma valores de la configuración compartida de todo el equipo, disponible para cualquier app — el mismo patrón, tres fuentes distintas, para que una app nunca tenga un host fijado a mano ni un secreto copiado y pegado que se desincronice de dónde vive el valor real.
Referencia completa: Variables y secretos.