skip to content
dz
1 min read

TIL: NixOS löscht Store-Pfade, die nur in Konfigdateien stehen

Read this in English →

Heute Nacht hat sich mein Server plötzlich nicht mehr aktualisiert. Jede Stunde kam eine Notification mit dem Fehler No such file or directory. Der Pfad dahinter beginnt mit /nix/store/, und git fetch brach damit jedes Mal ab.

Schuld war ein Pfad in der /etc/nixos/.git/config. Beim ersten Klonen hat mein Service dort per git config core.sshCommand den Wert von ${pkgs.openssh}/bin/ssh eingetragen, also etwas wie /nix/store/98xy…-openssh-10.5p1/bin/ssh.

Nix legt jedes Paket in einem eigenen Verzeichnis unter /nix/store ab, mit einem Hash im Namen. Ein Update überschreibt nichts, die alte Version bleibt liegen, bis die Garbage Collection (nix-gc) aufräumt. Die löscht alles, worauf nichts mehr verweist: kein Systemstand, den Nix aufbewahrt, und kein anderes Paket. Dafür sieht Nix nur in die Dateien, die es selbst verwaltet. Die .git/config gehört nicht dazu, und mit einem Cronjob, einem Skript oder einer Dotfile wäre derselbe Fehler aufgetreten. Nach dem Update auf openssh 10.6p1 war die alte Version für Nix überflüssig, und um Mitternacht räumte die Garbage Collection auf.

Die Lösung: Ich setze GIT_SSH_COMMAND jetzt als environment am Service. Die Variable hat Vorrang vor core.sshCommand, und weil sie in der Systemkonfiguration steht, hält Nix das Paket am Leben:

systemd.services.nixos-auto-rebuild = {
  environment.GIT_SSH_COMMAND =
    "${pkgs.openssh}/bin/ssh -i /root/.ssh/infra-pull";
};

Einem Nix-Profi wäre das vermutlich nicht passiert. Ich habe danach meine Nix-Konfiguration nochmal gewissenhaft nach ähnlichen Stellen durchgesehen. In der Serie hatte ich es übrigens schon richtig: Dort steht nur ssh, das über path aufgelöst wird.