<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>logiciel on Zwindler's Reflection</title><link>https://blog.zwindler.fr/categories/logiciel/</link><description>Recent content in logiciel on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 29 Jan 2024 06:00:00 +0200</lastBuildDate><atom:link href="https://blog.zwindler.fr/categories/logiciel/index.xml" rel="self" type="application/rss+xml"/><item><title>Planifier les posts de mon blog Hugo sur Clever Cloud</title><link>https://blog.zwindler.fr/2024/01/29/planifier-les-posts-clever-cloud/</link><pubDate>Mon, 29 Jan 2024 06:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2024/01/29/planifier-les-posts-clever-cloud/</guid><description>&lt;img src="https://blog.zwindler.fr/2022/05/clever-trott.webp" alt="Featured image of post Planifier les posts de mon blog Hugo sur Clever Cloud" /&gt;&lt;h2 id="suite-de-la-migration"&gt;Suite de la migration
&lt;/h2&gt;&lt;p&gt;Fin décembre, &lt;a class="link" href="https://blog.zwindler.fr/2023/12/30/its-migration-day-again" &gt;j&amp;rsquo;ai migré ce blog sur Clever Cloud&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cependant, David Legrand m&amp;rsquo;a fait remarquer que je n&amp;rsquo;avais plus de méthode pour planifier mes posts.&lt;/p&gt;
&lt;p&gt;Depuis quelque temps, je poste à flux tendu donc ça ne m&amp;rsquo;a pas encore gêné (j&amp;rsquo;écris un post, je le rends public dans la foulée) mais c&amp;rsquo;est vrai qu&amp;rsquo;il me manque cette possibilité par rapport à précédent mon hébergement (une VM).&lt;/p&gt;
&lt;p&gt;Cependant, il existe une solution sur Clever Cloud pour le faire. David en a d&amp;rsquo;ailleurs écrit un petit article sur son blog perso, adapté pour &amp;ldquo;Astro&amp;rdquo; son générateur de site statique.&lt;/p&gt;
&lt;p&gt;Je vais donc faire pareil pour mon propre blog avec Hugo.&lt;/p&gt;
&lt;h2 id="adaptations"&gt;Adaptations
&lt;/h2&gt;&lt;p&gt;Repartons donc d&amp;rsquo;où j&amp;rsquo;en étais au post précédent. Nous avons un blog avec Hugo qui se déploie quand on fait des &lt;code&gt;clever deploy&lt;/code&gt; (ou des commits sur le &lt;em&gt;git remote&lt;/em&gt; de clever).&lt;/p&gt;
&lt;p&gt;La première chose qu&amp;rsquo;on va devoir faire, c&amp;rsquo;est récupérer un token. En effet, c&amp;rsquo;est notre blog qui va déclencher de lui même les redéploiements, on va donc devoir lui donner de quoi s&amp;rsquo;authentifier.&lt;/p&gt;
&lt;p&gt;Si vous n&amp;rsquo;avez pas de token sous la main, on peut en retrouver un en faisant &lt;code&gt;clever login&lt;/code&gt; depuis un terminal, comme je l&amp;rsquo;expliquais dans l&amp;rsquo;article précédent.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/clever-login.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Et on va rajouter le TOKEN dans la liste des variables d&amp;rsquo;environnement de notre app :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_SECRET &lt;span class="s2"&gt;&amp;#34;aaaaaaaaaaaaaaaaaaaaaaaaaa&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_TOKEN &lt;span class="s2"&gt;&amp;#34;aaaaaaaaaaaaaaaaaaaaaaaaaa&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A partir de là on va créer plusieurs fichiers. D&amp;rsquo;abord, un script qui va déclencher ce fameux redéploiement :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; clever_rebuild.sh &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;#!/bin/bash -l
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;clever link ${APP_ID}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;clever restart --quiet --without-cache
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x clever_rebuild.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ensuite, je vais créer un fichier qui sera lu par clever-cloud et qui va déclencher ce redéploiement aux heures où je publie mes posts planifiés (le matin, un peu avant 9h) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir clevercloud
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;[&amp;#34;00 08 * * * $ROOT/clever_rebuild.sh&amp;#34;]&amp;#39;&lt;/span&gt; &amp;gt; clevercloud/cron.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Attention aux petites blaguounettes de timezone. Comme tous sysadmins qui se respectent, les gens de clever utilisent le temps UTC sur leurs serveurs (moi aussi). Cependant, ça nécessite une petite gymnastique intellectuelle si jamais vous n&amp;rsquo;utilisez pas aussi le temps UTC dans votre tête pour planifier les posts ;-P.&lt;/p&gt;
&lt;p&gt;Si tout se passe bien, vous verrez qu&amp;rsquo;il remarque qu&amp;rsquo;il y a un cron dans les logs :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;2024-01-25T14:05:21+01:00 Importing cronjobs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;2024-01-25T14:05:21+01:00 Starting crons setup
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;2024-01-25T14:06:05+01:00 (CRON) INFO (running with inotify support)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;2024-01-25T14:06:05+01:00 (CRON) INFO (RANDOM_DELAY will be scaled with factor 89% if used.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;2024-01-25T14:06:05+01:00 (CRON) STARTUP (1.7.0)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[...]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tout dernier point que j&amp;rsquo;ai éludé jusqu&amp;rsquo;à présent, il est possible de redémarrer une application à partir d&amp;rsquo;un cache (pour que ça aille plus vite). Cependant, il est nécessaire d&amp;rsquo;indiquer à clever cloud quoi mettre dans ce cache. On va donc ajouter &amp;ldquo;/clevercloud/cron.json:/clever_rebuild.sh&amp;rdquo; à la variable existante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# précédemment CC_OVERRIDE_BUILDCACHE &amp;#34;/public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_OVERRIDE_BUILDCACHE &lt;span class="s2"&gt;&amp;#34;/public:/clevercloud/cron.json:/clever_rebuild.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="fail-to-hack-the-template"&gt;(Fail to) hack the template
&lt;/h2&gt;&lt;p&gt;Si Hugo a bien un flag pour permettre de &amp;ldquo;builder&amp;rdquo; les posts dont la date de sortie est postérieure à la date actuelle (&lt;code&gt;buildFuture&lt;/code&gt;), mon thème &amp;ldquo;Stack&amp;rdquo; les affiche par défaut dans la liste des derniers posts ainsi que dans le flux RSS.&lt;/p&gt;
&lt;p&gt;La solution la plus simple à ce problème est de laisser les paramètres par défaut, et d&amp;rsquo;attendre que la date de publication soit dépassée (idéalement juste avant le passage d&amp;rsquo;un cron) et le tour est joué.&lt;/p&gt;
&lt;p&gt;Mais David a eu une autre approche qui m&amp;rsquo;a bien plu : ajouter une condition dans le template pour que le post ne soit pas visible dans la liste des posts, mais quand même publié.&lt;/p&gt;
&lt;p&gt;Avantage : on peut consulter l&amp;rsquo;article à paraître, si on a le lien. Il se rajoute à la liste des articles de la homepage de lui-même lors du prochain rebuild, une fois la date dépassée.&lt;/p&gt;
&lt;p&gt;Dans mon thème, la page d&amp;rsquo;accueil qui liste les posts &lt;a class="link" href="https://github.com/CaiJimmy/hugo-theme-stack/blob/master/layouts/index.html" target="_blank" rel="noopener"
&gt;est définie ici dans le code&lt;/a&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-diff" data-lang="diff"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ define &amp;#34;main&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ $pages := where .Site.RegularPages &amp;#34;Type&amp;#34; &amp;#34;in&amp;#34; .Site.Params.mainSections }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ $notHidden := where .Site.RegularPages &amp;#34;Params.hidden&amp;#34; &amp;#34;!=&amp;#34; true }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ {{ $notFuture := where .Site.RegularPages &amp;#34;.Date&amp;#34; &amp;#34;le&amp;#34; now }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gi"&gt;+ {{ $filtered := ($pages | intersect $notHidden | intersect $notFuture) }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gd"&gt;- {{ $filtered := ($pages | intersect $notHidden) }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ $pag := .Paginate ($filtered) }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;section class=&amp;#34;article-list&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ range $index, $element := $pag.Pages }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ partial &amp;#34;article-list/default&amp;#34; . }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/section&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;pagination.html&amp;#34; . -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{- partial &amp;#34;footer/footer&amp;#34; . -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; {{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[...]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En théorie, ça fonctionne. Sauf que je n&amp;rsquo;ai pas réussi à le faire marcher avec le thème &amp;ldquo;Stack&amp;rdquo; que j&amp;rsquo;utilise sur le site (j&amp;rsquo;ai réussi avec un thème &amp;ldquo;blank&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est peut-être lié à &lt;a class="link" href="https://github.com/gohugoio/hugo/issues/11916#issuecomment-1910462590" target="_blank" rel="noopener"
&gt;un problème d&amp;rsquo;appel multiple à la fonction &lt;code&gt;.Paginate()&lt;/code&gt;&lt;/a&gt;, qui &amp;ldquo;cache&amp;rdquo; la pagination la première fois qu&amp;rsquo;elle est lancée.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you call .Paginator or .Paginate multiple times on the same page, you should ensure all the calls are identical. Once either .Paginator or .Paginate is called while generating a page, its result is cached, and any subsequent similar call will reuse the cached result. This means that any such calls which do not match the first one will not behave as written.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://gohugo.io/templates/pagination/" target="_blank" rel="noopener"
&gt;https://gohugo.io/templates/pagination/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Même en partant du principe que j&amp;rsquo;arrive à le faire marcher, reste encore la problématique du flux RSS, comme j&amp;rsquo;ai pu le remarquer avec Seboss666 ;-)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2024/01/seboss666.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc laissé tomber cette idée. De toute façon, je n&amp;rsquo;avais jamais vraiment eu besoin jusqu&amp;rsquo;à présent puisque je n&amp;rsquo;y avais pas pensé ;-P.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc, comme avant, mes posts &amp;ldquo;planifiés&amp;rdquo; qui sont visible le matin de leur publication et c&amp;rsquo;est déjà bien comme ça (pour l&amp;rsquo;instant).&lt;/p&gt;
&lt;p&gt;Have fun !&lt;/p&gt;</description></item><item><title>Migration du blog sur Clever Cloud</title><link>https://blog.zwindler.fr/2023/12/30/its-migration-day-again/</link><pubDate>Sat, 30 Dec 2023 16:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2023/12/30/its-migration-day-again/</guid><description>&lt;img src="https://blog.zwindler.fr/2022/05/clever-trott.webp" alt="Featured image of post Migration du blog sur Clever Cloud" /&gt;&lt;h2 id="its-groundhog-migration-day-again"&gt;It’s &lt;del&gt;groundhog&lt;/del&gt; migration day, again
&lt;/h2&gt;&lt;p&gt;Tous les 6 mois environ, une mouche me pique.&lt;/p&gt;
&lt;p&gt;Après avoir migré un nombre incalculable de fois mon blog wordpress à droite / à gauche, puis &lt;a class="link" href="https://blog.zwindler.fr/2019/06/10/comment-migrer-de-wordpress-a-hugo/" &gt;migré sur Hugo&lt;/a&gt;, autohébergé, utilisé du managé chez &lt;a class="link" href="https://vercel.com/" target="_blank" rel="noopener"
&gt;vercel&lt;/a&gt;, chez &lt;a class="link" href="https://froggit.fr/" target="_blank" rel="noopener"
&gt;froggit&lt;/a&gt;, autohébergé encore&amp;hellip;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai décidé (un peu sur un coup de tête) de migrer le blog chez les copain⋅es de chez Clever Cloud.&lt;/p&gt;
&lt;p&gt;Et je vous montre comment j&amp;rsquo;ai fait.&lt;/p&gt;
&lt;h2 id="prérequis"&gt;Prérequis
&lt;/h2&gt;&lt;p&gt;Je pars du principe que vous avez comme moi un dépôt git / site hugo déjà fonctionnel. Et je ne vais pas non plus détailler la procédure pour activer un compte chez &lt;a class="link" href="https://www.clever-cloud.com/" target="_blank" rel="noopener"
&gt;Clever Cloud&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Je commence par installer la CLI, les &amp;ldquo;clever tools&amp;rdquo;. Pour les installer, il nous faut &lt;code&gt;npm&lt;/code&gt;. J&amp;rsquo;utilise rarement &lt;code&gt;npm&lt;/code&gt;, mais quand je le fais, j&amp;rsquo;utilise un autre tool, &lt;code&gt;volta&lt;/code&gt; (&lt;a class="link" href="https://volta.sh/" target="_blank" rel="noopener"
&gt;volta.sh&lt;/a&gt;), qui va me permettre de choisir la version dont j&amp;rsquo;ai besoin&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/idontalways.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ curl https://get.volta.sh | bash
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Une fois installé, je peux télécharger la version qui m&amp;rsquo;intéresse de npm (18 par exemple, la version minimum pour installer les clever tools)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ volta install node@20
success: installed and set node@20.10.0 (with npm@10.2.3) as default
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Je peux donc maintenant installer les clever tools :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;npm i -g clever-tools
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Puis me loguer depuis mon terminal&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ clever login
Opening https://console.clever-cloud.com/cli-oauth?cli_version=3.0.2&amp;amp;cli_token=xxxxxxxxxxxxxxxxx in your browser to log you in…
Login successful as [unspecified name] &amp;lt;xxx.yyy@example.org&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/clever-login.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Si jamais comme indiqué sur l&amp;rsquo;écran de login, vous avez besoin d&amp;rsquo;un token + secret (pour de la CI par exemple), sachez qu&amp;rsquo;ils sont stockés dans un fichier &lt;code&gt;~/.config/clever-cloud/clever-tools.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2024/01/clever-token.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Denier prérequis, je vais ajouter une &lt;a class="link" href="https://console.clever-cloud.com/users/me/ssh-keys" target="_blank" rel="noopener"
&gt;clé SSH dans ma console clever&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/add-ssh.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="création-de-lapplication"&gt;Création de l&amp;rsquo;application
&lt;/h2&gt;&lt;p&gt;A partir de maintenant, je suis capable d’interagir avec clever cloud en CLI. Je vais commencer par créer l&amp;rsquo;application qui va héberger mon site statique :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ clever create -t static-apache blog-zwindler
Your application has been successfully created!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Clever Cloud offre la possibilité de dissocier la taille des instances pour la partie run et la partie build. Je vais donc créer l&amp;rsquo;instance la plus petite possible pour le run (une nano), et une plus pêchue (une M) pour le build, histoire d&amp;rsquo;être plus réactif sur les commits de modifications :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ clever scale --build-flavor M
App rescaled successfully
$ clever scale --flavor nano
App rescaled successfully
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Je peux ensuite configurer quelques variables d&amp;rsquo;environnement (trouvées sur la doc de clever cloud) pour générer mon site statique avec l&amp;rsquo;image &lt;strong&gt;static-apache&lt;/strong&gt; de clever.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_WEBROOT &lt;span class="s2"&gt;&amp;#34;/public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_OVERRIDE_BUILDCACHE &lt;span class="s2"&gt;&amp;#34;/public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_PRE_BUILD_HOOK &lt;span class="s2"&gt;&amp;#34;bash setup_hugo.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ clever env &lt;span class="nb"&gt;set&lt;/span&gt; CC_POST_BUILD_HOOK &lt;span class="s2"&gt;&amp;#34;hugo --minify --gc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour finir, on crée le script &lt;code&gt;setup_hugo.sh&lt;/code&gt; à la racine de notre site statique Hugo :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &amp;gt; setup_hugo.sh &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;HUGO_VERSION=&amp;#34;0.121.1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;HUGO_URL=&amp;#34;https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;DEST_BIN=&amp;#34;${HOME}/.local/bin&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;FILENAME=&amp;#34;hugo.tar.gz&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# Download Hugo Extended and place it in a folder in the $PATH
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;curl --create-dirs -s -L -o ${DEST_BIN}/${FILENAME} ${HUGO_URL}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;cd ${DEST_BIN}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;tar xvf ${FILENAME} -C ${DEST_BIN}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;rm ${FILENAME}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On commit les fichiers créés :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git add .
git commit -m &amp;#34;Add clever&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="déployer-notre-code"&gt;Déployer notre code
&lt;/h2&gt;&lt;p&gt;A partir de là, on a notre instance qui est prête à démarrer, dès qu&amp;rsquo;elle aura reçu du code.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/app-created.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Ici, clever cloud attend un push sur un dépôt git.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/blog-zwindler-clever.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;La méthode la plus &amp;ldquo;simple&amp;rdquo; pour pousser du code sur clever à ce moment-là est donc de créer un dépôt distance (remote) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git remote add clever git+ssh://git@push-n3-par-clevercloud-customers.services.clever-cloud.com/app_xxxxxxxxxxxxxxxxxxxx.git
git push clever master
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le &amp;ldquo;problème&amp;rdquo; dans mon cas est que (pour l&amp;rsquo;instant), le nom de la branche n&amp;rsquo;est pas configurable et est forcément &amp;ldquo;master&amp;rdquo;, ce qui ne m&amp;rsquo;arrange pas puisque je bosse habituellement sur &amp;ldquo;main&amp;rdquo;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;remote: Error: You tried to push to a custom branch. This is not allowed.
remote: error: hook declined to update refs/heads/main
To git+ssh://push-n3-par-clevercloud-customers.services.clever-cloud.com/app_xxxxxxxxxxxxxxxxxxxx.git
! [remote rejected] main -&amp;gt; main (hook declined)
error: impossible de pousser des références vers &amp;#39;git+ssh://push-n3-par-clevercloud-customers.services.clever-cloud.com/app_xxxxxxxxxxxxxxxxxxxx.git&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2 manières de contourner ce problème :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;soit je force la branche master sur le remote clever dans git&lt;/li&gt;
&lt;li&gt;soit j&amp;rsquo;utilise la CLI &lt;code&gt;clever deploy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans un premier temps, je me contente de feinter git :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git push clever main:master
Énumération des objets: 30, fait.
Décompte des objets: 100% (24/24), fait.
Compression par delta en utilisant jusqu&amp;#39;à 16 fils d&amp;#39;exécution
Compression des objets: 100% (16/16), fait.
Écriture des objets: 100% (16/16), 287.70 Kio | 31.97 Mio/s, fait.
Total 16 (delta 8), réutilisés 0 (delta 0), réutilisés du pack 0
remote: [SUCCESS] The application has successfully been queued for redeploy.
To git+ssh://push-n3-par-clevercloud-customers.services.clever-cloud.com/app_xxxxxxxxxxxxxxxxxxxx.git
54ff42f..960ce62 main -&amp;gt; master
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On termine par la configuration du nom de domaine :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ clever domain add blog.zwindler.fr
Your domain has been successfully saved
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il ne nous reste plus qu&amp;rsquo;à mettre à jour le CNAME dans notre DNS (&lt;em&gt;domain.par.clever-cloud.com.&lt;/em&gt; dans mon cas, mais la bonne configuration est visible dans l&amp;rsquo;onglet &lt;strong&gt;Domain names&lt;/strong&gt; de l&amp;rsquo;application)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/12/dns.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="et-avec-clever-deploy-"&gt;Et avec &lt;code&gt;clever deploy&lt;/code&gt; ?
&lt;/h2&gt;&lt;p&gt;Eh bien en fait, c&amp;rsquo;est &amp;ldquo;encore plus simple&amp;rdquo;. Il me suffit juste de faire une modif, de commit&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;git add .
git commit -m &amp;#34;test clever deploy&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Puis de simplement lancer la commande &lt;code&gt;clever deploy&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ clever deploy
Remote git head commit is c4e3c283585cafff44f07c7d78d860065318cd68
Current deployed commit is c4e3c283585cafff44f07c7d78d860065318cd68
New local commit to push is 0b3536a9f1d61178a99f6238831ccb4197989ddf (from refs/heads/main)
Pushing source code to Clever Cloud…
Your source code has been pushed to Clever Cloud.
Waiting for deployment to start…
Deployment started (deployment_b5f841ff-a233-4bb4-8a16-f618ee69ef28)
Waiting for application logs…
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Quelle est donc cette diablerie ?&lt;/p&gt;
&lt;p&gt;En réalité, les informations nécessaires pour pousser le code sont en réalité simplement dans un fichier &lt;code&gt;.clever.json&lt;/code&gt; qui a été créé à la racine lorsqu&amp;rsquo;on a lancé la commande &lt;code&gt;clever create -t static-apache blog-zwindler&lt;/code&gt; au tout début du tuto.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;apps&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;app_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;app_xxxxxxxxxxxxxxxxxxx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;org_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;user_yyyyyyyyyyyyyyyyyyyyy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;deploy_url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://push-n3-par-clevercloud-customers.services.clever-cloud.com/xxxxxxxxxxxxxxxxxxxx.git&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;blog-zwindler&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;alias&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;blog-zwindler&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Évidemment, je ne vais pas m&amp;rsquo;amuser à faire un &lt;code&gt;clever login&lt;/code&gt; / &lt;code&gt;clever deploy&lt;/code&gt; à chaque fois que je veux pousser une modif sur mon blog. Et c&amp;rsquo;est là où nos CLEVER_TOKEN / CLEVER_SECRET seront utiles !&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Après quelques heures d&amp;rsquo;usage, je peux dire que &lt;strong&gt;dans le cadre de l&amp;rsquo;hébergement de mon blog&lt;/strong&gt;, j&amp;rsquo;aime bien utiliser Clever Cloud.&lt;/p&gt;
&lt;p&gt;Qu&amp;rsquo;on soit bien clair, c&amp;rsquo;est pour mon cas d&amp;rsquo;usage et comparé à :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vercel : l&amp;rsquo;expérience utilisateur est incroyable sur Vercel, mais j&amp;rsquo;ai toujours été un peu gêné par le côté &amp;ldquo;boite noire&amp;rdquo; (on a pas accès à beaucoup plus que des variables d&amp;rsquo;environnement). Et je ne parle pas des problématiques de privacy&amp;hellip;&lt;/li&gt;
&lt;li&gt;Deux serveurs physiques avec Proxmox VE en cluster étendu chez One-provider : à l&amp;rsquo;inverse héberger moi-même mon blog sur une machine (en vrai, 2) louée résout les problèmes de privacy et j&amp;rsquo;ai la main sur toute la stack, mais ça me demande de la maintenance pour des perfs minables. Ok, c&amp;rsquo;est pas cher, mais j&amp;rsquo;ai 2 à 3 minutes de rebuild avec le CPU à 100% sur mon Atom de 2010 chez Online&amp;hellip;&lt;/li&gt;
&lt;li&gt;Froggit : c&amp;rsquo;était du Gitlab + Gitlab pages et c&amp;rsquo;était très cool car c&amp;rsquo;est plus flexible que Vercel, mais j&amp;rsquo;avais dû passer un peu de temps à configurer la pipeline et leur faire pousser les murs pour que mon site rentre (les 400 Mo de médias n&amp;rsquo;étaient pas supportés au début et les transferts Gitlab =&amp;gt; Gitlab pages étaient un peu longs).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avec Clever, mes 450 articles (3600 pages générées, 400 Mo de média) sont très rapidement générés, transférés, et enfin mis à disposition (&amp;lt; 1 minute tout compris, plus rapide que les 3 solutions précédentes).&lt;/p&gt;
&lt;p&gt;Le tout avec une disponibilité/fiabilité sans aucun doute bien meilleure que ce que j&amp;rsquo;aurais pu faire moi-même en auto hébergé avec un coût similaire, et en très peu de temps.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai passé beaucoup plus de temps à écrire cet article qu&amp;rsquo;à migrer le blog, puisque la doc est bien écrite, le site est intuitif, et je n&amp;rsquo;ai été bloqué à aucun moment.&lt;/p&gt;
&lt;p&gt;Il me reste encore à optimiser l&amp;rsquo;étape de déploiement, pour qu&amp;rsquo;un commit/push sur mon dépôt git déclenche automatiquement un déploiement côté clever. Objectivement, ça ne devrait pas prendre trop longtemps (github action / gitlab CI)&amp;hellip;&lt;/p&gt;
&lt;p&gt;Et par contre, ça manque d&amp;rsquo;IPv6 natif, screugneugneu !&lt;/p&gt;</description></item><item><title>D’open source à BullShit Licence (BSL)</title><link>https://blog.zwindler.fr/2023/08/16/d-open-source-a-bullshit-licence-bsl/</link><pubDate>Wed, 16 Aug 2023 12:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2023/08/16/d-open-source-a-bullshit-licence-bsl/</guid><description>&lt;img src="https://blog.zwindler.fr/2023/08/28c1d418-5dd4-43c2-8345-4f4ce34f9ff2.webp" alt="Featured image of post D’open source à BullShit Licence (BSL)" /&gt;&lt;h2 id="résumé-des-épisodes-précédents"&gt;Résumé des épisodes précédents
&lt;/h2&gt;&lt;p&gt;Il y a à peine un mois, j&amp;rsquo;écrivais mon billet d&amp;rsquo;humeur annuel sur une boite, championne de l&amp;rsquo;open source (RHEL), qui utilise une faille de la licence GPL pour gratter un peu de thune en fermant ses sources aux &amp;ldquo;rebuilders&amp;rdquo; (je parle évidemment de l&amp;rsquo;article &lt;a class="link" href="https://blog.zwindler.fr/2023/07/11/oracle-a-la-rescousse-de-linux-quelle-blague" &gt;&amp;ldquo;Oracle à la rescousse de Linux ? Quelle blague!&amp;rdquo;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Je ne pensais pas que je devrais REFAIRE un article d&amp;rsquo;humeur sur un sujet similaire, un mois plus tard.&lt;/p&gt;
&lt;p&gt;Car jusqu&amp;rsquo;à présent, c&amp;rsquo;était plutôt des incidents &amp;ldquo;isolés&amp;rdquo; et dans des contextes assez spécifiques. &lt;a class="link" href="https://blog.zwindler.fr/2021/01/23/lopen-source-saute-a-lelastic-avec-la-sspl/" &gt;En 2021, c&amp;rsquo;était Elastic qui passait à la licence SSPL pour &amp;ldquo;lutter&amp;rdquo; contre les offres managées par AWS&lt;/a&gt; (après Mongo qui avait fait pareil en 2018).&lt;/p&gt;
&lt;p&gt;Si AWS était évidemment fautif dans cette histoire, ce move est catastrophique et a amorcé pas mal de backlash côté communauté (justifié, à mon avis) ainsi qu&amp;rsquo;une tempête de FUD de tous les côtés. Au final, c&amp;rsquo;est l&amp;rsquo;open source, qui devenait tout juste respectée en entreprise, qui en pâtie.&lt;/p&gt;
&lt;h2 id="rhel-ouvre-une-brèche-lopen-source-se-referme"&gt;RHEL ouvre une brèche, l&amp;rsquo;open source se referme
&lt;/h2&gt;&lt;p&gt;Car à peine quelque jour après le move de RHEL pour faire la nique à Rocky+Alma, on pensait souffler mais non, les mauvaises nouvelles s&amp;rsquo;enchaînent.&lt;/p&gt;
&lt;p&gt;Canonical, créateur de l&amp;rsquo;outil LXD (solution pour manager des containers LXC, que j&amp;rsquo;affectionne particulièrement) retire l&amp;rsquo;outil du Linux Containers project, un projet communautaire, qui le chapeautait.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While the team behind Linux Containers regrets that decision and will be missing LXD as one of its projects, it does respect Canonical’s decision and is now in the process of moving the project over.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://linuxcontainers.org/lxd/" target="_blank" rel="noopener"
&gt;linuxcontainers.org/lxd/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On peut aussi noter que ce move le lendemain de la démission d&amp;rsquo;un des développeurs de LXD chez Canonical :&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://stgraber.org/2023/07/10/time-to-move-on/" target="_blank" rel="noopener"
&gt;stgraber.org/2023/07/10/time-to-move-on/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Et que le créateur de LXD l&amp;rsquo;a forké :&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://linuxiac.com/incus-project-lxd-fork/" target="_blank" rel="noopener"
&gt;linuxiac.com/incus-project-lxd-fork/&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In response to Canonical’s takeover of LXD, the independent Incus project arose as a fork for this container and virtual machine manager.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="moi-je-laime-bien-la-mpl"&gt;Moi je l&amp;rsquo;aime bien la MPL&amp;hellip;
&lt;/h2&gt;&lt;p&gt;Et la semaine dernière (pendant mes vacances, ces cochons), Hashicorp a changé la licence de leurs produits de la MPL (Mozilla Public Licence, que je trouve être un bon compromis) à la BSL, une licence plus restrictive :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;BSL is a new alternative to closed source or open core licensing models. Under BSL, the source code is always publicly available. Non-production use of the code is always free, and the licensor can also make an Additional Use Grant allowing limited production use.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Qu&amp;rsquo;est ce que la BSL ?&lt;/p&gt;
&lt;p&gt;Grosso modo, c&amp;rsquo;est une licence qui n&amp;rsquo;est PAS open source (&lt;a class="link" href="https://blog.sentry.io/lets-talk-about-open-source/" target="_blank" rel="noopener"
&gt;cf ce post de Sentry qui reconnait que BSL n&amp;rsquo;est pas open source dans le sens OSI du terme&lt;/a&gt;), et qui permet à Hashicorp dans le cas présent de tuer la concurrence dans l&amp;rsquo;oeuf.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You may make production use of the Licensed Work, provided such use does not include offering the Licensed Work to third parties on a hosted or embedded basis which is competitive with HashiCorp&amp;rsquo;s products&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans le &lt;a class="link" href="https://www.hashicorp.com/blog/hashicorp-adopts-business-source-license" target="_blank" rel="noopener"
&gt;billet de blog pour parler du changement de licence&lt;/a&gt;, voilà comment c&amp;rsquo;est dit :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vendors who provide competitive services built on our community products will no longer be able to incorporate future releases, bug fixes, or security patches contributed to our products.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si vous voulez creuser un peu plus les réactions, The Register a fait un article assez cool sur ce move, les réactions et les conséquences que ça va avoir.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://www.theregister.com/2023/08/11/hashicorp_bsl_licence/" target="_blank" rel="noopener"
&gt;www.theregister.com/2023/08/11/hashicorp_bsl_licence/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Et je vous partage aussi cet excellent thread sur Twitter et son tout aussi excellent follow up de iamvlaaaaaaad&lt;/p&gt;
&lt;p&gt;Autant dire que de nombreuses personnes, dont des développeurs qui ont contribué à un projet open source et qui se retrouvent à avoir engraissé gratuitement Hashicorp, sont assez mécontents.&lt;/p&gt;
&lt;p&gt;Pour essayer d&amp;rsquo;éteindre l&amp;rsquo;incendie, il y a évidemment &lt;a class="link" href="https://www.hashicorp.com/license-faq" target="_blank" rel="noopener"
&gt;une FAQ pour dire que rien ne va changer&lt;/a&gt; et que l&amp;rsquo;utilisateur n&amp;rsquo;a rien à craindre, mais comme à chaque fois dans ces histoires de licences, c&amp;rsquo;est la licence qu&amp;rsquo;il faut lire, pas la FAQ. Ce n&amp;rsquo;est pas la FAQ qui vous sauvera du tribunal&amp;hellip;&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;était exactement la même salade avec MongoDB et Elastic. Beaucoup de craintes, du FUD, notamment de la part des opposants aux modèles open source (ahah vous voyez c&amp;rsquo;est pas clair l&amp;rsquo;open source !), et surtout un flou juridique immense que personne n&amp;rsquo;a encore réellement éclairci&amp;hellip;&lt;/p&gt;
&lt;p&gt;Le point positif, c&amp;rsquo;est que ça fait travailler les devrels et les avocats (cf le thread de vlad).&lt;/p&gt;
&lt;h2 id="hashi-cest-fini"&gt;Hashi, c&amp;rsquo;est fini
&lt;/h2&gt;&lt;p&gt;Note: &lt;a class="link" href="https://framapiaf.org/@clementd/110875367669781368" target="_blank" rel="noopener"
&gt;ce sous titre est gracieusement offert par (volé à) Clementd&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Autant dans le cas du bras de fer entre Mongo/Elastic avec AWS, j&amp;rsquo;arrivais à peu près à comprendre les motivations. En revanche, pour Hashicorp, on peine à trouver qui est visé par cette modification.&lt;/p&gt;
&lt;p&gt;Qu&amp;rsquo;avait à gagner Hashicorp à changer son modèle de licence, à part une communauté à dos et un fork dans les start-in blocks ?&lt;/p&gt;
&lt;p&gt;La seule cible qui me vient en tête n&amp;rsquo;est pas un gros méchant cloud provider, mais plutôt des offres alternatives à Terraform Cloud/Entreprise, comme &lt;a class="link" href="https://www.env0.com/" target="_blank" rel="noopener"
&gt;Env0&lt;/a&gt; ou &lt;a class="link" href="https://spacelift.io/" target="_blank" rel="noopener"
&gt;Spacelift&lt;/a&gt;. Et aussi de petit éditeurs / cloud providers locaux qui se reposent sur ces outils pour fournir de l&amp;rsquo;automatisation à leurs clients&amp;hellip;&lt;/p&gt;
&lt;p&gt;On est bien loin des méchants GAFAM qui &amp;ldquo;piquent not&amp;rsquo; travail&amp;rdquo; (ref south park, j&amp;rsquo;innove peu), ici il s&amp;rsquo;agit d&amp;rsquo;offres qui se sont construites &amp;ldquo;au-dessus&amp;rdquo; de Terraform, car elles ont apporté des choses &lt;strong&gt;en plus&lt;/strong&gt; qu&amp;rsquo;on ne trouvait pas dans les offres d&amp;rsquo;Hashicorp. Ces offres se retrouvent tuées dans l&amp;rsquo;oeuf maintenant qu&amp;rsquo;elles sont concurrentes à certains produits d&amp;rsquo;Hashicorp. Pratique&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2021/01/sp_vole_travail.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Plus cynique encore, on pourrait imaginer un scénario où une boite se créerait au dessus de terraform ou tout autre produit d&amp;rsquo;Hashicorp en étant totalement PAS concurrente de leurs offres, qui se mettrait à bien marcher. Hashicorp n&amp;rsquo;aurait qu&amp;rsquo;à artificiellement créer un produit concurrent (même tout pourri) et hop, on rafle le marché.&lt;/p&gt;
&lt;p&gt;On est plus proche du &lt;a class="link" href="https://en.wikipedia.org/wiki/Embrace,_extend,_and_extinguish" target="_blank" rel="noopener"
&gt;EEE&lt;/a&gt; que de la philosophie open source.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sauf que maintenant, c&amp;rsquo;est plus Microsoft : c&amp;rsquo;est RHEL, Canonical, Hashicorp&amp;hellip;&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="conclusion-rédigée-par-chatgpt-pour-le-lulz"&gt;Conclusion (rédigée par ChatGPT, pour le lulz)
&lt;/h2&gt;&lt;p&gt;Dans ce spectacle de l&amp;rsquo;open source, les spectateurs ne savent plus s&amp;rsquo;ils doivent rire ou pleurer&lt;/p&gt;
&lt;p&gt;Les entreprises qui semblaient autrefois être les champions du partage et de la collaboration semblent désormais être en compétition pour le titre de &amp;ldquo;Licence la plus énigmatique&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Et tandis que le rideau se lève sur ces actes étonnants, les développeurs, les utilisateurs et la communauté open source dans son ensemble se demandent peut-être si tout cela est un rêve étrange, ou simplement une réalité nouvelle et ironique.&lt;/p&gt;
&lt;h2 id="bonus"&gt;Bonus
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.env0.com/blog/hashicorp-license-change" target="_blank" rel="noopener"
&gt;La réaction d&amp;rsquo;Env0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.pulumi.com/blog/pulumi-hearts-opensource/" target="_blank" rel="noopener"
&gt;La réaction de Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://spacelift.io/blog/spacelift-latest-statement-on-hashicorp-bsl" target="_blank" rel="noopener"
&gt;La réaction de Spacelift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Oracle à la rescousse de Linux ? Quelle blague!</title><link>https://blog.zwindler.fr/2023/07/11/oracle-a-la-rescousse-de-linux-quelle-blague/</link><pubDate>Tue, 11 Jul 2023 06:00:00 +0200</pubDate><guid>https://blog.zwindler.fr/2023/07/11/oracle-a-la-rescousse-de-linux-quelle-blague/</guid><description>&lt;img src="https://blog.zwindler.fr/2023/07/oracle-linux.webp" alt="Featured image of post Oracle à la rescousse de Linux ? Quelle blague!" /&gt;&lt;h2 id="petit-billet-dhumeur-ça-faisait-longtemps"&gt;Petit billet d&amp;rsquo;humeur, ça faisait longtemps
&lt;/h2&gt;&lt;p&gt;Oracle vient à la rescousse de Linux ? Quelle blague&amp;hellip;&lt;/p&gt;
&lt;p&gt;En 2018, j&amp;rsquo;écrivais un article intitulé &lt;a class="link" href="https://blog.zwindler.fr/2018/10/19/lopen-source-bashing-a-encore-de-beaux-jours-devant-lui/" &gt;L’open source bashing a encore de beaux jours devant lui&lt;/a&gt;, prémisse d&amp;rsquo;un de mes tout premiers talks. A PSES ensuite, en 2019, je donnais une de mes toutes premières conférences en tant que speaker intitulée &amp;ldquo;Le logiciel libre a-t-il de beaux jours devant lui ?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Dans cet article et ce talk, j&amp;rsquo;avais parlé des &amp;ldquo;super-vilains&amp;rdquo; de l&amp;rsquo;histoire, les géants du monde propriétaires.&lt;/p&gt;
&lt;p&gt;Ceux qui étaient passés de l&amp;rsquo;ignorance du logiciel libre, à la moquerie, puis au combat. Et finalement du rachat de RedHat par IBM.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;First they ignore you,&lt;/p&gt;
&lt;p&gt;Then they laugh at you,&lt;/p&gt;
&lt;p&gt;Then they fight you,&lt;/p&gt;
&lt;p&gt;Then &lt;strong&gt;they buy you&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2023/07/then-they-buy.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="redhat-verrouille-des-sources-rhel-derrière-un-paywall"&gt;RedHat verrouille des sources RHEL derrière un paywall
&lt;/h2&gt;&lt;p&gt;Aujourd&amp;rsquo;hui, rien n&amp;rsquo;a changé.&lt;/p&gt;
&lt;p&gt;Les super-vilains cyniques sont les mêmes, ils changent juste alternativement de rôles dans le &lt;a class="link" href="https://fr.wikipedia.org/wiki/Triangle_dramatique" target="_blank" rel="noopener"
&gt;triangle de karpman&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Si vous avez loupé cette news qui a pas mal chahuté le petit monde de l&amp;rsquo;OSS et du logiciel libre, je vous ai fait une petite compilation de liens en fin d&amp;rsquo;article.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;IBM/RedHat tue CentOS en 2020 (alors que normalement le support de la 8 courrait pendant encore plusieurs années), puis utilise en juin 2023 &amp;ldquo;une faille&amp;rdquo; (selon Jeff Geerling) de la GPL pour empêcher les clones de RHEL.&lt;/p&gt;
&lt;p&gt;Et comme la saison du troll semble ainsi ouverte, aujourd&amp;rsquo;hui Oracle fait semblant d&amp;rsquo;aider l&amp;rsquo;open source (juste pour troller IBM), tout en ayant été de l&amp;rsquo;autre côté de la barrière tout aussi récemment.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.oracle.com/news/announcement/blog/keep-linux-open-and-free-2023-07-10/" target="_blank" rel="noopener"
&gt;Oracle.com - Keep Linux Open and Free—We Can’t Afford Not To&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et au milieu de tout ça, Microsoft Loves Linux, bien entendu 😏&lt;/p&gt;
&lt;p&gt;Bref, l&amp;rsquo;histoire de l&amp;rsquo;informatique est un éternel recommencement.&lt;/p&gt;
&lt;h2 id="addendum--suse"&gt;Addendum : SUSE
&lt;/h2&gt;&lt;p&gt;SUSE vient (aujourd&amp;rsquo;hui !) de rajouter un pavé dans la marre en annonçant forker RHEL et investissant plus de 10 millions de dollars dessus.&lt;/p&gt;
&lt;p&gt;*&lt;a class="link" href="https://www.suse.com/news/SUSE-Preserves-Choice-in-Enterprise-Linux/" target="_blank" rel="noopener"
&gt;SUSE Preserves Choice in Enterprise Linux by Forking RHEL with a $10+ Million Investment&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SUSE is committed to working with the open source community to develop a long-term, enduring compatible alternative for RHEL and CentOS users. SUSE plans to contribute this project to an open source foundation, which will provide ongoing free access to alternative source code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Merci à ceux qui me l&amp;rsquo;ont forwardé :)&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;p&gt;Pour comprendre rapidement (mais faut aimer les vidéos)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.youtube.com/watch?v=sxZLFxU2FEo" target="_blank" rel="noopener"
&gt;Vidéo Adrien LinuxTricks - Edito Red Hat : Debrief autour de la &amp;ldquo;fermeture des sources&amp;rdquo; &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les différents billets de blogs&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.redhat.com/en/blog/furthering-evolution-centos-stream" target="_blank" rel="noopener"
&gt;Le billet d&amp;rsquo;annonce des changements dans RHEL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fosspost.org/red-hat-is-shooting-itself-in-the-foot-again/" target="_blank" rel="noopener"
&gt;fosspost.org - Red Hat is Shooting Itself in the Foot, Again&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://linux.developpez.com/actu/345794/-Avez-vous-perdu-la-tete-Red-Hat-fustige-pour-le-verrouillage-des-sources-RHEL-derriere-un-paywall-Jeff-Geerling-AlmaLinux-et-Rocky-Linux-expriment-leur-deception/" target="_blank" rel="noopener"
&gt;linux.developpez.com - « Avez-vous perdu la tête ? », Red Hat fustigé pour « le verrouillage des sources RHEL derrière un paywall »&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.redhat.com/en/blog/red-hats-commitment-open-source-response-gitcentosorg-changes" target="_blank" rel="noopener"
&gt;Red Hat’s commitment to open source: A response to the git.centos.org changes (on est pas méchants, c&amp;rsquo;est faux !)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.jeffgeerling.com/blog/2023/im-done-red-hat-enterprise-linux" target="_blank" rel="noopener"
&gt;Jeff Geerling (geerlingguy) - I&amp;rsquo;m done with Red Hat (Enterprise Linux)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.oracle.com/news/announcement/blog/keep-linux-open-and-free-2023-07-10/" target="_blank" rel="noopener"
&gt;Oracle.com - Keep Linux Open and Free—We Can’t Afford Not To&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ma conférence à PSES 2019 / BDX I/O 2019 (sur mon peertube)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://peertube.zwindler.fr/w/qKSSnN8URQePggjxgdxfN3" target="_blank" rel="noopener"
&gt;PSES 2019 - Le logiciel libre a-t-il de beaux jours devant lui&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://peertube.zwindler.fr/w/kr5duRcm5quu1cfWKUjoo1" target="_blank" rel="noopener"
&gt;BDX IO 2019 - Le logiciel libre a-t-il de beaux jours devant lui&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>redalert : gérer les incidents avec un bot Slack</title><link>https://blog.zwindler.fr/2020/06/15/redalert-gerer-des-incidents-avec-un-bot-slack/</link><pubDate>Mon, 15 Jun 2020 06:40:00 +0000</pubDate><guid>https://blog.zwindler.fr/2020/06/15/redalert-gerer-des-incidents-avec-un-bot-slack/</guid><description>&lt;img src="https://blog.zwindler.fr/2020/06/Enterprise-D-bridge_2371-640x266-1.webp" alt="Featured image of post redalert : gérer les incidents avec un bot Slack" /&gt;&lt;p&gt;Il y a quelques mois, j’ai vu passer cet article écrit par un SRE de chez ManoMano : &lt;a class="link" href="https://medium.com/manomano-tech/incident-management-with-a-bot-7e80deb5b5e5" target="_blank" rel="noopener"
&gt;Incident Management with a bot&lt;/a&gt;. Il a été pas mal partagé et il m’a beaucoup plus, car il me permettait de creuser 2 sujets qui m’intéressaient justement à ce moment-là : les bots slack et la gestion d’incidents.&lt;/p&gt;
&lt;p&gt;Dans mon équipe actuelle, nous utilisons énormément Slack pour communiquer en interne. Au-delà du chit-chat quotidien, nous avons également pour habitude de créer des channels dédiés et d’y inviter les personnes concernées lors d’incidents sur la plateforme que nous administrons, de manière à centraliser les efforts entre les Ops, les Devs et les équipes support client.&lt;/p&gt;
&lt;p&gt;L’idée de pouvoir avoir un tool permettant à la fois de nous éviter de gérer à la main ces incidents tout en restant dans Slack était hyper séduisante&amp;hellip; Malheureusement, après avoir contacté l’auteur, celui-ci m’a confirmé qu’à l’heure actuelle, le tool de ManoMano n’était pas Open Source.&lt;/p&gt;
&lt;p&gt;Moult déceptions.&lt;/p&gt;
&lt;h2 id="yet-another-standard"&gt;Yet another standard
&lt;/h2&gt;&lt;p&gt;Clairement, j’étais grognon à l’idée de passer à côté d’un tool qui faisait EXACTEMENT ce que je voulais. Comme je n’aime pas réinventer la roue, je suis allé voir sur les Internets ce qui se fait ailleurs.&lt;/p&gt;
&lt;p&gt;Grosso modo, la solution qui m’a le plus plu est un outil qui a été open sourcé par Netflix et qui s’appelle &lt;strong&gt;Dispatch&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dispatch est &lt;a class="link" href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank" rel="noopener"
&gt;un VRAI outil d’Incident Management&lt;/a&gt;, avec des workflows et de nombreuses interactions avec des outils tiers. C’est très très classe, &lt;a class="link" href="https://hawkins.gitbook.io/dispatch/" target="_blank" rel="noopener"
&gt;il y a une doc superbe&lt;/a&gt;. Bref, c’est Netflix.&lt;/p&gt;
&lt;p&gt;Mais ce n’était pas tout à fait ce que je voulais. Aujourd’hui, Dispatch est clairement overkill pour les besoins de l’équipe. A l’heure actuelle, un simple workflow « j’ouvre un channel, j’invite des gens, j’archive le channel » nous suffit. D’où l’idée du bot slack de ManoMano.&lt;/p&gt;
&lt;h2 id="make-it-so"&gt;Make it so
&lt;/h2&gt;&lt;p&gt;Bon&amp;hellip; ManoMano a pondu l’idée du bot slack&amp;hellip; j’ai toujours eu envie d’écrire un bot slack&amp;hellip; et je suis en train de me (re)former à Python. Vous me voyez venir ?&lt;/p&gt;
&lt;p&gt;Et c’est ainsi que naquit &lt;a class="link" href="https://github.com/zwindler/redalert" target="_blank" rel="noopener"
&gt;Redalert, mon propre bot slack d’Incident Management&lt;/a&gt; (très&amp;hellip; très très) basique.&lt;/p&gt;
&lt;p&gt;Pour ceux qui ont un doute sur l’inspiration pour le nom, sachez que j’ai l’infâme défaut de n’avoir jamais joué à « Command and Conquer » (pas tapper), mais qu’en revanche je suis très fan de Star Trek.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2020/06/Enterprise-D-bridge_2371-640x266-1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="a-quoi-ça-ressemble-"&gt;A quoi ça ressemble ?
&lt;/h2&gt;&lt;p&gt;Assez de teasing, voilà à quoi ressemble l’outil une fois installé. Lorsqu’un incident arrive, n’importe qui peut écrire dans le channel slack « /incident open » et une fenêtre de dialogue va s’ouvrir dans Slack avec un certain nombre d’options.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2020/06/redalert_slash_incident.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2020/06/screen_redalert.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quand on tape « /incident open » dans un channel, voilà la popup qui s’ouvre&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C’est simple (voire simpliste) mais efficace.&lt;/p&gt;
&lt;h2 id="ce-que-loutil-fait"&gt;Ce que l’outil fait
&lt;/h2&gt;&lt;p&gt;Je ne vais pas vous copier-coller le contenu du README.md du projet, mais grosso modo les features actuelles (le « MVP » comme on dit dans le milieu) sont :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ouvrir une popup dans Slack via une commande « /incident open », permettant d’entrer un certain nombre d’informations puis d’ouvrir un channel Slack en fonction de ces paramètres&lt;/li&gt;
&lt;li&gt;configurer soit même les différents niveaux d’incident possibles&lt;/li&gt;
&lt;li&gt;ajouter de manière automatique une liste d’individus dans certains ou tous les niveaux d’incidents (de manière configurable)&lt;/li&gt;
&lt;li&gt;lister tous les incidents ouverts et/ou fermés (archivés)&lt;/li&gt;
&lt;li&gt;fermer un incident (en utilisant la fonction archiver de Slack)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ce-que-loutil-ne-fait-pas-encore"&gt;Ce que l’outil ne fait pas (encore)
&lt;/h2&gt;&lt;p&gt;Idéalement, dans le futur j’aimerais ajouter les fonctionnalités suivantes (quelque part entre « un jour » et « jamais »).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faciliter l’installation de redalert via une application packagée slack&lt;/li&gt;
&lt;li&gt;ajouter de manière optionnelle une base externalisée des incidents pour permettre des analyses a posteriori&lt;/li&gt;
&lt;li&gt;une gestion du « problem management » (au sens ITIL du terme, càd relier des incidents entre eux, entre autre)&lt;/li&gt;
&lt;li&gt;interagir avec des systèmes tiers tels que PagerDuty (prévenir l’OPS en astreinte), Trello, Confluence (Postmortems), &amp;hellip;&lt;/li&gt;
&lt;li&gt;Permettre dans le dialog d’ouverture d’incident d’ajouter plusieurs personnes d’un coup (a priori &lt;a class="link" href="https://stackoverflow.com/questions/48523512/slack-interactive-message-menu-select-multiple" target="_blank" rel="noopener"
&gt;pas techniquement possible pour l’instant dans l’API Slack&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Un vrai fichier de configuration custom qui remplace les valeurs par défaut du config.py pour ne pas avoir à le réécrire complètement.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="comment-linstaller-"&gt;Comment l’installer ?
&lt;/h2&gt;&lt;p&gt;Comme je suis sympa avec vous, j’ai mis à disposition sur le projet Github zwindler/redalert &lt;a class="link" href="https://github.com/zwindler/redalert" target="_blank" rel="noopener"
&gt;toute la documentation d’installation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Actuellement, le projet est distribué de 3 manières :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les sources du code python, que vous pouvez lancer sur n’importe quelle machine disposant de python 3.6+ avec les modules (pip) slack et flask&lt;/li&gt;
&lt;li&gt;une image Docker préconfigurée, disponible sur le Dockerhub&lt;/li&gt;
&lt;li&gt;un Chart que vous pouvez déployer sur Kubernetes avec Helm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tout est décrit pas à pas dans le &lt;a class="link" href="https://github.com/zwindler/redalert" target="_blank" rel="noopener"
&gt;README.md&lt;/a&gt; du projet.&lt;/p&gt;
&lt;p&gt;Je pense que le plus important a été dit. Donc en attendant vos retours =&amp;gt; Have fun :D&lt;/p&gt;
&lt;h2 id="bonus--comment-ça-marche-"&gt;Bonus : comment ça marche ?
&lt;/h2&gt;&lt;p&gt;Je ne vais pas passer trop de temps là-dessus (quitte à faire un article un peu plus long dédié à ça une autre fois), mais l&lt;a class="link" href="https://api.slack.com/#read_the_docs" target="_blank" rel="noopener"
&gt;‘API mise à disposition par Slack est relativement bien documentée&lt;/a&gt; et il existe des modules dans la plupart des langages courants qui intègrent des méthodes pour toutes les appels qui existent sur l’API.&lt;/p&gt;
&lt;p&gt;Autant dire que même pour un OPS, c’est accessible, si jamais vous avez une autre idée de bot slack en tête.&lt;/p&gt;
&lt;p&gt;Le seul vrai souci que j’ai rencontré a été que &lt;a class="link" href="https://api.slack.com/tutorials" target="_blank" rel="noopener"
&gt;les exemples donnés&lt;/a&gt; pour le sdk python du client Slack le sont dans 2 versions, et que les premiers exemples de code sur lesquels je suis tombé (les plus approchant de ce que je voulais faire) sont en version 1 alors que la version actuelle est la 2 (bien sûr&amp;hellip;).&lt;/p&gt;
&lt;p&gt;Le code source du projet en lui-même est relativement trivial. Mon serveur Flask écoute sur 3 URLs :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un /, notamment pour les healthchecks dans Kubernetes&lt;/li&gt;
&lt;li&gt;un /incident qui reçoit toutes les commandes « /incident open|list|close » et qui redispatche ensuite en fonction du contexte&lt;/li&gt;
&lt;li&gt;un /dialog qui, comme son nom laisse penser, permet de gérer le retour POST du dialog qui est popé après le /incident open&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bonus-2--contribuer-"&gt;Bonus 2 : contribuer ?
&lt;/h2&gt;&lt;p&gt;Pour être parfaitement honnête, il y a peu de chance que je bosse énormément dessus. Ce projet a été développé sur mon temps perso initialement, en side project un peu bébête. Et même si au final, on a fini par l’adopter en production sur notre Slack pro, pour l’instant il nous suffit tel qu’il est.&lt;/p&gt;
&lt;p&gt;Néanmoins, je suis plus qu’ouvert à toutes les propositions d’amélioration ou de contributions, dans le cas où cet outil vous plairait.&lt;/p&gt;
&lt;p&gt;Cela se fera en best effort et sans aucune garantie, mais si on est d’accords sur ce point, moi ça me fera plaisir de savoir que ça peut être utile à quelqu’un !&lt;/p&gt;</description></item><item><title>Déléguer l’authentification Gitlab à Azure AD avec OAuth2</title><link>https://blog.zwindler.fr/2019/05/14/deleguer-lauthentification-gitlab-a-azure-ad-avec-oauth2/</link><pubDate>Tue, 14 May 2019 11:45:56 +0000</pubDate><guid>https://blog.zwindler.fr/2019/05/14/deleguer-lauthentification-gitlab-a-azure-ad-avec-oauth2/</guid><description>&lt;img src="https://blog.zwindler.fr/2019/05/gitlab_azuread-1.webp" alt="Featured image of post Déléguer l’authentification Gitlab à Azure AD avec OAuth2" /&gt;&lt;h2 id="gérer-les-comptes-internes-à-gitlab-cest-bof-le-sso-cest-mieux-"&gt;Gérer les comptes internes à Gitlab, c’est bof, le SSO, c’est mieux !
&lt;/h2&gt;&lt;p&gt;Dans le cadre de l’hébergement d’un nouveau serveur Gitlab, j’ai voulu intégrer notre base de compte existante, synchronisée dans Azure à l’aide de l’outil Azure AD, qui est le pendant « cloud » de l’Active Directory, bien connus de mes amis Windowiens (oui, il y en a). La plupart des applications savent aujourd’hui déléguer l’authentification à des fournisseurs tiers, généralement de type LDAP, via des protocoles tels que SAML(2) ou OAuth(2).&lt;/p&gt;
&lt;p&gt;Cependant, bien que ces protocoles soient standards, leur implémentation dépend fortement du logiciel en question et il n’est pas toujours facile de s’y retrouver.&lt;/p&gt;
&lt;p&gt;Pour faciliter cette opération, Azure a mis à disposition, directement dans Azure AD, des objets préconfigurés pour des milliers d’applications tierces. C’est comme ça qu’on peut implémenter, de manière simple et rapide, le SSO Active Directory avec les produits Atlassian (JIRA + Confluence), par exemple.&lt;/p&gt;
&lt;h2 id="tout-commence-dans-azure"&gt;Tout commence dans Azure
&lt;/h2&gt;&lt;p&gt;Dans le portail Azure, ouvrir « Entreprise applications », puis cliquer sur « New Application »&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Malheureusement pour nous, il n’y a pas de template pour Gitlab ! Il va falloir le faire à la main.&lt;/p&gt;
&lt;p&gt;A noter, le principe déroulé dans ce tutoriel est valable pour n’importe quelle autre application supportant des mécanismes similaire. Il est possible de réutiliser un template utilisé pour un soft et le réadapter pour d’autres logiciels qui fonctionnent de la même façon. C’est juste une histoire de paramètres.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Le menu nous conseille donc de choisir « Non-gallery application », puisque nous ne trouvons pas Gitlab. Sauf que, bizarrement, il faut un compte Premium pour utiliser cette feature.&lt;/p&gt;
&lt;p&gt;On se rabat donc sur « Application you’re developing ». C’est d’ailleurs ce que conseille d’utiliser &lt;a class="link" href="https://docs.gitlab.com/ee/integration/azure.html" target="_blank" rel="noopener"
&gt;la documentation de Gitlab&lt;/a&gt;. Sauf que, pas de chance non plus, ça ne marche plus comme ça, maintenant ;)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread3.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="créer-une-app-registration-pour-gitlab"&gt;Créer une App registration pour Gitlab
&lt;/h2&gt;&lt;p&gt;Pour toutes les applications qui ne sont pas dans le store, on ne peut donc plus passer par les « Entreprise Applications ». On va donc créer une « App registration », qui n’est ni plus ni moins qu’un compte de service avec un ID et un (ou plusieurs) secrets.&lt;/p&gt;
&lt;p&gt;Cliquer sur « New registration », puis lui donner un nom.&lt;/p&gt;
&lt;p&gt;Sélectionner le type de comptes qui pourront accéder à cette application. Dans mon cas, il s’agit uniquement d’autoriser les comptes provenant de mon AD, mais on peut imaginer le cas d’une application ouverte en BtoB ou carrément ouverte à tout Internet.&lt;/p&gt;
&lt;p&gt;Enfin, renseigner l’URL de callback, qui permettra à Azure de rediriger l’utilisateur qui s’est authentifié avec succès vers notre Gitlab.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We’ll return the authentication response to this URI after successfully authenticating the user. Providing this now is optional and it can be changed later, but a value is required for most authentication scenarios.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans le cas précis de Gitlab, cette URL aura la forme : &lt;a class="link" href="https://mongitlab.example.org/users/auth/azure_oauth2/callback" target="_blank" rel="noopener"
&gt;mongitlab.example.org/users/auth/azure_oauth2/callback&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread4-1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="récupérer-des-valeurs-qui-intéressent-gitlab"&gt;Récupérer des valeurs qui intéressent Gitlab
&lt;/h2&gt;&lt;p&gt;Retourner ensuite dans l’overview de notre nouvelle « App registration ». Dans les détails, elle dispose d’un Application ID, aussi appelé Client ID et d’un Tenant ID :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread5.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;On va maintenant créer un Secret. Pour les secrets, on peut choisir soit d’uploader un certificat (conseillé car plus sécurisé), ou de lui générer un mot de passe. Pour la simplicité de ce tutoriel, je vais créer un mot de passe pour notre application, mais je le répète, mieux vaut uploader un certificat.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread6.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;On dispose maintenant de notre CLIENT_ID, notre TENANT_ID et de notre CLIENT_SECRET. Notez les bien, car une fois que la fenêtre sera fermée, il ne sera plus possible de relire à nouveau le secret et il faudra en générer un nouveau&amp;hellip;&lt;/p&gt;
&lt;h2 id="ajouter-des-restrictions-ou-des-fonctionnalités-complémentaires"&gt;Ajouter des restrictions ou des fonctionnalités complémentaires
&lt;/h2&gt;&lt;p&gt;En fonction de votre niveau de licence pour Azure AD, vous aurez accès à plus ou moins de choses. Moi, je n’ai accès à pratiquement aucune feature, mais si vous avez mieux, vous aller pouvoir ajouter des options très pratiques telles que le self service (les utilisateurs peuvent demander eux même à avoir accès à l’application, et si c’est validé, ils sont ajouté dans le bon groupe) et aux autorisations/restrictions par groupes Azure AD.&lt;/p&gt;
&lt;p&gt;Pour se faire, il faut RETOURNER dans les Entreprises Applications (#RollingEyes), puis chercher notre « App registration » qui y apparaît maintenant dans la liste (avec le filtre All applications).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread7.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="configuration-de-gitlab"&gt;Configuration de Gitlab
&lt;/h2&gt;&lt;p&gt;Gitlab ayant été installé avec les packages, la configuration se situe dans le fichier &lt;strong&gt;/etc/gitlab/gitlab.rb&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dans le fichier de configuration, ajouter le bloc suivant en remplaçant les valeurs en majuscules par celles qu’on vient de récupérer :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;gitlab_rails[&amp;#39;omniauth_providers&amp;#39;] = [
{
&amp;#34;name&amp;#34; =&amp;gt; &amp;#34;azure_oauth2&amp;#34;,
&amp;#34;args&amp;#34; =&amp;gt; {
&amp;#34;client_id&amp;#34; =&amp;gt; &amp;#34;CLIENT_ID&amp;#34;,
&amp;#34;client_secret&amp;#34; =&amp;gt; &amp;#34;CLIENT_SECRET&amp;#34;,
&amp;#34;tenant_id&amp;#34; =&amp;gt; &amp;#34;TENANT_ID&amp;#34;,
}
}
]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rechargez ensuite Gitlab pour prise en compte de ce nouveau paramètre&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo gitlab-ctl reconfigure
[...]
Running handlers complete
Chef Client finished, 13/637 resources updated in 26 seconds
gitlab Reconfigured!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Une boite d’authentification Azure Oauth2 devrait apparaître sous le login classique !! Youpi :)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread8.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;h2 id="et-voilà-cest-fini-ou-presque"&gt;Et voilà c’est fini&amp;hellip; ou presque&amp;hellip;
&lt;/h2&gt;&lt;p&gt;Vous avez maintenant ajouté du SSO et l’authentification via Azure AD pour l’accès à votre Gitlab ! On essaye de se connecter ?&lt;/p&gt;
&lt;p&gt;Et Paf !!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/05/git_azuread9.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Signing in using your Azure Oaut2 account without a pre-existing gitLab account is not allowed&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;En fait, c’est normal.&lt;/p&gt;
&lt;p&gt;Par défaut, il n’est pas possible de s’authentifier avec Azure Oauth2 si un compte n’existe pas préalablement dans Gitlab, ce qui est quand même bien dommage si vous avez beaucoup de comptes à créer.&lt;/p&gt;
&lt;p&gt;Deux cas de figure.&lt;/p&gt;
&lt;h3 id="soit-vous-ne-souhaitez-pas-que-nimporte-qui-dans-votre-ad-puisse-se-connecter-sans-votre-accord-préalable"&gt;Soit vous ne souhaitez pas que n’importe qui dans votre AD puisse se connecter sans votre accord préalable
&lt;/h3&gt;&lt;p&gt;Dans ce cas là, ce cas vous est finalement assez favorable, puisque vous allez pouvoir explicitement dire qui peut ou ne peut pas se connecter. Si vous ne disposez pas des bonnes licences et que vous avez pas pu restreindre l’accès à un groupe d’utilisateurs, c’est une « solution » de contournement acceptable.&lt;/p&gt;
&lt;p&gt;Cependant, pour éviter de créer à la main tous les comptes, il sera probablement préférable de les créer de manière automatique &lt;a class="link" href="https://docs.gitlab.com/ee/api/" target="_blank" rel="noopener"
&gt;à l’aide de l’API Gitlab&lt;/a&gt; et même &lt;a class="link" href="https://docs.ansible.com/ansible/latest/modules/gitlab_user_module.html" target="_blank" rel="noopener"
&gt;du très bon module Ansible gitlab_user&lt;/a&gt; :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;- name: &amp;#34;Create Gitlab User&amp;#34;
gitlab_user:
server_url: &amp;#34;{{gitlab_api}}&amp;#34;
login_token: &amp;#34;{{token}}&amp;#34;
validate_certs: True
name: &amp;#34;Zwindler&amp;#34;
username: &amp;#34;zwindler&amp;#34;
password: &amp;#34;{{ 99999999 | random | to_uuid }}&amp;#34;
confirm: no
email: &amp;#34;zwindler@zwindler.fr&amp;#34;
state: present
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="soit-à-linverse-vous-souhaitez-que-tous-les-utilisateurs-de-votre-ad-puissent-avoir-accès-sans-pour-autant-devoir-les-ajouter-uns-par-uns"&gt;Soit, à l’inverse, vous souhaitez que tous les utilisateurs de votre AD puissent avoir accès, sans pour autant devoir les ajouter uns par uns
&lt;/h3&gt;&lt;p&gt;Il existe alors des lignes sont à ajouter dans la configuration gitlab pour autoriser cette option :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;gitlab_rails[&amp;#39;omniauth_allow_single_sign_on&amp;#39;] = [&amp;#39;azure_oauth2&amp;#39;]
gitlab_rails[&amp;#39;omniauth_block_auto_created_users&amp;#39;] = false
gitlab_rails[&amp;#39;sync_profile_from_provider&amp;#39;] = [&amp;#39;azure_oauth2&amp;#39;]
gitlab_rails[&amp;#39;sync_profile_attributes&amp;#39;] = [&amp;#39;name&amp;#39;, &amp;#39;email&amp;#39;]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;D’un point de vue sécurité, c’est un peu moins bien puisque n’importe qui avec un compte pourra se connecter, sans que vous le sachiez.&lt;/p&gt;
&lt;p&gt;Cependant, ce problème est un peu moins grave qu’il n’y parait puisque l’utilisateur sera logué mais n’aura accès à rien (ou juste ce qui est « public »).&lt;/p&gt;
&lt;p&gt;Dans le cas d’un Gitlab d’entreprise, où tous les développeurs doivent pouvoir se connecter, cette seconde option me parait quasi obligatoire. C’est encore plus acceptable si vous avez pu restreindre l’accès au SSO par groupe dans Azure AD, comme indiqué plus haut.&lt;/p&gt;
&lt;p&gt;Have fun :)&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitlab.com/ee/integration/azure.html" target="_blank" rel="noopener"
&gt;docs.gitlab.com/ee/integration/azure.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://serverfault.com/questions/874484/gitlab-and-oauth-to-azure-ad" target="_blank" rel="noopener"
&gt;serverfault.com/questions/874484/gitlab-and-oauth-to-azure-ad&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Suivez le lapin Orange – Intro et bonnes pratiques d’infra RabbitMQ</title><link>https://blog.zwindler.fr/2019/04/16/suivez-le-lapin-orange-intro-et-bonnes-pratiques-dinfra-rabbitmq/</link><pubDate>Tue, 16 Apr 2019 11:45:07 +0000</pubDate><guid>https://blog.zwindler.fr/2019/04/16/suivez-le-lapin-orange-intro-et-bonnes-pratiques-dinfra-rabbitmq/</guid><description>&lt;img src="https://blog.zwindler.fr/2019/04/rabbitmq_logo2.webp" alt="Featured image of post Suivez le lapin Orange – Intro et bonnes pratiques d’infra RabbitMQ" /&gt;&lt;h2 id="cest-quoi-rabbitmq-"&gt;C’est quoi RabbitMQ ?
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.rabbitmq.com/" target="_blank" rel="noopener"
&gt;RabbitMQ&lt;/a&gt;® est un logiciel open source, développé par Pivotal. Il s’agit d’un message broker (bus/agent de messages), très simple à mettre en place, multiplateforme et multiprotocole (AMQP, MQTT, STOMP).&lt;/p&gt;
&lt;p&gt;RabbitMQ est donc particulièrement adapté pour monter rapidement une architecture microservice, &lt;strong&gt;voire même IoT&lt;/strong&gt;, nécessitant un bus de message pour garantir les communications entre les différentes briques de cette architecture.&lt;/p&gt;
&lt;p&gt;C’est justement dans mon contexte pro : nous disposons d’une architecture logicielle aux composantes très différentes (microservices, machines outils connectées, &amp;hellip;). Nous avons donc besoin de cette agilité, qu’on ne retrouve pas forcément dans les autres messages brokers, mais aussi de garanties et des contrôles sur les transports des messages que nous n’aurions pas forcément avec des API REST.&lt;/p&gt;
&lt;h2 id="architecture-et-bonnes-pratiques"&gt;Architecture et bonnes pratiques
&lt;/h2&gt;&lt;p&gt;Voici à quoi ressemble l’architecture RabbitMQ que nous utilisons :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/04/RabbitMQ_archi.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;A première vue, c’est assez simple. Mais si vous vous demandez si nous n’aurions pas pu faire encore plus simple, alors cet article est fait pour vous ;).&lt;/p&gt;
&lt;h2 id="amqps--webmqtts"&gt;AMQP&lt;u&gt;S&lt;/u&gt; / WebMQTT&lt;u&gt;S&lt;/u&gt;
&lt;/h2&gt;&lt;p&gt;Les plus observateurs d’entre vous auront peut être remarqués le « S » à la fin des deux protocoles que nous utilisons pour faire communiquer nos services entre eux :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AMQP / AMQPS&lt;/li&gt;
&lt;li&gt;WebMQTT / WebMQTTS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous l’aurez sûrement deviné, il s’agit de la déclinaison non-sécurisée/sécurisée (chiffrée) de chacun de ces protocoles.&lt;/p&gt;
&lt;p&gt;Par défaut dans RabbitMQ, les échanges ne sont pas chiffrés. Bien qu’il n’y ait pas de réponse universelle à la question « dois-je chiffrer l’ensemble de mes flux ? », l’Ops que je suis ne peux pas s&amp;rsquo;empêcher de répondre un grand &lt;strong&gt;OUI&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;C’est particulièrement vrai dans notre cas, où une partie des flux transite par Internet, et l’autre transite à l’intérieur du réseau de notre cloud provider. L’ajout du chiffrement est &lt;em&gt;obligatoire&lt;/em&gt;. Le risque d’espionnage, de détournement d’information, de Man in the Middle, sont suffisamment sérieux pour qu’on prenne le temps de configurer un chiffrement TLS.&lt;br&gt;
Cependant, l’impact sur les performances globales de la plateforme est réel et devra être pris en compte lors du choix de l’architecture.&lt;/p&gt;
&lt;h2 id="comment-activer-le-chiffrement-tls-sur-mes-interfaces-rabbitmq-"&gt;Comment activer le chiffrement TLS sur mes interfaces RabbitMQ ?
&lt;/h2&gt;&lt;p&gt;Tout se passe dans les fichiers de configuration. Il faudra déposer les fichiers de certificats (CA, certificat public et clé privée) et rajouter les lignes suivantes dans votre configuration :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[
{rabbit, [{ssl_options, [{cacertfile, /path/to/testca/cacert.pem&amp;#34;},
{certfile, /path/to/server_certificate.pem&amp;#34;},
{keyfile, /path/to/server_key.pem&amp;#34;},
{verify, verify_peer},
{fail_if_no_peer_cert, true}]}]}
].
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant, là aussi par défaut, il n’y a pas de restrictions sur les protocoles disponibles. Or, les failles sur SSL et TLS 1.0 de ces dernières années nous obligent à désactiver ces protocoles obsolètes (voire même TLS 1.1 aussi), ainsi que tous les ciphers non sécurisés, ce qui va nettement complexifier notre configuration :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;%% -*- mode: erlang -*-
[
{ssl, [
{versions, [&amp;#39;tlsv1.2&amp;#39;]}
]},
{rabbit, [
{ssl_listeners, [5672]},
{ssl_options, [
{cacertfile, /etc/rabbitmq/certs/cacert.pem&amp;#34;},
{certfile, /etc/rabbitmq/certs/cert.pem&amp;#34;},
{keyfile, /etc/rabbitmq/certs/key.pem&amp;#34;},
{versions, [&amp;#39;tlsv1.2&amp;#39;]},
{ciphers, [
{ecdhe_ecdsa,aes_256_gcm,null,sha384},
{ecdhe_rsa,aes_256_gcm,null,sha384},
{ecdhe_ecdsa,aes_256_cbc,sha384,sha384},
{ecdhe_rsa,aes_256_cbc,sha384,sha384},
{ecdh_ecdsa,aes_256_gcm,null,sha384},
{ecdh_rsa,aes_256_gcm,null,sha384},
{ecdh_ecdsa,aes_256_cbc,sha384,sha384},
{ecdh_rsa,aes_256_cbc,sha384,sha384},
{dhe_rsa,aes_256_gcm,null,sha384},
{dhe_dss,aes_256_gcm,null,sha384},
{dhe_rsa,aes_256_cbc,sha256},
{dhe_dss,aes_256_cbc,sha256}
]},
{verify, verify_peer},
{fail_if_no_peer_cert, false}]}
]}
].
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter, depuis la version 3.7 de RabbitMQ (dernière version en date, la 3.8 sort bientôt), le format de la configuration a changé (erlang =&amp;gt; sysctl) pour être plus lisible et plus simple à automatiser. Cependant, à ma connaissance, il n’est pas possible de configurer l’ensemble des limitations de ciphers/protocoles.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;« While the new config format is more convenient for humans to edit and machines to generate, it is also relatively limited compared to the classic config format used prior to RabbitMQ 3.7.0. »&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="et-pourquoi-3-nœuds-et-pas-juste-un-au-milieu-"&gt;Et pourquoi 3 nœuds et pas juste un, au milieu ?
&lt;/h2&gt;&lt;p&gt;Cette question est volontairement provocatrice ;-p.&lt;/p&gt;
&lt;p&gt;Comme tout service informatique, les objectifs en terme d’indisponibilités tendent forcément vers 0. Un moyen classique d’approcher cet objectif est de redonder les composants informatiques, pour éviter tout &lt;em&gt;Single Point of Failure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ça tombe très bien, puisque RabbitMQ propose nativement un mécanisme de clustering. Et comme dans tout cluster disposant d’un mécanisme de vote/d’élection, il est fortement conseillé d’avoir un nombre impair de nodes pour résoudre les cas de split brain (la majorité l&amp;rsquo;emporte en cas de partition réseau). D’où les 3 nœuds (mais on peut en avoir 5, 7, &amp;hellip;).&lt;/p&gt;
&lt;h2 id="le-clustering-dans-rabbitmq-comment-ça-marche-"&gt;Le clustering dans RabbitMQ, comment ça marche ?
&lt;/h2&gt;&lt;p&gt;Pour simplifier notre vie, le cluster RabbitMQ agit de telle sorte que tous les objets logiques (utilisateurs, queues, &amp;hellip;), où qu’ils soient, sont &lt;em&gt;connus&lt;/em&gt; et &lt;em&gt;adressables&lt;/em&gt; depuis tous les membres (attention, je n’ai pas dis &lt;em&gt;répliqués&lt;/em&gt;, on y reviendra).&lt;/p&gt;
&lt;p&gt;Ça, c’est super pratique. Quel que soit le nœud qu’on va contacter, si la queue est présente sur un autre serveur RabbitMQ, le message sera redistribué de manière transparente vers le nœud qui possède la queue.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/04/rabbitmq_cluster_redirect8229614691310308292.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Pour « masquer » la complexité induite par l’ajout de serveurs RabbitMQ supplémentaires, on a donc juste à ajouter un loadbalancer en amont du cluster. Le développeur envoie simplement le message au loadbalancer. Peu importe le nœud sur lequel le message sera réellement envoyé ensuite, il sera transféré instantanément.&lt;/p&gt;
&lt;h2 id="comment-démarrer-un-cluster-"&gt;Comment démarrer un cluster ?
&lt;/h2&gt;&lt;p&gt;Sans rentrer dans le détail de toutes les opérations nécessaires pour bootstrapper un cluster, ce qu’il faut savoir c’est que tous les nœuds doivent évidemment pouvoir se contacter et si possible être relativement &lt;em&gt;proches&lt;/em&gt; (en terme de latence).&lt;/p&gt;
&lt;p&gt;Les serveurs RabbitMQ doivent être configurés de manière à partager une même passphrase dans le fichier &lt;em&gt;/var/lib/rabbitmq/.erlang.cookie&lt;/em&gt;, et on doit ensuite joindre un des noeuds depuis les deux autres avec la commande suivante :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#sur le node rabbit2, puis rabbit3
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbit1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;la documentation qui est très bien écrite.&lt;/p&gt;
&lt;h2 id="maintenant-on-est-hautement-disponibles-"&gt;Maintenant, on est hautement disponibles ?
&lt;/h2&gt;&lt;p&gt;Vous vous dites : « Chouette ! J’ai un cluster ! Je suis hautement disponible ! »&lt;/p&gt;
&lt;p&gt;Et bien&amp;hellip; non.&lt;/p&gt;
&lt;p&gt;Un point pouvant induire une grande confusion dans RabbitMQ est la terminologie « cluster RabbitMQ ». Le fait de monter un cluster laisse penser que tout devient automatiquement hautement disponible.&lt;/p&gt;
&lt;p&gt;Or, en réalité, comme je l’ai écris plus haut, il s’agit uniquement de rendre &lt;em&gt;accessible&lt;/em&gt; et &lt;em&gt;addressable&lt;/em&gt; l’ensemble des objets logiques depuis tous les nœuds. En revanche, les queues, et a fortiori leur contenu, ne sont physiquement présentes que &lt;em&gt;sur un nœud et un seul&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ainsi, si un nœud du cluster disparaît, toutes les queues qu’il possède seront détruites (si elles sont Transient), ou bloquées jusqu’à ce que le nœud soit de nouveau disponible (si elles sont Durable).&lt;/p&gt;
&lt;p&gt;Dans tous les cas, il y aura interruption de service et éventuellement perte de messages, malgré le fait qu’on ait un cluster !&lt;/p&gt;
&lt;h2 id="haute-disponibilité-des-queues"&gt;Haute disponibilité des queues
&lt;/h2&gt;&lt;p&gt;Heureusement, il est également possible de répliquer les queues et leur contenu sur une partie ou la totalité des nœuds disponibles dans le cluster. On dispose alors d’une queue principale et de miroirs qui pourront prendre le relai en cas de défaillance d’un nœud.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/rabbitmq_master_relocate.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Ceci est configurable, par queue ou par policy (applicable à toutes les queues correspondant au pattern), avec les options &lt;em&gt;ha-mode&lt;/em&gt;, &lt;em&gt;ha-params&lt;/em&gt; et &lt;em&gt;ha-sync-mode&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ha-mode&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;all&lt;/strong&gt; : synchronisera votre queue sur des miroirs présents sur tous les nœuds du cluster&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exactly&lt;/strong&gt; : permettra d’indiquer, en positionnant également un nombre sur &lt;strong&gt;ha-params&lt;/strong&gt;, le nombre exact de nœuds sur lesquels les queues sont répliquées&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nodes&lt;/strong&gt; : synchronisera des miroirs sur une liste de nœuds explicitement nommés&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ha-sync-mode&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;automatic&lt;/strong&gt; : en cas d’apparition d’un nouveau miroir, tous les messages sont synchronisés immédiatement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;manual&lt;/strong&gt; : en cas d’ajout d’un nouveau miroir, seul les nouveaux messages sont synchronisés&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attention au mode &lt;strong&gt;automatic&lt;/strong&gt;, surtout en conjugaison avec le &lt;strong&gt;ha-mode&lt;/strong&gt; à &lt;strong&gt;all&lt;/strong&gt;. En effet, si ce mode est plus sécurisé puisqu’il garantie que tous les nœuds ont bien la totalité des messages, il a aussi l’inconvénient de bloquer les queues « à synchroniser » (tant que l’ensemble des messages ne sont pas répliqués partout).&lt;br&gt;
Dernier point d’attention, au même titre que le chiffrement, l’ajout de la haute disponibilité (et du clustering, dans une moindre mesure) a un impact sur les performances globales de la plateforme.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;RabbitMQ est un outil puissant et extrêmement simple à mettre en place. On peut le lancer et obtenir un broker de message robuste avec une simple commande « docker run ».&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -d --hostname my-rabbit --name some-rabbit rabbitmq:3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour autant, dans un environnement de production avec des objectifs en terme de haute disponibilité, il n’est pas si trivial de trouver les bons paramètres. Certains nécessiteront un peu de recherche et de configuration &lt;strong&gt;erlang&lt;/strong&gt;, d’autres nécessiteront un peu de benchmarking et de tuning, si les performances commencent à devenir un problème.&lt;/p&gt;
&lt;p&gt;Pour cette seconde catégorie, j’y reviendrai dans un autre article. Cependant, sachez quand même qu’on peut traiter sans trop de difficulté des milliers de messages par secondes, même avec des machines disposant de peu de CPU. Vous aurez surement le temps de voir venir ;).&lt;/p&gt;</description></item><item><title>Migration mongoDB à chaud depuis une 3.4 vers une 4.0 (replicaSet)</title><link>https://blog.zwindler.fr/2019/02/05/migration-mongodb-a-chaud-depuis-une-3-4-vers-une-4-0-replicaset/</link><pubDate>Tue, 05 Feb 2019 11:45:02 +0000</pubDate><guid>https://blog.zwindler.fr/2019/02/05/migration-mongodb-a-chaud-depuis-une-3-4-vers-une-4-0-replicaset/</guid><description>&lt;img src="https://blog.zwindler.fr/2019/01/mongo_upgrade-1.webp" alt="Featured image of post Migration mongoDB à chaud depuis une 3.4 vers une 4.0 (replicaSet)" /&gt;&lt;h2 id="mongodb"&gt;MongoDB
&lt;/h2&gt;&lt;p&gt;Depuis peu, j’administre des bases de données MongoDB !&lt;/p&gt;
&lt;p&gt;Pour le fun (et ceux qui ne connaissent pas), la définition qu’en donne &lt;a class="link" href="https://fr.wikipedia.org/wiki/MongoDB" target="_blank" rel="noopener"
&gt;Wikipedia&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; (de l’anglais &lt;em&gt;&lt;span class="lang-en" lang="en"&gt;&lt;a class="link" href="https://fr.wiktionary.org/wiki/humongous" target="_blank" rel="noopener"
&gt;humongous&lt;/a&gt;&lt;/em&gt; qui peut être traduit par « énorme ») est un &lt;a class="link" href="https://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_base_de_donn%C3%A9es" title="Système de gestion de base de données"
target="_blank" rel="noopener"
&gt;système de gestion de base de données&lt;/a&gt; &lt;a class="link" href="https://fr.wikipedia.org/wiki/Base_de_donn%C3%A9es_orient%C3%A9e_documents" title="Base de données orientée documents"
target="_blank" rel="noopener"
&gt;orientée documents&lt;/a&gt;, &lt;a class="link" href="https://fr.wikipedia.org/wiki/Scalability" title="Scalability"
target="_blank" rel="noopener"
&gt;répartissable sur un nombre quelconque d’ordinateurs&lt;/a&gt; et ne nécessitant pas de schéma prédéfini des données. Il est écrit en &lt;a class="link" href="https://fr.wikipedia.org/wiki/C%2B%2B" title="C&amp;#43;&amp;#43;"
target="_blank" rel="noopener"
&gt;C++&lt;/a&gt;. Le serveur et les outils sont distribués sous &lt;a class="link" href="https://fr.wikipedia.org/w/index.php?title=Server_Side_Public_License_%28SSPL%29&amp;amp;action=edit&amp;amp;redlink=1" title="Server Side Public License (SSPL) (page inexistante)"
target="_blank" rel="noopener"
&gt;licence AGPL&lt;/a&gt;{.new}, les pilotes sous &lt;a class="link" href="https://fr.wikipedia.org/wiki/Licence_Apache" title="Licence Apache"
target="_blank" rel="noopener"
&gt;licence Apache&lt;/a&gt; et la documentation sous &lt;a class="link" href="https://fr.wikipedia.org/wiki/Licence_Creative_Commons" title="Licence Creative Commons"
target="_blank" rel="noopener"
&gt;licence Creative Commons&lt;/a&gt;&lt;sup id="cite_ref-licensing_2-1" class="reference"&gt;&lt;/sup&gt;. Il fait partie de la mouvance &lt;a class="link" href="https://fr.wikipedia.org/wiki/NoSQL" title="NoSQL"
target="_blank" rel="noopener"
&gt;NoSQL&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Comme dans la vie de tout projets, on installe un logiciel, et sur le moment ça nous suffit, on est contents.&lt;/p&gt;
&lt;p&gt;Mais arrive le jour fatidique où le logiciel est obsolète et il faut mettre à jour la base. Sans aucun créneau de maintenance pour le faire bien entendu car elles sont évidemment utilisées en production ;-).&lt;/p&gt;
&lt;h2 id="prérequis"&gt;Prérequis
&lt;/h2&gt;&lt;p&gt;Bon point pour moi, je n’ai pas fais l’erreur d’avoir une base de données mongoDB « standalone ». Je dispose de cluster de bases de données MongoDB (replicaSet, dans la terminologie mongo), que je vais donc pouvoir mettre à jour à chaud. Ça sera juste un peu plus long ;-).&lt;/p&gt;
&lt;h2 id="34--40--pas-possible"&gt;3.4 =&amp;gt; 4.0 = pas possible
&lt;/h2&gt;&lt;p&gt;Bon quand même, fallait bien que je tombe dans le piège.&lt;/p&gt;
&lt;p&gt;La version majeure 3.4 (la dernière en date est la .19) ne peut pas directement être mise à jour vers une 4.0. Comme c’est une majeure, il faut passer d’abord par la majeure suivante, la 3.6 (c’est classique comme limitation).&lt;/p&gt;
&lt;h2 id="on-passe-en-36-alors"&gt;On passe en 3.6 alors
&lt;/h2&gt;&lt;p&gt;Pour me simplifier la vie, j’ai un mini playbook Ansible qui me permet d’ajouter les dépôts en fonction de la version que je veux.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;- name: Prepare mongodb upgrade
hosts: all
vars:
#mongo_repo : &amp;#34;deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse&amp;#34;
mongo_repo: &amp;#34;deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse&amp;#34;
#mongo_repo: &amp;#34;deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse&amp;#34;
tasks:
- name: &amp;#34;Add mongodb repository key&amp;#34;
apt_key:
keyserver: keyserver.ubuntu.com
id: &amp;#34;{{item}}&amp;#34;
state: present
loop:
- 0C49F3730359A14518585931BC711F9BA15703C6
- 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
- 9DA31620334BD75D9DCB49F368818C72E52529D4
- name: &amp;#34;Add mongodb repository&amp;#34;
apt_repository:
repo: &amp;#34;{{ mongo_repo }}&amp;#34;
state: present
update_cache: yes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Clairement, on peut faire plus propre. Ici, c’est du oneshot sur quelques machines Ubuntu, donc je n’ai pas automatisé plus que ça. Mais si vous avez plus de machines à faire que moi, je vous invite à le raffiner un peu, par exemple en ajoutant le repo et la clé en fonction de la version donnée en paramètre.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ansible-playbook -i inventory/prod/mongo-prod prepare_mongo_upgrade.yml -b
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="mise-à-jour-des-binaires-vers-la-36"&gt;Mise à jour des binaires vers la 3.6
&lt;/h2&gt;&lt;p&gt;Maintenant qu’on a bien les dépôts pour la version 3.6, on peut mettre à jour nos serveurs. Idéalement si on avait de nombreux clusters à migrer, il faudrait le faire avec un playbook Ansible (ou autre) qui passe sur les serveurs, uns par uns, les mets à jour et les redémarre.&lt;/p&gt;
&lt;p&gt;Cependant, pour simplifier l’explication, je vais laisser la procédure telle quelle et tout faire à la main.&lt;/p&gt;
&lt;p&gt;Sur les SECONDARY, &lt;strong&gt;uns par uns&lt;/strong&gt;, mettre à jour manuellement le serveur, puis le redémarrer :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apt-get update
apt-get upgrade mongodb-org-server mongodb-org-shell
[...]
Unpacking mongodb-org-server (3.6.10) over (3.4.19) ...
[...]
systemctl restart mongod
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vérifier que tout fonctionne à nouveau après redémarrage&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mongo
MongoDB shell version v3.6.10
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { &amp;#34;id&amp;#34; : UUID(&amp;#34;17272d4e-ecd0-49c2-a672-8804227ab0e4&amp;#34;) }
MongoDB server version: 3.6.10
rs:SECONDARY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Puis, se connecter sur le PRIMARY, et lui passer la commande suivante (qui va avoir pour effet de le rétrograder proprement et temporairement en tant que SECONDARY) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$&amp;gt; mongo
rs:PRIMARY&amp;gt; use admin
switched to db admin
rs:PRIMARY&amp;gt; db.auth(&amp;#39;myadmin&amp;#39;, &amp;#39;myawesomepassword&amp;#39;)
1
rs:PRIMARY&amp;gt; rs.stepDown(180)
[...]
2019-01-25T15:23:02.520+0000 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2019-01-25T15:23:02.548+0000 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) ok
rs:SECONDARY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et enfin, mettre à jour manuellement le serveur de la même manière que les autres :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apt-get update
apt-get upgrade mongodb-org-server mongodb-org-shell
systemctl restart mongod
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="compatibilité-36"&gt;Compatibilité 3.6
&lt;/h2&gt;&lt;p&gt;Ici, je viens de faire la migration de 3.4 vers 3.6. En réalité, ce n’est pas complètement terminé. L’ensemble des binaires ont beau être en version 3.6, la base elle, reste en « compatibilité » 3.4.&lt;/p&gt;
&lt;p&gt;Pour s’en assurer, une connexion sur n’importe quel serveur permet de le vérifier :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$&amp;gt; mongo
rs:SECONDARY&amp;gt; db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{ &amp;#34;featureCompatibilityVersion&amp;#34; : { &amp;#34;version&amp;#34; : &amp;#34;3.4&amp;#34; }, &amp;#34;ok&amp;#34; : 1 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On va donc aller sur le nœud PRIMARY pour passer la base en compatibilité 3.6 (le seul prérequis est qu’une majorité de serveurs aient leurs binaires mis à jour en 3.6 et redémarrés) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$&amp;gt; mongo
MongoDB shell version v3.6.10
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { &amp;#34;id&amp;#34; : UUID(&amp;#34;aaa-aaa-aaa-aaa-aaa&amp;#34;) }
MongoDB server version: 3.6.10
rs:PRIMARY&amp;gt; db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{ &amp;#34;featureCompatibilityVersion&amp;#34; : { &amp;#34;version&amp;#34; : &amp;#34;3.4&amp;#34; }, &amp;#34;ok&amp;#34; : 1 }
rs:PRIMARY&amp;gt; use admin
switched to db admin
rs:PRIMARY&amp;gt; db.auth(&amp;#39;myadmin&amp;#39;, &amp;#39;myawesomepassword&amp;#39;)
1
rs:PRIMARY&amp;gt; db.adminCommand( { setFeatureCompatibilityVersion: &amp;#34;3.6&amp;#34; } )
{ &amp;#34;ok&amp;#34; : 1 }
rs:PRIMARY&amp;gt; db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{ &amp;#34;featureCompatibilityVersion&amp;#34; : { &amp;#34;version&amp;#34; : &amp;#34;3.6&amp;#34; }, &amp;#34;ok&amp;#34; : 1 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK ! on a fait la moitié du chemin&amp;hellip;&lt;/p&gt;
&lt;h2 id="mettre-à-jour-le-replicaset-dans-la-version-1"&gt;Mettre à jour le ReplicaSet dans la version 1
&lt;/h2&gt;&lt;p&gt;Différence notable entre la version 3.4 et la version 3.6, c’est la façon dont sont gérés les replicaSets. La version 3.6 introduit la version 1 du protocol des replicaSet, et empêche les précédents clusters déclarés de fonctionner.&lt;br&gt;
Il est donc nécessaire de mettre à jour le protocole &lt;strong&gt;avant&lt;/strong&gt; de mettre à jour en 4.0.&lt;/p&gt;
&lt;p&gt;Ouvrir un shell mongo sur le PRIMARY, et modifier la configuration du replicaset (rs) :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cfg = rs.conf();
cfg.protocolVersion=1;
rs.reconfig(cfg);
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="mise-à-jour-des-binaires-vers-la-40"&gt;Mise à jour des binaires vers la 4.0
&lt;/h2&gt;&lt;p&gt;Bon, je ne vais pas vous refaire l’affront de vous copier coller la procédure de mise à jour : maintenant qu’on a mis à jour la version du replicaSet, c’est la même.&lt;/p&gt;
&lt;p&gt;Pour rappel :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Relancer le playbook pour ajouter le dépôt de la version 4.0 (décommenter la ligne 4.0)&lt;/li&gt;
&lt;li&gt;Mise à jour des serveurs SECONDARY puis redémarrage du serveur&lt;/li&gt;
&lt;li&gt;Step down du PRIMARY&lt;/li&gt;
&lt;li&gt;Mise à jour du PRIMARY devenu SECONDARY après le stepdown, puis redémarrage du serveur&lt;/li&gt;
&lt;li&gt;Mise à niveau de la compatibilité de la base en 4.0&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;rs:PRIMARY&amp;gt; db.adminCommand( { setFeatureCompatibilityVersion: &amp;#34;4.0&amp;#34; } )
{
&amp;#34;ok&amp;#34; : 1,
[...]
}
rs:PRIMARY&amp;gt; db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{
&amp;#34;featureCompatibilityVersion&amp;#34; : {
&amp;#34;version&amp;#34; : &amp;#34;4.0&amp;#34;
},
[...]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Et voilà, votre cluster est « up-to-date », après 2 upgrades de versions majeures et sans aucune interruption de service. Alors, comme on dit chez moi :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Encore une victoire de Canard !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;source : &lt;a class="link" href="https://player.ina.fr/player/embed/PUB417943064/1/1b0bd203fbcd702f9bc9b10ac3d0fc21" target="_blank" rel="noopener"
&gt;player.ina.fr/player/embed/PUB417943064/1/1b0bd203fbcd702f9bc9b10ac3d0fc21&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="sources"&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/" target="_blank" rel="noopener"
&gt;La documentation d’installation de MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://web.archive.org/web/20220705195701/https://www.mongodb.com/docs/manual/release-notes/3.6-upgrade-replica-set/" target="_blank" rel="noopener"
&gt;La documentation officielle de mise à jour d’un replicaSet MongoDB vers 3.6(lien mort, j&amp;rsquo;utilise Internet Archive)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://web.archive.org/web/20230325023508/https://www.mongodb.com/docs/manual/release-notes/4.0-upgrade-replica-set/" target="_blank" rel="noopener"
&gt;La documentation officielle de mise à jour d’un replicaSet MongoDB vers 4.0 (lien mort, j&amp;rsquo;utilise Internet Archive)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.mongodb.com/manual/reference/method/rs.stepDown/#rs.stepDown" target="_blank" rel="noopener"
&gt;La documentation officielle de la commande stepdown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>