--- comments_url: https://com.richard-dern.fr/post/550 cover: images/cover.png date: '2026-04-01 18:05:51' entreprises: - OpenAI tags: - ChatGPT - NixOS - SOPS title: ChatGPT a cassé mon serveur - mais il l'a réparé weather: humidity: 56.0 illuminance: 16328.4 precipitations: false pressure: 1022.68936938298 source: - influxdb temperature: 8.88888888888889 wind_direction: 102.0 wind_speed: 5.632704 --- Suite à [un article](https://xieme-art.org/post/gerer-ses-secrets-avec-sops/) relayé par [le journal du hacker](https://www.journalduhacker.net/s/v5e4rj/g_rer_ses_secrets_avec_sops), j'ai décidé de passer à [SOPS](https://getsops.io) pour la [gestion des secrets](https://github.com/Mic92/sops-nix) dans ma configuration de [NixOS](https://nixos.org/). En parallèle, j'ai confié à [ChatGPT](https://chat.openai.com/) [les clés de mon réseau](/interets/informatique/2026/03/04/free-ipv6-et-opnsense/) : je l'ai rendu capable d'administrer l'ensemble de mes serveurs. C'est lui qui a procédé à la migration vers SOPS, et ça a été un succès total pendant plusieurs jours. Jusqu'à aujourd'hui, que je redémarre mon serveur et qu'il ne réponde plus. ## (kernel) panique Après avoir branché un écran et un clavier, je vois que le chargement de NixOS bute (avec un `kernel panic`) sur la création du fichier de secret déchiffré pour la clé d'API de MeiliSearch, en raison d'un utilisateur inconnu (`meilisearch`). Logique : je (le module NixOS) n'ai pas créé d'utilisateur spécifique pour MeiliSearch. Je me dis que ce n'est pas bien grave, il me suffit de redémarrer sur une génération antérieure de NixOS. Après tout, le système est fait pour ça. Sauf que, c'est plus compliqué que ça, et aucune génération ne pouvait plus booter. Je redémarre la machine sur une clé d'installation de NixOS, pour au moins avoir un shell et accéder à mes fichiers sur le disque, au cas où tout espoir de reprise serait vaincu, puis j'en profite quand même pour voir ce que c'est que cette histoire d'utilisateur inconnu. Je monte les disques pour que l'installateur y ait accès : ```shell mkdir /mnt/boot mount /dev/disk/by-label/nixos /mnt mount /dev/disk/by-label/boot /mnt/boot ``` Et j'inspecte ma configuration, stockée dans `/mnt/etc/nixos/`. Je réalise alors que ChatGPT avait affecté ce fameux utilisateur `meilisearch` au fichier concerné : ```nix secrets."services/meilisearch/master-key" = mkSecret { path = "/etc/nixos/secrets/services/meilisearch/master-key"; owner = "meilisearch"; group = "meilisearch"; restartUnits = [ "meilisearch.service" ]; }; ``` C'est parfaitement logique pour un outil prédictif : s'il y a un service `meilisearch`, l'administrateur a forcément créé un utilisateur `meilisearch`. Principe de base de la sécurité informatique. Mais le paquet fournit par NixOS ne crée pas automatiquement cet utilisateur, et en prime, ce fichier doit être lisible à un utilisateur particulier (que j'avais pourtant indiqué à ChatGPT dans mes instructions). Je corrige la déclaration d'appartenance de ce fichier selon ma convenance, puis j'essaye de me `chroot` avec `nix-enter` afin d'appliquer ma configuration. Et là, les ennuis ont réellement commencé. ## Shell en état de choc ```shell [root@nixos:~]# nixos-enter --root /mnt setting up /etc ... setting up secrets... /nix/store/r6wx09ss7v1775x67pypl5gqzwm71irg-sops-install-secrets-0.0.1/bin/sops-install-secrets: manifest is not valid: failed to lookup user 'meilisearch': user: unknown user meilisearch Activation script snippet 'setupSecrets' failed (1) /nix/var/nix/profiles/system/activate: line 247: /run/current-system/sw/bin/mktemp: No such file or directory ``` Le problème à ce stade, c'est que j'ai cramé mes tokens Codex jusqu'au 3 avril (on est le 1er). Il n'y a que le chat en ligne qui peut m'aider, et il n'a pas accès à ma configuration (que je n'ai pas envie de lui envoyer compte tenu de sa complexité). Néanmoins, il me suggère quand même de faire autrement, sans `chroot`, avec un simple `nixos-install --root /mnt`. La commande échoue sur `error: path '/var/lib/sops-nix/recovery-keys.txt' does not exist`. Le point important est le suivant : en Nix, un chemin écrit comme un vrai chemin Nix, par exemple `/var/lib/...`, est traité comme un objet `path` et il doit exister au moment de l’évaluation. [La documentation Nix](https://nix.dev/manual/nix/2.18/language/builtins) indique bien qu’un chemin référencé doit exister, et que l’existence d’un chemin peut être testée à l’évaluation avec `builtins.pathExists`. Donc, dans ma configuration, au lieu de faire : ```nix sops.age.keyFile = /var/lib/sops-nix/recovery-keys.txt; ``` Je devais faire : ```nix sops.age.keyFile = "/var/lib/sops-nix/recovery-keys.txt"; ``` Notez les guillemets. Après cette rapide correction, je relance l'installation : ```shell [root@nixos:~]# nixos-install --root /mnt copying channel... building the configuration in /mnt/etc/nixos/configuration.nix... these 2 derivations will be built: /nix/store/r4bgszxqmfikbsg9xv40a1p034gl597g-manifest.json.drv /nix/store/rf2zl9lh7qiidifvckfr1c0kl633ss97-nixos-system-server-main-25.11.8023.4590696c8693.drv building '/nix/store/r4bgszxqmfikbsg9xv40a1p034gl597g-manifest.json.drv'... building '/nix/store/rf2zl9lh7qiidifvckfr1c0kl633ss97-nixos-system-server-main-25.11.8023.4590696c8693.drv'... /nix/store/isdjvp7wwxwi1a7c8vp3l8hgrdh5yfny-nixos-system-server-main-25.11.8023.4590696c8693 installing the boot loader... setting up /etc... setting up secrets... sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age13kq73j2ka8y5tq7nl4cccajk9dftz45k2jl7v2ymuuu24n5frues58h2r5 /nix/var/nix/profiles/system/activate: line 230: /run/current-system/sw/bin/mktemp: No such file or directory /nix/var/nix/profiles/system/sw/bin/bash: line 12: /run/current-system/bin/switch-to-configuration: No such file or directory ``` ChatGPT me conseille alors de rebooter sans tenir compte de ces erreurs. Je redémarre, mais je vois qu'il n'y a aucune entrée GRUB pour la nouvelle génération (logique : regardez la dernière ligne d'historique ci-dessus). Malheureusement, nouveau `kernel panic`, cette fois sur l'absence de `mktemp`. Nouveau redémarrage sur la clé et nouveau montage des disques, et en faisant `nixos-enter`, je commence à me dire qu'il ne sait pas où chercher ses exécutables. ```shell [root@nixos:~]# ls -l /mnt/nix/var/nix/profiles/system/bin ls -l /mnt/nix/var/nix/profiles/system/sw/bin | grep bootctl ls: cannot access '/mnt/nix/var/nix/profiles/system/bin': No such file or directory ls: cannot access '/mnt/nix/var/nix/profiles/system/sw/bin': No such file or directory ``` On sait qu'un truc déconne bien quand même `ls` ne répond pas... Pourtant, je vois que de nouvelles générations ont été produites : ```shell /run/current-system/sw/bin/ls -l /boot/loader/entries | /run/current-system/sw/bin/tail -n 10 ``` Me montre bien un fichier `nixos-generation-481.conf`. C'est donc à l'étape de la génération du bootloader que ça déconne. ## Laisser NixOS gérer les chemins de fichiers... On a finalement déterminé la cause exacte de mon problème : ```nix tmp=$(/run/current-system/sw/bin/mktemp) trap 'rm -f "$tmp"' EXIT /run/current-system/sw/bin/ssh-to-age -private-key -i "$agentSshKey" > "$tmp" ``` On ne devrait jamais déclarer un chemin vers un exécutable sans l'extrapoler depuis `pkgs`. Il a suffi de corriger cela : ```nix tmp=$(${pkgs.coreutils}/bin/mktemp -p /run sops-age-key.XXXXXXXXXX) trap '${pkgs.coreutils}/bin/rm -f "$tmp"' EXIT ${pkgs.ssh-to-age}/bin/ssh-to-age -private-key -i "$agentSshKey" > "$tmp" ``` Nouveau `nixos-install`. Les dernières étapes sont toujours problématiques, notamment la mise à jour de GRUB. Mais au moins, je pouvais enfin accéder à mon `chroot`, en précisant à `nixos-enter` la génération 482 qui devait avoir réglé mes problèmes, afin de régénérer GRUB manuellement : ```shell [root@nixos:~]# nixos-enter --root /mnt --system /nix/var/nix/profiles/system-482-link -- \ /nix/var/nix/profiles/system-482-link/sw/bin/bash --noprofile --norc setting up /etc... setting up secrets... sops-install-secrets: Imported /etc/ssh/ssh_host_ed25519_key as age key with fingerprint age13kq73j2ka8y5tq7nl4cccajk9dftz45k2jl7v2ymuuu24n5frues58h2r5 /nix/var/nix/profiles/system-482-link/activate: line 230: /run/current-system/sw/bin/mktemp: No such file or directory bash-5.3# /nix/var/nix/profiles/system-482-link/sw/bin/mkdir -p /run /nix/var/nix/profiles/system-482-link/sw/bin/ln -sfn /nix/var/nix/profiles/system-482-link /run/current-system export PATH=/run/current-system/sw/bin:/nix/var/nix/profiles/system-482-link/sw/bin:$PATH NIXOS_INSTALL_BOOTLOADER=1 /run/current-system/bin/switch-to-configuration boot Running in a chroot, enabling --graceful. Copied "/nix/store/bigkpra9jw48fip69q4wndsf4kb3d2w9-systemd-258.3/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/EFI/systemd/systemd-bootx64.efi". Copied "/nix/store/bigkpra9jw48fip69q4wndsf4kb3d2w9-systemd-258.3/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/EFI/BOOT/BOOTX64.EFI". ⚠️ Mount point '/boot' which backs the random seed file is world accessible, which is a security hole! ⚠️ ⚠️ Random seed file '/boot/loader/random-seed' is world accessible, which is a security hole! ⚠️ Random seed file /boot/loader/random-seed successfully refreshed (32 bytes). Created EFI boot entry "Linux Boot Manager". bash-5.3# /run/current-system/sw/bin/ls -l /boot/loader/entries | /run/current-system/sw/bin/tail -n 10 total 16 -rwxr-xr-x 1 root root 473 Apr 1 15:25 nixos-generation-479.conf -rwxr-xr-x 1 root root 473 Apr 1 15:25 nixos-generation-480.conf -rwxr-xr-x 1 root root 473 Apr 1 15:25 nixos-generation-481.conf -rwxr-xr-x 1 root root 473 Apr 1 15:25 nixos-generation-482.conf bash-5.3# ``` Un dernier `nixos-install` et, cette fois, il va jusqu'au bout, sans le moindre message d'erreur. J'ai redémarré, les entrées GRUB étaient mises à jour, et NixOS a démarré sans broncher. Aucune perte à déplorer. ## Conclusion Franchement, c'est flippant à mort quand on fait ce genre d'expérience pour la première fois. J'en ai voulu à ChatGPT, à SOPS et à NixOS, et j'étais en train de me demander si je n'allais pas formater et réinstaller. Le problème s'est révélé être double : - ChatGPT a présumé de l'existence d'un utilisateur, parce qu'en théorie, installer un service devrait s'accompagner de la création d'un utilisateur dédié (tous les modules que j'utilise le font, à l'exception donc de MeiliSearch) - ChatGPT n'a pas utilisé des chemins construits par NixOS (extrapolés par `pkgs`). Je suis totalement responsable du second point étant donné que je ne le fais pas toujours. Mais ChatGPT aurait pu prendre les devants et m'aider à les corriger, au lieu de se contenter de (mal) faire comme moi. Mais maintenant, je sais quelles instructions supplémentaires je dois donner à ChatGPT pour éviter qu'il ne commette à nouveau ce genre d'erreur (ne jamais indiquer des chemins sans extrapoler `pkgs` quand c'est possible, par exemple). Je n'ai pas moins confiance en ce que produit ChatGPT. Je ne crois pas que l'on doit donner moins de privilèges aux LLM. Je crois juste qu'ils ont besoin d'être cadrés, et je ne l'ai pas fait suffisamment.