diff --git a/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/data/images/cover.yaml b/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/data/images/cover.yaml new file mode 100644 index 00000000..93e72f6c --- /dev/null +++ b/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/data/images/cover.yaml @@ -0,0 +1,4 @@ +#title: "" +attribution: "ChatGPT" +description: "Il ne faut pas brider des LLM, il faut les cadrer." +#prompt: "" diff --git a/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/images/cover.png b/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/images/cover.png new file mode 100644 index 00000000..4c0b72c2 Binary files /dev/null and b/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/images/cover.png differ diff --git a/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/index.md b/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/index.md new file mode 100644 index 00000000..92df7324 --- /dev/null +++ b/content/interets/informatique/2026/04/01/chatgpt-a-casse-mon-serveur-mais-il-l-a-repare/index.md @@ -0,0 +1,213 @@ +--- +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. \ No newline at end of file