❌

Vue normale

Il y a de nouveaux articles disponibles, cliquez pour rafraĂźchir la page.
À partir d’avant-hierFlux principal

epub, le convertisseur EPUB3 à la volée de LinuxFr.org

4 novembre 2024 Ă  03:57

Le site LinuxFr.org utilise divers logiciels libres pour son fonctionnement et ses services : une large majoritĂ© provient de projets tiers (Debian, MariaDB, Redis - version d’avant le changement de licence, nginx, Postfix, conteneurs LXC et Docker, Ruby On Rails, Sympa, etc.) et d’autres composants sont dĂ©veloppĂ©s pour nos propres besoins. Cette derniĂšre catĂ©gorie comprend le code principal du site web en Ruby On Rails, et principalement 5 services autour : le cache d’images img, la tribune board, le convertisseur EPUB 3 epub, le partageur sur les rĂ©seaux sociaux share et le convertisseur LaTeX vers SVG svg. Cette dĂ©pĂȘche va s’intĂ©resser Ă  epub, un code sous AGPLv3.

Elle est nĂ©e d’une envie personnelle d’expliquer, documenter et montrer ce qui a Ă©tĂ© fait sur le convertisseur EPUB3 Ă  la volĂ©e de LinuxFr.org, et elle vient accompagner la prĂ©cĂ©dente sur img, le cache d’images sur LinuxFr.org.

    Sommaire

    Des EPUB de vos contenus et commentaires

    LinuxFr.org vous permet de lire les contenus et commentaires du site, au format EPUB3, par exemple dans votre liseuse préférée. Il y a une exception à cela, les liens, parce que certes ça ferait des EPUB tout mignons, mais surtout petits voire un poil inutiles. Le lien EPUB est présent automatiquement sur chaque contenu (hormis les liens donc).

    Le principe est simple : on donne un lien vers un contenu HTML Ă  epub, il le demande Ă  la partie Ruby on Rails du site, ainsi que les images associĂ©es, convertit le tout au format EPUB3 et le renvoie Ă  la personne qui l’a demandĂ©. Techniquement epub n'est pas exposĂ© frontalement mais se trouve derriĂšre un nginx.

    CÎté code Ruby on Rails

    C’est assez basique : on ajoute juste sur chaque contenu un lien pour tĂ©lĂ©charger au format EPUB. Ainsi, y compris sur cette dĂ©pĂȘche, vous allez trouver un lien Ă  la fin pour rĂ©cupĂ©rer le tout au format EPUB (et un autre pour rĂ©cupĂ©rer le source en Markdown mais c’est un autre sujet).

    app/views/news/_news.atom.builder:    epub = content_tag(:div, link_to("Télécharger ce contenu au format EPUB", "#{url}.epub"))
    app/views/polls/_poll.atom.builder:  epub = content_tag(:div, link_to("Télécharger ce contenu au format EPUB", "#{url}.epub"))
    app/views/posts/_post.atom.builder:  epub = content_tag(:div, link_to("Télécharger ce contenu au format EPUB", "#{url}.epub"))
    app/views/nodes/_actions.html.haml:    = link_to "EPUB", "#{path_for_content node.content}.epub", title: "Télécharger ce contenu au format EPUB", class: "action download"
    app/views/diaries/_diary.atom.builder:  epub = content_tag(:div, link_to("Télécharger ce contenu au format EPUB", "#{url}.epub"))
    app/views/wiki_pages/_wiki_page.atom.builder:  epub = content_tag(:div, link_to("Télécharger ce contenu au format EPUB", "#{url}.epub"))

    CÎté epub

    Le service est plutĂŽt simple, par rapport Ă  img, car il n’a pas de dĂ©pendance sur redis par exemple, et qu’il a, au final, peu de paramĂ©trage (un couple adresse+port d’écoute, un fichier de trace et un hĂŽte pour aller chercher les contenus).

    Il est possible de faire un GET /status et on obtient une rĂ©ponse HTTP 200 avec un contenu OK. C’est utile pour tester que le service est lancĂ© (depuis l’intĂ©rieur de la plateforme).

    Sinon on lui demande une dĂ©pĂȘche, un journal, une entrĂ©e de forum, un sondage, une entrĂ©e de suivi ou une page wiki en prenant le chemin sur LinuxFr.org et ajoutant un petit .epub Ă  la fin, et il va renvoyer un fichier EPUB. Ou bien il va rĂ©pondre un contenu non trouvĂ© HTTP 404 s’il y a un souci. Et vu son fonctionnement, si on a un souci de HTML non valide ou si img a un problĂšme avec une image, alors derriĂšre epub pourrait avoir le mĂȘme souci.

    epub est un binaire dynamique en Go. Il impose le https pour l’hĂŽte (du coup on aura tous les liens en HTTPS en interne normalement). Il ne peut pas vraiment ĂȘtre compilĂ© statiquement (on a besoin de libxml2, libonig2 et de la mĂȘme version de la libc au dĂ©ploiement). Il ne gĂšre pas les images in-line.

    Dans les logs on va trouver des infos comme :

    2024/11/03 16:34:02 Status code of http:/example.invalid/exemple.png is: 404
    (
)
    2024/11/03 16:38:23 Fetch https://linuxfr.org/news/capitole-du-libre-2024-au-programme-du-16-et-17-novembre
    2024/11/03 16:38:24 Fetch https://linuxfr.org/users/liberf0rce/journaux/libreast-2006-is-out-of-order
    

    Historique

    epub a Ă©tĂ© crĂ©Ă© par Bruno Michel en 2013 et Bruno est le seul Ă  travailler dessus (48 commits) jusqu’en 2018. Comme img, on peut considĂ©rer que epub a fait le job pendant ce temps-lĂ , sans besoin de retouche.

    Mon premier commit de 2021 concerne la gestion d’un cas de collision de nommages des images.

    En 2022, Bruno quitte l’équipe du site, et par ailleurs il y a des montĂ©es de versions et des migrations Ă  faire sur les serveurs de LinuxFr.org, et epub fait partie des services Ă  reprendre en main. Ce qui veut dire le comprendre, le documenter et au besoin l’amĂ©liorer.

    Bref je dĂ©cide de me plonger dans epub (2022-2024), dans la foulĂ©e de img, car a priori ce n’est pas un composant compliquĂ© du site (il vit dans son coin, il offre une interface, c’est du Go, donc on a un binaire seulement Ă  gĂ©rer - divulgĂąchage en fait non pas seulement).

    Le choix est le mĂȘme que pour img (cf la dĂ©pĂȘche prĂ©cĂ©dente) : ajouter un Dockerfile permettant de recompiler epub dans un conteneur, en contrĂŽlant la version de Go utilisĂ©e, en effectuant une dĂ©tection d’éventuelles vulnĂ©rabilitĂ©s au passage avec govulncheck. Cela me permet de valider que l’on sait produire le binaire d’une part, et que l’on offre Ă  tout le monde la possibilitĂ© de contribuer facilement sur ce composant. Et de dĂ©couvrir qu’une version statique n’est pas facilement envisageable.

    Puis je vais tester le composant pour vĂ©rifier qu’il fonctionne comme je le pense et qu’il fait ce qu’on attend de lui. Je vais ajouter une suite des tests qui couvrent les diffĂ©rentes fonctionnalitĂ©s et les vĂ©rifient en IPv4 et en IPv6, en HTTP 1.1 et en HTTP 2.0. Les tests utilisent Hurl et docker-compose, et encore une fois l’idĂ©e de donner la possibilitĂ© de contribuer facilement. Ils comprennent des tests de types de contenus non pris en charge, le test de la limite Ă  5 MiB, diffĂ©rents types de contenus, le test de vie, des appels erronĂ©s (mauvais chemin, mauvaise mĂ©thode, etc). Et surtout de vĂ©rifier avec epubcheck que le fichier epub produit est correct. Le choix des cas de tests est basĂ© sur le trafic rĂ©ellement constatĂ© sur le serveur de production, sur les diffĂ©rents cas dans le code et un peu sur l’expĂ©rience du testeur.

    Les différents travaux effectués vont permettre de détecter et corriger quelques soucis :

    Et Ă  la fin, j’écris une dĂ©pĂȘche pour parler de tout cela.

    Évolutions rĂ©centes

    Dockerfile

    Le fichier Dockerfile du projet permet :

    • de partir d’une image officielle Go d’une version donnĂ©e, basĂ©e sur une distribution Debian (en raison des dĂ©pendances)
    • de l’utiliser pendant la construction en prenant la liste des dĂ©pendances de compilation, en les tĂ©lĂ©chargeant, en prenant l’unique fichier source epub.go et en le compilant dynamiquement avec l’option pour retirer les chemins de compilation
    • de rechercher les Ă©ventuelles vulnĂ©rabilitĂ©s avec govulncheck
    • de tester avec golangci/golangci-lint le code (fait Ă  la construction de l’image, car on dispose de toutes les dĂ©pendances Ă  ce moment-lĂ )
    • de repartir d’une base Debian en y mettant les autoritĂ©s de certification, les dĂ©pendances de fonctionnement et le binaire issus de la partie construction, de dĂ©clarer le port d’écoute et de lancer le binaire avec des variables disposant de valeurs par dĂ©faut.

    La suite de tests

    Pour l’utiliser, c’est assez simple, il faut aller dans le rĂ©pertoire tests et lancer un docker-compose up --build, qui va produire le conteneur contenant epub, et dĂ©marrer le nginx-cert qui fournit les certificats et le nginx prĂ©configurĂ© pour les tests. Si tout va bien, on attend, et au bout d’un moment il s’affiche :

    linuxfr.org-epub-test_1  | All tests look good!
    tests_linuxfr.org-epub-test_1 exited with code 0
    

    Rentrons un peu dans les détails.

    D’abord un fichier docker-compose.yaml qui dĂ©crit le rĂ©seau IPv4/IPv6 utilisĂ© pour les tests, l’image nginx-cert qui sera utilisĂ©e pour crĂ©er une autoritĂ© de certification et un certificat serveur de test, l’image nginx qui sera utilisĂ©e avec sa configuration et ses fichiers Ă  servir pour les tests, l’image epub et son paramĂ©trage (dont l’accĂšs au nginx) ainsi que le rĂ©pertoire de l’autoritĂ© de certification de tests et enfin l’image de la suite de tests qui est construit avec son Dockerfile et son rĂ©pertoire de dĂ©pĂŽt des fichiers EPUB.

    Le Dockerfile de tests est basĂ© sur une image Hurl (un outil pour faire des tests HTTP). On ajoute les fichiers de tests en .hurl, le script shell qui pilote le tout, on prĂ©voit d’avoir les paquets dont on aura besoin : bash (pas par dĂ©faut dans les Alpine), curl, openjdk17 (pour epubcheck), openssl, unzip (transitoirement), bind-tools et shellcheck. On installe epubcheck. Et on lance les tests par dĂ©faut.

    La configuration nginx de test Ă©coute en HTTP sur le port 80 en IPV4 et IPv6 et permet de dĂ©finir des chemins avec des rĂ©ponses en HTTP 301, 302, 308, 400, 401, 403, etc. jusqu’à 530 et mĂȘme 666 pour les codes invalides, ainsi qu’une redirection infinie.

    Dans les données de tests servies par nginx, on trouve des contenus du mauvais type, des contenus dans divers formats, une image trÚs grande et des images qui ne seront pas accessibles.

    Sont aussi présents deux fichiers de tests avec une extension en .hurl :

    • le test de vie et les chemins hors des contenus autorisĂ©s
    • les tests sur les contenus

    Vient enfin le script shell qui pilote le tout :

    • on dĂ©finit les variables pour les cibles IPv4/IPv6 que l’on veut utiliser dans les autres conteneurs Docker
    • on purge le stockage des EPUB sur disque
    • on lance les premiers tests (en IPv4 et IPv6, en HTTP 1.1 et en HTTP 2.0)
    • sur chaque EPUB produit, on lance epubcheck et on regarde si la validation donne le rĂ©sultat attendu (succĂšs ou Ă©chec)
    • si on est arrivĂ© jusque-lĂ  on Ă©crit que tout va bien et on dĂ©clenche un sourire de satisfaction.

    Les problématiques restantes

    Il y a quelques entrées encore ouvertes dans le suivi :

    • les images trop grandes (en octet), non rĂ©cupĂ©rables, de format inconnu, etc. : la suite de tests actuelle « couvre Â» le cas des images de plus de 5 MiB ou non rĂ©cupĂ©rables, avec des tests qui Ă©chouent, comme prĂ©vu, vu que c’est img qui est censĂ© faire le job de les Ă©viter. Cependant il pourrait ĂȘtre sympa de remplacer toute image non disponible/invalide par une image de remplacement « Image indisponible Â» du bon Content-Type et du bon nom (vu qu’elle est dĂ©clarĂ©e dans le MANIFEST).
    • les images trop grandes (en pixel) : globalement on revient Ă  la question des images que laisse passer img
    • les epub non fonctionnels en rĂ©daction et modĂ©ration : pour des questions de droits, la gĂ©nĂ©ration EPUB ne marche pas dans les espaces de rĂ©daction et de modĂ©ration, Ă  voir si on trouve un contournement ou si on Ă©vite de proposer le lien.

    Il y a la question habituelle de la montĂ©e de versions des dĂ©pendances (pour nous actuellement contraintes celles du code Ruby on Rails). Et des questions Ă  se poser sur l’avenir de nginx ?. Les dĂ©pendances pendant le fonctionnement amĂšnent aussi leur lot de contraintes.

    Conclusion ?

    Encore une fois, sans surprise et me rĂ©pĂ©tant, il reste des problĂ©matiques et du code Ă  faire pour les gĂ©rer (c’est rare un composant sans demandes d’évolution ou de correction). Yapuka (mais probablement plus tard, il faut aussi partager le temps avec les autres composants, ou avoir plus de contributions).

    epub rend la fonction que l’on attend de lui, mĂȘme si on pourrait faire un peu mieux. Plonger dans ce composant s’est avĂ©rĂ© assez intĂ©ressant et formateur (et nĂ©cessaire) : techniquement cela a Ă©tĂ© l’occasion de faire du Go, du docker et du docker-compose, du nginx, du hurl, de l’HTTP et de gĂ©rer des problĂ©matiques statique/dynamique et des dĂ©pendances. Il s’agissait encore de comprendre ce que faisait un code Ă©crit par une autre personne, de se poser des questions pour choisir les tests et le contenu de la documentation, de se demander pour quelles raisons tel ou tel choix a Ă©tĂ© fait, de rendre ce composant plus « contribuable Â», et de complĂ©ter le tout de façon dĂ©taillĂ©e avec une dĂ©pĂȘche.

    Commentaires : voir le flux Atom ouvrir dans le navigateur

    img, le cache d’images sur LinuxFr.org

    Le site LinuxFr.org utilise divers logiciels libres pour son fonctionnement et ses services : une large majoritĂ© provient de projets tiers (Debian, MariaDB, Redis - version d’avant le changement de licence, nginx, Postfix, conteneurs LXC et Docker, Ruby On Rails, Sympa, etc.) et d’autres composants sont dĂ©veloppĂ©s pour nos propres besoins. Cette derniĂšre catĂ©gorie comprend le code principal du site web en Ruby On Rails, et principalement 5 services autour : le cache d’images img, la tribune board, le convertisseur EPUB 3 epub, le partageur sur les rĂ©seaux sociaux share et le convertisseur LaTeX vers SVG svg. Cette dĂ©pĂȘche va s’intĂ©resser Ă  img, un code sous AGPLv3.

    Elle est nĂ©e d’une envie personnelle d’expliquer, documenter et montrer ce qui a Ă©tĂ© fait sur le cache d’images de LinuxFr.org, complĂ©tĂ©e d’une demande d’un « article technique sur le fonctionnement de ce cache, les choix techniques qui ont Ă©tĂ© faits, les erreurs commises donc Ă  Ă©viter
 Â».

      Sommaire

      Des images sur le site

      LinuxFr.org vous permet d’utiliser des images externes dans les contenus et commentaires du site. Ces images sont incluses en syntaxe markdown avec ![description textuelle](adresse "titre optionnel") (soit en saisissant directement du Markdown, soit en cliquant sur l’icĂŽne d’ajout d’image dans l’éditeur). Profitons-en pour rappeler que pour utiliser une image sur LinuxFr.org, vous devez vous assurer de respecter sa licence.

      Nous vous encourageons donc Ă  utiliser des images sous licence libre et Ă  citer les auteurs (c’est mĂȘme obligatoire pour les licences CC-by et CC-by-sa). Cette citation est tirĂ©e de la dĂ©pĂȘche d’annonce Un nouveau reverse-proxy cache pour les images externes sur LinuxFr.org de 2012.

      Il est aussi recommandĂ© de mettre une vraie description textuelle, qui finira dans l’attribut alt de la balise img utilisĂ©e pour l’accessibilitĂ© ou si l’image ne peut ĂȘtre chargĂ©e. Il peut ĂȘtre utile de lui donner un titre qui apparaĂźtra l’autre du survol de l’image Ă  la souris par exemple.

      Exemple :

      ![Logo LinuxFr.org](https://linuxfr.org/images/logos/linuxfr2_classic_back.png "L’actualitĂ© du logiciel libre et des sujets voisins (DIY, Open Hardware, Open Data, les Communs, etc.), sur un site francophone contributif gĂ©rĂ© par une Ă©quipe bĂ©nĂ©vole par et pour des libristes enthousiastes.")

      Logo LinuxFr.org

      Buts du cache d’images

      Les raisons évoquées à la mise en place de img (sans ordre particulier) :

      • la sĂ©curitĂ© : si une image externe n’est servie qu’en HTTP (en clair donc) et est appelĂ©e au milieu d’une page LinuxFr.org elle-mĂȘme servie en HTTPS, alors le navigateur va rĂąler sur le mĂ©lange des genres. img permet de servir toutes les images identiquement (par exemple en HTTPS, et avec le certificat de LinuxFr.org, via le serveur frontal devant img). À noter que ces images ne sont pas servies directement depuis le domaine principal linuxfr.org mais depuis un sous-domaine img.linuxfr.org pour Ă©viter que le JavaScript embarquĂ© dans les images en SVG puisse servir de vecteur d’attaque contre le site.
      • la protection de la vie privĂ©e des personnes visitant LinuxFr.org : seul LinuxFr.org voit les informations en provenance de leur navigateur (dont l’adresse IP). Les Ă©quipes d’administration des diffĂ©rents sites ne les voient plus (elles voient l’adresse IP du serveur LinuxFr.org).
      • une meilleure gestion du trafic : au lieu d’envoyer tout notre public chercher individuellement chaque image, LinuxFr.org la rĂ©cupĂšre une fois et la rend disponible. Si le site externe fournissant l’image est un serveur Ă  faibles ressources (liaison ADSL avec faible dĂ©bit montant par exemple), la mise en cache permet de garantir qu’il ne recevra qu’un faible volume de requĂȘtes (la rĂ©cupĂ©ration se faisant initialement toutes les 10 min tant que des demandes arrivent, le cache expirant aprĂšs 10 min).
      • la conservation des images : les images incluses depuis des sites externes peuvent ne plus ĂȘtre disponibles (l’entitĂ© a disparu, le serveur a Ă©tĂ© arrĂȘtĂ©, le domaine a Ă©tĂ© perdu, l’adresse a changĂ©, etc.). Nous avons donc un mĂ©canisme de cache pour que nous puissions continuer Ă  servir une image mĂȘme si elle devient indisponible.

      Parmi les conséquences de cette implémentation initiale, on peut citer :

      • si le fichier est changĂ© sur le serveur distant (modifiĂ©, converti dans un autre format), l’ancien fichier est servi jusqu’à la prochaine rĂ©cupĂ©ration et le nouveau fichier ne sera servi qu’à la prochaine rĂ©cupĂ©ration ;
      • si le fichier est supprimĂ© sur le serveur distant, l’image ne sera plus servie aprĂšs la prochaine rĂ©cupĂ©ration (car le serveur a rĂ©pondu que l’image n’existe plus) ;
      • il est possible de modifier l’image au passage : les images d’avatar sont retaillĂ©es pour une hauteur de 64 pixels par exemple ;
      • il est possible de bloquer des images : les images problĂ©matiques (pub/spam, contenus pour adultes, images injurieuses, etc.) peuvent ĂȘtre bloquĂ©es et ne plus ĂȘtre servies ;
      • par ailleurs img n’accepte de servir que les images connues de LinuxFr.org dont le poids fait moins de 5 MiB.

      À l’utilisation

      Lors de l’écriture d’un commentaire ou d’un contenu sur LinuxFr.org, une personne va ajouter une image externe via la syntaxe Markdown, par exemple ![Logo LinuxFr.org](https://linuxfr.org/images/logos/linuxfr2_classic_back.png)

      Ce qui donne à l’affichage :

      Logo LinuxFr.org

      Et cÎté code HTML :

      <img src="https://linuxfr.org/images/logos/linuxfr2_classic_back.png" alt="Logo LinuxFr.org">

      OK, mauvais exemple ce n’est pas une image externe, puisqu’elle est hĂ©bergĂ©e sur LinuxFr.org justement. Prenons un autre exemple ![April - Campagne d’adhĂ©sion](https://april.org/campagne-2024/relais/banniereCampagneApril.svg).

      Ce qui donne à l’affichage :

      April - Campagne d’adhĂ©sion

      Et cÎté code :

      <img src="//img.linuxfr.org/img/68747470733a2f2f617072696c2e6f72672f63616d7061676e652d323032342f72656c6169732f62616e6e6965726543616d7061676e65417072696c2e737667/banniereCampagneApril.svg" alt="April - Campagne d’adhĂ©sion" title="Source : https://april.org/campagne-2024/relais/banniereCampagneApril.svg">

      Donc on sert l’image via le sous-domaine img.linuxfr.org. On peut aussi noter le titre rempli automatiquement avec la source. Expliquons la nouvelle adresse :

      • // on sert en https si la page est en https et en http si la page est en http (c’est plutĂŽt un oubli qu’autre chose, vu que le site est uniquement en https)
      • img.linuxfr.org on sert depuis un sous-domaine du site
      • 68747470733a2f2f617072696c2e6f72672f63616d7061676e652d323032342f72656c6169732f62616e6e6965726543616d7061676e65417072696c2e737667 est la version en texte-vers-hexadĂ©cimal de l’adresse d’origine (68 pour h, 74 pour t (deux fois), 70 pour p, etc.). Il existe des sites et des outils en local pour faire cette conversion, mais cela ne concerne pas la simple utilisation du site.
      • banniereCampagneApril.svg on met Ă  la fin le nom du fichier pour ĂȘtre sympa si vous voulez sauver l’image en local avec un nom plus explicite

      Ceci Ă©tait le cas oĂč tout se passe bien, comme prĂ©vu, comme le voulait la personne qui voulait utiliser une image externe.

      Voyons maintenant ce qui se passe dans le cas pas si rare oĂč la personne a donnĂ© une adresse d’image invalide, une adresse ne pointant pas vers une image vers autre chose (cas extrĂȘmement frĂ©quent), une image trop grosse (plus de 5 MiB), etc. Il se passe la mĂȘme chose cĂŽtĂ© code, mais cĂŽtĂ© affichage, pas d’image, et on voit seulement le texte alternatif dans son navigateur. Dans les coulisses, img a rĂ©pondu 404, cette adresse n’est pas disponible.

      On note donc qu’une mĂȘme image servie en http:// ou en https:// aura une adresse convertie en hexadĂ©cimal diffĂ©rente, donc sera vue comme une autre image par img. MĂȘme chose si le serveur externe accepte des adresses sans tenir compte de la casse, ou si on rajoute des paramĂštres dans l’adresse comme « ?mot_magique=merci Â».

      CÎté code Ruby on Rails

      Un contenu ou commentaire est en cours de crĂ©ation et une image externe a Ă©tĂ© mentionnĂ©e. Le code de gestion des images va vĂ©rifier que l’image est dĂ©clarĂ©e dans redis (crĂ©er l’entrĂ©e img/<adresse> avec adresse l’adresse de l’image en clair, ajouter un champ created_at avec l’horodatage, ajouter l’adresse dans la liste des derniĂšres images img/latest) et renvoyer l’adresse via img.

      Le code peut aussi modifier le champ status d’une image dans redis pour mettre ou enlever un blocage (valeur Blocked) par l’équipe du site, et l’ajouter/enlever de la liste des images bloquĂ©es img/blocked.

      CÎté img

      Les schémas dans la documentation du service img explicitent les possibilités et les comportements.

      Il est possible de faire un GET /status et on obtient une rĂ©ponse HTTP 200 avec un contenu OK. C’est utile pour tester que le service est lancĂ© (depuis l’intĂ©rieur de la plateforme).

      Sinon, on peut envoyer des requĂȘtes GET /img/<adresse_en_hexa> or GET /img/<adresse_en_hexa>/<nom_de_fichier> pour les images, et GET /avatars/<adresse_en_hexa> ou GET /avatars/<adresse_en_hexa>/<nom_de_fichier> pour les avatars.

      En se limitant aux requĂȘtes lĂ©gitimes, le comportement de img est le suivant :

      • l’adresse demandĂ©e a Ă©tĂ© prĂ©cĂ©demment dĂ©clarĂ©e (dans redis par la partie code Ruby On Rails) sinon il rĂ©pond 404 ;
      • l’adresse demandĂ©e n’est pas bloquĂ©e par l’équipe du site sinon il rĂ©pond 404 ;
      • l’adresse est dĂ©jĂ  dans le cache disque, alors il renvoie l’image ;
      • l’adresse n’est pas dans le cache disque et la rĂ©cupĂ©ration Ă©choue, il renvoie 404 (et va noter temporairement l’échec dans img/err/<uri>) ;
      • l’adresse n’est pas dans le cache disque et la rĂ©cupĂ©ration a lieu (notĂ© temporairement dans img/update/<uri>): si le serveur rĂ©pond positivement Ă  la demande, avec une image comme attendue, pas trop volumineuse, alors on la met en cache disque. Si c’est un avatar, on peut retailler l’image. On aura des champs supplĂ©mentaires stockĂ©s type avec la nature de l’image (en-tĂȘte Content-Type), checksum avec un hachage SHA1 et etag avec la valeur ETag (entĂȘte ETag).

      Le cache est rafraßchi réguliÚrement.

      img est un binaire statique en Go. Il offre des options pour dĂ©finir le couple adresse:port d’écoute, pour dĂ©finir oĂč envoyer les logs, pour se connecter Ă  une base redis, pour dĂ©finir le rĂ©pertoire du cache disque, pour choisir le User-Agent qui sera utilisĂ© pour les requĂȘtes externes, pour dĂ©finir l’avatar qui sera renvoyĂ© par dĂ©faut, et la possibilitĂ© de le lancer uniquement en mode audit interne pour vĂ©rifier la cohĂ©rence et l’état des donnĂ©es et des fichiers.

      Dans les logs on va trouver des infos comme :

      2024/10/20 20:39:24 Status code of http://example.invalid/exemple1.png is: 404
      2024/10/20 20:39:24 Fail to fetch http://example.invalid/exemple1.png (serve from disk cache anyway)
      2024/10/20 20:44:12 Fetch http://example.invalid/exemple2.png (image/png) (ETag: "be5e-4dba836030980")
      2024/10/20 20:44:12 http://example.invalid/exemple3.png has an invalid content-type: text/html;charset=UTF-8
      2024/10/20 20:44:12 Fail to fetch http://example.invalid/exemple3.png (serve from disk cache anyway)
      

      Ici l’exemple 1 est dĂ©jĂ  en cache et peut ĂȘtre servi mĂȘme si on Ă©choue Ă  le rĂ©cupĂ©rer Ă  ce moment-lĂ . L’exemple 2 vient d’ĂȘtre rĂ©cupĂ©rĂ©. L’exemple 3 a dĂ©sormais une adresse invalide (qui renvoie une page HTML au lieu d’une image) mais il existe en cache une image prĂ©cĂ©demment rĂ©cupĂ©rĂ©e.

      Historique

      img a Ă©tĂ© crĂ©Ă© par Bruno Michel en 2012. Adrien Kunysz amĂšne 5 commits en novembre 2013, mais globalement Bruno est le seul Ă  travailler dessus (43 commits) jusqu’en 2018. img fait le job et il n’est pas besoin d’y retoucher trop souvent.

      En 2022, Bruno quitte l’équipe du site, et par ailleurs il y a des montĂ©es de versions et des migrations Ă  faire sur les serveurs de LinuxFr.org, et img fait partie des services Ă  reprendre en main. Ce qui veut dire le comprendre, le documenter et au besoin l’amĂ©liorer.

      Bref je dĂ©cide de me plonger dans img (2022-2024), car a priori ce n’est pas le composant le plus compliquĂ© du site (il vit dans son coin, il offre une interface, c’est du Go, donc on a un binaire seulement Ă  gĂ©rer).

      Étape 1 : je vais commencer par ajouter un Dockerfile permettant de recompiler img dans un conteneur, en contrĂŽlant la version de Go utilisĂ©e, en effectuant une dĂ©tection d’éventuelles vulnĂ©rabilitĂ©s au passage avec govulncheck. Cela me permet de valider que l’on sait produire le binaire d’une part, et que l’on offre Ă  tout le monde la possibilitĂ© de contribuer facilement sur ce composant.

      Étape 2 : je vais tester le composant pour vĂ©rifier qu’il fonctionne comme je le pense et qu’il fait ce qu’on attend de lui. Je vais ajouter une suite des tests qui couvrent les diffĂ©rentes fonctionnalitĂ©s et les vĂ©rifient en IPv4 et en IPv6, en HTTP 1.1 et en HTTP 2.0. Les tests utilisent Hurl et docker-compose (avec des images redis et nginx), et encore une fois l’idĂ©e de donner la possibilitĂ© de contribuer facilement. Ils comprennent des tests de types de contenus non pris en charge, le test de la limite Ă  5 MiB, diffĂ©rents types d’images, le test de vie, des appels erronĂ©s (mauvais chemin, mauvaise mĂ©thode, etc). Le choix des cas de tests est basĂ© sur le trafic rĂ©ellement constatĂ© sur le serveur de production, sur les diffĂ©rents cas dans le code et un peu sur l’expĂ©rience du testeur.

      Étape 2,5 : l’avatar par dĂ©faut renvoie sur le site de production, y compris sur les tests en dĂ©veloppement en local et sur le serveur de test du site. J’en profite pour ajouter un paramĂštre pour cela (et cela permettra de passer du PNG au SVG par dĂ©faut).

      Étape 3 : encore une fois essayons de simplifier la vie d’hypothĂ©tiques personnes contributrices. Une petite modification pour que hurl et redis soient fournis via docker-compose et ne soient plus nĂ©cessaires sur le poste de dĂ©veloppement.

      Étape 4 : il est temps de documenter plus le fonctionnement. J’avais dĂ©jĂ  dĂ©crit les infos stockĂ©es dans redis, mais pour comprendre le systĂšme de cache, autant fournir des diagrammes pour illustrer ce qui se passe lors d’une requĂȘte et comment on passe d’un Ă©tat Ă  un autre. C’est aussi l’occasion de complĂ©ter la suite de tests en ajoutant des tests avant et aprĂšs expiration du cache, histoire de pouvoir documenter ces cas prĂ©cis.

      Étape 5 : en cas d’échec de rĂ©cupĂ©ration, une image Ă©tait indisponible jusqu’à la prochaine rĂ©cupĂ©ration (donc potentiellement pendant 10 min). Autant servir l’ancienne version en cache lorsque cela se produit : je modifie le code et les tests en consĂ©quence.

      Étape 6 : je sais que certaines images ont Ă©tĂ© perdues, que des adresses d’images ont toujours Ă©tĂ© erronĂ©es, que des contenus et commentaires ont Ă©tĂ© supprimĂ©s et qu’il n’y a donc plus lieu de garder les images associĂ©es. Je dĂ©cide d’implĂ©menter dans img un audit interne qui indiquera si des anomalies sont prĂ©sentes dans redis, si des images sont indisponibles ou si des entrĂ©es dans le cache disque ne correspondent plus Ă  aucune image. Et j’ajoute cet audit dans la suite de tests.

      Étape 7 : j’écris une dĂ©pĂȘche pour parler de tout cela.

      Évolutions rĂ©centes

      Dockerfile

      Le fichier Dockerfile du projet permet :

      • de partir d’une image officielle Go d’une version donnĂ©e, basĂ©e sur une distribution minimale Alpine
      • de l’utiliser pendant la construction en prenant la liste des dĂ©pendances, en les tĂ©lĂ©chargeant, en prenant l’unique fichier source img.go et en le compilant statiquement avec l’option pour retirer les chemins de compilation
      • de rechercher les Ă©ventuelles vulnĂ©rabilitĂ©s avec govulncheck
      • d’ajouter le paquet tzdata pour avoir les dĂ©finitions fuseaux horaires (nĂ©cessaire pour les conversions de/vers GMT pour les entĂȘtes type Last-Modified).
      • de repartir d’une base Alpine en y mettant les dĂ©finitions de fuseaux horaires et le binaire issus de la partie construction, de dĂ©clarer le port d’écoute et de lancer le binaire avec des variables disposant de valeurs par dĂ©faut.

      La suite de tests

      Pour l’utiliser, c’est assez simple, il faut aller dans le rĂ©pertoire tests et lancer un docker-compose up --build, qui va produire le conteneur contenant img, et dĂ©marrer le redis et le nginx prĂ©configurĂ©s pour les tests. Si tout va bien, on attend, et au bout d’un moment il s’affiche :

      linuxfr.org-img-test_1  | All tests look good!
      tests_linuxfr.org-img-test_1 exited with code 0
      

      Rentrons un peu dans les détails.

      D’abord un fichier docker-compose.yaml qui dĂ©crit le rĂ©seau IPv4/IPv6 utilisĂ© pour les tests, l’image redis qui sera utilisĂ©e (stockage gĂ©rĂ© par docker), l’image nginx qui sera utilisĂ©e avec sa configuration et ses fichiers Ă  servir pour les tests, l’image img et son paramĂ©trage (dont l’accĂšs au redis et au nginx) ainsi que le rĂ©pertoire du cache et enfin l’image de la suite de tests qui est construit avec son Dockerfile, prĂ©vue pour faire du Docker-in-Docker et avoir accĂšs au cache img et aux fichiers nginx.

      Le Dockerfile de tests est basĂ© sur une image Hurl (un outil pour faire des tests HTTP). On ajoute les fichiers de tests en .hurl, le script shell qui pilote le tout, on prĂ©voit d’avoir les paquets dont on aura besoin : bash (pas par dĂ©faut dans les Alpine), coreutils, docker et xxd (pour les conversions texte vers hexadĂ©cimal). Et on lance les tests par dĂ©faut.

      La configuration nginx de test Ă©coute en HTTP sur le port 80 en IPV4 et IPv6 et permet de dĂ©finir des chemins avec des rĂ©ponses en HTTP 301, 302, 308, 400, 401, 403, etc. jusqu’à 530 et mĂȘme 666 pour les codes invalides, ainsi qu’une redirection infinie.

      Dans les donnĂ©es de tests servies par nginx, on trouve des contenus du mauvais type, une image destinĂ©e Ă  ĂȘtre bloquĂ©e, des images dans divers formats, une image trĂšs grande en pixels mais pas trop en octets, une image trop grande en octets, et un avatar Ă  servir par dĂ©faut.

      Sont aussi présents cinq fichiers de tests avec une extension en .hurl :

      • le test de vie et les chemins hors img/ et avatars/
      • les tests sur les avatars : adresse valide ou invalide, image inexistante, bon et mauvais types, comportements sur les diffĂ©rents codes HTTP et sur une boucle de redirection infinie
      • les tests sur les images (dĂ©coupĂ©s en trois parties, la partie initiale, la partie entre la rĂ©cupĂ©ration initiale et l’expiration du cache et enfin la partie aprĂšs la rĂ©cupĂ©ration et l’expiration du cache.

      Vient enfin le script shell qui pilote le tout :

      • on dĂ©finit les variables pour les cibles IPv4/IPv6 et les binaires redis et img que l’on veut utiliser dans les autres conteneurs Docker
      • on liste les images dans diffĂ©rentes catĂ©gories :
        • celles qui vont Ă©chouer et ne comporteront donc qu’une entrĂ©e dans redis sans rien dans le cache disque (avec sous-catĂ©gories possibles bloquĂ©es/non-bloquĂ©es)
        • les images devant ĂȘtre en erreur
        • les images qui iront normalement dans le cache
      • on prĂ©pare des images qui seront altĂ©rĂ©es plus tard
      • on purge le cache sur disque, on nettoie redis et on dĂ©clare toutes nos images comme le faire le code Ruby on Rails. Certaines sont dĂ©clarĂ©es bloquĂ©es pour les tests.
      • on lance les premiers tests (en IPv4 et IPv6, en HTTP 1.1 et en HTTP 2.0)
      • on modifie certaines images pour simuler un changement sur le serveur externe, une suppression sur le serveur externe ou un blocage par l’équipe de site
      • on lance les tests post-rĂ©cupĂ©ration initiale mais avant l’expiration du cache (toujours avec toutes les variantes)
      • on force l’expiration du cache
      • on lance les tests post-expiration du cache (toujours avec toutes les variantes)
      • si on est arrivĂ© jusqu’ici, c’est qu’on a passĂ© tous les tests Hurl, alors maintenant on recompte ce que l’on a dans redis et sur disque et on vĂ©rifie si ça correspond Ă  nos attentes
      • on nettoie les images mises volontairement en Ă©chec
      • on lance le test d’audit interne qui doit nous dire que tout va bien
      • si on est arrivĂ© jusque-lĂ  on Ă©crit que tout va bien et on dĂ©clenche un sourire de satisfaction.

      L’audit interne

      L’objectif est de vĂ©rifier la cohĂ©rence des donnĂ©es dans redis, si des images sont indisponibles ou si des entrĂ©es dans le cache disque ne correspondent plus Ă  aucune image.

      Le binaire d’img peut donc ĂȘtre appelĂ© en mode audit et lancer des contrĂŽles internes.

      D’abord il collecte la liste des fichiers dans le cache disque.

      Ensuite il vérifie que toutes les images listées dans les derniÚres images (img/latest) existent comme entrées individuelles.

      Puis il vĂ©rifie s’il existe des images bloquĂ©es (il rĂąlera s’il y en a) et si chacune existe comme entrĂ©e individuelle le cas Ă©chĂ©ant.

      Ensuite on parcourt tous les entrĂ©es individuelles d’images :

      • on rĂąle si on tombe sur une entrĂ©e img/updated/ ou img/err/ sans date d’expiration
      • on rĂąle si on tombe sur une entrĂ©e img/ sans champ created_at, sans type ou d’un type inconnu, sans checksum, avec un statut inconnu, une image bloquĂ©e non prĂ©sente dans les images bloquĂ©es, un champ inconnu, une prĂ©sence inattendue dans le cache disque, etc. Et on marque les images que l’on a vu passer comme attendu dans le cache.
      • on rĂąle sur tous les fichiers du cache restants (ne correspondant Ă  aucune image)
      • si on a rĂąlĂ©, on renvoie 1, sinon 0

      Le grand nettoyage

      img a fonctionnĂ© pendant 12 ans en production : il a rencontrĂ© des bugs, des comportements inattendus, des contenus et commentaires ont Ă©tĂ© supprimĂ©s ou rĂ©Ă©ditĂ©s, etc. Il est donc probable qu’il y ait besoin d’aller dĂ©poussiĂ©rer un peu tout cela et de retirer ce qui est inutile.

      Les traces du grand nettoyage sont d’abord visibles dans la rĂ©trospective de la premiĂšre quinzaine de septembre 2024 :

      • une « image Â» sur sept prĂ©sente un souci (n’est pas une image, adresse invalide, trop grosse, etc.) et n’est donc pas dans le cache sur disque (ce qui a conduit Ă  pas mal de taf sur la partie gestion des images)
      • les types de contenu (Content-Type) en provenance de sites variĂ©s et divers, c’est quelque chose
 entre les « image/JPEG » ou « image/PNG » en majuscules parce que, les charset=utf-8 ou UTF-8 ou
 sur du binaire, les name= qui ne sont pas dans la norme
 Wikimedia renvoie aussi du profile="https://www.mediawiki.org/wiki/Specs/SVG/1.0.0" (pareil ça semble en dehors de tout standard).

      D’abord j’attaque le sujet la fleur au fusil en me disant que ça va passer crĂšme, je fais un joli tableau qui rĂ©sume l’état initial :

                                    img/<uri>   img/updated/<uri>   img/err/<uri>   blocked
      total                           25565 -21       634               160            5
      
      no created_at                      23 -23         0                 0            0
      created_at                       2857 -3          0                 5            1
      created_at+type                   222             0                 0            0
      total not in cache               3104 -26         0                 0            0
      
      created_at+type+checksum(+etag) 22463 +5        634               155            4
      
      files in cache                  22778 +5
      

      Donc on a officiellement 25 565 images, mais 23 sont mal crĂ©Ă©es (Ă©tat thĂ©oriquement impossible hors race condition), 222 sont incomplĂštes (Ă©tat thĂ©oriquement impossible race condition), 22 463 sont attendues en cache et on a 22 778 fichiers dans le cache. Ça part mal. Je nettoie en premier le plus facile (on voit le delta +/- de mes corrections). Et on arrive Ă  une situation oĂč une image sur sept prĂ©sente alors un souci et il faut gĂ©rer un grand volume de corrections Ă  faire.

      Parmi les soucis on trouve des types de contenus inattendus (image/PNG ou image/JPEG avec majuscules, image, des images binaires annoncĂ©es avec un charset, des types invalides comme image/jpg au lieu de image/jpeg, etc), des erreurs de notre lectorat (mauvais lien, mauvais copier-coller, lien vers une page web au lieu d’une image), mais aussi des espaces insĂ©cables et autres blancs inopportuns, des guillemets convertis, des doubles scheme (http://https:// ou http://file://).

      AprĂšs cela se cache une autre catĂ©gorie encore plus pĂ©nible : les images que l’on a en cache, mais qui ne sont plus utiles au site : par exemple celles qui Ă©taient dans des contenus ou commentaires supprimĂ©s (notamment le spam), celles qui Ă©taient dans des commentaires ou contenus rĂ©Ă©ditĂ©s depuis, etc.

      Un problĂšme connu est devenu vite pĂ©nible : on n’a pas d’association entre les images externes et les contenus/commentaires concernĂ©s. Donc il faut d’abord extraire la liste de toutes les dĂ©clarations d’images externes des 12 tables SQL oĂč l’on peut trouver des images et des avatars, sous forme HTML ou Markdown.

      Ensuite il faut sortir toutes les entrĂ©es dans redis et regarder si on les retrouve en clair ou converties en hexadĂ©cimal dans l’extraction SQL.

      Et par sécurité on fera une double vérification pour celles détectées en erreur, en relançant une recherche en base (attention à la casse dans la recherche texte).

      Au final, on peut supprimer des milliers d’entrĂ©es redis et de fichiers dans le cache.

      Et un jour l’audit dit :

      Connection 127.0.0.1:6379 0
      2024/10/19 12:11:21 Sanity check mode only
      2024/10/19 12:11:37 Files in cache: 17926
      2024/10/19 12:11:39 Total img keys in redis: 18374
      OK
      

      Ça aura pris un mois et demi (l’audit a Ă©tĂ© fusionnĂ© le 8 septembre 2024), certes pas en continu, mais ça a Ă©tĂ© long et guĂšre palpitant de faire ce grand mĂ©nage. Et j’ai refait une seconde passe du traitement complet la semaine d’aprĂšs pour vĂ©rifier que tout se passait correctement et que les soucis rĂ©siduels aprĂšs tout ça Ă©taient minimes ou nuls.

      Parmi les anecdotes, Web Archive / archive.org a eu sa fuite de comptes utilisateurs et a Ă©tĂ© indisponible sur la fin (ce qui rendait compliquĂ© la rĂ©cupĂ©ration d’images perdues ou leur remplacement par un lien valide par exemple). Et, mentionnĂ© dans la rĂ©trospective de la seconde quinzaine de septembre 2024, un compte de spammeur de 2015 supprimé  mieux vaut tard que jamais : dĂ©tectĂ© parce que comme beaucoup de visiteurs, le spammeur ne fait pas la diffĂ©rence entre un lien vers un document et l’ajout d’une image.

      Les problématiques restantes

      Il y a la question habituelle de la montĂ©e de versions des dĂ©pendances (pour nous actuellement contraintes celles du code Ruby on Rails) et du remplacement des composants devenus non-libres (migrer vers valkey plutĂŽt que redis ? Questions Ă  se poser sur l’avenir de nginx ?).

      On pourrait aussi ajouter la prise en charge du TLS et d’un certificat X.509 directement dans img plutĂŽt que dans un frontal. Mais ce n’est utile que si on les sĂ©pare sur deux serveurs distants, ce qui n’est pas le cas actuellement. Donc mĂȘme si ça ne paraĂźt pas compliquĂ© Ă  faire, ce n’est pas urgent.

      Ensuite une entrĂ©e de suivi existe pour sĂ©parer le cache des avatars du cache des autres images : les contraintes pour le cache des avatars Ă©tant diffĂ©rentes de celui des autres images, le stockage en cache devrait ĂȘtre diffĂ©rent. Cela reste un problĂšme mineur. Le changement doit d’abord ĂȘtre fait cĂŽtĂ© Ruby on Rails pour dĂ©finir les avatars avec des clĂ©s redis diffĂ©rentes (genre avatars/ au lieu de img/). Ensuite on peut modifier img pour sĂ©parer le traitement des requĂȘtes HTTP /img/<adresse_hexa> vers les clĂ©s redis img/<adresse> et le cache disque des images par rapport aux requĂȘtes /avatars/<adresse_hexa> vers les clĂ©s avatars/<adresse> et le cache des avatars. Il faudra aussi dĂ©placer les avatars stockĂ©s dans l’actuel cache des images dans leur propre cache. Et lĂ  on devrait pouvoir avoir la mĂȘme adresse dans les deux caches mais avec un rendu Ă©ventuellement diffĂ©rent.

      Un autre problĂšme concerne la non-association des contenus ou commentaires avec les images externes qu’ils contiennent, ce qui rend l’administration des anciennes images un peu pĂ©nible. Le fait que les contenus et commentaires peuvent ĂȘtre rĂ©Ă©ditĂ©s ou simplement prĂ©visualisĂ©s (donc que des images peuvent ĂȘtre supprimĂ©es et d’autres ajoutĂ©es) vient compliquer un peu la tĂąche. Actuellement un ensemble de scripts permettent d’obtenir ces infos et fournissent un contournement, mais ça reste un peu laborieux.

      Un cache rafraĂźchi pĂ©riodiquement conserve les images pour Ă©viter de surcharger le site d’origine, pas si le site a changĂ©, dĂ©placĂ© ou perdu l’image. La modification pour servir depuis le cache disque en cas d’échec de rĂ©cupĂ©ration couvre le cas de la disparition d’une image avec une erreur sur l’adresse, pas celui oĂč le serveur rĂ©pond une mauvaise image. Il y a donc une autre entrĂ©e de suivi images et disparition du web Ă©voquant l’augmentation des soucis sur les images externes avec un cache rafraĂźchi, en raison des domaines rĂ©cupĂ©rĂ©s par des spammeurs et autres pĂ©nibles, ou perdus ou utilisĂ©s pour du phishing (imageshack.us, aprĂšs framapic, pix.toilelibre, etc.). Diverses problĂ©matiques sont mentionnĂ©es comme la perte d’information et donc la diminution de l’intĂ©rĂȘt des contenus anciens, la prime aux pĂ©nibles du rĂ©fĂ©rencement SEO qui pourrissent le net en rĂ©cupĂ©rant les vieux domaines, la modification possible des images publiĂ©es. Pour rĂ©soudre cela techniquement, ça nĂ©cessite de suivre les images et les domaines perdus, et d’intervenir de façon rĂ©guliĂšre. Ou bien de ne plus rafraĂźchir le cache (que cela soit jamais, aprĂšs la publication ou au bout d’un certain temps aprĂšs la publication). Pour juste Ă©viter la perte d’info, il est possible de remplacer par une image locale rĂ©cupĂ©rĂ©e d’une archive du net type archive.org, avec le cĂŽtĂ© « pĂ©nible Ă  faire Â» et sans garantie que ça soit toujours possible (merci waybackpy).

      Enfin une troisiĂšme entrĂ©e de suivi suggĂšre l'hĂ©bergement des images des dĂ©pĂȘches (et Ă©ventuellement des journaux), idĂ©alement en permettant d’avoir une version modifiĂ©e d’une image en changeant sa taille. On peut citer en vrac comme problĂ©matiques la responsabilitĂ© lĂ©gale, l’éventuelle volumĂ©trie, l’impossibilitĂ© de corriger une image publiĂ©e facilement par la personne qui l’a soumise, la centralisation et la perte de rĂ©fĂ©rencement pour des tiers, l’éventuelle rĂ©troactivitĂ© et le traitement de l’historique, le fait qu’il faut traiter tous les autres contenus/commentaires pouvant accueillir des images, etc. Autre question, faut-il diffĂ©rencier les images passĂ©es en modĂ©ration a priori de celles en modĂ©ration a posteriori ?

      Conclusion ?

      Bref sans surprise, il reste des problĂ©matiques et du code Ă  faire pour les gĂ©rer (c’est rare un composant sans demandes d’évolution ou de correction). Yapuka (mais probablement plus tard, il faut aussi partager le temps avec les autres composants, ou avoir plus de contributions).

      img apporte les fonctionnalitĂ©s que l’on attendait de lui mĂȘme si on pourrait faire mieux. Plonger dans ce composant s’est avĂ©rĂ© assez intĂ©ressant et formateur (et nĂ©cessaire) : techniquement cela a Ă©tĂ© l’occasion de faire du Go, du docker et du docker-compose, du redis et du nginx, du hurl et de l’HTTP. Et de comprendre ce que faisait un code Ă©crit par une autre personne, de se poser des questions pour choisir les tests et le contenu de la documentation, de se demander pour quelles raisons tel ou tel choix a Ă©tĂ© fait, de rendre ce composant plus « contribuable Â», et de complĂ©ter le tout de façon dĂ©taillĂ©e avec une dĂ©pĂȘche. Reste Ă  savoir si j’ai rĂ©pondu Ă  l’attente d’un article technique sur le fonctionnement de ce cache, les choix techniques qui ont Ă©tĂ© faits, les erreurs commises donc Ă  Ă©viter
 et la rĂ©ponse est Ă  trouver dans les commentaires.

      Commentaires : voir le flux Atom ouvrir dans le navigateur

      L’auteur de Nginx enfourche le proprio

      15 février 2024 à 18:01

      Maxim Dounin, l'un des principaux dĂ©veloppeurs de NGINX (il est Nginx disent mĂȘme certains) se barre et crĂ©e un fork.

      Nginx est l'un des principaux serveurs web, voire le plus utilisĂ© mais ça dĂ©pend des statistiques. Il est rĂ©putĂ© pour sa vitesse, sa lĂ©gĂšretĂ© et sa soliditĂ©. La version libre est au coeur d'Nginx, aussi costaud, rapide et sĂ©curisĂ©e que la version avec quelques extensions propriĂ©taire. Malheureusement, ça pourrait ne plus ĂȘtre le cas :

      En 2019, F5 Networks a rachetĂ© la sociĂ©tĂ© derriĂšre Nginx. En 2022, F5 a fermĂ© les bureaux de Moscou, signant un accord avec Maxim Dounin qui continuait bĂ©nĂ©volement Ă  travailler sur Nginx. Ayant quittĂ© la sociĂ©tĂ©, il veillait sur cette piĂšce essentielle du web et du libre. Or en 2024, la nouvelle direction d'F5 n'entend que pouic Ă  la technique et se focalise sur le marchĂ©. Elle s'est mĂȘlĂ©e des questions de sĂ©curitĂ©, prĂ©fĂ©rant une version libre moins robuste afin de vendre plus de prestations — d'aprĂšs Maxim Dounin.

      Le 14 février, il en a eu marre et a lancé le projet Freenginx pour garantir un développement sans interférences marketing.

      Commentaires : voir le flux Atom ouvrir dans le navigateur

      Échirolles libĂ©rĂ©e ! La dĂ©googlisation (3)

      Par : Framasoft
      24 mars 2023 Ă  02:42

      Voici dĂ©jĂ  le troisiĂšme volet du processus de dĂ©googlisation de la ville d’Échirolles (si vous avez manquĂ© le dĂ©but) tel que Nicolas Vivant nous en rend compte. Nous le re-publions volontiers, en souhaitant bien sĂ»r que cet exemple suscite d’autres migrations vers des solutions libres et plus respectueuses des citoyens.


      DĂ©googlisation d’Échirolles, partie 3 : les solutions

      par Nicolas Vivant

      L’organisation est structurĂ©e, les enjeux sont posĂ©s, place Ă  la mise en Ɠuvre opĂ©rationnelle.

      L’ñge de la maturitĂ©

      Les informaticiens utilisent des logiciels libres, pour le fonctionnement de leur systĂšme d’information, depuis toujours. Pas par militantisme, dans la plupart des cas, mais simplement parce que ce sont les plus stables, les plus sĂ»rs et souvent les meilleurs. L’immense majoritĂ© des serveurs web, par exemple, fonctionne avec Apache ou, de plus en plus, NGINX, et tournent sur des systĂšmes d’exploitation libres (GNU/Linux, souvent).

      La nouveautĂ© concerne le poste client, la communication et les applications mĂ©tier. Dans ces trois domaines, les logiciels libres ont atteint un niveau de maturitĂ© inĂ©dit jusqu’alors. L’absence de publicitĂ© et de marketing ne favorise pas la dĂ©couverte des solutions disponibles, mais certains logiciels ont fait leur chemin dans les organisations. Comment ? Par le bouche Ă  oreille, les Ă©changes sur les rĂ©seaux sociaux, la communication (et le travail) de diffĂ©rentes associations et structures Ă©tatiques (Adullact, April, Framasoft, Etalab, etc.) ou la contagion entre collectivitĂ©s : une collectivitĂ© utilise un logiciel, j’en entends parler (ou je l’utilise dans mes Ă©changes avec elle), je me renseigne et je finis par l’adopter.

      Souvent, plusieurs solutions libres existent pour un mĂȘme usage. L’exemple de la messagerie Ă©lectronique est parlant. Microsoft (avec Outlook/Exchange) et Google (Gmail) sont dominants sur le marchĂ©. Pourtant, il existe au moins 6 alternatives « open source Â» : Zimbra, BlueMind, OpenXchange, SOGo, Kolab et eGroupWare qui ont peu ou prou les mĂȘmes fonctionnalitĂ©s ? Comment faire un choix ?

      Savoir faire un choix

      À Échirolles, aprĂšs que les aspects fonctionnels sont validĂ©s, nous nous appuyons sur 4 piliers :

      → Le schĂ©ma directeur Ă©voque des solutions gĂ©rĂ©es et maintenues en interne et met en avant les concepts de souverainetĂ© numĂ©rique et d’autonomie vis-Ă -vis des Ă©diteurs. C’est une premiĂšre base de jugement : lesquelles de ces solutions correspondent le mieux aux enjeux identifiĂ©s par nos Ă©lus ?
      → L’analyse technique permet de vĂ©rifier les qualitĂ©s intrinsĂšques de la solution, son interopĂ©rabilitĂ© correcte avec les outils existants, notre capacitĂ© Ă  la gĂ©rer en autonomie, sa cohĂ©rence avec notre prĂ©occupation de l’impact environnemental
      → La coopĂ©ration intercommunale nous permet d’avoir une idĂ©e des problĂšmes rencontrĂ©s, de la rĂ©activitĂ© des Ă©ventuels prestataires et, globalement, du niveau de satisfaction des collĂšgues.
      → Le coĂ»t est Ă©valuĂ© sur devis (le code de la commande publique nous contraignant, Ă  raison, Ă  la consultation de plusieurs acteurs et Ă  la justification de nos choix) et par la vĂ©rification des rĂ©fĂ©rences existantes mĂȘme si pour nous, bien souvent, libre veut dire gratuit.

      Les échanges entre services, et en interne au sein de la direction de la stratégie numérique, éclairent également nos décisions.

      Go go go !

      Sur la base de ces critĂšres, Échirolles a fait le choix de SOGo, une solution fonctionnelle, Ă©prouvĂ©e (par Gandi, notamment, en France), solide et qui semble le mieux correspondre Ă  ce que sont nos orientations. D’autres communes font d’autres choix, privilĂ©giant d’autres critĂšres (le nombre et la qualitĂ© des prestataires susceptibles d’apporter une assistance sur la solution, par exemple).

      Le choix d’une solution de Cloud et d’édition collaborative (alternative Ă  Microsoft Teams ou Google Workspace) s’est fait selon les mĂȘmes critĂšres. Pour la partie Cloud/gestion de fichiers, la coopĂ©ration intercommunale nous a conduit Ă  Ă©liminer Alfresco Share, peu adaptĂ© Ă  nos usages. Pour l’édition collaborative, nous avons prĂ©fĂ©rĂ© Collabora Ă  OnlyOffice, sur les conseils de diffĂ©rentes associations et partenaires et parce que le projet nous semblait mieux correspondre Ă  nos valeurs.

      Enfin, le passage Ă  un systĂšme d’exploitation libre pour les postes clients est entamĂ© Ă  Échirolles. La ville a fait le choix de Zorin OS, pour de nombreuses raisons qui ont Ă©tĂ© expliquĂ©es dans des articles plus complets :

      → La stratĂ©gie gagnante d’une migration du poste de travail sous Linux (LeMagIT)
      → Le poste de travail Linux (Ă©tude d’ATOS rĂ©alisĂ©e par Arawa pour le MinistĂšre des Finances)

      Pour le reste, nous utilisons trop de logiciels libres pour les lister tous (les systĂšmes de gestion de bases de donnĂ©es, par exemple). Certains sont en place depuis trĂšs longtemps (Firefox, Thunderbird, 7zip
), d’autres ont Ă©tĂ© installĂ©s rĂ©cemment (Peertube, Nextcloud, Joplin, Psono
), d’autres sont en cours de dĂ©ploiement (Proxmox, Maarch courrier, Keycloak
). Quelques-uns, mĂ©connus ou parce qu’ils ont fait l’objet d’une mise en Ɠuvre particuliĂšre, ont fait l’objet d’articles dĂ©diĂ©s sur mon blog : Mastodon, OBS Studio, Porteus Kiosk, BigBlueButton, etc.

      Liste non exhaustive de logiciels libres utilisĂ©s Ă  Échirolles

      Postes clients :

      Applications collectivitĂ© :

      Applications DSI :

      Communication :

      DĂ©matĂ©rialisation :

      À noter l’excellente initiative de l’Adullact Ă  destination des collectivitĂ©s et des prestataires, qui permet d’identifier les acteurs pour chaque logiciel rĂ©fĂ©rencĂ© : Comptoir du Libre. Échirolles y maintient les informations concernant les choix de logiciels de la commune.

      Cet article ne serait pas complet sans dire un mot sur l’équipement des Ă©coles maternelles et Ă©lĂ©mentaires, dont l’équipement en informatique incombe aux communes. Si les postes clients disposent des mĂȘmes logiciels que ceux que nous dĂ©ployons au sein des services municipaux, le passage Ă  Linux attendra encore un peu, pour des raisons que j’ai dĂ©taillĂ©es dans un article dĂ©diĂ©.

      Structuration, transformation, mise en Ɠuvre opĂ©rationnelle, tout cela est bel et bon. Mais comment ĂȘtre sĂ»r de ne laisser personne au bord de la route ? C’est tout l’enjeu de l’inclusion numĂ©rique, sujet de l’article suivant.

      → L’épisode 1 (structuration)
      → L’épisode 2 (transformation)

      ***
        • Source image :

      https://commons.wikimedia.org/wiki/File:Eug%C3%A8ne_Delacroix_-_Le_28_Juillet._La_Libert%C3%A9_guidant_le_peuple.jpg

      • Auteur : Erich Lessing Culture and Fine Arts Archives via artsy.net
      • Description : Tableau d’EugĂšne Delacroix « La LibertĂ© Guidant le Peuple Â», commĂ©morant la rĂ©volution des Trois Glorieuses (27-28-29 juillet 1830) en France.
      • Licence : Domaine public

      Retrouvez-moi sur Mastodon : https://colter.social/@nicolasvivant

      ❌
      ❌