NixOS und Geheimnisse
(isabelroses.com)- Wenn Geheimnisse in NixOS im Nix-Setup, in einem privaten Git-Repository oder mit
git-cryptim Klartext liegen, kann sie wegen des für alle lesbaren Nix store jeder mit Maschinenzugriff lesen - sops-nix verschlüsselt Geheimnisdateien mit Regeln aus
.sops.yamlund demsops-Bearbeitungsablauf und entschlüsselt sie bei der Aktivierung mit dem SSH-Hostschlüssel, wobei der Klartext im tmpfs unter/run/secrets/<name>liegt - agenix legt in
secrets.nixfür jedes Geheimnis öffentliche Empfängerschlüssel fest und entschlüsselt.age-Dateien im tmpfs unter/run/agenix/<name>; bei neuen Hosts oder Schlüsselwechseln ist ein Rekeying nötig - Geheimnisse direkt im Dateisystem abzulegen ist für einen einzelnen Server oder Laptop möglich, aber wenn sie zur Auswertungszeit mit
builtins.readFile "/var/lib/myservice/token"gelesen werden, landet der Wert im Nix store und das sollte vermieden werden - Für den Einstieg und einige unabhängige Tokens ist agenix mit weniger Aufwand verbunden; für Hosts mit vielen zusammengehörigen Geheimnissen wie einem Mailserver passt sops-nix besser, weil mehrere Werte in einer Datei gebündelt werden können
Grundlegendes Risiko beim Umgang mit Geheimnissen in NixOS
- Das Verwalten von Geheimnissen in NixOS lässt sich in
sops-nix,agenix/ragenix, die Nutzung des Dateisystems, private Git-Repositories,git-cryptund das direkte Eintragen in die Nix-Konfiguration einteilen - Private Git-Repositories,
git-cryptund das direkte Eintragen in die Nix-Konfiguration sollte man nicht verwenden, wenn man sich eine Maschine teilt oder plant, die Konfiguration zu veröffentlichen- Der Nix store ist für alle lesbar, daher kann jeder mit Zugriffsrechten auf die Maschine die Geheimnisse lesen
- Dieses Risiko ist besonders wichtig in Zeiten von Schwachstellen wie CVE-2026-31431(copyfail) und CVE-2026-43284 sowie CVE-2026-43500(dirtyfrag)
- In veröffentlichten Konfigurationen sind Geheimnisse mindestens zweimal offengelegt worden; Beispiele sind 1, 2
sops-nix
- sops-nix kann sich anfangs schwer einzurichten anfühlen, aber die Dokumentation wurde deutlich verbessert, und dass
sopsdie Ver- und Entschlüsselung von Geheimnissen mit SSH-Schlüsseln inzwischen direkt unterstützt, ist eine große Verbesserung - Allerdings hinkt
sops-nixbei dieser SSH-Schlüssel-Unterstützung noch hinterher; entsprechende Arbeiten laufen in sops-nix#779 und sops-nix#922 - Der typische Ablauf besteht darin, in
.sops.yamlRegeln für Ver- und Entschlüsselung anzulegen und Geheimnisdateien mit demsops-Befehl zu bearbeiten- Ein Beispiel ist, für den Pfad
secrets/*.yamleinen SSH-öffentlichen Schlüssel alsage-Empfänger festzulegen - Führt man
sops secrets/shush.yamlaus, öffnet sich der gewählte Editor, und man kann YAML-Werte wiehello: sopseintragen - Nach dem Schließen des Editors werden die Werte in einer Form wie
ENC[AES256_GCM,...]verschlüsselt und können mit demselben Befehl erneut bearbeitet werden
- Ein Beispiel ist, für den Pfad
- In der NixOS-Konfiguration übernimmt das
sops-nix-Modul den Großteil der Arbeit- Mit
defaultSopsFile = ./secrets/shush.yaml;wird die Standarddatei für Geheimnisse festgelegt - Mit
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];wird der SSH-Hostschlüssel angegeben - Unter
secrets."hello"könnenowner,groupundmodegesetzt werden, um Dateirechte festzulegen
- Mit
- Beim Aktivieren entschlüsselt
sops-nixdie Datei mit dem SSH-Hostschlüssel und legt den Klartext unter/run/secrets/<name>ab- Dieser Pfad liegt auf tmpfs, daher berühren die Geheimnisse nicht die Festplatte
- Dienste, die den Wert benötigen, können einfach diesen Pfad lesen
- Die Template-Funktion ist nützlich für gemeinsam genutzte Konfigurationen oder Konfigurationen, auf die andere Benutzer zugreifen
- Wenn eine Dienstkonfigurationsdatei Klartext und einige Geheimnisse zusammen benötigt, muss nicht die gesamte Datei verschlüsselt werden
- Zum Beispiel kann
SMTP_USER=isabelim Klartext bleiben, während ein Platzhalter für ein Geheimnis wieSMTP_PASSWORD=${config.sops.placeholder."mailserver/smtp_password"}eingefügt wird
agenix
- agenix fühlt sich im Unterschied zu
sops-nixstärker nach Nix an, weil Geheimnisse und zugriffsberechtigte Schlüssel insecrets.nixkonfiguriert werden - In
secrets.nixwerden die öffentlichen SSH-Schlüssel von Benutzern und Hosts gebunden, und für jede.age-Datei wird festgelegt, welche öffentlichen Schlüssel darauf zugreifen dürfen- Zum Beispiel kann man
"secret1.age".publicKeys = [ isabel host1 ];und"secret2.age".publicKeys = [ isabel host2 ];setzen, sodass jedes Geheimnis eine andere Empfängerliste hat
- Zum Beispiel kann man
- Die Geheimnisdateien müssen mit der
agenix-CLI erstellt werden- Mit dem Befehl
agenix -e secret1.agekannsecret1.ageerzeugt oder später erneut bearbeitet werden
- Mit dem Befehl
- Die Einbindung in die Hostkonfiguration ähnelt
sops-nix, aber da jedes Geheimnis eine eigene Datei hat, ist die Oberfläche kleiner- Mit
age.secrets.secret1.file = ./secrets/secret1.age;wird die Datei angegeben - Mit
owner,groupundmodewerden Eigentümer und Rechte festgelegt
- Mit
- Beim Booten wird jede
.age-Datei mit dem SSH-Hostschlüssel entschlüsselt und unter/run/agenix/<name>abgelegt- Auch dieser Pfad liegt auf tmpfs
- Der häufigste Stolperstein ist das Rekeying
- Wenn ein neuer Host hinzukommt oder ein Schlüssel ausgetauscht wird, müssen alle Geheimnisse erneut verschlüsselt werden, deren
publicKeys-Liste sich insecrets.nixgeändert hat agenix --rekeyübernimmt das, benötigt aber den privaten Schlüssel eines aktuellen Empfängers, um den vorhandenen Chiffretext lesen zu können- In der Praxis geschieht das Rekeying daher auf der Maschine, der man am meisten vertraut, nicht auf dem neuen Host selbst
- Wenn ein neuer Host hinzukommt oder ein Schlüssel ausgetauscht wird, müssen alle Geheimnisse erneut verschlüsselt werden, deren
Ansatz nur mit dem Dateisystem
- Geheimnisse direkt im Dateisystem abzulegen hat den Nachteil, dass die Konfiguration die Maschine nicht mehr vollständig beschreibt
- Bei einer Neuinstallation müssen alle Dateien erneut mit dem richtigen Pfad und den korrekten Besitzrechten abgelegt werden
- Bei Wiederherstellungsarbeiten, etwa wenn man um 2 Uhr nachts einen Server retten muss, kann das zur Katastrophe werden
- Ein Muster, das man vermeiden sollte, ist
builtins.readFile "/var/lib/myservice/token"- Dabei wird die Datei zur Auswertungszeit gelesen und ihr Inhalt in den Nix store aufgenommen
- Da der Nix store für alle lesbar ist, entspricht das exakt derselben Fehlkonfiguration, vor der anfangs gewarnt wurde
- Stattdessen sollte man einem Dienst nicht den Wert selbst, sondern den Pfad übergeben
- Dafür lassen sich zum Beispiel Optionen wie services.*.environmentFiles verwenden
- Für einen einzelnen Server oder Laptop kann das in Ordnung sein, aber bei einer Flotte oder in Umgebungen, die man allein aus der Konfiguration neu aufbauen möchte, sind
sops-nixoderagenixbesser geeignet - Wenn es pro Maschine nur ein oder zwei Werte gibt, die wirklich nicht ins Repository gehören, ist das noch vertretbar, aber die Verantwortung, sie später wieder einzuspielen, bleibt beim zukünftigen Ich hängen
Vergleich von sops-nix und agenix
- Der Hauptgrund für
sops-nixist, dass sich möglichst viele Daten in einer einzigen Datei bündeln lassen- Wenn es wie bei einem Mailserver viele zusammengehörige Geheimnisse gibt, kann man deutlich mehr davon in einer Datei halten, statt sie wie bei
agenixauf etwa fünf Dateien zu verteilen - Es ist ein leistungsfähiges Werkzeug für den dauerhaften Einsatz und eine gute erste Wahl für Hosts mit sehr vielen Geheimnissen, etwa Mailserver
- Wenn es wie bei einem Mailserver viele zusammengehörige Geheimnisse gibt, kann man deutlich mehr davon in einer Datei halten, statt sie wie bei
agenixpunktet mit Einfachheit- Es gibt kein YAML-Schema, das man lernen muss
- Es gibt keine
.sops.yaml, die synchron gehalten werden muss secrets.nixist einfach Nix, sodass man dieselbenlet ... in-Bindings wie für Hosts und Benutzer auch für Schlüssel verwenden kann- Das Denkmodell ist „ein Geheimnis, eine Datei, eine Empfängerliste“ und passt gut zum Zugriffsmodell
- Weil es die wenigsten beweglichen Teile hat und trotzdem hostbezogene Schlüssel-Zugriffskontrolle bietet, ist es eine gute Empfehlung für Menschen, die erstmals nach Geheimnisverwaltung auf NixOS fragen
- Beide Werkzeuge lösen das Problem; die heutigen Unterschiede liegen größtenteils bei der Benutzbarkeit
- Wenn man gerade erst anfängt und mehrere Dienste zusammengehörige Geheimnisbündel brauchen, skaliert
sops-nixbesser - Wenn man gerade erst anfängt und meist nur ein paar unabhängige Tokens hat, kommt man mit
agenixmit weniger Schritten ans Ziel - Wenn man sein erstes Geheimniswerkzeug auswählt, ist es sinnvoll, mit
agenixden Ablauf kennenzulernen und erst dann zusops-nixzu wechseln, wenn sich „eine Datei pro Geheimnis“ in der Praxis wirklich als unhandlich erweist
- Wenn man gerade erst anfängt und mehrere Dienste zusammengehörige Geheimnisbündel brauchen, skaliert
- Angaben zur Quantenresistenz wurden korrigiert
1 Kommentare
Lobste.rs-Kommentare
Liegen nicht sowohl das verschlüsselte Geheimnis als auch sein Schlüssel auf der Festplatte? Oder wird eines von beidem an einem Ort wie einem TPM gespeichert?
Ich habe gerade erst angefangen, Nix zu benutzen, und bei kleinen Self-Hosting-Deployments verwende ich der Einfachheit halber die Methode, Dateien per
scpins Dateisystem zu legen.Nach etwas Suchen scheint man SSH-Private-Keys mit einem TPM schützen zu können, und ich habe mich gefragt, ob das auch in einer VM möglich ist, aber anscheinend gibt es vTPM-Support, also habe ich mir die Antwort wohl selbst gegeben.
Auf der Serverseite gibt es auch Zugriff über NixOps. Schau dir an, wie Colmena das macht: https://colmena.cli.rs/0.4/features/keys.html
Im Kern schiebt eine vertrauenswürdige Maschine, die die Geheimnisse besitzt, sie auf die entfernten Server. Das ist ähnlich zu dem, was du gerade mit
scpmachst, nur Nix-typischer umgesetzt.Ich habe in den letzten Nächten mein agenix-Setup in meinem System-Flake neu eingerichtet, daher kann ich nur über agenix sprechen. Für Interessierte habe ich agenix-rekey gewählt, weil ich keine
.yml-Datei mit Geheimnissen vorhalten muss und, wie bereits gemacht, alle Geheimnisse direkt in Nix konfigurieren kann.Die verschlüsselten Geheimnisse liegen im Nix Store und sind wie die anderen Dinge im Nix Store global lesbar. Der SSH-Private-Key, der diese Geheimnisse entschlüsselt, ist normalerweise der Private-Key des eigentlichen SSH-Servers, kann aber optional auch anders sein. Die Geheimnisse werden bei der Aktivierung, ungefähr beim Booten, entschlüsselt und unter
/run/agenix/<user>abgelegt.Das Tool secrix geht noch weiter und bindet Geheimnisse an systemd-Services und diese Services wiederum an die Services, die die Geheimnisse benötigen. Dadurch werden die Geheimnisse nur entschlüsselt, solange der betreffende Service läuft. Praktisch bedeutet das allerdings oft nur, dass sie die meiste Zeit entschlüsselt sind, weil NixOS-Nutzer Services selten ständig an- und ausschalten. Für Geheimnisse zur Systemaktivierung, etwa für das Anlegen von Benutzern, könnte das aber passend sein.
agenix-rekey macht Rekeying weniger lästig und ersetzt
secrets.nixdurch Flake-Outputs. Es verwendet für eine Hälfte des Schlüssels eine YubiKey-Split-Identität. Beim Rekeying werden die Geheimnisse mit diesem Schlüssel und Authentifizierung über die andere Hälfte entschlüsselt und dann erneut mit dem SSH-Public-Key des Servers verschlüsselt. Der Public-Key wird bei der Systeminstallation erzeugt; ich hole den im Installations-Closure erzeugten Schlüssel mit--copy-host-keysin nixos-anywhere. Die verschlüsselten Geheimnisse liegen im Repository, aber in einem separaten Submodul, auf das nur vertrauenswürdige Builder zugreifen können.Übrigens ist vTPM normalerweise nicht hardwarebasiert, und viele Anbieter liefern, selbst wenn sie TPM anbieten, meist nur TPM v1.2 statt TPM v2. Mein Anbieter BinaryLane ist auch so. Das ist zwar eine zusätzliche Sicherheitsschicht, aber kein magisches HSM wie ein echtes TPM und schützt nicht vor einer Kompromittierung des Anbieters oder des Host-Nodes. Ein echtes HSM-basiertes vTPM zu ermöglichen wäre für Anbieter vermutlich sehr teuer, und AWS bietet es wohl zu AWS-Preisen an.
agenix+agenix-rekey+age-plugin-1p.Der Master-Key liegt in 1Password, sodass ich ohne irgendwelche Zugangsdaten auf der Festplatte meines Laptops die Passwörter jedes Servers bearbeiten, ansehen und neu verschlüsseln kann.
Servern, die zur Laufzeit Zugriff auf Schlüssel brauchen, kann man Berechtigungen geben. Man sagt agenix-rekey, welche Schlüssel ein bestimmter Server sehen darf, und führt
agenix rekeyaus; dann wird eine verschlüsselte Version des Schlüssels, die dieser Server entschlüsseln kann, im Nix Store hinterlegt. Der SSH-Private-Key dieses Servers befindet sich nur auf diesem Server und verlässt ihn nie. agenix-rekey braucht zum Rekeying nur den Public-Key.Entsprechend würden Geheimnisse kompromittiert, wenn entweder mein 1Password-Konto gehackt wird oder der Server, der das Geheimnis verwendet, kompromittiert wird.
/etc/ssh/ssh_host_ed25519_keyentschlüsselt und dann in ein unter/run/agenix.dgemountetes ramfs gelegt.Also ja: Verschlüsselter Inhalt, Verschlüsselungsschlüssel und entschlüsselter Inhalt sind alle über das Dateisystem zugänglich.
https://github.com/oddlama/agenix-rekey
Außerdem gibt es immer weniger langlebige Zugangsdaten. Wir entfernen uns von der Kopie langlebiger Zugangsdaten hin zu hardwarebasierten Zugangsdaten, die entweder direkt verwendet oder gegen kurzlebige Zugangsdaten eingetauscht werden.