1 points par GN⁺ 2025-06-09 | 1 commentaires | Partager sur WhatsApp
  • Railway a repensé le builder qui crée des images de conteneurs à partir du code utilisateur, et transpose dans Railpack l’expérience acquise avec Nixpacks, qui a servi à builder plus de 14 millions d’apps
  • Nixpacks convenait à 80 % des utilisateurs, mais les 200 000 autres utilisateurs de Railway pouvaient se heurter à des limites de gestion des versions, de taille d’image et de mise en cache
  • Railpack améliore la reproductibilité des builds avec des versions major.minor.patch, le verrouillage des dépendances et un flux d’installation basé sur Mise, au lieu de la gestion de versions de Nix basée sur les commits
  • En générant directement BuildKit LLB et Frontend, les images Node par défaut sont devenues 38 % plus petites, et les images Python par défaut 77 % plus petites ; il devient aussi possible de partager le cache entre environnements
  • Railpack est actuellement en bêta et peut être activé dans les paramètres du service ; Railway privilégie d’abord la qualité de prise en charge des langages les plus utilisés plutôt qu’une couverture très large

Pourquoi Railway a créé un nouveau builder

  • Railway a présenté Railpack comme la prochaine étape du builder Railway
  • Railpack a été développé de zéro à partir de l’expérience acquise avec Nixpacks, qui a permis de builder plus de 14 millions d’apps
  • Après sa publication il y a environ trois ans, Nixpacks est devenu la méthode par défaut pour builder des images à partir du code utilisateur sur Railway
  • Il fonctionnait bien pour 80 % de l’ensemble des utilisateurs, mais les 200 000 autres utilisateurs de Railway pouvaient rencontrer des limitations
  • Railway a estimé qu’il fallait améliorer fortement le builder pour faire passer sa base d’utilisateurs de 1 million à 100 millions

Les limites rencontrées par Nixpacks avec Nix

  • Le principal problème était la gestion des versions de paquets basée sur les commits de Nix
    • Chaque paquet ne proposait que la dernière version majeure
    • Les versions étaient liées à un commit précis du repo nixpkgs
  • Les tentatives de prise en charge de toutes les versions de patch ont abouti à une structure qui faisait correspondre manuellement les chaînes de version et les SHA de commit, ce qui n’était ni clair ni facile à maintenir pour les contributeurs peu familiers avec la gestion des versions de Nix
  • Des langages comme Node et Python ont fini par ne prendre en charge que la dernière version majeure
  • Lorsqu’un SHA de commit était mis à jour pour prendre en charge une version plus récente d’un paquet, les versions d’autres paquets pouvaient aussi changer
    • Si la version par défaut changeait, des builds utilisateur qui fonctionnaient jusque-là risquaient davantage d’échouer avec des erreurs inattendues
    • Railway considérait qu’un build auparavant réussi qui casse soudainement était pire que l’impossibilité pour l’utilisateur d’accéder aux paquets les plus récents

Problèmes de taille d’image et de cache

  • La manière dont Nixpacks récupérait les dépendances avec Nix produisait souvent de grosses images
  • Nix, ainsi que les paquets et bibliothèques associés nécessaires au build et au runtime, se retrouvaient dans une seule couche /nix/store
  • Comme il n’existait aucun moyen de séparer les dépendances Nix dans des couches distinctes, la réduction de la taille finale de l’image était limitée
    • Railway y voyait non pas un problème propre à Nix, mais un problème lié à la manière dont Nixpacks utilisait Nix
  • Pour le cache aussi, il était difficile de contrôler quand le cache de couche était invalidé
  • Railway injecte dans tous les builds une variable d’environnement d’ID de déploiement
    • Dans un Dockerfile, les couches exécutées après l’ajout de cette variable étaient toujours invalidées et ne pouvaient pas être mises en cache
  • L’approche consistant à masquer aux utilisateurs les éléments essentiels de Nix ne convenait pas non plus
    • Railway voulait éviter que les utilisateurs aient besoin de comprendre ce qu’est une derivation, ou pourquoi Node 22.14.0 se trouve dans une version d’archive précise du canal unstable

Changements structurels de Railpack

  • Railway a créé Railpack pour résoudre les problèmes rencontrés avec Nixpacks
  • En s’éloignant de Nix, le nom est passé de Nixpacks à Railpack
  • La base de code est passée de Rust à Go en raison de la bibliothèque BuildKit
  • Railpack contrôle plus directement la façon dont l’image finale est créée
    • Il génère directement BuildKit LLB et Frontend
    • Par rapport à Nixpacks, l’image Node par défaut est 38 % plus petite, et l’image Python par défaut 77 % plus petite
    • Il utilise Mise pour la résolution des versions et l’installation de la plupart des paquets
    • Il laisse la possibilité de prendre en charge d’autres sources d’exécutables à l’avenir
  • Les dépendances utilisées dans un build réussi peuvent être verrouillées
    • Cela permet d’éviter qu’un build casse si la version par défaut de Node passe de 22 à 24
  • Les BuildKit secrets sont utilisés pour éviter que les variables d’environnement secrètes n’apparaissent dans les logs de build ou dans l’image finale

Fonctionnement d’un build Railpack

  • Le processus Railpack est divisé en trois étapes
    • Analyze : examine le code et détermine les paquets à installer, les commandes à exécuter et la commande de démarrage
    • Plan : crée un plan de build sérialisable en JSON, composé de plusieurs étapes ; chaque étape prend ses entrées depuis d’autres étapes ou depuis l’image complète
    • Generate : construit le graphe de build BuildKit à partir des entrées et sorties du plan
  • Un Dockerfile est linéaire, mais un graphe BuildKit est structuré de manière beaucoup plus parallèle
  • Chaque commande s’exécute dans son propre stage d’un build multi-stage, ce qui permet de contrôler finement les couches d’entrée et la façon dont le système de fichiers final est assemblé
  • Railpack génère un plan de build contenant toutes les étapes nécessaires
    • Chaque étape définit précisément les étapes précédentes ou les images dont elle a besoin
    • Ce format est de plus bas niveau que celui utilisé par Nixpacks
    • Le plan est transformé en graphe au format LLB puis interprété
  • BuildKit part de la fin et travaille à rebours : il récupère depuis le cache lorsque c’est possible et n’exécute les commandes que lorsque c’est nécessaire pour résoudre les couches demandées
  • Pour invalider une couche lorsque certaines variables d’environnement changent, Railpack hache les valeurs des variables utilisées et monte un fichier contenant ce hash dans le système de fichiers d’entrée
    • Si le code et les variables utilisées ne changent pas, le cache de couche est utilisé
  • Railpack peut définir entièrement la façon dont une image est créée

Ce que Railpack rend possible

  • Builder et déployer des sites statiques Vite, Astro, CRA et Angular sans configuration
  • Une intégration plus étroite entre les builds et l’UI Railway
  • La prise en charge des dernières versions des langages sans release de Railpack
  • Une mise en cache de couches optimisée sur plusieurs environnements d’un projet

Utilisation actuelle et périmètre de prise en charge

  • Railpack est actuellement disponible en bêta et peut être activé dans les paramètres du service
  • Il est déjà utilisé pour les builds de railway.com et de central station
  • Les éléments actuellement pris en charge sont les suivants
    • Node
    • Python
    • Go
    • PHP
    • Déploiement de HTML statique
    • Prise en charge par défaut des sites statiques Vite, Astro, CRA et Angular
  • Railway vise un environnement permettant de déployer facilement à la fois les frontends et les backends
  • La prise en charge des frameworks et des langages continue d’être ajoutée
    • Les demandes peuvent être envoyées via Help Station
    • Tant que l’API centrale et les abstractions ne sont pas stabilisées, Railway privilégie la profondeur de prise en charge des langages très utilisés plutôt qu’une couverture large
  • Railpack est open source et la documentation est disponible sur railpack.com

1 commentaires

 
GN⁺ 2025-06-09
Avis sur Hacker News
  • Je suis un amateur de Nix, mais je ne cherche pas à critiquer Railway parce qu’ils s’éloignent de Nix. Cela dit, certaines plaintes semblent mériter davantage d’explications.
    Nixpkgs est excellent, mais ce n’est pas la même chose que Nix, et si l’on veut récupérer des versions arbitraires de toolchains, Nixpkgs n’est tout simplement pas idéal. Les outils Nix permettant de récupérer des versions arbitraires de Rust sont déjà très bons, et d’autres outils de développement basés sur Nix ont montré comment bien gérer cela.
    Je ne comprends pas non plus l’affirmation selon laquelle « il n’y a aucun moyen de séparer les dépendances Nix dans une couche distincte ». On peut simplement les découper comme on veut, et les outils Docker intégrés à Nixpkgs offrent même une certaine prise en charge.
    Le passage de Rust à Go n’a pas de lien direct avec Nix, mais il est intéressant, et cela donne aussi l’impression que Railpacks et Nixpacks ont été créés par des personnes différentes. J’ai vu des situations assez mauvaises quand des gens peu familiers avec Nix se retrouvent responsables d’une solution Nix inachevée au sein d’une organisation ; c’est pour cette raison que, au travail, j’évite généralement d’introduire ce genre de situation avec Nix.

    • Je n’utilise pas Nix, mais la réponse « Nixpkgs n’est pas Nix » me paraît un peu dismissive. Si Nixpkgs est le choix par défaut et que les alternatives demandent des recherches et des efforts supplémentaires, alors pour la plupart des utilisateurs, c’est de fait cela, Nix.
      Dire « il suffit de découper les couches comme on veut » pose aussi la question de savoir si c’est clair, simple et le comportement par défaut.
    • Chaque fois qu’un problème d’utilisabilité de base apparaît avec Nix, la réponse « il existe un contournement » revient, et c’est usant. Ce contournement nécessite du savoir transmis oralement, il faut écrire des dizaines voire des centaines de lignes dans un langage qui se comporte très différemment des langages grand public, et les messages d’erreur comme la documentation de la bibliothèque standard ne sont pas bons.
      Si les gens se plaignent de Nix, ce n’est pas parce qu’il ne serait pas Turing-complet, mais parce qu’il ne fournit pas d’API de première classe simple, qui s’intègre directement aux projets idiomatiques de l’écosystème concerné, et finit donc par créer plus de problèmes qu’il n’en résout.
      Si chaque projet qui veut utiliser Nix finit par écrire ses propres modules pour corriger les problèmes de Nix, il y a peu de raisons de choisir Nix plutôt que des outils grand public mieux documentés. Ce cas-ci ressemble exactement à cela, et la plupart des gens choisiront probablement simplement Docker.
      Il est frustrant de voir un produit destiné aux développeurs s’accrocher à des flakes idéologiquement purs, plutôt que de résoudre des problèmes pratiques d’expérience développeur à une vitesse autre que géologique. Je comprends qu’il s’agit de contributions bénévoles, mais c’est vraiment dommage de voir autant d’efforts techniques consacrés à quelque chose qui devient difficile à utiliser en pratique à cause d’une mauvaise expérience utilisateur.
    • Le point facile à manquer, c’est que les utilisateurs de Railway sont des développeurs qui veulent spécifier leurs propres dépendances et versions pour des paquets arbitraires.
      Dans la manière dont Nix fonctionne avec la structure de Nixpkgs, figer une version de paquet revient à figer le commit de tout l’arbre nixpkgs. Les builds de paquets node/python/ruby dépendent aussi de l’état de l’arbre en dehors du répertoire du paquet, ce qui impose d’établir une correspondance entre versions et commits.
      Cette abstraction fuit, donc Railway doit l’exposer à ses utilisateurs ; et un utilisateur qui voulait simplement faire yarn add new-fancy-nodejs-package-with-linked–native-deps peut se retrouver à devoir faire correspondre plusieurs états du dépôt nixpkgs.
      Pour des usages au périmètre restreint, utiliser Nix sans Nixpkgs peut se défendre, mais pour une plateforme comme Railway, cela semble difficile à justifier.
    • J’ai entendu des propos du genre « Nix != Nixpkgs » aussi à propos des ports FreeBSD quand j’ai essayé FreeBSD. pkg fonctionnait globalement bien, mais un jour, en voulant compiler vim depuis les ports avec des flags USE personnalisés, il a récupéré plus de 20 dépendances, m’a demandé des options à chaque make menuconfig, puis le 16e paquet sur 23 a échoué avec un message du type « ceci nécessite cela, et cela nécessite Fubar3.32.1, mais Fubar3 est déprécié au profit de Fubar4 », et j’ai abandonné.
      Je comprends que les développeurs du Core OS ne puissent pas prendre en charge plus de 10 000 paquets, mais il faut aussi être clair sur le fait que, dès qu’on essaie d’activer des fonctionnalités personnalisées, la probabilité d’échec est élevée. Sinon, il vaudrait mieux imposer qu’un build standard généré indépendamment réussisse avant d’apparaître dans les ports, et retirer de la liste des ports ce qui ne compile pas.
    • Je trouve que c’est bien formulé. J’ajouterais que, même si nixpkgs n’est pas Nix lui-même, nixpkgs est aussi l’un des bons côtés. Depuis que j’utilise NixOS, c’est la première fois que j’utilise la toute dernière version du noyau Linux le jour de sa sortie, et c’est assez remarquable. Avec l’âge, j’ai aussi fini par accepter Debian Stable, mais j’ai toujours un peu l’impression de revenir quelques années en arrière.
      On pourrait critiquer le langage Nix pendant des heures, mais il est ancien, il faisait probablement de son mieux à l’époque, et il n’est peut-être plus très pertinent de le changer maintenant. Le système de build de Nix paraît assez primitif, et il reconstruit souvent des choses qu’on n’aurait pas l’impression de devoir reconstruire. Par exemple, une bonne partie du build de l’ISO d’installation de NixOS dépend de la ligne de commande passée au noyau, console=ttyS2,1500000n8, si bien que changer seulement la vitesse du port série entraîne environ 3 minutes de build. C’est amusant, mais ce n’est pas ce qui me fera abandonner Nix ; en revanche, je n’autoriserais pas cela dans mes propres builds.
      Pour les images Docker, je pense personnellement que c’est le domaine où Nix est le plus mauvais. Il y a longtemps, en développant un logiciel Go, je devais ajouter le binaire pg_dump de Postgres dans une image de conteneur ; sur recommandation de l’équipe infra, j’ai utilisé Nix, et l’image de 50 Mo contenant le binaire Go compressé est devenue un mystérieux monstre de 1,5 Go. pg_dump fait 464 Ko. J’ai finalement utilisé Bazel et rules_debian pour installer le paquet apt, et le résultat sur une base distroless était bien plus propre et plus petit. D’après mon expérience réelle de Nix, j’ai l’impression que le système Nix finit toujours par faire 1,4 Go. L’ISO d’installation fait aussi 1,4 Go, et une machine fraîchement installée aussi.
      Le cas où l’on veut builder un gros projet C++ est déjà une voie bien balisée, et remplacer C++ par Rust ne change pas fondamentalement la situation. Il existe des systèmes de build qui rendent la gestion des bibliothèques moins douloureuse ; ils sont aussi complexes que Nix, mais certains sont mieux adaptés à cet usage. Comme Nix cherche à devenir un système de build pour les logiciels des autres et pour nixpkgs, il se place dans une approche très générale. Les systèmes de build conçus pour builder son propre logiciel font généralement mieux ce travail. Personnellement, je suis satisfait de Bazel et, en dehors de go build pour les projets uniquement en Go, je pense que je n’utiliserai presque rien d’autre, mais il y a beaucoup d’options. Dans 99 % des cas, mieux vaut utiliser l’un de ces outils plutôt que Nix, puis écrire une flake pour que les gens puissent installer la dernière version avec home-manager.
  • La partie sur le choix des versions paraît étrange. Les versions de nixpkgs ont du sens quand on exécute ou qu’on build un système, mais si l’on fournit un runtime ou un compilateur en tant que plateforme, il faut une approche qui fournit directement les versions, comme devenv
    Si l’on build un ancien système pour fournir un vieux nodejs, on passe à côté des correctifs de sécurité des dépendances. Devenv gère cela, par exemple, avec https://github.com/cachix/nixpkgs-python, en « maintenant toutes les versions de Python à jour toutes les heures avec Nix »
    Le fait que Railway injecte une variable d’environnement d’ID de déploiement dans tous les builds aurait aussi pu se faire dans une couche après l’installation. On peut aussi diviser les paquets en plusieurs couches, et il existe de l’automatisation par lots pour réduire le nombre de couches

  • « Le problème ne vient pas de Nix lui-même, mais de notre façon de l’utiliser » est un bon exemple de choisir le bon outil pour le bon usage. Nix est excellent pour certains cas et catastrophique pour d’autres
    Le problème, c’est que la courbe d’apprentissage de Nix est si raide que, au moment où l’on le comprend assez pour en juger, on y a déjà investi tellement de temps qu’il paraît dommage de revenir en arrière, et on finit par le faire rentrer de force pour résoudre le besoin initial

    • Je ressens un peu la même chose, mais d’une certaine façon Nix est plus proche d’un paradigme de programmation général que les autres systèmes d’exploitation. Nous n’avons simplement pas l’habitude de penser les systèmes d’exploitation de cette manière. Une expression Nix a des entrées, contient un dépôt de paquets et beaucoup de paires clé-valeur, et produit en sortie un système Linux. Dans quelques années, cela paraîtra peut-être beaucoup plus banal
      Ce paradigme rend très facile pour l’IA de créer un shell.nix ou un configuration.nix conforme à une spécification. Par exemple, on peut y mettre des paquets Python, des paquets Linux, des variables d’environnement, des entrées de chemin, etc.
      J’utilise souvent cela pour inclure dans un dépôt un environnement qui prend entièrement en charge le paquet concerné. Avec flakes ce serait plus reproductible, mais je comprends pour l’instant flake.nix comme une sorte de shell.nix avec verrouillage des versions, et je suis encore en train d’apprendre
  • On dirait qu’ils essaient de forcer des versions là où il n’y en a pas. C’est comme essayer de faire entrer un cube carré dans un trou rond
    Dire qu’une « version par défaut » casse ce qui en dépend, je ne vois pas ce que cela veut dire. C’est comme utiliser le tag :latest de Docker et être surpris que, chaque fois qu’un nouveau serveur démarre, il casse parce qu’il n’a pas la même version que l’ancienne image « par défaut »
    Je ne comprends aucune des explications de ce billet. On dirait des gens qui ne savent absolument pas ce qu’est une « version » de logiciel
    Je ne vois pas non plus pourquoi « il n’y a pas de moyen de séparer les dépendances Nix dans des couches distinctes ». Bien sûr qu’on peut diviser /nix/store en autant de couches que nécessaire. Je me demande même s’ils savent comment utiliser les conteneurs et Nix à la base
    Vu cette immaturité manifeste, il n’est pas surprenant que la solution proposée sente le poisson pourri. C’est un syndrome NIH typique, et il me semble très probable que les mêmes problèmes qu’ils n’ont pas su résoudre avec Nix se propagent aussi à leur nouvelle « solution »

    • Je suis tout à fait favorable au fait de ne pas utiliser Nix, surtout là où cela n’a pas de sens. Mais reconstruire de zéro un système fonctionnel pour des raisons qui ne sont pas réellement des problèmes, alors qu’en quelques heures on peut voir comment les gens les résolvent déjà, paraît fondamentalement étrange
      Comme d’autres l’ont dit, nix2container et flakes semblent résoudre tous les problèmes qu’ils avaient
      Concernant la gestion des versions, des flakes que j’ai écrites il y a 3 ans se buildent encore aujourd’hui avec exactement les mêmes versions et les mêmes sorties qu’au moment où je les ai créées
      Cela dit, on dirait qu’ils veulent aller sur le marché comme plateforme et lever des fonds
      Édition : je viens de regarder le GitHub de nixpacks, et j’ai tout de suite remarqué qu’ils utilisent rustPlatform de nixpkgs, au lieu du rust-overlay[0] d’oxalica, qu’une simple recherche sur les problèmes Rust aurait fait ressortir. rust-overlay est l’un des overlays les plus utiles et les plus puissants que j’aie utilisés
      [0] https://github.com/oxalica/rust-overlay
    • Si l’objectif est d’obtenir des financements VC, une plateforme de déploiement passe mieux qu’un wrapper Nix
  • nix2container[1] permet effectivement de séparer les dépendances dans des couches distinctes. On peut créer explicitement une couche ne contenant qu’une partie des dépendances nécessaires à l’image, et il y a un exemple dans cette section : https://github.com/nlewo/nix2container?tab=readme-ov-file#is...
    Par exemple, si des images utilisent bash, on peut créer explicitement une couche contenant la closure de bash. Cette couche est réutilisée par toutes les images, et n’est rebuildée et repoussée que lorsque cette closure bash change
    L’idée que les images grossissent à cause d’une couche /nix/store unique vaut pour la fonction de base nixpkgs.dockerTools.buildImage, mais pas pour nix2container ni pour nixpkgs.dockerTools.streamLayeredImage. Ces outils, au lieu d’écrire les couches dans le Nix store, créent un script qui pousse effectivement l’image en utilisant les chemins existants du store. L’implémentation de nix2container crée un fichier JSON décrivant les chemins du Nix store de toutes les couches, et Skopeo consomme ce JSON pour pousser l’image vers le démon Docker, un registre, podman, etc.
    Pour info, je suis l’auteur de nix2container
    [1] https://github.com/nlewo/nix2container

    • J’utilise nix2container pour des déploiements AWS ECR, et grâce à lui le temps d’itération entre les builds est descendu à quelques secondes, moins de dix
    • J’avais justement prévu de prendre le temps d’expérimenter nix2container à cause de problèmes de taille d’images Docker. Merci pour le travail
  • Le problème central ici, c’est de s’accrocher à l’attitude de soupe de versions sur mesure encouragée par les gestionnaires de paquets des langages. Cette approche est totalement intenable
    L’alternative, Mise, ne semble pas capable de comprendre les contraintes de version entre paquets, ni lancer des tests pour vérifier que chaque paquet installé fonctionne bien avec les versions environnantes. Dans ce cas, on n’obtient pas du tout la même chose

  • La « soupe de versions personnalisées » n’est pas durable, mais l’une des raisons pour lesquelles les gens continuent à l’utiliser, c’est qu’en général ça fonctionne bien. L’une des raisons pour lesquelles ça fonctionne bien, c’est que les bibliothèques au niveau du système d’exploitation viennent d’un autre monde, beaucoup plus conservateur, et qu’elles essaient autant que possible d’éviter de casser la rétrocompatibilité
    On peut donc partir d’un système d’exploitation stable et bien maintenu, empiler par-dessus une soupe de versions personnalisées d’outils et de runtimes de langage avec des outils comme mise ou asdf, puis lancer l’app. Ça casse rarement. Quand ça casse, on bidouille les versions et quelques petits correctifs jusqu’à ce que ça remarche, puis on passe à autre chose. Le fait que ça ait cassé est agaçant, mais pas important. Ajouter de la friction, exiger de l’apprentissage ou demander plus de travail, c’est une perte de temps
    À l’inverse, il y a aussi des gens qui cherchent une solution pour que ça ne casse plus jamais. Pour eux, le problème est important ; donc si la solution demande de la friction, de l’apprentissage et du travail supplémentaire, ça leur va. Ce sont ces gens qui veulent Nix
    La plupart des gens appartiennent au premier groupe, donc une entreprise comme Railway, qui veut croître, finit forcément par choisir une solution adaptée à ce groupe

    • Peux-tu expliquer davantage ce que signifie l’attitude de « soupe de versions personnalisées » et quelles sont les alternatives ?
    • Si c’est bien fait, on peut avoir les deux. Par exemple, construire des paquets Rust avec Nix à partir d’un fichier Cargo.lock, c’est trivial. nixpkgs va dans la direction opposée à la soupe de versions personnalisées, mais Nix lui-même peut aussi gérer correctement cette approche
  • D’après mon expérience en DevOps/SRE, quand quelqu’un essaie de créer un système pour gérer les dépendances, etc., on finit généralement sur l’une de deux voies. On peut prendre Python comme exemple
    Option 1 : « utilisons un grand dépôt partagé unique ». L’avantage, c’est que tout est au même endroit, que ce dont on a besoin y est inclus, et que tout le monde utilise la même chose, ce qui facilite la correction de problèmes comme les vulnérabilités. L’inconvénient, c’est qu’il y a toujours quelqu’un qui veut une version spéciale, que les déploiements progressifs sont difficiles et que les changements tendent à devenir des big bang, puis arrive la question : « comment fait-on une petite version Docker ? »
    Option 2 : « chacun a son propre conda/venv ». L’avantage, c’est que chacun obtient exactement ce qu’il veut, n’utilise pas de paquets inutiles et peut faire des mises à niveau par étapes facilement. L’inconvénient, c’est qu’on en arrive à « mais combien d’environnements conda existe-t-il ? », que les bibliothèques de différents groupes peuvent ne pas être testées avec la même combinaison de bibliothèques Python, et que la gestion des vulnérabilités devient un cauchemar parce qu’on ne sait même pas où se trouvent les différents environnements conda
    Donc je suis toujours sceptique face aux affirmations du type « cette nouvelle approche résout tout ». Plus ma carrière avance, plus l’idée qu’« il n’y a pas de solution, seulement des compromis » me paraît vraie

  • Même avec seulement un peu d’expérience de Nix, les arguments ici ne me semblent pas très justes
    Il est dit que « ce n’est ni clair ni maintenable pour les contributeurs qui ne sont pas familiers avec la gestion des versions de Nix » et que « Node et Python n’en sont venus à prendre en charge que les dernières versions majeures ». Je ne vois pas pourquoi ce serait impossible à maintenir. Si c’est parce qu’il faut produire une liste des versions disponibles, je me demande si ça ne peut pas être automatisé
    Plus encore, je ne comprends pas pourquoi Railway définit la manière dont les utilisateurs emploient Nix. L’un des points centraux de Nix n’est-il pas de pouvoir configurer une machine vide avec les versions exactes des paquets que l’on veut ? Je ne vois pas pourquoi Railway devrait s’interposer entre l’utilisateur et ces versions pour les limiter
    Si la structure empêche les utilisateurs de voir Nix directement, alors la question initiale reste entière. Est-il impossible d’automatiser une liste de versions de paquets ?

    • La limitation des versions vient du fait que le cache Nix ne conserve pas les anciennes versions. Donc si vous utilisez une ancienne version, il faut compiler depuis les sources. On dirait qu’ils ne voulaient pas fournir eux-mêmes un cache pour les anciennes versions, mais ça ne semble pas demander un effort si énorme
      Honnêtement, les raisons avancées ne paraissent pas très solides. Peut-être que la personne qui avait introduit Nix est partie, et que les personnes restantes ne l’aimaient pas vraiment. Le langage lui-même n’est pas terrible, et l’ancienne documentation n’était pas excellente non plus
      Cela dit, je ne connais pas suffisamment la stack qu’ils ont choisie, mais je me demande si elle offre un niveau de déterminisme proche de Nix. Sinon, ça pourrait leur revenir en boomerang plus tard ou rendre l’exploitation plus difficile
    • Le billet dit : « la manière dont Nixpacks récupère les dépendances aboutit à une énorme image avec une seule couche /nix/store, qui contient tous les paquets et bibliothèques liés à Nix nécessaires à la build et au runtime »
      C’est un peu comme dire : « on n’arrivait pas à faire avancer une voiture, donc on abandonne la voiture ». C’est l’une des choses que Nix sait faire de la manière la plus fiable. Il détecte automatiquement les dépendances runtime effectivement référencées par le binaire final en faisant correspondre les chaînes de hachage de /nix/store
      S’ils n’ont pas réussi à le faire, c’est qu’ils l’utilisaient d’une manière assez étrange ou qu’ils se sont sérieusement trompés. J’ai même du mal à imaginer comment empêcher Nix de résoudre ça automatiquement
      Donc je ne prendrais pas leur expérience de Nix trop au pied de la lettre. Tout ce qui concerne la gestion des versions est un problème très courant que tout le monde rencontre ; cela aurait été plus intéressant s’ils avaient essayé de le résoudre
    • Le fait que la structure empêche les utilisateurs de voir Nix directement correspond au moins à ma compréhension
    • Même si le projet n’a aucun Dockerfile, quand on pousse le code sur Railway, il construit une image avec Nixpacks. Les logs de build montrent des éléments liés à Nix, mais la plupart des choses se passent en arrière-plan
  • Nix n’offre pas une garantie sur des versions arbitraires, mais une garantie sur les commits. Quand des cas limites apparaîtront, ils souffriront à cause de changements de glibc ou de bibliothèques partagées en conflit
    C’est peut-être un peu tard, mais je serais volontiers disponible pour du consulting afin de le faire fonctionner de manière idiomatique avec Nix. Le produit a l’air chouette

    • Nix résout les problèmes d’incompatibilité de bibliothèques partagées de manière extrêmement conservatrice. Dès que quoi que ce soit change, qu’il s’agisse d’un changement significatif ou non — même une correction de commentaire, un changement de documentation ou l’ajout d’un cas de test — il reconstruit toutes les dépendances
      Et pas seulement ça : les dépendances des dépendances, puis les dépendances de ces dépendances, et ainsi de suite, ce qui provoque souvent de très grosses reconstructions
      Cela évite les conflits de bibliothèques partagées, mais cette solution est extrêmement coûteuse et peut aussi rendre le développement pénible. Il suffit de regarder le processus de staging de nixpkgs pour s’en rendre compte
    • Je comprends parfaitement la proposition de valeur de Nix. Cela dit, je trouve que l’expression « ils souffriront » est un peu exagérée. Au maximum, je dirais plutôt : « ils perdent une garantie assez importante par rapport à Nix »
      Malgré tout, ça devrait être « empaqueté avec une forte probabilité de fonctionner correctement » par rapport à 95 % des logiciels dans le monde
  • Je ne comprends pas pourquoi ils n’ont pas pu créer leurs propres derivations au lieu de dépendre des hachages nixpkgs