← Blog

Wenn ein Secret eine Datei sein muss, keine Umgebungsvariable

Railyard

18. September 2026 · 2 Min. Lesezeit

Das Meiste, was eine App braucht, ist ein einfaches KEY=VALUE-Paar, und die meisten PaaS-Plattformen sind komplett um diese Annahme herum gebaut. Dann taucht ein Google-Cloud-Service-Account-JSON auf — ein paar Kilobyte strukturierter Credential-Daten, die Googles eigene SDKs an einem Dateipfad erwarten, nicht in einer Umgebungsvariable — und der übliche Workaround ist, das Ganze base64-kodiert in eine Variable zu packen und in einem Entrypoint-Skript zu dekodieren. Es funktioniert, aber es ist ein Workaround, kein Feature.

Der tatsächliche Mechanismus

Variables → File secrets nimmt einen Namen und den Inhalt direkt — bis zu 64 KB, genug für ein Service-Account-JSON, ein Client-Zertifikat oder ähnliche strukturierte Credentials. Es wird verschlüsselt gespeichert, wie jedes andere Secret, und read-only im Container unter /etc/railyard/secrets/<name> gemountet — kein base64-Umweg, kein Entrypoint-Skript, das eine Variable dekodiert, bevor die App starten kann.

Der Teil, der den üblichen zweiten Schritt entfernt: Sein Pfad wird auch als eigene Umgebungsvariable freigelegt, RAILYARD_SECRET_FILE_<NAME>. Eine Google-Client-Library, die erwartet, dass GOOGLE_APPLICATION_CREDENTIALS auf eine Datei zeigt, bekommt einfach:

GOOGLE_APPLICATION_CREDENTIALS=${RAILYARD_SECRET_FILE_GCP_KEY_JSON}

Kein zusätzlicher Schritt löst diese Referenz auf — es ist derselbe Variablen-Referenz-Mechanismus wie überall sonst, nur dass er auf einen Pfad statt auf einen Wert zeigt. Das Entfernen eines Datei-Secrets greift beim nächsten Deployment, genau wie jede andere Variablenänderung.

Wo das neben allem anderen steht, das schon automatisch passiert

Provisionierte Services injizieren bereits ihre eigenen Variablen, ohne gefragt zu werden — DATABASE_URL, die einzelnen Felder DATABASE_HOST/PORT/USER/PASSWORD/NAME, REDIS_URL, Storage-Keys, RAILYARD_URL und Verwandte. Die dokumentierten Variablen einer App (die konkreten Namen, die sie als benötigt angibt, wie PGHOST oder BIND_ADDRESS) werden dort, wo sich die Namen überschneiden, automatisch aus diesen Services befüllt, und Secrets, die der App selbst gehören — SECRET_KEY_BASE, APP_KEY, JWT_SECRET — werden einmal generiert statt leer gelassen zu werden. Was dieser Mechanismus absichtlich nicht macht, ist, ein Drittanbieter-Credential an deiner Stelle zu erfinden — einen GCP-Service-Account, einen Stripe-Key, irgendetwas, das tatsächlich zu einem externen Konto gehört. Die musst du immer selbst liefern, und genau dafür existieren File-Secrets.

Auf einen Service verweisen statt einen Host hartzukodieren

Dieselbe ${{...}}-Referenzsyntax, die für File-Secret-Pfade genutzt wird, funktioniert generell über Services hinweg: ${{api.RAILYARD_PRIVATE_URL}} löst sich zur privaten Adresse dieses Services innerhalb derselben Umgebung auf, und ${config.KEY} zieht aus teamweiter geteilter Config, verfügbar für jede App — dasselbe Muster, drei verschiedene Quellen, sodass eine App nie einen hartkodierten Host oder ein kopiertes Secret hat, das von dem Ort, wo der tatsächliche Wert lebt, abweicht.

Vollständige Referenz: Variablen und Secrets.

Füge ein Datei-Secret unter Variables hinzu.

Verschlüsselt gespeichert, read-only gemountet, sein Pfad automatisch als Umgebungsvariable freigelegt.

Kostenloser Plan, keine Kreditkarte, und 14 Tage Pro für jedes neue Team. Ein fester Preis pro Team.