<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>MACVLAN on Ink&#39;Hey</title>
    <link>https://inkey-art.net/tags/macvlan/</link>
    <description>Recent content in MACVLAN on Ink&#39;Hey</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>fr-FR</language>
    <lastBuildDate>Sun, 17 May 2026 00:18:09 +0200</lastBuildDate>
    
	<atom:link href="https://inkey-art.net/tags/macvlan/index.xml" rel="self" type="application/rss+xml" />
    
    
    
    <item>
      <title> 🖧 Réseau moderne sous linux: 2. Routeur avec networkd</title>
      <link>https://inkey-art.net/r%C3%A9seau-moderne-sous-linux-2.-routeur-avec-networkd/</link>
      <pubDate>Sat, 23 May 2026 19:01:12 +0200</pubDate>
      
      <guid>https://inkey-art.net/r%C3%A9seau-moderne-sous-linux-2.-routeur-avec-networkd/</guid>
      <description>&lt;p&gt;Dans cet article, je vais présenter rapidement comment vous pouvez faire un &lt;strong&gt;routeur minimaliste&lt;/strong&gt; avec &lt;code&gt;systemd‑networkd&lt;/code&gt; et
remplacer totalement ou partiellement votre &lt;em&gt;box internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nous partirons du principe d&amp;rsquo;une box avec 2 liens :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wan&lt;/code&gt; branché sur l&amp;rsquo;ONT ou une box en mode bridge.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lan&lt;/code&gt; connecté à votre réseau local.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous allons partir sur un approché minimaliste :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;En IPv6 , &lt;strong&gt;adresse globale&lt;/strong&gt; (GUA: préfix 2000::/3) et &lt;strong&gt;Lien-local&lt;/strong&gt; (LLA: préfix fe80::/10) pour les machines côté lan.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pas de pare-feu&lt;/strong&gt; pour le moment (on verra ça ensuite dans un autre sujet).&lt;/li&gt;
&lt;li&gt;En IPv4 : un &lt;strong&gt;NAT&lt;/strong&gt; tout simple qui converti les addresse locale vers l&amp;rsquo;internet (massquerade). Uniquement les connections sortante
sont concernés.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;router1.svg&#34; alt=&#34;routeur&#34;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note : configurer un routeur et vérifier son bon fonctionnement n&amp;rsquo;est pas simple,
Des commandes comme &lt;code&gt;ip address&lt;/code&gt;, &lt;code&gt;ip route&lt;/code&gt;, &lt;code&gt;traceroute&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt; ou encore le logiciel &lt;code&gt;wireshark&lt;/code&gt; sont très utile
pour vous aider à corriger votre configuration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;côté-wan&#34;&gt;Côté Wan&lt;/h1&gt;
&lt;h2 id=&#34;cela-dépend-vraiment-du-fai&#34;&gt;Cela dépend vraiment du FAI&lt;/h2&gt;
&lt;p&gt;La partie la plus complexe est celle consistant à brancher votre routeur et à récupérer les ip (v4 et V6) depuis
le fournisseur d&amp;rsquo;accès, la méthode varie d&amp;rsquo;un fournisseur d&amp;rsquo;accès à l&amp;rsquo;autre.&lt;/p&gt;
&lt;p&gt;La méthode varie selon les fournisseurs d&amp;rsquo;accès :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Certain fournissent (ou vous donne accès si vous les contactez) à un boitier externe ONT qui converti le signal fibre
en ethernet.&lt;/li&gt;
&lt;li&gt;D&amp;rsquo;autre fournissent uniquement des box dont l&amp;rsquo;ONT est intégré et dans ce cas précis, il n&amp;rsquo;est pas possible de se débarrasser de la box,
vous pouvez néanmoins la placer en mode &lt;em&gt;bridge&lt;/em&gt;, ce qui vous permet de router avec votre machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il peut être aussi possible de faire fonctionner un ONT différent sur le réseau, mais cela est un point délicat que je
n&amp;rsquo;aborderais pas.&lt;/p&gt;
&lt;p&gt;La récupération des IPs diffère, elle aussi entre les fournisseurs d&amp;rsquo;accès avec diverses mécaniques :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;certain permettent de récupérer les IPs via du &lt;strong&gt;DHCP/DHCPv6&lt;/strong&gt; d&amp;rsquo;autre oblige à créer un &lt;strong&gt;lien PPPoE&lt;/strong&gt;, enfin d&amp;rsquo;autres ne fournissent pas de méthode standard, il vous faudra donc &lt;strong&gt;assigner manuellement toute ou partie des IPs&lt;/strong&gt;…&lt;/li&gt;
&lt;li&gt;Selon les fournisseurs, &lt;strong&gt;il est parfois nécessaire de configurer des interfaces utilisant des VLAN&lt;/strong&gt;, chez &lt;a href=&#34;ttps://lafibre.info/remplacer-livebox/remplacer-la-livebox-par-systemd-networkd-nftables/&#34;&gt;orange le DHCP passe par le VLAN 832&lt;/a&gt;, et &lt;a href=&#34;https://lafibre.info/remplacer-bbox/recap-2025-a-lire-pour-les-nouveaux-arrivants/&#34;&gt;chez bouygue le traffic internet&lt;/a&gt; est sur le vlan 100
Si vous êtes établis en france, le mieux est de chercher sur le forum &lt;em&gt;&lt;a href=&#34;https://lafibre.info/routeurs/&#34;&gt;lafibre&lt;/a&gt;&lt;/em&gt; pour trouver la configuration spécifique à votre FAI .&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Note : j&amp;rsquo;omets volontairement la question de la téléphonie/télévision de l&amp;rsquo;équation. Il est effectivement
possible de récupérer ces services dans certain cas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;base-générique&#34;&gt;Base Générique&lt;/h2&gt;
&lt;p&gt;Dans tous les cas vous allez vous retrouver avec un fichier &lt;code&gt;.network&lt;/code&gt; pour l&amp;rsquo;interface &lt;code&gt;wan&lt;/code&gt;  :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/wan.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;wan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Link]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RequiredForOnline&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Si vous utilisez le DHCP (en tant que client, valable qu&amp;#39;avec certain FAI)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dans le cas où vous voulez router en ipv6, vous pouvez ajouter ceci:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/wan.network.d/ipv6.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv6Forwarding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Pour récupèrer les ipv6 en DHCPv6 (valable qu&amp;#39;avec certains FAI)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;LinkLocalAddressing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;ipv6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCPPrefixDelegation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv6AcceptRA&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;et en ipv4:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/wan.network.d/ipv4.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv4Forwarding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour ipv6, il est nécessaire d&amp;rsquo;activer le forwarding de façon globale en plus :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/networkd.conf.d/router.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv6Forwarding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Il n&amp;#39;est pas nécessaire de faire pareil en ipv4:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# IPv4Forwarding=yes &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La raison est un &lt;a href=&#34;https://github.com/systemd/systemd/issues/33414&#34;&gt;comportement différent entre ipv6 et ipv4 dans le kernel&lt;/a&gt;. Il n&amp;rsquo;est pas super clair pour moi si cela est un bug ou pas, mais cela rend les choses pas super simple à comprendre.&lt;/p&gt;
&lt;h2 id=&#34;dhcpdhcpv6&#34;&gt;DHCP/DHCPv6&lt;/h2&gt;
&lt;p&gt;Si vous utilisez du DHCP/DHCPv6, il est probable que la configuration varie beaucoup d&amp;rsquo;un fournisseur à l&amp;rsquo;autre,
par exemple en cherchant sur le forum lafibre, on voit qu&amp;rsquo;une configuration dhcp pour orange ressemblerait &lt;a href=&#34;https://lafibre.info/remplacer-livebox/remplacer-la-livebox-par-systemd-networkd-nftables/&#34;&gt;plutôt à ça&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note : pour orange une configuration supplémentaire pour utiliser une interface sur le VLAN 832 est nécessaire&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/orange.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# orange is wan vlan 832&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;orange&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[DHCPv4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ClientIdentifier&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;mac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;VendorClassIdentifier&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;sagem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UserClass&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;FSVDSL_livebox.Internet.softathome.Livebox3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# A modifier avec des identifiants de connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;SendOption&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;90:string:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x09\x00\x00\x05\x58\x01\x03\x41\x01\x0D\x66\x74\x69\x2F\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseHostname&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDomains&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[DHCPv6]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WithoutRA&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;solicit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UserClass&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;FSVDSL_livebox.Internet.softathome.livebox4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# A modifier avec des identifiants de connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;SendOption&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;11:string:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x09\x00\x00\x05\x58\x01\x03\x41\x01\x0D\x66\x74\x69\x2F\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**\x**&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# A modifier avec des identifiants de connection&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;SendOption&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;16:string:\x00\x00\x04\x0e\x00\x05\x73\x61\x67\x65\x6d&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseNTP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[IPv6AcceptRA]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCPv6Client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDomains&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et une configuration dhcp pour sfr plutôt à &lt;a href=&#34;https://lafibre.info/remplacer-sfr/configuration-de-systemd-networkd/msg1047970/#msg1047970&#34;&gt;ça&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/wan.network.d/sfr.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Link]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# set this to your router mac address&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MACAddress&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;00:00:5E:00:53:00 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[DHCPv4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ClientIdentifier&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;mac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseGateway&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseHostname&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;VendorClassIdentifier&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;neufbox_bypass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[DHCPv6]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DUIDType&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;link-layer-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;PrefixDelegationHint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;::/56&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RapidCommit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;No&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;SendOption&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;16:string:\x00\x00\xa0\x0c\x00\x0e\x6e\x65\x75\x66\x62\x6f\x78\x5f\x62\x79\x70\x61\x73\x73&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseDelegatedPrefix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WithoutRA&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;solicit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UseHostname&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;No&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bref, &lt;strong&gt;cette partie est un peu complexe et très variable d&amp;rsquo;un fournisseur à l&amp;rsquo;autre&lt;/strong&gt; et l&amp;rsquo;on trouve des tonnes de discussion
sur le sujet qu&amp;rsquo;il peut être fastidieux de lire.
Je vous conseille selon votre fournisseur d&amp;rsquo;&lt;strong&gt;expérimenter et si possible de partager&lt;/strong&gt; (sauf les secrets bien sûr) votre
configuration fonctionnelle pour permettre à d&amp;rsquo;autre de s&amp;rsquo;éviter ces recherches fastidieuses.&lt;/p&gt;
&lt;h1 id=&#34;côté-lan&#34;&gt;Côté LAN&lt;/h1&gt;
&lt;p&gt;La partie Lan est beaucoup plus simple à configurer dans le sens ou elle ne dépend pas de fournisseur d&amp;rsquo;accès.
Tout d&amp;rsquo;abord, nous allons activer mdns (&lt;a href=&#34;http://localhost:1313/r%C3%A9seau-moderne-sous-linux-1.quelques-astuces-avec-networkd/&#34;&gt;relire la partie 1 pour la configuration systemd-resolved&lt;/a&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/lan.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;lan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MulticastDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ipv6&#34;&gt;IPv6&lt;/h3&gt;
&lt;p&gt;En IPv6, c&amp;rsquo;est relativement facile, il faut déléguer un prefix de sous réseau /64 pour l&amp;rsquo;interface lan:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/lan.network.d/ipv6.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv6SendRA&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCPPrefixDelegation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv6Forwarding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[IPv6SendRA]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Vous pouvez définir ici explicitement le dns à partager:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;2a13:1001::86:54:11:100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[DHCPPrefixDelegation]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;UplinkInterface&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;wan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;SubnetId&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;0x1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Announce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ipv4&#34;&gt;IPv4&lt;/h3&gt;
&lt;p&gt;En IPv4 c&amp;rsquo;est moins cool. Il faut passer du nat et faire du DHCP (en tant que serveur) :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/lan.network.d/ipv4.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Address&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;192.168.1.1/24&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCPServer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# note: you may want to do masquerade by you firewall rule instead&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPMasquerade&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv4Forwarding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[DHCPServer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;PoolOffset&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;PoolSize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;EmitDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Vous pouvez définir ici explicitement le dns à partager:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;86.54.11.100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Avec cette configuration, vous devriez avoir un &lt;strong&gt;accès internet fonctionnel&lt;/strong&gt; dans tout votre réseau et la possibilité
de communiquer en dualstack (ipv6 et ipv4).&lt;/p&gt;
&lt;p&gt;Néanmoins cette configuration à des défauts :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Pas de pare-feu&lt;/em&gt;, les machine (en ipv6 au moins) peuvent donc être accessible depuis l&amp;rsquo;extérieur, ce qui n&amp;rsquo;est pas recommandé.&lt;/li&gt;
&lt;li&gt;La configuration n&amp;rsquo;est &lt;em&gt;pas conçu pour rendre un serveur accessible depuis l&amp;rsquo;extérieur en ipv4&lt;/em&gt; (pas de port-forwarding).&lt;/li&gt;
&lt;li&gt;Pas d&amp;rsquo;&lt;em&gt;ipv6-mostly&lt;/em&gt; : la configuration actuelle est purement en mode double-stack. Il est possible de forcer les chose pour utiliser au maximum ipv6.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;J&amp;rsquo;étudierai donc ces sujets ainsi que l&amp;rsquo;installation d&amp;rsquo;un vpn wireguard dans les prochains articles…&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title> 🖧 Réseau moderne sous linux: 1.Quelques astuces avec networkd</title>
      <link>https://inkey-art.net/r%C3%A9seau-moderne-sous-linux-1.quelques-astuces-avec-networkd/</link>
      <pubDate>Sun, 17 May 2026 00:18:09 +0200</pubDate>
      
      <guid>https://inkey-art.net/r%C3%A9seau-moderne-sous-linux-1.quelques-astuces-avec-networkd/</guid>
      <description>&lt;p&gt;Dans cette nouvelle série d&amp;rsquo;articles, je vais parler de configuration réseau sous linux avec
des outils modernes &lt;code&gt;Gnu/Linux&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Dans ces premiers partis, je vais simplement présenter des astuces de configuration networkd, que
j&amp;rsquo;ai découvert en passant beaucoup de temps dans la &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/latest/systemd-networkd.service.html#&#34;&gt;documentation&lt;/a&gt;,
et parfois à l&amp;rsquo;aide de quelques articles de blog ou autre.&lt;/p&gt;
&lt;p&gt;Personnellement, j&amp;rsquo;aime beaucoup networkd même si je trouve la documentation un peu difficile d&amp;rsquo;accès, l&amp;rsquo;internet ne
contient pas assez d&amp;rsquo;exemple et d&amp;rsquo;article de blog à mon goût permettant de facilement trouver la solution à son problème,
il faut donc parfois passer un temps non négligeable à creuser la documentation.&lt;/p&gt;
&lt;h2 id=&#34;1activer-mdns&#34;&gt;1.Activer Mdns&lt;/h2&gt;
&lt;p&gt;Pour accéder localement facilement aux machines via les adresse en &lt;em&gt;nomdemachine&lt;/em&gt;.local, il est utile d&amp;rsquo;avoir mdns d&amp;rsquo;activé , pour cela
si vous utilisez &lt;code&gt;systemd-networkd&lt;/code&gt;, vous aurez besoin d&amp;rsquo;installer &lt;code&gt;systemd-resolved&lt;/code&gt; et de vérifier qu&amp;rsquo;il est actif.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install systemd-resolved
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;resolvectl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si vous constater que mdns est désactivé sur votre interface (avec un résultat de commande contenant&lt;code&gt;‑mDNS&lt;/code&gt;), il faut
ajuster la configuration globale de resolved et/ou ajuster la configuration de l&amp;rsquo;interface:&lt;/p&gt;
&lt;p&gt;Pour la configuration globale, vous devez créer un fichier :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/resolved.conf.d/99-enable-mdns.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Resolve]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MulticastDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# protocole similair à MDNS mais qui semble de moins en moins en usage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;LLMNR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour la configuration spécifique de l&amp;rsquo;interface, il vous faudra dans le fichier &lt;code&gt;.network&lt;/code&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/moninterface.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Activer mdns (les addresse en .local)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MulticastDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Note: ce dernier élément est un exemple, pas un vrai fichier &lt;code&gt;.network&lt;/code&gt; fonctionnel, vous aurez besoin d&amp;rsquo;une directive
&lt;code&gt;[Match]&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;2renommer-une-interface&#34;&gt;2.Renommer une interface&lt;/h2&gt;
&lt;p&gt;Dans un cas simple où vous avez une interface ethernet non usb,
il est aisé de renommer son interface via un fichier &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/latest/systemd.link.html&#34;&gt;.link&lt;/a&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/lan0.link&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MACAddress&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;00-00-5E-00-53-01&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Link]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# le nouveau nom&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;lan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;comme vu &lt;a href=&#34;https://inkey-art.net/des-d%C3%A9clenchement-selon-l%C3%A9tat-du-r%C3%A9seau/&#34;&gt;précédemment&lt;/a&gt; le cas de périphérique USB est plus compliqué, certaines
cartes change d&amp;rsquo;addresses mac à chaque connection tandis que certain conservent leur addresses mac.&lt;/p&gt;
&lt;p&gt;La configuration des distributions peut changer les choses aussi.
Ainsi, sous Debian Trixie, il &lt;a href=&#34;https://unix.stackexchange.com/a/736277&#34;&gt;peut être nécessaire de surcharger &lt;code&gt;73-usb-net-by-mac.link&lt;/code&gt;&lt;/a&gt; ,
pour éviter que le système renomme nos interfaces USB et ainsi nous permettre nous même de les modifier.&lt;/p&gt;
&lt;h2 id=&#34;3-switch-virtuel-et-virtualisation-des-interfaces&#34;&gt;3. Switch Virtuel et virtualisation des interfaces&lt;/h2&gt;
&lt;p&gt;Il peut se trouver que les interface physiques ne correspondent pas exactement au réseau que vous voudriez obtenir :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vous voulez utiliser plusieurs ports ethernet de votre système comme &lt;strong&gt;switch réseau&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Vous voulez des &lt;strong&gt;interfaces réseau virtuelles séparées&lt;/strong&gt;, par exemple pour des conteneurs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces ajustements sont possible via systemd-networkd.&lt;/p&gt;
&lt;p&gt;Prénons un cas d&amp;rsquo;usage où l&amp;rsquo;on veut véritablement séparer les interfaces réseau utiliser des interfaces physiques réelles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nous avons 4 interface réelle de &lt;code&gt;lan0&lt;/code&gt; à &lt;code&gt;lan3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Nous voulons les regrouper dans un switch virtuel que nous nommeront &lt;code&gt;vslan&lt;/code&gt; pour &lt;em&gt;virtual switch lan&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Nous voulons 2 interfaces virtuelles pour, &lt;code&gt;vslan1&lt;/code&gt; pour l&amp;rsquo;hôte et &lt;code&gt;vslan2&lt;/code&gt; pour une machine virtuelle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;vslan.svg&#34; alt=&#34;Switch Virtuel et Macvlan&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;le-switch-virtuel&#34;&gt;Le switch virtuel&lt;/h3&gt;
&lt;p&gt;Il suffit de créer une interface pont :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/vslan.netdev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[NetDev]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Kind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;bridge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On attache un par un les ports lan à ce pont, par exemple pour &lt;code&gt;lan0&lt;/code&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/lan0.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;lan0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Bridge&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il faut répéter cette étape pour les autres ou utiliser un pattern par exemple : &lt;code&gt;Name=lan*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;À partir de cette étape, si vous redémarrez networkd ou toute la machine, vous avez bel et bien un switch virtuel.&lt;/p&gt;
&lt;h2 id=&#34;macvlan--plusieurs-interfaces-virtuelles-réseau-de-niveau-2&#34;&gt;MacVlan : plusieurs interfaces virtuelles réseau de niveau 2&lt;/h2&gt;
&lt;p&gt;Pour avoir plusieurs addresses sur la machine, au niveau 2, c&amp;rsquo;est-à-dire que chaque machine aura une interface avec une
adresse mac dédié et sera donc virtuellement totalement séparées, on utilise une fonctionnalité appelée &lt;em&gt;MACVLAN&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Une limitation de ce mécanisme sous 🐧 Linux est que l&amp;rsquo;interface parente ne peut pas communiquer avec l&amp;rsquo;interface enfant,
ainsi si j&amp;rsquo;avais une interface &lt;code&gt;eth0&lt;/code&gt; que je séparerais par &lt;em&gt;MACVLAN&lt;/em&gt; en &lt;code&gt;virt10@eth0&lt;/code&gt; et &lt;code&gt;virt2@eth0&lt;/code&gt; et que j&amp;rsquo;attribuerais
des addresses à ces 3 interfaces, &lt;code&gt;eth0&lt;/code&gt; ne pourrait communiquer avec &lt;code&gt;virt10@eth0&lt;/code&gt; et &lt;code&gt;virt10@eth1&lt;/code&gt; et inversement.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;astuce pour contourner le problème dans notre cas, est simplement :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;de ne pas attribuer d&amp;rsquo;adresse à notre pont, ainsi le pont ne sera pas utiliser directement pour la communication réseau.&lt;/li&gt;
&lt;li&gt;ajouter un macvlan spécifique pour l&amp;rsquo;hôte (&lt;code&gt;vslan1&lt;/code&gt; dans le cas présent).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On configure ce pont pour fournir des macvlan pour nos adresses virtuelles :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/vslan.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MACVLAN&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MACVLAN&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ConfigureWithoutCarrier&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# désactiver la récupèration/génération d&amp;#39;addresse en ipv6 et ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;IPv6AcceptRA&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;LinkLocalAddressing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;no&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il nous manque plus que les interfaces virtuelles MACLAN, ça se fait à l&amp;rsquo;aide de 2 fichiers.
Par exemple pour vslan1, on définit notre macvlan :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/vslan1.netdev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[NetDev]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Kind&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;macvlan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[MACVLAN]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Mode&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;bridge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On peut ensuite configurer l&amp;rsquo;interface vslan1:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/network/vslan1.network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Activer mdns (les addresse en .local)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;MulticastDNS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Activer la récupèration d&amp;#39;ip via le dhcp utile pour ipv4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# La récupèration d&amp;#39;addresse ipv6 est ici implicite (valeur par défaut), mais il est possible d&amp;#39;être explicite:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# IPv6AcceptRA=yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# LinkLocalAddressing=yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# il est possible d&amp;#39;assigner si besoin manuellement une addresse ULA (locale) en plus de l&amp;#39;addresse globale obtenu&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# via le routeur.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# un des avantages et que l&amp;#39;addressage ne changera pas même en cas de coupure de l&amp;#39;internet/changement du prefixe globale&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# assigné. Il faut néanmoins ajuster le réseau et les autres machine pour que la connectivité suivent. Par défault, sur&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# mon réseau, mon routeur ne &amp;#34;route&amp;#34; pas ces addresse. il faut donc que les différence machine soit assigné avec des&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ipv6 ULA du même sous réseau /64 ou ajuster le routeur en conséquence.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Address=fd70::b/64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[IPv6AcceptRA]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Optionel: cela force le suffixe de l&amp;#39;ip globale généré. C&amp;#39;est pertinent amha pour des machine dont l&amp;#39;ipv6 devra&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# être indiqué dans des enregistrement dns AAAA.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Token&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;::b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il vous suffira ensuite de donner l&amp;rsquo;autre interface &lt;code&gt;vslan2&lt;/code&gt; à votre conteneur/machine virtuel avec les outils dédiés.&lt;/p&gt;
&lt;h3 id=&#34;interface-avec-systemd-nspawn&#34;&gt;Interface avec systemd-nspawn&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Note : Si vous utilisez &lt;code&gt;systemd-nspawn&lt;/code&gt;, vous pouvez aussi utiliser la directive MACVLAN
qui vous permet de déléguer la création de l&amp;rsquo;interface.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/nspawn/container.nspawn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Private&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Solution basique : délégation de l&amp;#39;interface créer exprès pour le conteneur&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Interface&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;vslan2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Solution alternative, laissez nspawn gérer la création d&amp;#39;une interface MACVLAN à partir de vslan &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# l&amp;#39;interface s&amp;#39;appelera &amp;#34;lan&amp;#34; à l&amp;#39;intérieur.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# MACVLAN=vslan:lan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;allez-plus-loin&#34;&gt;Allez plus loin&lt;/h2&gt;
&lt;p&gt;L&amp;rsquo;article suivant de cette série est à propos de réaliser un &lt;a href=&#34;https://inkey-art.net/r%C3%A9seau-moderne-sous-linux-2.-routeur-avec-networkd/&#34;&gt;Routeur avec networkd&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🌐 Des déclenchement selon l&#39;état du réseau</title>
      <link>https://inkey-art.net/des-d%C3%A9clenchement-selon-l%C3%A9tat-du-r%C3%A9seau/</link>
      <pubDate>Sun, 24 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://inkey-art.net/des-d%C3%A9clenchement-selon-l%C3%A9tat-du-r%C3%A9seau/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Dans un &lt;a href=&#34;https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-instantan%C3%A9e-btrfs/&#34;&gt;précédent article&lt;/a&gt;, j&amp;rsquo;ai
présenté le fait qu&amp;rsquo;il est possible sans grande difficulté de démarrer des services systemd avec des règles udev,
ce qui est très pratique pour détecter le branchement d&amp;rsquo;un disque dur ou d&amp;rsquo;une carte sd.&lt;/p&gt;
&lt;p&gt;Mais qu&amp;rsquo;en est-il quand on veut faire des actions liées au réseau ?&lt;/p&gt;
&lt;aside id=&#34;toc&#34;&gt;
    &lt;h4&gt;Sommaire&lt;/h4&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cas-1-événement-sur-lexistence-de-linterface-réseau&#34;&gt;Cas 1 : Événement sur l&amp;rsquo;existence de l&amp;rsquo;interface réseau&lt;/a&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;a href=&#34;#forcer-un-nom-dinterface-stable-avec-networkd&#34;&gt;Forcer un nom d&amp;rsquo;interface stable avec networkd&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maintenant-testons-notre-service&#34;&gt;Maintenant testons notre service&lt;/a&gt;&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cas-2--événement-sur-létat-du-réseau--de-linterface-réseau&#34;&gt;Cas 2 : Événement sur l&amp;rsquo;état du réseau / de l&amp;rsquo;interface réseau&lt;/a&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;a href=&#34;#network-onlinetarget&#34;&gt;network-online.target&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#script-dispatcher&#34;&gt;Script &amp;ldquo;Dispatcher&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#la-solution-idéale-&#34;&gt;La solution idéale ?&lt;/a&gt;&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cas-3-évènements-sur-la-connectivité-à-linternet&#34;&gt;Cas 3 : Évènements sur la connectivité à l&amp;rsquo;internet&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cas-4--évènement-sur-lactivation-dun-socket&#34;&gt;Cas 4 : Évènement sur l&amp;rsquo;activation d&amp;rsquo;un socket.&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/nav&gt;
&lt;/aside&gt;
&lt;h2 id=&#34;cas-1-événement-sur-lexistence-de-linterface-réseau&#34;&gt;Cas 1 : Événement sur l&amp;rsquo;existence de l&amp;rsquo;interface réseau&lt;/h2&gt;
&lt;p&gt;Le point le plus simple et le plus similaire au cas précédent est de réaliser une action sur le &amp;ldquo;branchement&amp;rdquo;
d&amp;rsquo;une interface réseau.
Cela peut avoir du sens dans certains cas particulier tel que le partage de connection usb depuis un téléphone :
L&amp;rsquo;interface n&amp;rsquo;existe que si le téléphone active l&amp;rsquo;option et disparaît à l&amp;rsquo;instant où le partage se termine.&lt;/p&gt;
&lt;p&gt;Dans ce cas présent, la méthode la plus fiable est de jouer là aussi avec les règles udev.
Mais si vous pouvez garantir la stabilité du nom de l&amp;rsquo;interface, par exemple avec networkd, une méthode plus simple existe :&lt;/p&gt;
&lt;p&gt;En effet, le système présente les interfaces réseau sous la forme de &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/latest/systemd.device.html&#34;&gt;device systemd&lt;/a&gt;.
Il est ainsi possible d&amp;rsquo;utiliser ces éléments pour exécuter un service&lt;/p&gt;
&lt;p&gt;Pour voir les interfaces réseaux découvertes sur votre machine par systemd :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep sys-subsystem-net-devices
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Voyons donc comment faire dans un cas concrêt&lt;/p&gt;
&lt;h3 id=&#34;forcer-un-nom-dinterface-stable-avec-networkd&#34;&gt;Forcer un nom d&amp;rsquo;interface stable avec networkd&lt;/h3&gt;
&lt;p&gt;Par défault sur ma machine, le nom des interfaces usb de tethering sont systématiquement modifié à la reconnection
ce qui n&amp;rsquo;est pas pratique dans notre cas.&lt;/p&gt;
&lt;p&gt;Pour ce faire, je vais utiliser networkd car la configuration de celui-ci est très simple. Il est possible
de forcer un nom d&amp;rsquo;interface stable avec networkd sans passer par de la configuration udev.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Petit aparté sur la cohabitation &lt;code&gt;systemd-networkd&lt;/code&gt; / &lt;code&gt;NetworkManager&lt;/code&gt;:
Contrairement à ce que peut faire croire certaines documentations, il est aujourd&amp;rsquo;hui tout à fait possible
de faire tourner à la fois network-manager et network-manager sur la même machine dans le même temps. Il faut
juste clarifier quelle interface vous gérer avec quel outil. Network-manager
excelle pour les configurations dynamiques (connection wifi par exemple),
là où systemd-networkd est idéal pour des interfaces statiques.
Cet état de gestion partiel par un outil abouti à ce que l&amp;rsquo;outil obtienne une vision réduite sur l&amp;rsquo;interface, mais
il reste néanmoins conscient de leur existence.
De ma connaissance le seul conflit qu&amp;rsquo;il peut être nécessaire de résoudre est d&amp;rsquo;éviter d&amp;rsquo;avoir à la fois
&lt;code&gt;systemd-networkd-wait-online.service&lt;/code&gt; et &lt;code&gt;NetworkManager-wait-online.service&lt;/code&gt; actif en même temps.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans le cas présent, on fixe vis à vis du port usb car c&amp;rsquo;est plus simple, mais il est probablement possible de fixer cela
mieux, néanmoins je manque de meilleures idées.&lt;/p&gt;
&lt;p&gt;Pour cela, il faut évidemment que networkd soit activé, comme dit précédemment, ce n&amp;rsquo;est pas
un gros soucis (du moins sous debian) même si vous utilisez déjà &lt;code&gt;NetworkNanager&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/systemd/network/10-netusb.link&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# À ajuster avec le path obtenu pour l&amp;#39;interface avec udevadm info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# udevadm info /sys/class/net/enx02e17d08a1ad&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;pci-*** &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Link]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;netusb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;/etc/systemd/network/10-netusb.network&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Match]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;netusb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Network]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;DHCP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;yes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Relancez networkd:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl daemon-reload &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo systemctl restart systemd-networkd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;maintenant-testons-notre-service&#34;&gt;Maintenant testons notre service&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;$HOME/.config/systemd/user/test_network.service&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;test_network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;sys-subsystem-net-devices-netusb.device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;sys-subsystem-net-devices-netusb.device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;echo &amp;#34;running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RemainAfterExit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;sys-subsystem-net-devices-netusb.device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il vous faut l&amp;rsquo;activez:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl --user &lt;span class=&#34;nb&#34;&gt;enable&lt;/span&gt; test_network
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Maintenant si vous activez le partage réseau sur le téléphone le service démarrera. Il vivra même le temps de l&amp;rsquo;interface
réseau grâce à BindTo et RemainAfterExit.&lt;/p&gt;
&lt;h2 id=&#34;cas-2--événement-sur-létat-du-réseau--de-linterface-réseau&#34;&gt;Cas 2 : Événement sur l&amp;rsquo;état du réseau / de l&amp;rsquo;interface réseau&lt;/h2&gt;
&lt;p&gt;Pouvoir réagir sur l&amp;rsquo;existence d&amp;rsquo;une interface réseau, c&amp;rsquo;est bien, mais pouvoir réagir sur l&amp;rsquo;état d&amp;rsquo;une interface réseau
ça semble néanmoins un cas plus pertinent : Démarrer son service quand le réseau est actif, redémarrer un service
si le réseau &amp;ldquo;saute&amp;rdquo;, lancer un script de backup local quand le réseau se déconnecte, etc.&lt;/p&gt;
&lt;h3 id=&#34;network-onlinetarget&#34;&gt;network-online.target&lt;/h3&gt;
&lt;p&gt;La première intuition serait d&amp;rsquo;utiliser ce qui existe dès à présent dans systemd, la target &amp;ldquo;network-online.target&amp;rdquo;.
Malheureusement, elle n&amp;rsquo;est utile que pour &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html&#34;&gt;le premier accès au réseau de la machine&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that this unit is only useful during the original system start-up logic. After the system has completed booting up, it will not track the online state of the system anymore. Due to this it cannot be used as a network connection monitor concept, it is purely a one-time system start-up concept.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cela peut être utile dans de nombreux cas cependant, mais ne couvre pas tous les usages.&lt;/p&gt;
&lt;h3 id=&#34;script-dispatcher&#34;&gt;Script &amp;ldquo;Dispatcher&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;Faute de solution systemd qui semble purement intégré et standard, il faut donc soit :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;nous tourner vers des solutions dépendantes de nos outils réseaux : NetworkManager, systemd-networkd, …&lt;/li&gt;
&lt;li&gt;créer nous même notre solution logicielle pour répondre à ce problème.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il existe quelques logiciels existant pour gérer ce genre de cas :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;NetworkManager possède &lt;a href=&#34;https://networkmanager.dev/docs/api/latest/NetworkManager-dispatcher.html&#34;&gt;mécanisme de script dit &amp;ldquo;dispatcher&amp;rdquo;&lt;/a&gt; qui semble plutôt éprouvé.&lt;/li&gt;
&lt;li&gt;Systemd-networkd ne possède actuellement (août 2025) pas de solution, mais des logiciels tiers comparables au &lt;code&gt;dispatcher&lt;/code&gt; de NetworkManager existe :
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gitlab.com/craftyguy/networkd-dispatcher&#34;&gt;networkd-dispatcher&lt;/a&gt; qui semble à priori un bon choix avec sa présence dans les dépôts, dans les fait le logiciel s&amp;rsquo;avère pour le moment décevant.
&lt;ul&gt;
&lt;li&gt;La gestion des interfaces qui change de nom est &lt;a href=&#34;https://gitlab.com/craftyguy/networkd-dispatcher/-/issues/55&#34;&gt;dysfonctionnelle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Contrairement à NetworkManager, il semblerait qu&amp;rsquo;il soit obligatoire de placer les scripts dans des &lt;a href=&#34;https://gitlab.com/craftyguy/networkd-dispatcher/-/issues/77&#34;&gt;dossiers par état&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bpetlert/networkd-broker&#34;&gt;network-broker&lt;/a&gt; : non testé, en rust, mais qui semble basé sur la même logique que networkd-dispatcher donc probablement les mêmes problèmes, pas beaucoup de développeurs.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/vmware/network-event-broker&#34;&gt;network-event-broker&lt;/a&gt; : Non testé , en go, créé par vmware.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dans tous les cas, il s&amp;rsquo;agit là de script bash pour gérer le réseau. Ce n&amp;rsquo;est pas le plus élégant,
mais il est évidemment envisageable de convertir ces scripts pour lancer/arrêter des target/service systemd
correspondant à nos besoins.&lt;/p&gt;
&lt;h4 id=&#34;exemple-networkmanagers-dispatcher&#34;&gt;Exemple: NetworkManagers Dispatcher&lt;/h4&gt;
&lt;p&gt;Un petit exemple pour forcer un logiciel à se redémarrer si une nouvelle connexion gérée par NetworkManager est &amp;ldquo;UP&amp;rdquo; :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/NetworkManager/dispatcher.d/01-restart-myservice-on-new-network-up&lt;/code&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$2&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  up&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    systemctl try-restart --no-block myservice.service
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  *&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;la-solution-idéale-&#34;&gt;La solution idéale ?&lt;/h3&gt;
&lt;p&gt;La solution qui me paraîtrait idéal pour des cas simple, serait tout simplement d&amp;rsquo;avoir un service :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;capable d&amp;rsquo;écouter en dbus sur les évènements networkd.&lt;/li&gt;
&lt;li&gt;capable via ces données d&amp;rsquo;activer/désactiver des target systemd correspond au fait que l&amp;rsquo;interface réseau fonctionne.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une implémentation assez simple de ma part se trouve &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/networkd_status_targets&#34;&gt;ici&lt;/a&gt;
En démarrant le script python &lt;code&gt;listen_events.py&lt;/code&gt; via le service &lt;code&gt;networkd_listener.service&lt;/code&gt; (il vous faut &lt;code&gt;dbus-fast&lt;/code&gt;),&lt;/p&gt;
&lt;p&gt;les targets suivantes sont gérés :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;networkd_status.service&lt;/code&gt; correspond à l&amp;rsquo;état général de la connectivité de la machine (faire partie d&amp;rsquo;un réseau). le service est actif si l&amp;rsquo; &amp;ldquo;OperationalState&amp;rdquo; général est &amp;ldquo;routable&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;networkd_link_status@[interface_name}.target&lt;/code&gt; correspond à l&amp;rsquo;état de la connectivité d&amp;rsquo;une des interfaces. le service est actif si l&amp;rsquo; &amp;ldquo;OperationalState&amp;rdquo; de l&amp;rsquo;interface est &amp;ldquo;routable&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avec une telle solution, on ne peut pas forcément gérer des cas fin de réseaux, mais on peut gérer relativement simplement le cas qui seront probablement le plus commun :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Démarrer/arrêter des services selon si le réseau est actif ou nom, généralement ou pour une interface spécifique.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On peut imaginer par exemple une autre version du service test_network qui ne fonctionne que si l&amp;rsquo;interface usb est
fonctionnelle (et non existante comme dans l&amp;rsquo;exemple précédént) :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;test_network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_link_status@netusb.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_link_status@netusb.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;echo &amp;#34;running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RemainAfterExit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_link_status@netusb.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et Si l&amp;rsquo;interface réseau n&amp;rsquo;importe pas :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;test_network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_status.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_status.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;echo &amp;#34;running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RemainAfterExit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_status.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;cas-3-évènements-sur-la-connectivité-à-linternet&#34;&gt;Cas 3 : Évènements sur la connectivité à l&amp;rsquo;internet&lt;/h2&gt;
&lt;p&gt;La version précédente, permet de faire fonctionner un service si le réseau existe (= possède une adresse) mais
ne garantie pas de l&amp;rsquo;accès internet est bel et bien présent.&lt;/p&gt;
&lt;p&gt;On peut imaginer une solution simple pour ce cas :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un script python utilisant ping testant de temps en temps la connectivité&lt;/li&gt;
&lt;li&gt;un service systemd qui utilise ce script.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;ping_test.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;random&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;subprocess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;test_targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    Tests connection to target, return true if one of the target is reachable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;ping_process&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subprocess&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ping&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ping_process&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;returncode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ping_targets&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PING_TARGETS&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ping_targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ping_targets&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ping_targets&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;heartbeat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;HEARTBEAT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;60&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ping_count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;  &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PING_COUNT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shuffle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ping_targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;test_targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ping_targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ping_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; - HEARTBEAT FAILED&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; - HEARTBEAT SUCCESS&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;heartbeat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;wan.service&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Internet working ?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_status.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_status.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# check with multiple url in case, one of them fail for internal reason&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;PING_TARGETS=inkey-art.net,perdu.com,perdus.com,linuxfr.org&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# heartbeat in sec (verify connection each 2min)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;HEARTBEAT=120&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/opt/ping_test.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Restart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;networkd_status.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On peut d&amp;rsquo;ailleurs comme dans l&amp;rsquo;exemple ici profiter de l&amp;rsquo;existence de &lt;code&gt;networkd_status.target&lt;/code&gt; pour éviter
de ping quand le réseau est assurément non disponible.&lt;/p&gt;
&lt;h2 id=&#34;cas-4--évènement-sur-lactivation-dun-socket&#34;&gt;Cas 4 : Évènement sur l&amp;rsquo;activation d&amp;rsquo;un socket.&lt;/h2&gt;
&lt;p&gt;Il reste un dernier cas, un peu différent, mais il me fallait l&amp;rsquo;aborder, d&amp;rsquo;autant qu&amp;rsquo;il est très
bien intégré à systemd.
C&amp;rsquo;est l&amp;rsquo;activation par socket.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée n&amp;rsquo;est là pas tant d&amp;rsquo;agir sur le réseau au sens interface réseau, mais plutôt au sens connection, au
sens socket.&lt;/p&gt;
&lt;p&gt;Le principe de l&amp;rsquo;activation par socket est de pouvoir démarrer un service que si une connection au socket
associé est ouverte.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;y vois 2 grand intérêt :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;réduire la latence du boot (pas de nécessité de démarrer un démon ssh si le port ssh n&amp;rsquo;est pas contacté)&lt;/li&gt;
&lt;li&gt;réduire l&amp;rsquo;usage des services utilisé peu régulièrement. Je pense que la mémoire vive est probablement là où ça doit jouer le plus.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce cas est déjà bien présenté dans le blog d&amp;rsquo;&lt;a href=&#34;https://ilmanzo.github.io/post/systemd-socket-activated-services/&#34;&gt;ilManzo&amp;rsquo;s&lt;/a&gt;
en anglais. Je vous conseille donc d&amp;rsquo;y jeter un œil.&lt;/p&gt;
&lt;p&gt;Pour résumer rapidement la procédure :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Il vous faut un fichier &lt;code&gt;.service&lt;/code&gt; et un fichier &lt;code&gt;.socket&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Le fichier &lt;code&gt;.socket&lt;/code&gt; doit être activé et démarré pour écouter sur le port voulu.&lt;/li&gt;
&lt;li&gt;Il faut adapter le code du serveur pour qu&amp;rsquo;il puisse utiliser le socket déjà ouvert.&lt;/li&gt;
&lt;li&gt;Il est possible via diverses astuces notamment &lt;a href=&#34;https://unix.stackexchange.com/a/701241&#34;&gt;systemd-socket-proxyd&lt;/a&gt; de gérer le service
de sorte à qu&amp;rsquo;il s&amp;rsquo;arrête s&amp;rsquo;il n&amp;rsquo;y a plus d&amp;rsquo;activité sur le socket.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Creuser cette question m&amp;rsquo;a beaucoup amusé.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai été un peu déçu du manque de complétion de systemd sur la partie événement lié au réseau, mais comme
on le voit, il est possible assez facilement d&amp;rsquo;y remédier. On peut espérer néanmoins à l&amp;rsquo;avenir quelques mécanismes
un peu plus solides et intégrer pour ce type d&amp;rsquo;évènement dans systemd. Le cas de vouloir démarrer un service à
la connection/déconnexion d&amp;rsquo;une interface réseau ne me semble pas si extravagant que systemd ne mériterait
une intégration de ce nom.&lt;/p&gt;
&lt;p&gt;En attendant, il est possible de bricoler des targets et du service systemd pour un peu tout ce qu&amp;rsquo;on veut et
ainsi avoir un système plus &amp;ldquo;réactif&amp;rdquo;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🔗 Dans la jungle des IPCs</title>
      <link>https://inkey-art.net/dans-la-jungle-des-ipcs/</link>
      <pubDate>Fri, 27 Jun 2025 14:20:00 +0200</pubDate>
      
      <guid>https://inkey-art.net/dans-la-jungle-des-ipcs/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Dans les programmes informatiques, les &lt;a href=&#34;https://fr.wikipedia.org/wiki/Communication_inter-processus&#34;&gt;IPCs&lt;/a&gt; sont partout et de types très divers.&lt;/p&gt;
&lt;p&gt;Pour rappel, il s&amp;rsquo;agit là de diverses technologies qui permettent à plusieurs processus de communiquer entre deux (comprendre : se partager des données).&lt;/p&gt;
&lt;p&gt;Il y a, à mon sens 2 niveaux d&amp;rsquo;IPCs :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les IPCs &amp;ldquo;bas niveau&amp;rdquo;, implémenté par le kernel :
&lt;ul&gt;
&lt;li&gt;implémente des fonctionnalités simples.&lt;/li&gt;
&lt;li&gt;peu abstrait (besoin de définir la taille de l&amp;rsquo;espace alloué dans le cas d&amp;rsquo;un segment de mémoire partagé par exemple).&lt;/li&gt;
&lt;li&gt;Sous linux, on à notamment :
&lt;ul&gt;
&lt;li&gt;Tube(pipe)&lt;/li&gt;
&lt;li&gt;Fichier&lt;/li&gt;
&lt;li&gt;Socket (utilisé pour le réseau notamment)&lt;/li&gt;
&lt;li&gt;Signaux (plutôt utilisé pour agir sur l&amp;rsquo;état du service, sens standardisé)&lt;/li&gt;
&lt;li&gt;Segment de mémoire partagée&lt;/li&gt;
&lt;li&gt;des mécanismes de synchronisations : ex : les semaphores.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Les IPCs &amp;ldquo;haut niveau&amp;rdquo; :
&lt;ul&gt;
&lt;li&gt;Basé sur les IPC bas niveau (très souvent les sockets).&lt;/li&gt;
&lt;li&gt;Plus abstraits.&lt;/li&gt;
&lt;li&gt;Ajoute de diverses garanties selon les technologies, par exemple :
&lt;ul&gt;
&lt;li&gt;bonne récéption des données.&lt;/li&gt;
&lt;li&gt;validation d&amp;rsquo;un format des données.&lt;/li&gt;
&lt;li&gt;récéption synchrone (RPC) ou asynchrone (mq)&lt;/li&gt;
&lt;li&gt;diverse paradigme de communication (Stream, PubSub), etc.&lt;/li&gt;
&lt;li&gt;Logique unidirectionnelle, bidirectionnelle ou encore vers n récepteurs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si l&amp;rsquo;on comprend les IPC &amp;ldquo;haut-niveau&amp;rdquo;, les technologies de communications entre processus
sont très nombreuses et il n&amp;rsquo;est pas toujours si simple de savoir quoi utiliser, ce qui abouti dans de nombreux
cas à utiliser les technologies connu plutôt qu&amp;rsquo;une éventuelle meilleure technologie pour le cas d&amp;rsquo;usage.&lt;/p&gt;
&lt;p&gt;Bref, j&amp;rsquo;avais du temps à perdre et j&amp;rsquo;ai donc réalisé un petit programme nommé &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/universal-ping&#34;&gt;Universal Ping&lt;/a&gt;,
ou j&amp;rsquo;ai testé plus des dizaines d&amp;rsquo;IPC avec ces contraintes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Langage Python&lt;/li&gt;
&lt;li&gt;Communication simple type &amp;ldquo;RPC&amp;rdquo;:
&lt;ul&gt;
&lt;li&gt;Appel &amp;ldquo;Ping&amp;rdquo; avec variable de nombre &amp;ldquo;n&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Retour &amp;ldquo;n&amp;rdquo; fois &amp;ldquo;Pong…&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;en ai profité pour essayer de clarifier dans ma tête tout cela.
Voici donc ma façon, sous forme d&amp;rsquo;arbres de décisions de présenter la diversité des ces IPCs :&lt;/p&gt;
&lt;h1 id=&#34;quel-ipc-choisir-&#34;&gt;Quel IPC Choisir ?&lt;/h1&gt;
&lt;p&gt;J&amp;rsquo;ai organisé les IPCs autour d&amp;rsquo;un point qui me semble assez important : L&amp;rsquo;IPC fournit-elle une API ? Et si oui, est-elle
prévu pour être utilisé publiquement (comprendre par des programmes totalement extérieurs sans difficultés).&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc séparé les IPC en trois catégories :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Les IPCs conçu pour fournir une API &amp;ldquo;publique&amp;rdquo; explicite.&lt;/li&gt;
&lt;li&gt;Les IPCs conçu pour fournir une API &amp;ldquo;privée&amp;rdquo; explicite (plutôt conçu pour une application en plusieurs parties).&lt;/li&gt;
&lt;li&gt;Les IPCs sans support intégré de mécanisme d&amp;rsquo;API.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Note : Il s&amp;rsquo;agit là d&amp;rsquo;une organisation &lt;code&gt;subjective&lt;/code&gt;. Bien évidemment, il est toujours tout à fait possible d&amp;rsquo;utilisé une IPC sans mécanisme d&amp;rsquo;API et d&amp;rsquo;ajouter une documentation d&amp;rsquo;une API
et/ou un sur-couche logicielle qui gèrerait l&amp;rsquo;API, mais cela sera moins &amp;ldquo;standard&amp;rdquo; qu&amp;rsquo;une technologie qui est conçue dans ce but.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;api-publique&#34;&gt;API Publique&lt;/h2&gt;
&lt;p&gt;Si je veux concevoir un logiciel sur lequel d&amp;rsquo;autres logiciels peuvent se brancher, c&amp;rsquo;est vers ces solutions que je
me tournerais :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;decision_ipc_api_publique.svg&#34; alt=&#34;ipc avec api publique&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;api-privée&#34;&gt;API Privée&lt;/h2&gt;
&lt;p&gt;Si je devais faire un logiciel &amp;ldquo;en plusieurs parties&amp;rdquo;, ces solutions sont élégantes :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;d%C3%A9cision_ipc_api_privee.svg&#34; alt=&#34;ipc avec api publique&#34;&gt;&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;aspect API est particulièrement intéressant si vous voulez travailler à plusieurs sur différente partie sans
vous marcher dessus.&lt;/p&gt;
&lt;h2 id=&#34;les-autres-ipcs&#34;&gt;Les autres IPCs&lt;/h2&gt;
&lt;p&gt;Ces technos requièrent une clarification d&amp;rsquo;API entre les différents processus
utilisant la technologie pour être utilisé convenablement. Cependant, elles sont pour beaucoup simple d&amp;rsquo;accès et
n&amp;rsquo;ont pas forcément les mêmes avantages que les technologies précédentes, je pense en particulier :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L&amp;rsquo;aspect &lt;code&gt;stockage&lt;/code&gt; des BDD&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;aspect &lt;code&gt;asynchrone&lt;/code&gt; des Messages Queue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Certaines ont aussi des cas d&amp;rsquo;usage très défini et sont quasi-imbattable dans ce cadre précis, je pense en particulier à
&lt;code&gt;MQTT&lt;/code&gt; pour des capteurs. L&amp;rsquo;absence d&amp;rsquo;API clarifié n&amp;rsquo;est pas forcément un gros soucis notamment ll est très facile de regarder le flux avec un outil comme &lt;a href=&#34;http://mqtt-explorer.com/&#34;&gt;MqttExplorer&lt;/a&gt; et
que les avantages du protocole surpassent cet inconvénient mineur pour ce cas d&amp;rsquo;usage.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;decision_ipc_sans_api.svg&#34; alt=&#34;ipc avec api publique&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;mon-avis-&#34;&gt;Mon avis ?&lt;/h1&gt;
&lt;p&gt;En faisant ce petit test de divers IPC, il y a clairement des technologies que j&amp;rsquo;apprécie plus que d&amp;rsquo;autres :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;IPC trop complexe à mon goût (besoin très particulier, gros projet, usage legacy) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IPC bas niveau&lt;/strong&gt; : Amusant jusqu&amp;rsquo;au moment ou il faut réimplémenter les fonctionnalité d&amp;rsquo;un ZMQ.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GRPC/Thrift&lt;/strong&gt;: Je trouve l&amp;rsquo;intégration dans Python, en particulier de GRPC très lourde.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RabbitMQ&lt;/strong&gt; (et probablement Kafka) : Le code python pour mon petit RPC m&amp;rsquo;a paru inutilement compliqué.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Standard de fait :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenAPI, Rest&lt;/strong&gt; : Pour tout ce qui est Web.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MQTT&lt;/strong&gt; : Pour les capteurs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;D-BUS&lt;/strong&gt; : Pour la communication avec un démon quelconque dans un Linux Desktop.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Simple et efficace :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;varlink&lt;/strong&gt;: Je pense que c&amp;rsquo;est l&amp;rsquo;idéal si vous avez besoin d&amp;rsquo;une API de communication qui &amp;ldquo;sort&amp;rdquo; d&amp;rsquo;un logiciel dans un conteneur.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rpyc&lt;/strong&gt;: Très facile à prendre en main, parfait pour prototyper un logiciel distribué rapidement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ZMQ&lt;/strong&gt; : Super simple d&amp;rsquo;accès là aussi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redis/Valkey&lt;/strong&gt; : BDD très versatile, intéressant pour partager des données à faible durée de vie.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;👋 Voilà, Voilà, plus qu&amp;rsquo;à trouver des cas d&amp;rsquo;usage concrêt pour jouer avec plus de ces technos 😅 !&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>⚙️ Sur les OS et les noyaux</title>
      <link>https://inkey-art.net/%EF%B8%8F-sur-les-os-et-les-noyaux/</link>
      <pubDate>Thu, 08 May 2025 17:50:59 +0100</pubDate>
      
      <guid>https://inkey-art.net/%EF%B8%8F-sur-les-os-et-les-noyaux/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;J&amp;rsquo;utilise Gnu/Linux tous les jours, j&amp;rsquo;ai eu autrefois cours sur les systèmes d&amp;rsquo;exploitation, fait un peu de &lt;code&gt;VHDL&lt;/code&gt; et d&amp;rsquo;&lt;code&gt;assembleur&lt;/code&gt;…
Et pourtant le tutoriel &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/&#34;&gt;Operating System in 1,000 Lines 🇬🇧&lt;/a&gt; m&amp;rsquo;a appris, réappris et fait mieux comprendre ce qu&amp;rsquo;est réellement
un système d&amp;rsquo;exploitation et quel est le rôle concrêt d&amp;rsquo;un noyau (aka kernel).&lt;/p&gt;
&lt;p&gt;Cela a aussi abouti à pas mal de questionnement sur le fonctionnement de tout cela auquel j&amp;rsquo;ai recherché des réponses.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc décidé de re-clarifier pour moi et pour d&amp;rsquo;éventuels lecteurs, quelques points en essayant de rester à la fois
simple et clair.&lt;/p&gt;
&lt;h1 id=&#34;lespace-de-mémoire-physique-présenté-au-processeur-est-virtuel&#34;&gt;L&amp;rsquo;espace de mémoire physique présenté au processeur est &amp;ldquo;virtuel&amp;rdquo;.&lt;/h1&gt;
&lt;p&gt;Un noyau doit décider comment il organise la mémoire. Le processus de boot lui donne accès à un espace mémoire dite &amp;ldquo;physique&amp;rdquo;.
Pour être un plus concrêt, un noyau à d&amp;rsquo;une façon ou d&amp;rsquo;une autre une &amp;ldquo;carte&amp;rdquo; de l&amp;rsquo;organisation de la mémoire, par exemple via un &lt;a href=&#34;https://github.com/nuta/operating-system-in-1000-lines/blob/main/kernel.ld&#34;&gt;linker script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mais qu&amp;rsquo;est-ce qui se cache derrière l&amp;rsquo;adresse &lt;code&gt;0x00000&lt;/code&gt; ou &lt;code&gt;0x30000&lt;/code&gt; ? la RAM ? un contrôleur de la carte mère quelconque ? le GPU ? Autre-chose ?&lt;/p&gt;
&lt;p&gt;En réalité, l&amp;rsquo;allocation de tel ou tel parti de cet espace à tel ou tel mémoire est &lt;strong&gt;définie pas une spécification&lt;/strong&gt; (lié à l&amp;rsquo;architecture du processeur et le processeur en lui-même).
Il y a ainsi un bon nombre de &amp;ldquo;trou&amp;rdquo; dans cet adressage. L&amp;rsquo;adresse &lt;code&gt;0x02323&lt;/code&gt; pointe peut-être vers rien du tout.&lt;/p&gt;
&lt;p&gt;Donc &lt;strong&gt;l&amp;rsquo;espace de mémoire &amp;ldquo;physique&amp;rdquo; est, lui-même, une représentation « virtuelle » de différentes mémoires accessibles&lt;/strong&gt;, non pas forcément dans le sens ou l&amp;rsquo;on pourrait le changer dynamiquement (il n&amp;rsquo;est pas très clair pour moi ce qui est physiquement fixé ou non là-dedans),
mais plutôt dans le sens ou &lt;strong&gt;plusieurs mémoires bien différentes se retrouve accessibles depuis un même espace d&amp;rsquo;adressage de façon transparente pour le noyau&lt;/strong&gt; (qui a intérêt à savoir réellement où se trouve chaque chose bien évidemment).&lt;/p&gt;
&lt;p&gt;Il existe deux grandes méthodes pour organiser l&amp;rsquo;adressage l&amp;rsquo;espace mémoire classique (RAM) et l&amp;rsquo;espace IO :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Avoir deux espaces mémoire séparé entre IO et RAM&lt;/strong&gt; et donc des instructions CPU spécifiques. C&amp;rsquo;est le mécanisme de port IO. C&amp;rsquo;est ce que faisaient les anciens systèmes informatiques.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoir un seul espace avec un branchement &amp;ldquo;physique&amp;rdquo; avec le/les contrôleurs IO&lt;/strong&gt; de sorte que les IO puisse apparaître à des addresses mémoire &amp;ldquo;physique&amp;rdquo;. C&amp;rsquo;est ce qui est utilisé quasi-systématiquement de nos jours.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On pourrait penser que les addresses des IO sont fixés, mais cela ne semble pas si simple. Il existe des interactions possibles pour allouer la mémoire nécessaire.&lt;/p&gt;
&lt;p&gt;Un exemple concrêt de l&amp;rsquo;interaction possible est la technologie &lt;code&gt;rezisable BAR&lt;/code&gt; pour les GPU qui permet de négocier la taille allouer pour l&amp;rsquo;accès au GPU, autrement la taille sera limité et il faut donc un mécanisme pour passer à la donnée suivante et ainsi
des cycles cpu perdus.&lt;/p&gt;
&lt;p&gt;Dans le cas de périphériques tel qu&amp;rsquo;un disque dur ou autres, un &lt;a href=&#34;https://stackoverflow.com/questions/69641722/will-dd-for-nvme-use-mmio-or-dma&#34;&gt;principe&lt;/a&gt; qu&amp;rsquo;on retrouve beaucoup est :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L&amp;rsquo;accessibilité des bits de configuration ou d&amp;rsquo;instructions via un &lt;strong&gt;MMIO&lt;/strong&gt; (&lt;code&gt;memory mapped IO&lt;/code&gt;), c&amp;rsquo;est-à-dire un branchement direct
entre l&amp;rsquo;appareil et le périphérique, ce qui implique un délai d&amp;rsquo;accès lecture/écriture relativement important.&lt;/li&gt;
&lt;li&gt;La présence des espaces mémoire lecture/écriture plus important sous la forme d&amp;rsquo;un &lt;strong&gt;DMA&lt;/strong&gt; (&lt;code&gt;direct memory access&lt;/code&gt;). C&amp;rsquo;est-à-dire un tampon mémoire synchronisé entre l&amp;rsquo;appareil IO et l&amp;rsquo;ordinateur. Un exemple très parlant de ça, et le besoin d&amp;rsquo;éjecter la clé usb proprement mal gré que la copie (sur le tampon et non sur la clé usb) semble terminé.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;physical_memory.svg&#34; alt=&#34;Adressage Physique&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;les-processus-sont-déjà-une-première-sorte-de-conteneur&#34;&gt;Les processus sont déjà une première sorte de &amp;ldquo;conteneur&amp;rdquo;.&lt;/h1&gt;
&lt;p&gt;Si vous connaissez les conteneurs et leur logique d&amp;rsquo;isolation, pensez que les &lt;code&gt;processus&lt;/code&gt; sont déjà un premier mécanisme d&amp;rsquo;isolation du système :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Par l&amp;rsquo;accès mémoire : &lt;strong&gt;Les processus n&amp;rsquo;ont accès qu&amp;rsquo;à une mémoire &amp;ldquo;virtuelle&amp;rdquo;&lt;/strong&gt;, les addresses qu&amp;rsquo;il utilise ne sont valides qu&amp;rsquo;à l&amp;rsquo;intérieur de ceux-ci. Il y a tout &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/11-page-table&#34;&gt;un mécanisme dit de pagination&lt;/a&gt;, que je ne vais pas expliciter ici.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;pagination.svg&#34; alt=&#34;Pagination&#34;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Par l&amp;rsquo;accès aux périphériques et autres : &lt;strong&gt;Les processus doivent demander l&amp;rsquo;accès au noyau pour de nombreuses tâches comme écrire sur le disque, via des fonctions appelés &lt;code&gt;appels systèmes&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;syscall.svg&#34; alt=&#34;syscall&#34;&gt;&lt;/p&gt;
&lt;p&gt;Ainsi les processus ne peuvent pas intéragir sur d&amp;rsquo;autre processus par défault et doivent demander l&amp;rsquo;accès pour bon nombre de tâches.
Un certain nombre de mécanismes existent néanmoins (en passant obligatoirement par des syscall) pour au final permettre à ces
processus de pouvoir communiquer entre eux, ce sont les &lt;strong&gt;IPC&lt;/strong&gt;(&lt;code&gt;Inter processus communication&lt;/code&gt;)… mais ce sera un sujet pour un autre article 😉.&lt;/p&gt;
&lt;h2 id=&#34;le-noyau-définis-des-concepts-basiques-de-linformatique&#34;&gt;Le noyau définis des concepts basiques de l&amp;rsquo;informatique&lt;/h2&gt;
&lt;p&gt;Les concepts tels que la &lt;a href=&#34;https://fr.wikipedia.org/wiki/Pile_(informatique)&#34;&gt;pile&lt;/a&gt;, le &lt;a href=&#34;https://fr.wikipedia.org/wiki/Tas_(informatique)&#34;&gt;tas&lt;/a&gt;, les &lt;a href=&#34;https://fr.wikipedia.org/wiki/Processus_(informatique)&#34;&gt;processus&lt;/a&gt; sont tellement habituel pour un informaticien lambda qu&amp;rsquo;ils
apparaissent comme naturel, il est donc un peu troublant, de se retrouver à &lt;strong&gt;devoir les implémenter, concrètement, simplement&lt;/strong&gt;
et de se demander à quoi pourrait ressembler un autre paradigme de fonctionnement de l&amp;rsquo;OS sans ces éléments ?&lt;/p&gt;
&lt;p&gt;Ainsi dans le tutoriel, on implémente des choses telles que :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/10-process#process-control-block&#34;&gt;processus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/07-kernel-panic&#34;&gt;kernel Panic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;La notion d&amp;rsquo;&lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/14-system-call#user-library&#34;&gt;appel système&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;La &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/10-process#context-switch&#34;&gt;commutation de contexte&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La structure d&amp;rsquo;un processus dans le tutoriel est &lt;a href=&#34;https://github.com/nuta/operating-system-in-1000-lines/blob/main/kernel.h#L45&#34;&gt;très simple&lt;/a&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;process&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 0 if it&amp;#39;s an idle process
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// PROC_UNUSED, PROC_RUNNABLE, PROC_EXITED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;vaddr_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// kernel stack pointer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;uint32_t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// points to first level page table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8192&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// kernel stack
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bien évidemment, dans le cas d&amp;rsquo;un noyau vraiment utilisé, les choses sont &lt;a href=&#34;https://linux-kernel-labs.github.io/refs/heads/master/lectures/processes.html&#34;&gt;plus&lt;/a&gt; &lt;a href=&#34;https://github.com/torvalds/linux/blob/4f79eaa2ceac86a0e0f304b0bab556cca5bf4f30/include/linux/sched.h#L813&#34;&gt;complexe&lt;/a&gt;.
Mais il est amusant de voir à quel point tout cela est à la fois simple et réellement compliqué.&lt;/p&gt;
&lt;p&gt;Un autre point intéressant a noté de voir qu&amp;rsquo;&lt;strong&gt;une partie de la mécanique tiens dans le code du kernel et une autre dans le rôle et l&amp;rsquo;implémentation même des instructions CPU&lt;/strong&gt;.
Ainsi, on a :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/11-page-table#switching-page-tables&#34;&gt;instructions CPU pour gérer/mettre à jour l&amp;rsquo;adressage mémoire virtuel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;des &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/13-user-mode#transition-to-user-mode&#34;&gt;instructions CPU pour changer de &amp;ldquo;mode&amp;rdquo;&lt;/a&gt; (Kernel ou utilisateur), permettant ainsi d&amp;rsquo;interdire aux instructions suivantes du programme de faire tel ou telles instructions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces éléments sont un peu complexe à comprendre, notamment, car il nécessite de se plonger dans les méandres de la documentation d&amp;rsquo;architecture CPU,
mais ce qu&amp;rsquo;il faut en déduire c&amp;rsquo;est que le CPU possède divers mécanismes pour simplifier la vie des concepteurs de système d&amp;rsquo;exploitation.&lt;/p&gt;
&lt;h1 id=&#34;programmer-un-pilote-driver-nest-presque-quimplémenter-une-spécification-dapi&#34;&gt;Programmer un pilote (driver) n&amp;rsquo;est (presque) qu&amp;rsquo;implémenter une spécification d&amp;rsquo;API&lt;/h1&gt;
&lt;p&gt;Dans la partie sur l&amp;rsquo;espace d&amp;rsquo;adresse physique, je parlais d&amp;rsquo;espace de configuration disponible via MMIO pour les IO.
Mais il ne s&amp;rsquo;agit pas de remplis ces espaces de données au hasard.&lt;/p&gt;
&lt;p&gt;Les appareils d&amp;rsquo;entrée/sortie une toute une spécification, je dirais même une &lt;em&gt;API&lt;/em&gt; que le noyau doit respecter
pour utiliser l&amp;rsquo;appareil, &lt;strong&gt;c&amp;rsquo;est (presque) aussi simple que ça un pilote&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Le tutoriel pour sa part nous donne pour mission d&amp;rsquo;implémenter un &lt;a href=&#34;https://operating-system-in-1000-lines.vercel.app/en/15-virtio-blk#virtio&#34;&gt;disque virtuel via Virtio&lt;/a&gt;
et il est relativement amusant de voir qu&amp;rsquo;il s&amp;rsquo;agit pour une bonne grosse part de l&amp;rsquo;application stricte d&amp;rsquo;une spécification.&lt;/p&gt;
&lt;h1 id=&#34;les-interruptions-cpu-sont-essentielles-au-fonctionnement&#34;&gt;Les interruptions CPU sont essentielles au fonctionnement&lt;/h1&gt;
&lt;h2 id=&#34;les-interruptions-&#34;&gt;Les interruptions ?&lt;/h2&gt;
&lt;p&gt;Les interruptions CPU sont un mécanisme, à l&amp;rsquo;image des &lt;code&gt;Signaux POSIX&lt;/code&gt; (SIGINT, SIGKILL, etc.) qui permet au CPU d&amp;rsquo;exécuter
un code spécifique (configurable) quand le CPU est confronté à des événements tels que :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un périphérique émet un signalement.&lt;/li&gt;
&lt;li&gt;certaines instruction CPU.&lt;/li&gt;
&lt;li&gt;une erreur CPU : division par 0, erreur de segmentation, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tout comme les Signaux POSIX, il est possible de se &amp;ldquo;brancher dessus&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est ce que fait le noyau :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pour l&amp;rsquo;&lt;a href=&#34;https://github.com/nuta/operating-system-in-1000-lines/blob/66793879a87569beaaf86edc707ce53d97100d5f/kernel.c#L544&#34;&gt;implémentation du kernel panic&lt;/a&gt;
dans d&amp;rsquo;éventuel cas.&lt;/li&gt;
&lt;li&gt;pour les syscall permettant aux processus
en mode utilisateur d&amp;rsquo;exécuter par ce biais du code kernel en mode kernel notamment pour pouvoir intéragir avec les périphériques.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;process_life.svg&#34; alt=&#34;vie d&amp;rsquo;un processus&#34;&gt;&lt;/p&gt;
&lt;p&gt;Un processus passe généralement souvent dans le mode noyau à intervalles réguliers, ne serait qu&amp;rsquo;à cause des appels systèmes.&lt;/p&gt;
&lt;h2 id=&#34;les-interruptions-sont-la-base-dun-os-préemptif&#34;&gt;Les interruptions sont la base d&amp;rsquo;un os préemptif&lt;/h2&gt;
&lt;p&gt;Dans le tutoriel, l&amp;rsquo;os se veut coopératif, le processus en cours indique de lui-même quand il redonne la main au noyau pour une nouvelle tâche.&lt;/p&gt;
&lt;p&gt;Dans les systèmes d&amp;rsquo;exploitation récents, le mécanisme est &lt;a href=&#34;https://fr.wikipedia.org/wiki/Multit%C3%A2che_pr%C3%A9emptif&#34;&gt;préemptif&lt;/a&gt;, c&amp;rsquo;est-à-dire que le noyau
peut arrêter un processus en cours de route.&lt;/p&gt;
&lt;p&gt;Seulement voilà, comment faire cela ?&lt;/p&gt;
&lt;p&gt;La solution ce sont les interruptions. Tout le mécanisme de préemption fonctionne dessus. En trouvant différente manière
de profiter d&amp;rsquo;interruption qui interromprait le processus, on revient au mode noyau et on peut alors, décider de ne plus
re-exécuter le code de ce processus.&lt;/p&gt;
&lt;p&gt;Dans les faits, il y a toute une mécanique très complexe d&amp;rsquo;ordonnancement dans linux là-dessus pour organiser au mieux le temps alloué aux différents processus et leur ordre.&lt;/p&gt;
&lt;p&gt;Quant aux interruptions, une astuce pour éviter qu&amp;rsquo;un processus reste éternellement en fonctionnement en mode utilisateur si aucune
interruption n&amp;rsquo;est provoqué, est tout simplement l&amp;rsquo;&lt;a href=&#34;https://www.reddit.com/r/linux/comments/1bymi4n/how_does_the_interrupt_timer_frequency_affect/&#34;&gt;existence d&amp;rsquo;interruption à intervalles réguliers&lt;/a&gt;,
configurable via l&amp;rsquo;option de Compilation &lt;code&gt;CONFIG_HZ&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;pour-conclure&#34;&gt;Pour conclure&lt;/h1&gt;
&lt;p&gt;Le développement de Kernel/Noyau ne semble pas pour moi, j&amp;rsquo;ai l&amp;rsquo;impression qu&amp;rsquo;une partie notable du travail consiste à implémenter des spécifications complexes (jeux d&amp;rsquo;instruction CPU, spécification de pilote)
dans le contexte d&amp;rsquo;un langage relativement bas niveaux, c&amp;rsquo;est &lt;strong&gt;une discipline très exigeante&lt;/strong&gt; à mille lieues de la fluidité du développement python auquel j&amp;rsquo;ai l&amp;rsquo;habitude.&lt;/p&gt;
&lt;p&gt;Néanmoins, &lt;strong&gt;mieux comprendre et démythifié les bases sur lequel son propre code fonctionne permet d&amp;rsquo;avoir une capacité supplémentaire d&amp;rsquo;action en cas de problèmes&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Je ne peux donc que vous conseiller de faire ce tutoriel. Le tutoriel s&amp;rsquo;avère plus ou moins rude selon vos connaissances ainsi je vous conseillerais de ne
pas forcément chercher à comprendre le moindre détail, mais d&amp;rsquo;&lt;strong&gt;avancer tranquillement dessus&lt;/strong&gt; (et ne pas hésiter le copier/coller… vous n&amp;rsquo;avez pas tous prévu de développer des OS, non ?).&lt;/p&gt;
&lt;p&gt;Bonne création de noyau à tous 😀.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🫙 Systemd dans un conteneur avec Podman</title>
      <link>https://inkey-art.net/systemd-dans-un-conteneur-avec-podman/</link>
      <pubDate>Sun, 27 Apr 2025 20:50:59 +0100</pubDate>
      
      <guid>https://inkey-art.net/systemd-dans-un-conteneur-avec-podman/</guid>
      <description>&lt;h2 id=&#34;interaction-entre-systemd-et-les-conteneurs&#34;&gt;Interaction entre Systemd et les conteneurs&lt;/h2&gt;
&lt;p&gt;Systemd est le &lt;a href=&#34;https://fr.wikipedia.org/wiki/Init&#34;&gt;programme d&amp;rsquo;initialisation ou init&lt;/a&gt; le plus courant dans les systèmes Gnu/Linux modernes,
c&amp;rsquo;est-à-dire le premier processus (PID 1) démarré par le système qui éxecute tous les autres et permet de gérer l&amp;rsquo;ordre de démarrage, etc.
C&amp;rsquo;est très utile pour pouvoir gérer un ensemble de processus qui tournent en parallèles sur le système.&lt;/p&gt;
&lt;p&gt;Les phases d&amp;rsquo;initialisations d&amp;rsquo;un système sur une machine physique :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;init.svg&#34; alt=&#34;Phase d&amp;rsquo;initialisation d&amp;rsquo;un système&#34;&gt;&lt;/p&gt;
&lt;p&gt;Dans le cas d&amp;rsquo;un conteneur, le kernel est déjà fonctionnel, le premier (et souvent le seul) processus
lancé dans le conteneur (PID 1) n&amp;rsquo;a pas besoin d&amp;rsquo;être un logiciel spécialisé en init, on lance donc généralement directement
le logiciel dont on a besoin.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;init_container.svg&#34; alt=&#34;Phase d&amp;rsquo;initialisation d&amp;rsquo;un système&#34;&gt;&lt;/p&gt;
&lt;p&gt;De fait, un outil comme docker n&amp;rsquo;est pas conçu pour fonctionner avec un init tel que systemd.
Ce n&amp;rsquo;est pas tant un souci technique (des méthodes existent) que philosophique qu&amp;rsquo;on pourrait résumer simplement par :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Un conteneur doit contenir le minimum de choses : taille minimale et un seul processus. Si on veut plusieurs processus, on utilise plusieurs conteneurs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On est donc là dans une approche assez microservice avec docker ou autre en orchestrateur de conteneur démarrant chacun un unique processus.&lt;/p&gt;
&lt;p&gt;On voit bien là que les 2 programmes que sont &lt;code&gt;docker&lt;/code&gt; et &lt;code&gt;systemd&lt;/code&gt; se recoupe un peu, chacun a sa manière gère des processus et leur ordonnancement,
et l&amp;rsquo;usage de l&amp;rsquo;un ou l&amp;rsquo;autre dépendra de la couche ou l&amp;rsquo;ordonnancement se fait.&lt;/p&gt;
&lt;p&gt;il est ainsi possible de :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gérer des conteneurs via systemd, pour ce faire la meilleure méthode aujourd&amp;rsquo;hui semble &lt;a href=&#34;https://podman.io/&#34;&gt;podman&lt;/a&gt; avec &lt;a href=&#34;https://linuxtricks.fr/wiki/quadlet-execution-de-conteneurs-podman-sous-systemd&#34;&gt;quadlet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;gérer avec systemd différents niveaux plus ou moins procĥe d&amp;rsquo;un conteneur avec uniquement systemd :
&lt;ul&gt;
&lt;li&gt;Une isolation partielle du service avec différentes directives tel que &lt;code&gt;ProtectSystem&lt;/code&gt; , &lt;code&gt;ProtectHome&lt;/code&gt;, &lt;code&gt;DynamicUser&lt;/code&gt;, &lt;a href=&#34;https://www.redhat.com/en/blog/mastering-systemd&#34;&gt;…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Un vrai mécanisme de conteneur avec &lt;a href=&#34;https://wiki.archlinux.org/title/Systemd-nspawn&#34;&gt;systemd-nspawn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Une &amp;ldquo;portabilité&amp;rdquo; des services avec les &lt;a href=&#34;https://systemd.io/PORTABLE_SERVICES/&#34;&gt;portables service&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;démarrer systemd dans un conteneur : Ce qu&amp;rsquo;on va faire ici :&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;init_container_systemd.svg&#34; alt=&#34;Phase d&amp;rsquo;initialisation d&amp;rsquo;un système&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;pourquoi-mettre-systemd-dans-un-conteneur-&#34;&gt;Pourquoi mettre systemd dans un conteneur ?&lt;/h2&gt;
&lt;p&gt;Les conteneurs sont très bien, mais la philosophie classique consistant à avoir des conteneurs minimale ne faisant tourner qu&amp;rsquo;un unique service se révèle de fait
&lt;strong&gt;pas toujours la plus pertinente&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En effet :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les outils d&amp;rsquo;orchestration de conteneurs ne sont &lt;strong&gt;pas forcément plus pratique dans certain contexte qu&amp;rsquo;un systemd&lt;/strong&gt;. Un administrateur système préfèrera &lt;strong&gt;ne pas avoir deux mécanismes d&amp;rsquo;orchestration totalement disjoints&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Les conteneurs OCI (utilisé par docker et podman) sont très pratique et simple à partager, c&amp;rsquo;est une méthode pratique pour fournir du logiciel, &lt;strong&gt;pourquoi ne pas pouvoir fournir directement un logiciel complet plutôt qu&amp;rsquo;une pile de composants à orchestrer ?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Le fait de ne pas utiliser systemd avec les conteneurs, implique pour un logiciel qu&amp;rsquo;on envisage de packager pour une distribution comme debian de &lt;strong&gt;devoir dupliqué un même savoir (la gestion du service/processus) dans deux formats différents (service systemd vs paramètre docker/docker-compose/kubernetes)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans ces conditions, il me semble que pour un logiciel assez simple avec plusieurs composants qu&amp;rsquo;on envisage de packager maintenant ou à terme, il est &lt;strong&gt;plus simple de simplement générer un conteneur activant le/les mêmes services systemd que le paquet de distribution&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Bien évidemment, il faut &lt;strong&gt;choisir intelligemment les composant à intégrer ou pas dedans&lt;/strong&gt;. Selon les besoins, dans l&amp;rsquo;exemple ci-dessous, il n&amp;rsquo;aurait pas exemple été peut être plus pertinent que le conteneur requiert un service valkey externe plutôt que de l&amp;rsquo;intégrer directement.&lt;/p&gt;
&lt;h2 id=&#34;exemple&#34;&gt;Exemple :&lt;/h2&gt;
&lt;h3 id=&#34;explication&#34;&gt;Explication&lt;/h3&gt;
&lt;p&gt;J&amp;rsquo;ai réalisé un exemple de conteneur avec systemd à l&amp;rsquo;intérieur.
Il contient une application web minimale avec plusieurs éléments :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Une base de donnée clé/valeur (&lt;code&gt;valkey&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Un serveur web python (&lt;code&gt;uvicorn&lt;/code&gt;) contenant une api (avec &lt;code&gt;fastapi&lt;/code&gt;) et utilisant la BDD.&lt;/li&gt;
&lt;li&gt;Un frontal web &lt;code&gt;nginx&lt;/code&gt; en &lt;a href=&#34;https://fr.wikipedia.org/wiki/Proxy_inverse&#34;&gt;proxy inverse&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;utilise podman plutôt que docker dans ce cas de figure, car l&amp;rsquo;intégration systemd est plutôt poussé et ne requiert aucun effort,
podman détecte par défault automatiquement le conteneur utilisant systemd et fait le nécessaire pour que le tout soit fonctionnel.&lt;/p&gt;
&lt;p&gt;Ordonnancement prévu des services :&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;dependances_container.svg&#34; alt=&#34;Ordonnancement des services&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;
&lt;p&gt;C&amp;rsquo;est relativement facile à faire, voici le &lt;code&gt;Containerfile&lt;/code&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-Dockerfile&#34; data-lang=&#34;Dockerfile&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# On installe la base du système&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; debian:trixie as build&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;RUN&lt;/span&gt; apt-get update &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install -y systemd nginx valkey-server &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    python3-fastapi python3-uvicorn python3-sdnotify python3-redis&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# On ajoute les fichiers de notre application, notez le fichier webapp.service !&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;COPY&lt;/span&gt; nginx/conf.d /etc/nginx/conf.d&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;COPY&lt;/span&gt; www /var/www/html&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;COPY&lt;/span&gt; webapp.service /etc/systemd/system&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;COPY&lt;/span&gt; api/* /srv&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;RUN&lt;/span&gt; rm /etc/nginx/sites-available/* &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm /etc/nginx/sites-enabled/* &lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# On à besoin de systemd fonctionnel pour lancer systemctl donc un nouveau stage est nécessaire&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; build&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# On active ici nos services spéciaux, dans le cas présent on préferera un unique service ou target&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# contenant toutes les dépendances&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;RUN&lt;/span&gt; systemctl &lt;span class=&#34;nb&#34;&gt;enable&lt;/span&gt; webapp&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# la commande magique qui lance systemd en processus principal&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;CMD&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/lib/systemd/systemd&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;EXPOSE&lt;/span&gt;&lt;span class=&#34;s&#34;&gt; 80 6379&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et le service &lt;code&gt;webapp.service&lt;/code&gt; qu&amp;rsquo;on lance :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Webapp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On lance toutes les dépendances de notre service ici&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Wants&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;valkey.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Wants&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;nginx.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;valkey.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;nginx.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Le service python qu&amp;#39;on lance implémente sd-notify donc on&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;notify&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;NotifyAccess&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;all&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;EnvironmentFile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/srv/api_config.env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Restart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RestartSec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WorkingDirectory&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/srv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStartPre&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;mkdir -p /run/uvicorn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;python3 -m uvicorn --workers ${WORKERS_NB} --uds /run/uvicorn/appname.sock api:app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStopPost&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;rm -rf /run/uvicorn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vous pouvez voir le détail &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/systemd-in-container&#34;&gt;ici&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On pourrait bien évidemment profiter de la puissance de systemd ici et ajouter facilement des services :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Qui s&amp;rsquo;active en fonction d&amp;rsquo;évènements : &lt;a href=&#34;http://0pointer.de/blog/projects/socket-activation.html&#34;&gt;socket&lt;/a&gt;, &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/latest/systemd.path.html&#34;&gt;modification de fichier&lt;/a&gt;, …&lt;/li&gt;
&lt;li&gt;Qui s&amp;rsquo;exécute à interval régulier avec les &lt;a href=&#34;https://blog.stephane-robert.info/docs/admin-serveurs/linux/timers/&#34;&gt;timers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;et probablement d&amp;rsquo;autres trucs amusants auquel je n&amp;rsquo;ai pas pensé.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;et-les-logs-&#34;&gt;Et les logs ?&lt;/h3&gt;
&lt;p&gt;Un point particulier à gérer dans ce cas est l&amp;rsquo;obtention des logs.
Dans le cas standard, la méthode classique pour avoir les logs du conteneur (&lt;code&gt;test&lt;/code&gt; dans ce cas),
donne uniquement le contenu de la sortie standard, ce qui n&amp;rsquo;est pas très utile.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;❯ podman logs &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemd 257.5-2 running in system mode &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;+PAM +AUDIT +SELINUX +APPARMOR +IMA +IPE +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Detected virtualization podman.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Detected architecture x86-64.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Welcome to Debian GNU/Linux trixie/sid!
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bpf-restrict-fs: BPF LSM hook not enabled in the kernel, BPF LSM not supported.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Queued start job &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; default target graphical.target.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Created slice system-getty.slice - Slice /system/getty.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.........
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Reached target getty.target - Login Prompts.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Started dbus.service - D-Bus System Message Bus.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Started systemd-logind.service - User Login Management.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Started valkey-server.service - Advanced key-value store.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Started nginx.service - A high performance web server and a reverse proxy server.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Reached target multi-user.target - Multi-User System.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;  OK  &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Reached target graphical.target - Graphical Interface.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         Starting webapp.service - Webapp...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Debian GNU/Linux trixie/sid 96206de07c7c console
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;idem avec &lt;code&gt;journalctl CONTAINER_NAME=test&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ce qu&amp;rsquo;il nous faut ce sont les logs des services suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;valkey-server.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nginx.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;webapp.service&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On peut donc lancer &lt;code&gt;journalctl&lt;/code&gt; dans le conteneur avec exec :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman &lt;span class=&#34;nb&#34;&gt;exec&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; journalctl
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# pour un service spécifique&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman &lt;span class=&#34;nb&#34;&gt;exec&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; journalctl -u nginx.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il est probablement possible d&amp;rsquo;accéder au log &lt;code&gt;journalctl&lt;/code&gt; du conteneur d&amp;rsquo;une façon plus élégante depuis le &lt;code&gt;journalctl&lt;/code&gt; de l&amp;rsquo;hôte.&lt;/p&gt;
&lt;p&gt;Une méthode &lt;a href=&#34;https://www.linuxembedded.fr/2022/03/un-introduction-a-journald&#34;&gt;semble être&lt;/a&gt; en partageant le dossier /var/log/journal (montage de volume du conteneur) avec le paramètre &lt;code&gt;--directory&lt;/code&gt; de &lt;code&gt;journalctl&lt;/code&gt;,
mais mon test n&amp;rsquo;a pas été concluant, car la version de systemd n&amp;rsquo;étant pas compatible l&amp;rsquo;hôte n&amp;rsquo;étais pas en mesure de lire le journal du conteneur.&lt;/p&gt;
&lt;p&gt;Une &lt;a href=&#34;https://harryhodge.co.uk/posts/2021/07/centralised-logging-with-systemd-and-journald/&#34;&gt;autre méthode&lt;/a&gt; probablement plus fiable, mais nécessitant des ajustements est d&amp;rsquo;utiliser &lt;a href=&#34;https://www.freedesktop.org/software/systemd/man/latest/systemd-journal-remote.service.html&#34;&gt;systemd-journal-remote&lt;/a&gt;, qui permet de
transmettre les logs par le réseau en http&lt;/p&gt;
&lt;p&gt;Je pense qu&amp;rsquo;il doit exister d&amp;rsquo;autres solutions en creusant bien (compatibilité syslog ? partage de socket ?).&lt;/p&gt;
&lt;h2 id=&#34;pour-conclure&#34;&gt;Pour conclure :&lt;/h2&gt;
&lt;p&gt;Systemd dans un conteneur, c&amp;rsquo;est possible et pas bien compliqué 😀.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>💬 Envoyez des notifications XMPP avec Sendi</title>
      <link>https://inkey-art.net/envoyez-des-notifications-xmpp-avec-sendi/</link>
      <pubDate>Mon, 04 Nov 2024 17:10:00 +0200</pubDate>
      
      <guid>https://inkey-art.net/envoyez-des-notifications-xmpp-avec-sendi/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;J&amp;rsquo;utilise beaucoup XMPP pour communiquer, j&amp;rsquo;ai ainsi mon propre serveur XMPP.&lt;/p&gt;
&lt;p&gt;Un des usages, en tant qu&amp;rsquo;administrateur système d&amp;rsquo;un serveur, est d&amp;rsquo;utiliser XMPP pour m&amp;rsquo;alerter d&amp;rsquo;évènements
qui ont lieu sur le serveur. J&amp;rsquo;utilisais jusqu&amp;rsquo;à présent un petit logiciel qui s&amp;rsquo;appelle &lt;code&gt;sendxmpp&lt;/code&gt;. Mon cas d&amp;rsquo;usage
est de le placer dans des scripts systemd avant ou après des scripts pour me dire un peu plus sur l&amp;rsquo;état du système.&lt;/p&gt;
&lt;p&gt;Un exemple par exemple est dans le cas du service &lt;code&gt;backup.service&lt;/code&gt; présenté dans le &lt;a href=&#34;https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-instantan%C3%A9e-btrfs/&#34;&gt;dernier article&lt;/a&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;XMPP_NOTIFY_ACCOUNT=me@mysuperdomainname.ndd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;me&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/bin/sendxmpp ${XMPP_NOTIFY_ACCOUNT} -t -m /path/of/the/message/after/success/backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce logiciel sendxmpp à un gros défault qui me gêne dans son utilisation : il est basé sur le fait d&amp;rsquo;utiliser
quasi nécessairement l&amp;rsquo;entrée standard, par exemple :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ls -la &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sendxmpp me@mysuperdomainname.ndd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et si on ne veut pas faire ça, la seule option qui reste est alors de données un chemin avec &lt;code&gt;-m&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ce choix technique, s&amp;rsquo;il est très pertinent dans des scripts bash, n&amp;rsquo;est vraiment pas pratique lorsque qu&amp;rsquo;on veut
utiliser ce logiciel dans systemd.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idéal, pour moi, serait de pouvoir faire quelque chose comme ça :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/bin/monprogramme ${XMPP_NOTIFY_ACCOUNT} -m &amp;#34;masupercommande ${UNE VARIABLE}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ensuite sendxmpp souffre un peu de son âge, créé en 2004, il ne supporte ainsi rien de très original. C&amp;rsquo;est le genre
de logiciel ancien, mais efficace pour sa tâche. Il est malheureusement plus réellement maintenu avec une dernière version
en &lt;a href=&#34;https://github.com/lhost/sendxmpp/tree/v1.24&#34;&gt;2014&lt;/a&gt; !&lt;/p&gt;
&lt;h2 id=&#34;sendi&#34;&gt;Sendi&lt;/h2&gt;
&lt;p&gt;Pour pallier ce problème d&amp;rsquo;entrée, j&amp;rsquo;aurais pu éventuellement faire un bête script autour de sendxmpp, mais je
me suis dit qu&amp;rsquo;il devait être possible de faire les choses mieux.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai découvert un logiciel intéressant &lt;a href=&#34;https://github.com/caronc/apprise&#34;&gt;apprise&lt;/a&gt; qui a comme objectif de servir pour des notifications de tout type.
Cela m&amp;rsquo;a intéressé. Malheureusement le support xmpp &lt;a href=&#34;https://github.com/caronc/apprise/commit/df15de1fc425c1f4af5f8655f0ba95519811b7da&#34;&gt;a été supprimé&lt;/a&gt;, en effet la librairie qu&amp;rsquo;il utilise est asynchrone
et n&amp;rsquo;est du coup pas si simple a utilisé pour ce cas d&amp;rsquo;usage.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai senti alors le défi et j&amp;rsquo;ai développé &lt;strong&gt;Sendi&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Sendi est un autre programme en ligne de commande pour envoyer des notifications XMPP. Il n&amp;rsquo;utilise pas la sortie standard
et supporte l&amp;rsquo;envoi de fichier par http &lt;a href=&#34;https://xmpp.org/extensions/xep-0363.html&#34;&gt;XEP-0363&lt;/a&gt; et le chiffrement OMEMO &lt;a href=&#34;https://xmpp.org/extensions/xep-0384.html&#34;&gt;XEP-0384&lt;/a&gt; et &lt;a href=&#34;https://xmpp.org/extensions/xep-0454.html&#34;&gt;XEP-0454&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Attention la peinture est toute fraîche, c&amp;rsquo;est probablement un peu bogué. N&amp;rsquo;hésitez pas à faire des retours, le but
du projet étant d&amp;rsquo;avoir quelque-chose d&amp;rsquo;assez fiable.&lt;/p&gt;
&lt;p&gt;Je remercie chaleureusement les développeurs xmpp de &lt;a href=&#34;https://slixmpp.readthedocs.io/en/latest/&#34;&gt;slixmpp&lt;/a&gt; et en particulier Syndace, développeur de &lt;a href=&#34;https://github.com/Syndace/slixmpp-omemo&#34;&gt;slixmpp-omemo&lt;/a&gt; qui
m&amp;rsquo;a bien aidé pour déboguer la partie omemo de mes tests automatisés.&lt;/p&gt;
&lt;h2 id=&#34;comment-utiliser-sendi-avec-systemd&#34;&gt;Comment utiliser sendi avec systemd :&lt;/h2&gt;
&lt;p&gt;Dans mon cas particulier, bien qu&amp;rsquo;il soit possible d&amp;rsquo;installer sendi &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/sendi#experimental-install-as-deb-using-wheel2deb&#34;&gt;via paquet debian&lt;/a&gt; (experimental),
j&amp;rsquo;ai testé dans un premier temps avec podman en générant l&amp;rsquo;image localement.&lt;/p&gt;
&lt;p&gt;Je me suis fait un petit script pour que ça soit plus facile à utiliser :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ❯ cat /usr/local/bin/sendi 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#!/bin/bash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -euo pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman run --rm --net&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;host &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;         -v &lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/.config/sendi:/config &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;         -v &lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/.cache/sendi_container:/root/.cache/sendi &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;         -v &lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/.sendi_upload:/upload &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;         localhost/sendi:1.0.0 --config-file&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/config/config.toml &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$@&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Je peux ainsi avoir cette configuration pour &lt;code&gt;backup.service&lt;/code&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;SENDI_ACCOUNT_NAME=adminuser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;XMPP_NOTIFY_ACCOUNT=me@mysuperdomainname.ndd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;me&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/local/bin/sendi ${SENDI_ACCOUNT_NAME} ${XMPP_NOTIFY_ACCOUNT} --message &amp;#34;Backup process ended 😼&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Une bonne partie de la magie se situe dans le fichier &lt;code&gt;$HOME/.config/sendi/config.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[adminuser]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;mysuperdomainname.ndd&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;5222&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;password&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;A SUPER PASSWORD&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;jid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;bot@mysuperdomainname.ndd&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;connection_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;standard&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;security_level&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;encrypted&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;lang&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;fr&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Avec cette configuration, les messages sont envoyé par &lt;code&gt;bot@mysuperdomainname.ndd&lt;/code&gt; en chiffré bout en bout (via omemo).&lt;/p&gt;
&lt;p&gt;La configuration sans podman via les paquets est un peu plus simple, vous n&amp;rsquo;avez besoin que de &lt;code&gt;$HOME/.config/sendi/config.toml&lt;/code&gt; et
d&amp;rsquo;une configuration comme cela :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;SENDI_ACCOUNT_NAME=adminuser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Environment&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;XMPP_NOTIFY_ACCOUNT=me@mysuperdomainname.ndd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;me&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/bin/sendi ${SENDI_ACCOUNT_NAME} ${XMPP_NOTIFY_ACCOUNT} --message &amp;#34;Backup process ended 😼&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Noter que dans le cas présent le chemin vers sendi a changé, mais le reste est quasiment identique pour cet exemple.&lt;/p&gt;
&lt;h2 id=&#34;pour-conclure&#34;&gt;Pour conclure&lt;/h2&gt;
&lt;p&gt;Sendi est dès à présent disponible en version 1.0 via &lt;a href=&#34;https://pypi.org/project/sendi/&#34;&gt;Pypi&lt;/a&gt;, le code est lui disponible sur &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/sendi/&#34;&gt;framagit&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>💾 Sauvegarde au branchement avec Systemd: Instantanée BTRFS</title>
      <link>https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-instantan%C3%A9e-btrfs/</link>
      <pubDate>Sun, 15 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-instantan%C3%A9e-btrfs/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Dans l&amp;rsquo;article sur &lt;a href=&#34;https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-photos/&#34;&gt;la sauvegarde automatique dès le branchement pour mes photos&lt;/a&gt;,
j&amp;rsquo;indiquais comment j&amp;rsquo;avais réussi à gérer des sauvegardes automatiques au branchement pour mes photos.
Cela est très bien, mais pourquoi pas ne pas étendre la mécanique pour la sauvegarde de fichiers ?
La mécanique de base s&amp;rsquo;avère très proche, mais complété pas les fonctionnalités du système de fichier btrfs,
cela donne un système de sauvegarde très flexible.&lt;/p&gt;
&lt;p&gt;Contrairement aux sauvegardes de photos qui allait de la carte SD au NAS, l&amp;rsquo;idée là est inverse.
On veut pouvoir connecter un disque et le système va écrire de lui-même sur ce disque la nouvelle sauvegarde.&lt;/p&gt;
&lt;aside id=&#34;toc&#34;&gt;
    &lt;h4&gt;Sommaire&lt;/h4&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#principe&#34;&gt;Principe&lt;/a&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;a href=&#34;#enregistrement-automatique-de-sauvegarde-dun-disque-dur&#34;&gt;Enregistrement automatique de sauvegarde d&amp;rsquo;un disque dur&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#ajoutons-un-peu-de-btrfs-par-dessus&#34;&gt;Ajoutons un peu de BTRFS par-dessus&lt;/a&gt;&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#la-pratique&#34;&gt;La pratique&lt;/a&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;a href=&#34;#prérequis-utiliser-btrfs-et-les-sous-volumes&#34;&gt;Prérequis : utiliser btrfs et les sous-volumes&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#créer-une-règle-udev&#34;&gt;Créer une règle Udev&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#point-de-montage&#34;&gt;Point de montage&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#btrbk&#34;&gt;Btrbk&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#snapshot-régulier-et-sauvegarde-si-possible&#34;&gt;Snapshot régulier et sauvegarde si possible&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#récapitulatif-scénario&#34;&gt;Récapitulatif Scénario&lt;/a&gt;&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/nav&gt;
&lt;/aside&gt;
&lt;h2 id=&#34;principe&#34;&gt;Principe&lt;/h2&gt;
&lt;h3 id=&#34;enregistrement-automatique-de-sauvegarde-dun-disque-dur&#34;&gt;Enregistrement automatique de sauvegarde d&amp;rsquo;un disque dur&lt;/h3&gt;
&lt;p&gt;Le principe est assez simple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Je branche un disque dur à mon NAS, le disque dur contient une partition avec le label &amp;ldquo;backup&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Le disque dur est détecté et la partition &amp;ldquo;backup&amp;rdquo; est monté par le système.&lt;/li&gt;
&lt;li&gt;Le système démarre la sauvegarde, ici avec l&amp;rsquo;aide de btrbk et de systemd.&lt;/li&gt;
&lt;li&gt;Le système démonte la partition du disque automatiquement lorsque la sauvegarde est terminé.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ajoutons-un-peu-de-btrfs-par-dessus&#34;&gt;Ajoutons un peu de BTRFS par-dessus&lt;/h3&gt;
&lt;p&gt;Le système de fichiers btrfs par ses fonctionnalités : gestion de &lt;a href=&#34;https://btrfs.readthedocs.io/en/latest/Subvolumes.html&#34;&gt;sous-volume&lt;/a&gt; et instantané (snapshot), nous permet de figer
l&amp;rsquo;image d&amp;rsquo;un sous-volume à un instant T directement sans copie. Cette image peut être en lecture seule. C&amp;rsquo;est un instantané.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;intérêt ? Il est possible de stocker nos données à sauvegarder dans un sous-volume btrfs, qui sera alors sauvegardé sous la forme d&amp;rsquo;un instantané
en lecture seule qu&amp;rsquo;on pourra ainsi transmettre sur un autre disque sans risque de corruption de données lié à des modifications durant la sauvegarde.&lt;/p&gt;
&lt;p&gt;Les instantanés permettent aussi localement un mécanisme de sauvegarde simple permettant de &amp;ldquo;revenir dans le temps&amp;rdquo;.
L&amp;rsquo;autre avantage des instantanés btrfs est qu&amp;rsquo;ils permettent d&amp;rsquo;utiliser le mécanisme &lt;a href=&#34;https://btrfs.readthedocs.io/en/latest/Send-receive.html&#34;&gt;send-receive&lt;/a&gt; qui permet
de copier efficacement des sous-volumes (et donc des instantanés) d&amp;rsquo;un volume btrfs à un autre, potentiellement d&amp;rsquo;une façon incrémentale en utilisant les sous-volumes déjà transmis.&lt;/p&gt;
&lt;p&gt;Donc le principe est le suivant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On met en route une sauvegarde.&lt;/li&gt;
&lt;li&gt;Le système crée un instantané sur le volume source.&lt;/li&gt;
&lt;li&gt;Le système copie cet instantané sur le disque de sauvegarde grâce au mécanisme &lt;code&gt;send-receive&lt;/code&gt;. il tire parti des instantanés déjà transmis pour ne pas tout retransmettre.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les limitations de la mécanique sont les suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;send-receive&lt;/code&gt; ne gère pas les coupures de réseau, donc pas très efficace par le réseau, car il devra renvoyer tout l&amp;rsquo;instantané en cas d&amp;rsquo;interruption.&lt;/li&gt;
&lt;li&gt;il ne faut pas abuser des instantanés, l&amp;rsquo;impact de beaucoup d&amp;rsquo;instantanés sur l&amp;rsquo;espace disque et les performances peuvent être important, il faut donc faire le ménage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;la-pratique&#34;&gt;La pratique&lt;/h2&gt;
&lt;h3 id=&#34;prérequis-utiliser-btrfs-et-les-sous-volumes&#34;&gt;Prérequis : utiliser btrfs et les sous-volumes&lt;/h3&gt;
&lt;p&gt;Pour pouvoir utiliser la fonctionnalité, il faut que le disque à sauvegarder utilise btrfs, et il est conseillé
de créer des sous-volumes pour définir les différents traitements.&lt;/p&gt;
&lt;p&gt;Considérons que l&amp;rsquo;on veut sauvegarder la partition &lt;code&gt;/home&lt;/code&gt; seulement, il faut donc un sous-volume sur home :&lt;/p&gt;
&lt;p&gt;Imaginons qu&amp;rsquo;on a cette arborescence :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── srv : point de montage direct du volume btrfs (voir fstab)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── @home : emplacement du sous-volume `@home` dans le sous-volume par défault de btrfs.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└─ home : On va monter @home ici (voir fstab)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On aurait ainsi des paramètres de montage dans le fichier &lt;code&gt;/etc/fstab&lt;/code&gt; similaire à ça :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;UUID=6875f33c-4fed-4f43-bf34-4af0b2412ca4 /srv auto defaults 0 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;UUID=6875f33c-4fed-4f43-bf34-4af0b2412ca4 /home auto subvol=@home 0 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vous noterez que l&amp;rsquo;UUID est le même, car on pointe littéralement sur la même partition.&lt;/p&gt;
&lt;p&gt;Quant au sous-volume @home, il a pu être créé tout simplement avec cette commande (volume /srv monté)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo btrfs subvolume create /srv/@home
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour ce qui est des instantanés, nous les placerons dans le dossier &lt;code&gt;snapshots&lt;/code&gt; à la raçine de &lt;code&gt;/srv&lt;/code&gt; et les sauvegardes
seront dans le dossier &lt;code&gt;snapshots&lt;/code&gt; à la racine de &lt;code&gt;/mnt/backup&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Je ne rentrerai pas plus dans le détail de la mécanique de btrfs, il existe une &lt;a href=&#34;https://debian-facile.org/doc:systeme:btrfs&#34;&gt;littérature importante à ce sujet&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;créer-une-règle-udev&#34;&gt;Créer une règle Udev&lt;/h3&gt;
&lt;p&gt;Comme &lt;a href=&#34;https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-photos/&#34;&gt;précédemment&lt;/a&gt;, il nous faut passer par udev
pour gérer l&amp;rsquo;aspect montage automatique.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;99-automount_backup_drive.rules&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Automount usb backup drive on insertion
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ACTION!=&amp;#34;remove&amp;#34;, SUBSYSTEM==&amp;#34;block&amp;#34;, ENV{ID_PART_ENTRY_NAME}==&amp;#34;backup&amp;#34;, ENV{SYSTEMD_WANTS}+=&amp;#34;backup.service&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce qui signifie :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si une action provenant d&amp;rsquo;un périphérique de système block d&amp;rsquo;un périphérique donc le label de partition est &lt;code&gt;backup&lt;/code&gt; active un évènement qui
n&amp;rsquo;est pas &amp;ldquo;remove&amp;rdquo;, alors, on demande à activer l&amp;rsquo;unité systemd &lt;code&gt;backup.service&lt;/code&gt;. On reviendra plus en détail ensuite sur pourquoi &lt;code&gt;backup.service&lt;/code&gt; et pas &lt;code&gt;mnt-backupt.mount&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📝 Note : l&amp;rsquo;action est sur les périphériques de type block, ce qui signifie que c&amp;rsquo;est agnostique du moyen de communication utilisé : USB, SATA, NVME, Réseau.
Du moment que le système voit une partition labellisée &lt;code&gt;backup&lt;/code&gt;, il tentera de la monter.&lt;/p&gt;
&lt;h3 id=&#34;point-de-montage&#34;&gt;Point de montage&lt;/h3&gt;
&lt;p&gt;Comme &lt;a href=&#34;https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-photos/&#34;&gt;précédemment&lt;/a&gt;, il nous faut un fichier &lt;code&gt;.mount&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/systemd/system/mnt-backup.mount&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Mount Backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Mount]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;What&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/dev/disk/by-partlabel/backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Where&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/mnt/backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ReadWriteOnly&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrfs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Avec ce point de montage, systemd sait maintenant, qu&amp;rsquo;en cas d&amp;rsquo;activation de &lt;code&gt;mnt-backup.mount&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;qu&amp;rsquo;il doit monter la partition de label &lt;code&gt;backup&lt;/code&gt; dans &lt;code&gt;/mnt/backup&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;qu&amp;rsquo;il doit la monter en lecture/écriture (sinon on va avoir des soucis) !&lt;/li&gt;
&lt;li&gt;qu&amp;rsquo;il doit démarrer &lt;code&gt;btrbk_resume.service&lt;/code&gt;. Je reviens dessus après.&lt;/li&gt;
&lt;li&gt;qu&amp;rsquo;il doit la monter en btrfs. Il s&amp;rsquo;agit là d&amp;rsquo;une vérification supplémentaire, car on va utiliser des outils spécifiques à btrfs. si l&amp;rsquo;on branche un disque de sauvegarde en ext4, il faut mieux que le processus s&amp;rsquo;arrête au plus tôt.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;btrbk&#34;&gt;Btrbk&lt;/h3&gt;
&lt;p&gt;Pour gérer efficacement la sauvegarde après quelques hésitations et un script perso, j&amp;rsquo;ai finalement décidé d&amp;rsquo;utiliser &lt;a href=&#34;https://github.com/digint/btrbk&#34;&gt;btrbk&lt;/a&gt;.
&lt;code&gt;btrbk&lt;/code&gt; est un outil en perl pour gérer les sauvegarde via btrfs, notamment avec la méthode &amp;ldquo;création d&amp;rsquo;instantanés puis envois sur disque via btrfs send/receive&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Il a beaucoup d&amp;rsquo;avantages :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://packages.debian.org/btrbk&#34;&gt;paquet debian&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;gère correctement l&amp;rsquo;incrémental.&lt;/li&gt;
&lt;li&gt;gére toute la mécanique de rotation des sauvegardes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En bref, il nous simplifie la vie pour utiliser les fonctionnalités de btrfs dans notre cas.&lt;/p&gt;
&lt;p&gt;Il faut néanmoins un peu de temps pour l&amp;rsquo;apprivoiser les règles de conservations sont ainsi assez compliqué à comprendre.
Je vous laisse chercher dans la &lt;a href=&#34;https://digint.ch/btrbk/doc/readme.html&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dans notre cas simple, on aura donc une configuration de ce style :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;transaction_log            /var/log/btrbk.log
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# les snapshot du volume src et targets seront placé dans le dossier snapshot à la racine
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;snapshot_dir               snapshots
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# règle de conservation des snapshots
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;snapshot_preserve_min   2d
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;snapshot_preserve       14d
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# règle de conservation des sauvegardes sur le disque de sauvegarde
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;target_preserve_min     no
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;target_preserve         20d 10w *m
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# on définis ici qu&amp;#39;on fait des snapshot pour le sous volume @home de /srv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# et qu&amp;#39;on les copie en mode send-receive vers /mnt/backup
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;volume /srv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  target send-receive /mnt/backup
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  subvolume @home
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On pourrait s&amp;rsquo;arrêter là et modifier le système pour que &lt;code&gt;backup.service&lt;/code&gt; lance le &lt;code&gt;btrbk.service&lt;/code&gt; du paquet debian et ça fonctionnerait
pour la sauvegarde à chaud. Mais mon souhait et d&amp;rsquo;avoir un snapshot journalier dans tous les cas et éventuellement une sauvegarde si le disque
de sauvegarde est branché.&lt;/p&gt;
&lt;h3 id=&#34;snapshot-régulier-et-sauvegarde-si-possible&#34;&gt;Snapshot régulier et sauvegarde si possible&lt;/h3&gt;
&lt;p&gt;Pour réaliser cette mécanique d&amp;rsquo;instantanés réguliers en plus de la sauvegarde à chaud, il faut jouer un peu avec systemd.&lt;/p&gt;
&lt;p&gt;Btrbk, permet de séparer la transmission de sauvegarde de la réalisation de snapshot.
Pour ce faire, au lieu de faire &lt;code&gt;btrbk run&lt;/code&gt; on peut utiliser &lt;code&gt;btrbk snapshot -p&lt;/code&gt;et &lt;code&gt;btrbk resume&lt;/code&gt;.
Avec quelques override systemd, on peut arriver au bon résultat :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On surcharge &lt;code&gt;btrbk.service&lt;/code&gt; pour ne faire que des instantanés et ne rien supprimer(&lt;code&gt;-p&lt;/code&gt;):&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /lib/systemd/system/btrbk.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Documentation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;man:btrbk(1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/sbin/btrbk run&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/system/btrbk.service.d/override.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/sbin/btrbk snapshot -p&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;On ajoute &lt;code&gt;btrbk_resume.service&lt;/code&gt; pour faire la transmission des sauvegardes:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/system/btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 📝 note: on demande implicitement `mnt-backup.mount`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RequiresMountsFor&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/mnt/backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RefuseManualStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 📝 note: On n&amp;#39;a pas mis de `-p` ici, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# la rotation des instanées et sauvegardes se fera à la fin de la transmission des sauvegardes.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/usr/sbin/btrbk resume&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;On crée &lt;code&gt;backup.service&lt;/code&gt; notre point d&amp;rsquo;entrée pour tous processus de sauvegarde qui fera :
&lt;ul&gt;
&lt;li&gt;la création des instantanés&lt;/li&gt;
&lt;li&gt;tentera d&amp;rsquo;exécuter la sauvegardes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/system/backup.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk.service btrbk_resume.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 📝 Note: Ce service est un peu subtil, car on tire profit des spécificités des services oneshot. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Ce service lancera les 2 services btrbk et restera en activating, jusqu&amp;#39;à qu&amp;#39;ils s&amp;#39;arrêtent et donc sera enfin `inactivate`.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# il n&amp;#39;est à ma connaissance pas possible de faire la même chose avec des `.target` qui seront en `activate` à la fin du processus.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Fausse commande car c&amp;#39;est obligatoire pour les service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/bin/true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;On surcharge aussi &lt;code&gt;btrbk.timer&lt;/code&gt; des paquets pour démarrer notre point d&amp;rsquo;entrée :&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /lib/systemd/system/btrbk.timer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;btrbk daily backup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Timer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;OnCalendar&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;daily&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;AccuracySec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;10min&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Persistent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;WantedBy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/systemd/system/btrbk.timer.d/override.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Timer]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Unit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;backup.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;📝 Note : Il ne faut pas oublier d&amp;rsquo;activer ce service sinon vous n&amp;rsquo;aurez pas les sauvegardes régulières&lt;/p&gt;
&lt;h3 id=&#34;récapitulatif-scénario&#34;&gt;Récapitulatif Scénario&lt;/h3&gt;
&lt;p&gt;On à donc les 3 scénarios suivants :&lt;/p&gt;
&lt;h4 id=&#34;1-branchement-à-chaud&#34;&gt;1. Branchement à chaud&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;On branche le disque de sauvegarde.&lt;/li&gt;
&lt;li&gt;udev demande à démarrer &lt;code&gt;backup.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup.service&lt;/code&gt; démarre d&amp;rsquo;abord &lt;code&gt;btbrk.service&lt;/code&gt; car &lt;code&gt;btrbk_resume.service&lt;/code&gt; demande à être exécuté après.&lt;/li&gt;
&lt;li&gt;les snapshots sont créés, &lt;code&gt;btrbk_resume.service&lt;/code&gt; est démarré.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;btrbk_resume.service&lt;/code&gt; monte &lt;code&gt;mnt-backup.service&lt;/code&gt;. Il fait la sauvegarde.&lt;/li&gt;
&lt;li&gt;À la fin de &lt;code&gt;btrbk_resume&lt;/code&gt;, &lt;code&gt;mnt-backup.service&lt;/code&gt; est démonté&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;2-sauvegarde-régulière&#34;&gt;2. Sauvegarde régulière&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;btrbk.timer&lt;/code&gt; démarre &lt;code&gt;backup.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup.service&lt;/code&gt; démarre d&amp;rsquo;abord &lt;code&gt;btbrk.service&lt;/code&gt; car &lt;code&gt;btrbk_resume.service&lt;/code&gt; demande à être exécuté après.&lt;/li&gt;
&lt;li&gt;les snapshots sont créés, &lt;code&gt;btrbk_resume.service&lt;/code&gt; est démarré.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;btrbk_resume.service&lt;/code&gt; monte &lt;code&gt;mnt-backup.service&lt;/code&gt;. Il fait la sauvegarde.&lt;/li&gt;
&lt;li&gt;À la fin de &lt;code&gt;btrbk_resume&lt;/code&gt;, &lt;code&gt;mnt-backup.service&lt;/code&gt; est démonté.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;3-sauvegarde-régulière-sans-disque-branché&#34;&gt;3. Sauvegarde régulière sans disque branché&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;btrbk.timer&lt;/code&gt; démarre &lt;code&gt;backup.service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup.service&lt;/code&gt; démarre d&amp;rsquo;abord &lt;code&gt;btbrk.service&lt;/code&gt; car &lt;code&gt;btrbk_resume.service&lt;/code&gt; demande à être exécuté après.&lt;/li&gt;
&lt;li&gt;les snapshots sont créés, &lt;code&gt;btrbk_resume.service&lt;/code&gt; est démarré.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;btrbk_resume.service&lt;/code&gt; monte &lt;code&gt;mnt-backup.service&lt;/code&gt; mais &lt;code&gt;mnt-backup.service&lt;/code&gt; ne peut être démarré. arrêt du service.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backup.service&lt;/code&gt; se stoppe, mais les instantanés ont bien été créés.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Btrfs n&amp;rsquo;est pas si facile à prendre en main, mais les concepts bien compris et à l&amp;rsquo;aide de systemd, on
peut créer des mécanismes de sauvegardes puissants.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>📦 Article sur Linux Embedded: Introduction au paquetage pour debian</title>
      <link>https://inkey-art.net/article-sur-linux-embedded-introduction-au-paquetage-pour-debian/</link>
      <pubDate>Fri, 17 May 2024 17:40:32 +0100</pubDate>
      
      <guid>https://inkey-art.net/article-sur-linux-embedded-introduction-au-paquetage-pour-debian/</guid>
      <description>&lt;p&gt;J’ai publié un article technique sur la création de paquet Debian sur le blog Linux Embedded.&lt;/p&gt;
&lt;h2 id=&#34;pourquoi-un-article-sur-les-paquets-debian-&#34;&gt;Pourquoi un article sur les paquets Debian ?&lt;/h2&gt;
&lt;p&gt;La création de paquet logiciel pour la distribution Gnu/Linux Debian peut se révéler vraie galère, car les outils sont nombreux, de différents niveaux&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;,
conçu pour répondre à différents d’usage.&lt;/p&gt;
&lt;p&gt;Il existe de nombreuses documentations et tutoriels en ligne, mais peu de ressources permettant d’avoir
une vision d’ensemble un peu claire du sujet, de sorte qu’il devient assez difficile de trouver la bonne information,
on se retrouve facilement à lire des discussions stackoverflow qui propose chacune une façon différente de faire les choses ce
qui au lieu de vous aider, vous embrouillent encore un peu plus.&lt;/p&gt;
&lt;p&gt;Pour cette raison, j’ai beaucoup creusé et j’ai cherché à clarifier le sujet.&lt;/p&gt;
&lt;p&gt;Les paquets Debian sont un sujet à la fois super vaste et difficile à maîtriser pour la plupart des développeurs, à moins
d’être mainteneurs de paquet, car :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quand un logiciel est configuré pour être packager, on revient à la marge sur la configuration et donc
on peut très vite être perdu lors de la création d’un nouveau paquet des mois ou des années après.&lt;/li&gt;
&lt;li&gt;Un logiciel pourra se mettre en paquet d’une manière très différente d’un autre.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il me paraissait donc nécessaire d’avoir un article condensé permettant à la fois pour un novice d’avoir
une 1ére approche, mais aussi des éléments sur le contexte logiciel très large de la création de paquet debian
pour savoir un peu mieux où chercher et où trouver l’information.&lt;/p&gt;
&lt;h2 id=&#34;je-veux-lire-larticle-&#34;&gt;Je veux lire l’article !&lt;/h2&gt;
&lt;p&gt;Cet article ne permettra donc pas de répondre dans le détail sur comment faire votre paquet, mais vous donnera, je l’espère,
les éléments pour partir dans la bonne direction si vous envisagez d’en créer un.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://linuxembedded.fr/2024/04/introduction-au-paquetage-pour-debian&#34;&gt;Aller voir l’article&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Bonne lecture 😄 !&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;J’espère beaucoup de &lt;a href=&#34;https://nthykier.wordpress.com/2023/10/08/a-new-debian-package-helper-debputy/&#34;&gt;Debputy&lt;/a&gt;
pour pouvoir à terme générer des paquets à la norme Debian sans devoir subir toutes les couches successives d’outils Debian
de génération de paquets. Mais cela reste pour l’instant qu’un outil expérimental incomplet. Le paquetage Debian mériterait
d’avoir un outil de génération plus monolithique et moins permissif afin d’être plus accueillant.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    <item>
      <title>💾 Sauvegarde au branchement avec Systemd: Photos</title>
      <link>https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-photos/</link>
      <pubDate>Sat, 10 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-photos/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Dans l&amp;rsquo;article sur &lt;a href=&#34;https://inkey-art.net/mon-process-de-gestion-des-photos/&#34;&gt;mon processus de gestion de photos&lt;/a&gt;,
je notais que je n&amp;rsquo;avais pas poussé l&amp;rsquo;automatisation à fond sur la partie sauvegardes du contenu des cartes avec
le NAS. C&amp;rsquo;est maintenant chose faite.
Je vais donc dans cette logique, expliquer ici comment on peut facilement gérer ce type d&amp;rsquo;automatisation
avec udev et systemd.&lt;/p&gt;
&lt;h1 id=&#34;enregistrement-automatique-de-carte-sd&#34;&gt;Enregistrement automatique de carte sd&lt;/h1&gt;
&lt;p&gt;Le principe est assez simple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Je branche une carte SD à mon NAS.&lt;/li&gt;
&lt;li&gt;La carte est détecté et est monté par le système.&lt;/li&gt;
&lt;li&gt;Le système démarre la sauvegarde, ici avec le logiciel `phockup qui me trie en même temps le tout.&lt;/li&gt;
&lt;li&gt;Le système démonte la carte automatiquement lorsque la sauvegarde est terminé.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;créer-une-règle-udev&#34;&gt;Créer une règle Udev&lt;/h2&gt;
&lt;p&gt;Systemd n&amp;rsquo;est pas capable par lui-même d&amp;rsquo;écouter les évènements provenant des périphériques.
Le logiciel permettant cela est udev. Il faut donc rajouter une nouvelle règle &lt;code&gt;.rules&lt;/code&gt; dans le dossier &lt;code&gt;/etc/udev/rules.d/&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;la commande &lt;code&gt;udevadm monitor&lt;/code&gt; permet d&amp;rsquo;écouter les évènements Udev, elle nous permet ainsi de pouvoir constater
que l&amp;rsquo;évènement de branchement/débranchement de la carte est bien défini. Cela me permet ainsi de découvrir
que le peripheral de carte SD, est, dans mon cas &lt;code&gt;/dev/mmcblk0&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Il est possible d&amp;rsquo;en savoir plus tant que le périphérique est branché avec la commande : &lt;code&gt;udevadm info --query=all --name=&amp;lt;devname&amp;gt;&lt;/code&gt;,
elle retourne plein d&amp;rsquo;informations par périphérique qu&amp;rsquo;on pourra ensuite utilisé pour notre règle.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📝 Note : j&amp;rsquo;ai volontairement affiché ici que quelques résultats de la commande.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ udevadm info --query&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;all --name&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/dev/mmcblk0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;N: mmcblk0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;E: &lt;span class=&#34;nv&#34;&gt;SUBSYSTEM&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;block
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;E: &lt;span class=&#34;nv&#34;&gt;DEVNAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/dev/mmcblk0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ udevadm info --query&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;all --name&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/dev/mmcblk0p1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;N: mmcblk0p1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;E: &lt;span class=&#34;nv&#34;&gt;SUBSYSTEM&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;block
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;E: &lt;span class=&#34;nv&#34;&gt;DEVNAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/dev/mmcblk0p1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il est assez facile dans le cas présent de bien filtré dans mon cas :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/udev/rules.d/20-automount_sd_cards.rules&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Automount sd card on insertion
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ACTION!=&amp;#34;remove&amp;#34;, SUBSYSTEM==&amp;#34;block&amp;#34;, KERNEL==&amp;#34;mmcblk0p*&amp;#34;, ENV{SYSTEMD_WANTS}+=&amp;#34;mnt-sdcard.mount&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce qui signifie :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si une action provenant d&amp;rsquo;un périphérique de système block d&amp;rsquo;un périphérique donc le nom kernel commence par &lt;code&gt;mmcblk0p&lt;/code&gt; (une partition de mmcblk0) active un évènement qui
n&amp;rsquo;est pas &amp;ldquo;remove&amp;rdquo;, alors, on demande à activer l&amp;rsquo;unité systemd &lt;code&gt;mnt-sdcard.mount&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📝 Note : Il est &lt;a href=&#34;https://github.com/systemd/systemd/issues/26171#issuecomment-1410175173&#34;&gt;préférable pour des raisons de fiabilité&lt;/a&gt; d&amp;rsquo;utilisé &lt;code&gt;ACTION!=&amp;quot;remove&amp;quot;&lt;/code&gt; plutôt que &lt;code&gt;ACTION==&amp;quot;add&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;point-de-montage&#34;&gt;Point de montage&lt;/h2&gt;
&lt;p&gt;Les points de montages avec systemd peuvent être aussi bien créé avec des fichiers &lt;code&gt;.mount&lt;/code&gt; qu&amp;rsquo;avec une syntaxe &lt;code&gt;/etc/fstab&lt;/code&gt;.
Aucune des deux méthodes n&amp;rsquo;est plus valable. La mécanique de &lt;code&gt;.mount&lt;/code&gt; à l&amp;rsquo;avantage/le désavantage de produire des fichiers séparer pour chaque point
de montage, ce qui est à la fois plus complexe, mais bien plus pratique, notamment si vous cherchez à empaqueter la configuration.&lt;/p&gt;
&lt;p&gt;Attention le nommage doit &amp;ldquo;correspondre&amp;rdquo; au point de montage ainsi &lt;code&gt;mnt-sdcard&lt;/code&gt; correspond à &lt;code&gt;/mnt/sdcard&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/systemd/system/mnt-sdcard.mount&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Mount SD Card&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# liaison forte à save_photos.service, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# - Demande que save_photos.service soit activé&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# - s&amp;#39;arrètera quand save.photos.service s&amp;#39;arrêtera.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;save_photos.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Mount]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;What&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/dev/mmcblk0p1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Where&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/mnt/sdcard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On préfèrera ne pas monter la carte en écriture.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Options&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Avec ce point de montage, systemd sait maintenant, qu&amp;rsquo;en cas d&amp;rsquo;activation de &lt;code&gt;mnt-sdcard.mount&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;qu&amp;rsquo;il doit monter la 1ére partition de &lt;code&gt;mmcblk0&lt;/code&gt;, &lt;code&gt;mmcblk0p1&lt;/code&gt; dans &lt;code&gt;/mnt/sdcard&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;qu&amp;rsquo;il doit la monter en lecture seule.&lt;/li&gt;
&lt;li&gt;qu&amp;rsquo;il doit démarrer &lt;code&gt;save_photos.service&lt;/code&gt;.
Les cartes SD de photos ne contenant qu&amp;rsquo;une seule partition, cela rend les choses plus simples.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;service-de-sauvegarde&#34;&gt;Service de sauvegarde&lt;/h2&gt;
&lt;p&gt;On peut maintenant faire la sauvegarde a proprement dit :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/systemd/system/save_photos.service&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# liaison forte à mnt-sdcard.mount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# - Demande que mnt-sdcard.mount soit activé.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# - s&amp;#39;arrètera quand  mnt-sdcard.mount s&amp;#39;arrêtera.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# - On met une relation d&amp;#39;ordre pour que le montage s&amp;#39;execute avant.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;After&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;mnt-sdcard.mount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BindsTo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;mnt-sdcard.mount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On empêche le démarrage manuel, seul mnt-sdcard.service doit démarrer ce service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;RefuseManualStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# on démarre le service avec les droits utilisateur&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;inkey&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# le type oneshot permet facileent de cumuler les commandes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;Type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;oneshot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Photos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/home/inkey/.local/bin/phockup /mnt/sdcard/ /home/inkey/Images/Photos/ -c 6 --progress --file-type image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Video&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;ExecStart&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/home/inkey/.local/bin/phockup /mnt/sdcard/ /home/inkey/Vidéos/Perso/ -c 6 --progress --file-type video&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;📝 Note : j&amp;rsquo;ai installé phockup dans &lt;code&gt;$HOME/.local/bin&lt;/code&gt; pour le moment&lt;/p&gt;
&lt;h2 id=&#34;aller-plus-loin-&#34;&gt;Aller plus loin ?&lt;/h2&gt;
&lt;h3 id=&#34;notification&#34;&gt;Notification&lt;/h3&gt;
&lt;p&gt;Le système ici ne notifie ni quand la copie est démarré ni quand elle est finie. Pour ma part, j&amp;rsquo;ai complété ce
mécanisme avec des commandes qui me notifie avec xmpp. C&amp;rsquo;est très facile avec &lt;code&gt;ExecStartPre&lt;/code&gt; et &lt;code&gt;ExecStartPost&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;sécurisation&#34;&gt;Sécurisation&lt;/h3&gt;
&lt;p&gt;Si vous voulez vous amuser un peu, vous pouvez sécuriser un peu plus le service à l&amp;rsquo;aide de:
&lt;code&gt;systemd-analyze security save_photos.service&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;mécanisme-de-sauvegarde-de-données-hors-ligne-backup&#34;&gt;Mécanisme de Sauvegarde de données hors-ligne (&amp;ldquo;backup&amp;rdquo;)&lt;/h3&gt;
&lt;p&gt;La mécanique pourrait être ajusté pour gérer un système de sauvegarde du contenu du NAS :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on branche un disque&lt;/li&gt;
&lt;li&gt;le système détecte qu&amp;rsquo;il s&amp;rsquo;agit d&amp;rsquo;un disque de sauvegarde, probablement à l&amp;rsquo;aide d&amp;rsquo;un label de partition.&lt;/li&gt;
&lt;li&gt;la sauvegarde commence.&lt;/li&gt;
&lt;li&gt;la sauvegarde se termine et le disque est démonté automatiquement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C&amp;rsquo;est une méthode à la fois simple et efficace pour pouvoir faire des sauvegardes et s&amp;rsquo;assurer de cette façon
que la sauvegarde est bel et bien offline.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Il est assez facile de gérer les points de montage avec systemd pour ce type d&amp;rsquo;usage.
Bref Systemd, c&amp;rsquo;est sympa, c&amp;rsquo;est puissant, n&amp;rsquo;hésitez pas à jouer avec 😃.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🌐 Connexion directe en Ethernet via ipv6 et mDns</title>
      <link>https://inkey-art.net/connexion-directe-en-ethernet-via-ipv6-et-mdns/</link>
      <pubDate>Sun, 29 Oct 2023 16:22:08 +0100</pubDate>
      
      <guid>https://inkey-art.net/connexion-directe-en-ethernet-via-ipv6-et-mdns/</guid>
      <description>&lt;p&gt;Comment facilement créer un réseau rapidement entre 2 appareils connectés en direct en Ethernet ?&lt;/p&gt;
&lt;h3 id=&#34;lien-local-ipv6&#34;&gt;Lien local IPV6&lt;/h3&gt;
&lt;p&gt;L&amp;rsquo;ipv6 à une fonctionnalité d&amp;rsquo;ip de lien local, qui commence par &lt;code&gt;fe80&lt;/code&gt;.
Sous Gnu/linux. Cette fonctionnalité fonctionne par défault sans la moindre modification.
Cela permet à chaque appareil d&amp;rsquo;avoir une IP par défault sans configuration.&lt;/p&gt;
&lt;p&gt;Sous Gnome, il peut être nécessaire de modifier la méthode ivp6, afin d&amp;rsquo;avoir la méthode de lien locale
fonctionnelle.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;ipv6/lien-local.png&#34; alt=&#34;IPV6&#34;&gt;&lt;/p&gt;
&lt;p&gt;La commande &lt;code&gt;ip -br -c a&lt;/code&gt; devrait vous permettre rapidement de constater que l&amp;rsquo;adresse ip existe bel et bien
sur chacune des machines.&lt;/p&gt;
&lt;p&gt;Pour tester manuellement le lien local, on peut le faire comme ceci :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ping de l&amp;#39;autre machine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ping6 -I enp0s31f6 fe80::bf48:d6d:de5a:5542
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# exemple pour ssh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh user@fe80::bf48:d6d:de5a:5542%enp0s31f6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On remarque qu&amp;rsquo;il faut définir à chaque fois l’interface.&lt;/p&gt;
&lt;h3 id=&#34;accès-facile-via-mdns&#34;&gt;Accès facile via mDns&lt;/h3&gt;
&lt;p&gt;Le fonctionnement du lien local est intéressant, mais on remarque qu&amp;rsquo;il est nécessaire de définir chaque
fois l&amp;rsquo;interface d&amp;rsquo;une part et d&amp;rsquo;autre part, il faut connaître les addresses IPs, ce qui n&amp;rsquo;est pas très pratique.&lt;/p&gt;
&lt;p&gt;Une méthode pratique pour éviter de devoir apprendre l&amp;rsquo;adresse ip, on peut utiliser &lt;code&gt;mDns&lt;/code&gt; (nommé aussi &lt;code&gt;avahi/bonjour/zeroconf&lt;/code&gt;),
qui fournit automatiquement des adresses en &lt;code&gt;hostname.local&lt;/code&gt; pour les ordinateurs du réseau local.&lt;/p&gt;
&lt;p&gt;Une modification est nécessaire sous Debian aujourd&amp;rsquo;hui (Debian 12) pour pouvoir faire fonctionner les addresses &lt;code&gt;.local&lt;/code&gt;
avec le lien-local ipv6 :&lt;/p&gt;
&lt;p&gt;En replacement la ligne &lt;code&gt;hosts&lt;/code&gt;, pour activer mdns en ipv6 en plus d&amp;rsquo;ipv4 :&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;hosts:          files mdns4_minimal [NOTFOUND=return] dns myhostname
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;par:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;hosts:          files mdns_minimal [NOTFOUND=return] dns myhostname
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Après ce changement et un redémarrage des machines, il suffit de faire :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ping de l&amp;#39;autre machine&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ping hostname.local
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# exemple pour ssh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh hostname.local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    
    
    <item>
      <title>🪄 Rendre un blog hugo plus dynamique avec HTMX</title>
      <link>https://inkey-art.net/rendre-un-blog-hugo-plus-dynamique-avec-htmx/</link>
      <pubDate>Sat, 09 Sep 2023 13:30:00 +0200</pubDate>
      
      <guid>https://inkey-art.net/rendre-un-blog-hugo-plus-dynamique-avec-htmx/</guid>
      <description>&lt;p&gt;Je suis un développeur très orienté backend, logique interne et rarement amené à me poser des questions
d&amp;rsquo;interface, néanmoins, j&amp;rsquo;ai suivi dans les grandes lignes les évolutions des technologies d&amp;rsquo;interface
côté frontend d&amp;rsquo;application web. Nous sommes ainsi passé, dans le monde du web, d&amp;rsquo;applicatif fortement géré par le backend à
un frontend quasi-autonome à base de beaucoup de javascript, les fameuses « &lt;a href=&#34;https://en.wikipedia.org/wiki/Single-page_application&#34;&gt;Single Pages Apps&lt;/a&gt; » avec les
frameworks tel que &lt;em&gt;Vue&lt;/em&gt;, &lt;em&gt;React&lt;/em&gt;, &lt;em&gt;Angular&lt;/em&gt; ou encore &lt;a href=&#34;https://svelte.dev/&#34;&gt;Svelte&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Je ne suis pas un grand fan de configurer des interfaces et ces logiciels me font un peu peur de prime abord,
il existe tout un écosystème très complexe et complet autours et je n&amp;rsquo;ai ni l&amp;rsquo;envie ni le temps d&amp;rsquo;y jeter un œil
approfondi.&lt;/p&gt;
&lt;p&gt;Une technologie va peut-être me réconcilier un peu avec les interfaces, c&amp;rsquo;est &lt;a href=&#34;https://htmx.org/&#34;&gt;HTMX&lt;/a&gt;.
L&amp;rsquo;idée est de convertir le plus possible de javascript en html et ainsi de compléter la logique
d&amp;rsquo;hypermédia qui lui été prévu à l&amp;rsquo;origine. À propos d&amp;rsquo;&lt;em&gt;hypermédia&lt;/em&gt;, le livre &lt;a href=&#34;https://hypermedia.systems/&#34;&gt;Hypermedia Systems&lt;/a&gt; est super intéressant.&lt;/p&gt;
&lt;p&gt;En cherchant un peu dans HTMX, j&amp;rsquo;ai trouvé de quoi rendre ce site un peu plus interactif grâce à simplement
2 propriétés : &lt;a href=&#34;https://htmx.org/attributes/hx-indicator/&#34;&gt;hx-indicator&lt;/a&gt; et &lt;a href=&#34;https://htmx.org/attributes/hx-boost/&#34;&gt;hx-boost&lt;/a&gt;, en rendant le changement de page un légèrement plus interactif tout
en restant fonctionnel sans javascript.&lt;/p&gt;
&lt;p&gt;Voici mes changements dans mon thème custom Hugo basé sur le thème &lt;em&gt;etch&lt;/em&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/themes/etch/layouts/_default/baseof.html b/themes/etch/layouts/_default/baseof.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index 0a5d1f7..1196478 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;--- a/themes/etch/layouts/_default/baseof.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/themes/etch/layouts/_default/baseof.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -1,7 +1,7 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt; &amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;lt;html lang=&amp;#34;{{ .Site.Language.Lang }}&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     {{- partial &amp;#34;head.html&amp;#34; . -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;-    &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+    &amp;lt;body hx-boost=&amp;#34;true&amp;#34;  hx-indicator=&amp;#34;#spinner&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;         {{- partial &amp;#34;header.html&amp;#34; . -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &amp;lt;main id=&amp;#34;content&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         {{- block &amp;#34;main&amp;#34; . }}{{- end }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/themes/etch/layouts/partials/head.html b/themes/etch/layouts/partials/head.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index d6aed0c..e4e261f 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;--- a/themes/etch/layouts/partials/head.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/themes/etch/layouts/partials/head.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -27,6 +27,8 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt;     {{ $css := $resources | resources.Concat &amp;#34;css/style.css&amp;#34; | minify }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     {{ printf `&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; href=&amp;#34;%s&amp;#34;&amp;gt;` $css.RelPermalink | safeHTML }}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+    {{ $js := (resources.Get &amp;#34;javascript/htmx-1.9.5.min.js&amp;#34;) }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+    {{ printf `&amp;lt;script src=&amp;#34;%s&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;` $js.RelPermalink | safeHTML }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;     &amp;lt;link rel=&amp;#34;canonical&amp;#34; href=&amp;#34;{{ .Permalink }}&amp;#34; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &amp;lt;title&amp;gt;{{ .Title }}&amp;lt;/title&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/themes/etch/layouts/partials/header.html b/themes/etch/layouts/partials/header.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index 9a66449..23a2642 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gd&#34;&gt;--- a/themes/etch/layouts/partials/header.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/themes/etch/layouts/partials/header.html
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;&lt;span class=&#34;gu&#34;&gt;@@ -1,4 +1,6 @@
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;&lt;/span&gt; &amp;lt;header id=&amp;#34;banner&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+    {{ $svg := resources.Get &amp;#34;svg/bars.svg&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+    &amp;lt;img  id=&amp;#34;spinner&amp;#34; class=&amp;#34;htmx-indicator&amp;#34; src=&amp;#34;{{$svg.RelPermalink}}&amp;#34; alt=&amp;#34;Updating page..&amp;#34;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;&lt;/span&gt;     &amp;lt;h2&amp;gt;&amp;lt;a href=&amp;#34;{{ .Site.BaseURL }}&amp;#34;&amp;gt;{{ .Site.Title }}&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &amp;lt;nav&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &amp;lt;ul&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;J&amp;rsquo;ai ainsi une jolie animation de chargement qui apparaît à chaque changement de page 😃.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>📘 Déploiement Blog Hugo</title>
      <link>https://inkey-art.net/d%C3%A9ploiement-blog-hugo/</link>
      <pubDate>Fri, 25 Aug 2023 18:09:50 +0200</pubDate>
      
      <guid>https://inkey-art.net/d%C3%A9ploiement-blog-hugo/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Article original du 2023-05-06 :&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pour déployer facilement mon blog avec hugo en auto-hébergé tout en gardant le code sur gitlab, j&amp;rsquo;utilise la méthode suivante :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Un repository gitlab distant avec mon code.&lt;/li&gt;
&lt;li&gt;Une intégration continue gitlab qui génère une archive du site : &lt;a href=&#34;https://gohugo.io/hosting-and-deployment/hosting-on-gitlab/&#34;&gt;voir ici&lt;/a&gt;, mais qui n&amp;rsquo;est pas déployé&lt;/li&gt;
&lt;li&gt;Un script local sur mon serveur me permettant de déployer mon site sans difficulté en modifiant le contenu d&amp;rsquo;un répertoire présenté par mon serveur web&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voici ainsi le type de script que j&amp;rsquo;ai ainsi utilisé, le principe est de récupérer le dernier artefact de gitlab et
ensuite de le déployer dans le dossier &lt;code&gt;/var/www/public&lt;/code&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# CONFIG&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;ARCHIVE_PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/tmp/artifacts.zip&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PROJECT_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;YOURPROJECTNUMBER&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;DEST_PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/var/www/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;GITLAB_ACCESS_TOKEN&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;YOURTOKEN&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;GITLAB_INSTANCE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;YOURINSTANCE&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;BRANCH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;YOUR BRANCHE&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;JOB_NAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;pages&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# DEPLOY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl --location --header &lt;span class=&#34;s2&#34;&gt;&amp;#34;PRIVATE-TOKEN: &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GITLAB_ACCESS_TOKEN&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$GITLAB_INSTANCE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/api/v4/projects/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PROJECT_NUMBER&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/jobs/artifacts/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$BRANCH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/download?job=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$JOB_NAME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --output &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ARCHIVE_PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo rm -R &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DEST_PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo unzip &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ARCHIVE_PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; -d &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DEST_PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo chown -R www-data:www-data &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DEST_PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ARCHIVE_PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il suffit alors d&amp;rsquo;attendre que la CI passe et soit validé côté gitlab pour pouvoir appliquer le script. 😀&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mise à jour 2023-08-25 : J&amp;rsquo;ai amélioré le mécanisme pour le rendre automatique. Voici comment faire : &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On peut aller plus loin et rendre le système automatique.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optionel: Régénération du pipeline à intervalles réguliers, pour gérer les &lt;a href=&#34;https://gohugo.io/getting-started/usage/#draft-future-and-expired-content&#34;&gt;articles futurs ou expirés&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ajout d&amp;rsquo;un &lt;a href=&#34;https://docs.gitlab.com/ee/user/project/integrations/webhooks.html&#34;&gt;webhook &lt;em&gt;Pipeline events&lt;/em&gt;&lt;/a&gt; dans Gitlab.&lt;/li&gt;
&lt;li&gt;Installation d&amp;rsquo;un serveur &lt;a href=&#34;https://github.com/adnanh/webhook&#34;&gt;webhook&lt;/a&gt; pour répondre aux hooks Gitlab et lance le script bash ci-dessus.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voici un exemple naif de configuration du serveur webhook :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;blog_update&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;execute-command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/home/me/monscript.sh&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;command-working-directory&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/home/me&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;response-message&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;redeploy blog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;trigger-rule&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;and&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DONOTLEAKTHIS&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;parameter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nt&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;header&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;X-Gitlab-Token&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Pipeline Hook&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;parameter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nt&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;header&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;X-Gitlab-Event&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nt&#34;&gt;&amp;#34;parameter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nt&#34;&gt;&amp;#34;source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;payload&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              &lt;span class=&#34;nt&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;builds.0.status&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Des ajustements sont nécessaires pour gérer ça correctement et de façon sécurisée. En effet, l&amp;rsquo;utilisation d&amp;rsquo;un webhook est potentiellement dangereux, il pourrait rendre possible à un tier d&amp;rsquo;exécuter du code non voulu, il faut donc :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Empêcher au maximum la possibilité d&amp;rsquo;éditer le script.&lt;/li&gt;
&lt;li&gt;Donner juste assez de droits pour que l&amp;rsquo;utilisateur du script soit en capacité de le lancer sans pouvoir modifier d&amp;rsquo;autres choses.&lt;/li&gt;
&lt;li&gt;Gérer https pour ne pas faire transiter le token en clair.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà si vous avez fait tout ça bien, vous pouvez pousser votre code sur Gitlab et tada, automatiquement, il sera mis à jour.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🐍 Avoir des type plus précis en Python</title>
      <link>https://inkey-art.net/avoir-des-type-plus-pr%C3%A9cis-en-python/</link>
      <pubDate>Sun, 13 Aug 2023 16:30:55 +0200</pubDate>
      
      <guid>https://inkey-art.net/avoir-des-type-plus-pr%C3%A9cis-en-python/</guid>
      <description>&lt;aside id=&#34;toc&#34;&gt;
    &lt;h4&gt;Sommaire&lt;/h4&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#avoir-des-types-plus-précis-&#34;&gt;Avoir des types plus précis ?&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#méthodes&#34;&gt;Méthodes&lt;/a&gt;
      &lt;ol&gt;
        &lt;li&gt;&lt;a href=&#34;#1-commentaire&#34;&gt;1. Commentaire&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#2-programmation-par-contratassert&#34;&gt;2. Programmation par contrat(assert)&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#3-annotated&#34;&gt;3. Annotated&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#4-alias-de-type&#34;&gt;4. Alias de type&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#5-newtype&#34;&gt;5. NewType&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#6-sous-classe&#34;&gt;6. Sous-classe&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#résumé&#34;&gt;Résumé&lt;/a&gt;&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#contrainte-sur-les-entiers&#34;&gt;Contrainte sur les entiers&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#id-de-type-existant-&#34;&gt;Id de type existant ?&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#le-cas-des-unités-de-mesure&#34;&gt;Le cas des unités de mesure.&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#pour-conclure&#34;&gt;Pour Conclure&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#allez-plus-loin&#34;&gt;Allez plus loin :&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/nav&gt;
&lt;/aside&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;En python, le typage est &lt;em&gt;dynamique fort&lt;/em&gt;. De sorte que :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;super&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#Traceback (most recent call last):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#  File &amp;#34;………………………….&amp;#34;, line 3, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#    c = a + b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#        ~~^~~&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#TypeError: can only concatenate str (not &amp;#34;int&amp;#34;) to str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Python est capable à la fois de savoir que &amp;ldquo;a&amp;rdquo; est une chaine de caractères à l&amp;rsquo;exécution (typage dynamique) mais reste pour autant capable d&amp;rsquo;interdire à l&amp;rsquo;exécution certaines opérations pour des raisons d&amp;rsquo;incompatibilité de type (d&amp;rsquo;où le &lt;code&gt;fort&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Il se trouve que depuis un certain nombre d&amp;rsquo;années, une nouvelle &amp;ldquo;mode&amp;rdquo; lié à des besoins de clarté et validation du code a poussé le monde python
tout comme celui d&amp;rsquo;autre langage dynamique à proposer des solutions pour permettre d&amp;rsquo;être plus explicite.&lt;/p&gt;
&lt;p&gt;En python, c&amp;rsquo;est la &lt;a href=&#34;https://peps.python.org/pep-0484/&#34;&gt;PEP 0484&lt;/a&gt; ajoutant les « annotations de type » dans Python.
Ces annotations ne changent rien à l&amp;rsquo;exécution du langage sauf que :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Elles permettent de documenter efficacement du code.&lt;/li&gt;
&lt;li&gt;Elles peuvent être vérifiées statiquement par des outils externes tels que &lt;a href=&#34;&#34;&gt;mypy&lt;/a&gt;, ou directement dans votre IDE préféré.&lt;/li&gt;
&lt;li&gt;Elles peuvent être vérifiées dynamiquement via des librairies de validation, c&amp;rsquo;est le cas de &lt;a href=&#34;&#34;&gt;Serpyco&lt;/a&gt; et de &lt;a href=&#34;&#34;&gt;Pydantic&lt;/a&gt; au contraire de &lt;a href=&#34;https://marshmallow.readthedocs.io/en/stable/&#34;&gt;Marshmallow&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bref, ces annotations peuvent nous rendre un fier service :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;En détectant des erreurs, avant l&amp;rsquo;exécution du code.&lt;/li&gt;
&lt;li&gt;En forçant à être plus explicite sur ce qu&amp;rsquo;on veut, si on s&amp;rsquo;oblige à les utiliser.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;avoir-des-types-plus-précis-&#34;&gt;Avoir des types plus précis ?&lt;/h2&gt;
&lt;p&gt;Avec tout cas, vient une idée. Comment avoir des types les plus précis possible afin de limiter au maximum les bugs ?
Les types en Python sont souvent avant tout une affaire de comportement, mais il arrive parfois qu&amp;rsquo;on aimerait être
un peu plus strict sur ce qu&amp;rsquo;on en attend d&amp;rsquo;eux : Valider une propriété supplémentaire, clarifier une certaine sémantique.&lt;/p&gt;
&lt;h2 id=&#34;méthodes&#34;&gt;Méthodes&lt;/h2&gt;
&lt;h3 id=&#34;1-commentaire&#34;&gt;1. Commentaire&lt;/h3&gt;
&lt;p&gt;La première solution consiste à utiliser les commentaires pour clarifier l&amp;rsquo;usage :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Simple à utiliser et à comprendre.&lt;/li&gt;
&lt;li&gt;✅ Utilisable pour tout : Sémantique/Contraintes à respecter&lt;/li&gt;
&lt;li&gt;❌ aucune validation statique possible.&lt;/li&gt;
&lt;li&gt;❌ aucune validation dynamique possible.&lt;/li&gt;
&lt;li&gt;⚠ La coloration syntaxique ne met pas forcément très en avant la documentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# variable:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# in seconds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# function:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    :param duration: in seconds
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    :return: nothing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2-programmation-par-contratassert&#34;&gt;2. Programmation par contrat(assert)&lt;/h3&gt;
&lt;p&gt;Une solution alternative pour définir des contraintes est la programmation par contrat, par exemple par l&amp;rsquo;usage d&amp;rsquo;assert.
À noter que des solutions plus complètes existent notamment la librairie &lt;a href=&#34;https://github.com/life4/deal&#34;&gt;deal&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Simple à utiliser et à comprendre.&lt;/li&gt;
&lt;li&gt;✅ Utilisable pour définir des contraintes à respecter&lt;/li&gt;
&lt;li&gt;✅ validation dynamique.&lt;/li&gt;
&lt;li&gt;❌ pas utilisable pour ajouter de la sémantique&lt;/li&gt;
&lt;li&gt;❌ aucune validation statique possible.&lt;/li&gt;
&lt;li&gt;⚠ Un peu trop dissocié de la définition de la variable à mon goût.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# function:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;3-annotated&#34;&gt;3. Annotated&lt;/h3&gt;
&lt;p&gt;Une solution, consiste à utiliser &lt;a href=&#34;https://docs.python.org/3/library/typing.html#typing.Annotated&#34;&gt;Annotated&lt;/a&gt;:
Une certaine &amp;ldquo;normalisation&amp;rdquo; de cas simple existe avec, la librairie &lt;code&gt;annotated_types&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Il est donc  possible de définir par exemple facilement si l&amp;rsquo;on veut :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Utilisable pour tout : Sémantique/Contraintes à respecter, mais bien plus adapté pour des contraintes à mon avis.&lt;/li&gt;
&lt;li&gt;❌ Très verbeux, et syntaxe redondante en cas de nombreuse utilisation.&lt;/li&gt;
&lt;li&gt;⚠ validation statique et dynamique envisageable si usage d&amp;rsquo;une syntaxe génériquement admise&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;annotated_types&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Annotated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;annotated_types&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Annotated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;annotated_types&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;4-alias-de-type&#34;&gt;4. Alias de type&lt;/h3&gt;
&lt;p&gt;Les alias de type sont une autre fonctionnalité envisageable :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Permet facilement de simplifier un type complexe.&lt;/li&gt;
&lt;li&gt;❌ Sémantiquement pas idéal pour définir une contrainte supplémentaire ni une distinction.&lt;/li&gt;
&lt;li&gt;❌ L&amp;rsquo;existence de 3 syntaxes différentes rend les choses un peu confuses.&lt;/li&gt;
&lt;li&gt;❌ validation statique et dynamique impossible :
&lt;ul&gt;
&lt;li&gt;pas de distinction de type réelle &lt;code&gt;PositiveInt = int&lt;/code&gt; et donc &lt;code&gt;int = PositiveInt&lt;/code&gt;, la validation ne vérifiera rien de pertinent.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isinstance&lt;/code&gt; ne fonctionne pas avec la syntaxe 3 utilisant &lt;code&gt;type&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TypeAlias&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# syntax 1: Implicit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# syntax 2: Explicit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TypeAlias&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# syntax 3 (python 3.12)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# type PositiveInt = int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;5-newtype&#34;&gt;5. NewType&lt;/h3&gt;
&lt;p&gt;Pour distinguer des types, il existe &lt;a href=&#34;&#34;&gt;NewType&lt;/a&gt;, une sorte de sous-classe fantôme.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Pratique pour éviter de mélanger des données sémantiquement différentes, mais de même type.&lt;/li&gt;
&lt;li&gt;✅ validation statique possible.&lt;/li&gt;
&lt;li&gt;⚠ Nommage à faire avec précaution comme pour les sous-classes, selon le cas, il peut être pertinent de cacher ou de rendre clairement
visible dans le nommage le type original. Attention à ne pas cacher le type original alors que l&amp;rsquo;utilisateur peut en avoir besoin.&lt;/li&gt;
&lt;li&gt;⚠ Un peu complexe d&amp;rsquo;utilisation, car pas un vrai type.&lt;/li&gt;
&lt;li&gt;❌ validation dynamique impossible (pas un vrai type, `isinstance non opérant).&lt;/li&gt;
&lt;li&gt;❌ ne permet pas d&amp;rsquo;ajouter des contraintes.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;SecondsInt&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;6-sous-classe&#34;&gt;6. Sous-classe&lt;/h3&gt;
&lt;p&gt;Une solution simple, mais efficace est tout simplement de créer des sous-classes spécifiques&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ facile à utiliser&lt;/li&gt;
&lt;li&gt;✅ utilisable pour à la fois de la sémantique et des contraintes de valeurs&lt;/li&gt;
&lt;li&gt;✅ validation statique et dynamique possible&lt;/li&gt;
&lt;li&gt;⚠ Potentiellement coûteux (vrai type)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;résumé&#34;&gt;Résumé&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;facile à l&amp;rsquo;usage&lt;/th&gt;
          &lt;th&gt;distinction sémantique&lt;/th&gt;
          &lt;th&gt;ajout de contraintes&lt;/th&gt;
          &lt;th&gt;validation statique&lt;/th&gt;
          &lt;th&gt;validation dynamique&lt;/th&gt;
          &lt;th&gt;simple à l&amp;rsquo;oeil&lt;/th&gt;
          &lt;th&gt;usage&lt;/th&gt;
          &lt;th&gt;coût en performance nul&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;commentaire&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;🆗&lt;/td&gt;
          &lt;td&gt;🆗&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;clarification&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;assertions&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;contraintes&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Annotated&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;🆗&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;contraintes&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;TypeAlias&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;simplification&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;NewType&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;distinction sémantique&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Sous-Classe&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;✅&lt;/td&gt;
          &lt;td&gt;Sémantique et contraintes&lt;/td&gt;
          &lt;td&gt;❌&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Il n&amp;rsquo;y a pas de solution parfaite, la solution idéale peut notamment être une combinaison de solutions.&lt;/p&gt;
&lt;p&gt;Voici quelque exemple concrêt et les solutions que j&amp;rsquo;utiliserais à ce jour:&lt;/p&gt;
&lt;h2 id=&#34;contrainte-sur-les-entiers&#34;&gt;Contrainte sur les entiers&lt;/h2&gt;
&lt;p&gt;Un cas simple est de vouloir un entier positif, une solution simple si vous utilisez pydantic pour d&amp;rsquo;autres raisons
et de récupérer le type &lt;code&gt;PositiveInt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# in pydantic.types&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;annotated_types&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Annotated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;annotated_types&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Gt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notons que dans le cas de l&amp;rsquo;implémentation de pydantic ce n&amp;rsquo;est pas un NewType, donc comme il n&amp;rsquo;est pas garanti que l&amp;rsquo;analyser
statique comprenne la contrainte supplémentaire, un code de la sorte peut être déclaré valide :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pydantic.types&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pydantic lui est capable de vérifier PositiveInt, mais seulement durant l&amp;rsquo;exécution du programme si on lui demande explicitement.&lt;/p&gt;
&lt;p&gt;Un autre cas similaire que j&amp;rsquo;ai eu était de trouver une solution pour représenter la contrainte d&amp;rsquo;un type Rust dans
du code python utilisant pyo3:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;annotated_types&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Interval&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Unsigned Int 8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;MAX_U8&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;MIN_U8&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;U8&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;U8&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Annotated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Interval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ge&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MIN_U8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;le&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MAX_U8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;id-de-type-existant-&#34;&gt;Id de type existant ?&lt;/h2&gt;
&lt;p&gt;Les identifiants sont un exemple de distinction sémantique de type sans nécessairement ajout de contrainte.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;exemple de &lt;code&gt;NewType&lt;/code&gt; dans la documentation officielle contient cela :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;UserId&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_user_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La fonction peut paraitre moyennement intéressante notamment par la redondance de &amp;ldquo;user_id&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est intéressant si vous déplacez beaucoup une valeur sans vous soucier détail de l&amp;rsquo;implémentation du contenu. Ce qui arrive souvent avec les identifiants.
En réduisant la surface de code utilisant les spécificités du type,
ont s&amp;rsquo;évite l&amp;rsquo;incompréhension (&amp;ldquo;UserId est de type int ou str ?&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Voici un exemple d&amp;rsquo;usage, que je pourrais avoir :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;dataclasses&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pydantic.types&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;UserId&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;RoomId&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;RoomId&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PositiveInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Room&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;room_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RoomId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;HTTPRequestData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_current_user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;user_id&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_current_room_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RoomId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RoomId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;room_id&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;DB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UserId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;User&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;select * from user where id = &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_room&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;room_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RoomId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Room&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Room&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;select * from room where id = &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;room_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;le-cas-des-unités-de-mesure&#34;&gt;Le cas des unités de mesure.&lt;/h2&gt;
&lt;p&gt;Un cas intéressant est celui des unités de mesure telle que la seconde ou encore le millimètre.
Les unités de mesure ont un sens et il existe toute une logique de conversion entre elles.
Ainsi des objets spécifiques, à l&amp;rsquo;aide de &lt;strong&gt;sous-classe&lt;/strong&gt; semble la solution le plus adaptés.
Il existe des librairies python à cet usage, tel que &lt;a href=&#34;https://github.com/hgrecco/pin&#34;&gt;pint&lt;/a&gt; ou encore &lt;a href=&#34;https://docs.astropy.org/en/stable/units/index.html&#34;&gt;astropy&lt;/a&gt;, mais n&amp;rsquo;en ayant testé aucun, je ne pourrais pas vous conseiller.&lt;/p&gt;
&lt;p&gt;Pour des cas plus simple. Les solutions que le privilégierait seraient NewType ou encore des commentaires :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NewType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;SecondsInt&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SecondsInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notons que contrairement aux identifiants, dans ce cas présent, je préfère être précis sur le type pour
plus de clarté.&lt;/p&gt;
&lt;p&gt;Cela dit selon votre cas, dans le cas précis de la durée de temps, il peut être plus pertinent d&amp;rsquo;utiliser timedelta :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;one_minute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;pour-conclure&#34;&gt;Pour Conclure&lt;/h2&gt;
&lt;p&gt;Difficile de conseiller un usage spécifique, bien que j&amp;rsquo;aime beaucoup Annotated, TypeAlias et NewType, ils ne conviennent
malheureusement pas à tous les cas d&amp;rsquo;usage. Je trouve néanmoins le combo NewType/Annotated intéressant, en espérant
que mypy et autre seront capable de gére les contraintes définies dans annotated_types dans un futur proche.&lt;/p&gt;
&lt;p&gt;Quant À TypeAlias, je reste plus que mitigé sur les cas d&amp;rsquo;usage pertinent :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si Le nom de type est trop court, l&amp;rsquo;intérêt est nul.&lt;/li&gt;
&lt;li&gt;Si on commence à utiliser des types complexes tel que &lt;code&gt;Dict[str, Union[int, float, str]]&lt;/code&gt;, ne faudrait-il pas considérer
sérieusement utiliser un type spécifique, un objet spécifique, ou peut-être un &lt;code&gt;TypedDict&lt;/code&gt; ?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;allez-plus-loin&#34;&gt;Allez plus loin :&lt;/h2&gt;
&lt;p&gt;Quelques ressources intéressantes sur le sujet que j&amp;rsquo;ai consulté :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://justincaustin.com/blog/python-typing-newtype/&#34;&gt;https://justincaustin.com/blog/python-typing-newtype/&lt;/a&gt; : Sur la différence NewType/TypeAlias.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.agest.am/phantom-types-in-python&#34;&gt;https://www.agest.am/phantom-types-in-python&lt;/a&gt; : Parle notamment de la librairie &lt;a href=&#34;https://github.com/antonagestam/phantom-types&#34;&gt;phantom-types&lt;/a&gt; qui propose un mécanisme de contrainte avec des types &amp;ldquo;fantômes&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Marshmallow est une librairie plus ancienne que l&amp;rsquo;instauration des annotations de type en Python, elle n&amp;rsquo;a pas
pu utiliser cette syntaxe&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/annotated-types/annotated-types/issues/33&#34;&gt;https://github.com/annotated-types/annotated-types/issues/33&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    <item>
      <title>📄 Comparaison visuelle de page web</title>
      <link>https://inkey-art.net/comparaison-visuelle-de-page-web/</link>
      <pubDate>Mon, 24 Jul 2023 13:05:10 +0200</pubDate>
      
      <guid>https://inkey-art.net/comparaison-visuelle-de-page-web/</guid>
      <description>&lt;p&gt;Une petite astuce utilisée lors de certains développements où je devais « debugger » l&amp;rsquo;apparence d&amp;rsquo;un front un peu complexe :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Obtenir une image de la page &lt;strong&gt;dans son entièreté&lt;/strong&gt;, firefox à la capacité de le faire naturellement au clic-droit.&lt;/li&gt;
&lt;li&gt;Utiliser &lt;a href=&#34;https://imagemagick.org/script/compare.php&#34;&gt;imagemagick&lt;/a&gt; pour faire un &lt;strong&gt;différentiel visuel des deux images&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cette méthode peut paraître un peu « lourde », mais permet de tester ce qui importe vraiment : &lt;strong&gt;le rendu&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;aller-plus-loin&#34;&gt;Aller plus loin&lt;/h3&gt;
&lt;p&gt;Un autre outil de comparaison intéressant à envisager pour des cas un peu différent (moins visuel et besoin d&amp;rsquo;exactitude sur les fichiers rendu) est &lt;a href=&#34;https://diffoscope.org/&#34;&gt;diffoscope&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🗂 Tirer parti de la déduplication de BTRFS: cas concret du versionnage</title>
      <link>https://inkey-art.net/tirer-parti-de-la-d%C3%A9duplication-de-btrfs-cas-concret-du-versionnage/</link>
      <pubDate>Sun, 23 Jul 2023 11:47:32 +0200</pubDate>
      
      <guid>https://inkey-art.net/tirer-parti-de-la-d%C3%A9duplication-de-btrfs-cas-concret-du-versionnage/</guid>
      <description>&lt;h2 id=&#34;le-problème&#34;&gt;Le problème&lt;/h2&gt;
&lt;p&gt;Il m&amp;rsquo;est arrivé à plusieurs reprises de travailler sur des projets utilisant la librairie python &lt;a href=&#34;https://pypi.org/project/filedepot/&#34;&gt;filedepot&lt;/a&gt;,
cette librairie est bien pratique pour gérer le stockage de fichier notamment en combinaison avec &lt;em&gt;Sqlalchemy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Un point qui ne reste néanmoins pas forcément évident à gérer par-dessus ce type de librairie est la question
du versionnage. Un cas que j&amp;rsquo;ai eu l&amp;rsquo;occasion de voir est le versionnage dans &lt;em&gt;Tracim&lt;/em&gt; ou un contenu à diverse révision
qui peuvent ou non avoir un contenu fichier associé différent.&lt;/p&gt;
&lt;p&gt;Le fonctionnement du champ &lt;code&gt;UploadedFileField&lt;/code&gt; proposé pour &lt;code&gt;Sqlalchemy&lt;/code&gt; par &lt;code&gt;filedepot&lt;/code&gt;, fonctionne de sorte à considérer
que le fichier est liée uniquement à une ligne de base de donnée et il peut être compliqué de tenter de partage un identifiant d&amp;rsquo;un même fichier entre divers
contenus, car par exemple, la suppression d&amp;rsquo;une ligne avec le contenu 1 supprimera le fichier associé, 2 pointant
vers le même contenu ne pourra plus y accéder.&lt;/p&gt;
&lt;p&gt;Comment alors éviter que pour une modification mineure non liée au fichier, que le fichier soit dupliqué inutilement consommant
ainsi de l&amp;rsquo;espace inutilement ?&lt;/p&gt;
&lt;p&gt;Je vois alors plusieurs approches :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Mettre cette intelligence de « versionnage » dans &lt;code&gt;filedepot&lt;/code&gt;, mais cela demanderait un gros travail.&lt;/li&gt;
&lt;li&gt;Mettre cette intelligence de « versionnage » dans l&amp;rsquo;application qui utilise filedepot notamment une table association entre l&amp;rsquo;identifiant du fichier pour l&amp;rsquo;application
et le champ. Ce qui réduirait un peu l&amp;rsquo;intérêt simplificateur de filedepot à mon sens.&lt;/li&gt;
&lt;li&gt;Créer une sorte de couche intermédiaire d&amp;rsquo;intelligence entre filedepot qui gère cela. Cela pourrait être aussi l&amp;rsquo;occasion
de gérer d&amp;rsquo;autres features lié au traitement du fichier : indexation, génération de preview, &amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Si la troisième solution me semble la plus intéressante a creusé, elle demande du temps à mettre en place.&lt;/p&gt;
&lt;p&gt;Ayant envie de gagner un peu d&amp;rsquo;espace disponible sur mon serveur utilisant &lt;code&gt;Tracim&lt;/code&gt;,
j&amp;rsquo;ai trouvé une solution de contournement à partir du fait que btrfs supporte la fonctionnalité de déduplication.&lt;/p&gt;
&lt;h2 id=&#34;la-déduplication-quézako-&#34;&gt;La Déduplication Quézako ?&lt;/h2&gt;
&lt;p&gt;La déduplication est une fonctionnalité de système de fichier qui permet à un système de fichier de dire qu&amp;rsquo;un certain
contenu utilisé par plusieurs fichiers est au même endroit. Ainsi, il est possible de copier via &lt;code&gt;cp --reflink=always&lt;/code&gt;
sans utiliser d&amp;rsquo;espace supplémentaire (sauf quelques meta-données).
Seul certain système de fichier supporte cette fonctionnalité dont &lt;em&gt;BTRFS&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;À noter que cette fonctionnalité &lt;a href=&#34;https://lists.gnu.org/archive/html/info-gnu/2021-09/msg00010.html&#34;&gt;est activé par default dans cp quand c&amp;rsquo;est possible à partir de coreutils-9.0&lt;/a&gt;.
Ainsi, si vous utilisez un simple &lt;code&gt;cp&lt;/code&gt; dans un &lt;em&gt;Gnu/Linux&lt;/em&gt; assez récent et utilisé un système de fichier comme btrfs, votre copie
sera gérer automatiquement intelligemment sans réelle copie.&lt;/p&gt;
&lt;h2 id=&#34;revenons-à-nos-moutons&#34;&gt;Revenons à nos moutons&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Mais du coup, qu&amp;rsquo;est-ce que ça change pour nous ?
Parce qu&amp;rsquo;on pourrait effectivement ajuster &lt;code&gt;filedepot&lt;/code&gt; pour faire de la copie via &lt;code&gt;reflink&lt;/code&gt;, mais il faudrait pour cela…
Qu&amp;rsquo;il soit conscient qu&amp;rsquo;il réalise une copie. Et donc on retombe dans une problématique de développement plus ou moins
complexe…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Oui … Sauf qu&amp;rsquo;il y a une astuce !&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Il est possible de réaliser la déduplication a posteriori, quand on considère que c&amp;rsquo;est nécessaire grâce à un outil
comme &lt;code&gt;Duperemove&lt;/code&gt;. Ainsi, il m&amp;rsquo;est possible de récupérer de l&amp;rsquo;espace disque sans avoir à me soucier de l&amp;rsquo;optimalité ou
non des solutions techniques de stockage utilisé par le logiciel utilisé.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;autre grosse force est que cela fonctionne pour tous les fichiers sans la moindre distinction. Ainsi peu importe si
la duplication est le fait d&amp;rsquo;un utilisateur qui aurait copié 2 fois le même fichier, d&amp;rsquo;un mécanisme de versionnage non intelligent,
ou simplement le hasard de 2 utilisateurs qui ne se connaissent même pas qui téléverse l&amp;rsquo;exacte, même contenu, la déduplication
s&amp;rsquo;effectuera.&lt;/p&gt;
&lt;p&gt;Voici un exemple, Avec un tracim 4.5 tout neuf en conteneur et son contenu dans un système btrfs tout propre dans un fichier (&lt;a href=&#34;https://unix.stackexchange.com/questions/368182/create-a-file-thats-treated-like-a-btrfs-file-system/368186#368186&#34;&gt;grâce à ce commentaire&lt;/a&gt;) :&lt;/p&gt;
&lt;p&gt;Ajout d&amp;rsquo;un 1 fichier un peu gros sur l&amp;rsquo;instance :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;df -h .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Filesystem      Size  Used Avail Use% Mounted on
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/dev/loop0        10G  219M  9,3G   3% /mnt/dsk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Création de 2 nouvelles révisions sans vraie modification du fichier :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Filesystem      Size  Used Avail Use% Mounted on
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/dev/loop0        10G  639M  8,9G   7% /mnt/dsk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s go la déduplication (en utilisant l&amp;rsquo;exemple de &lt;a href=&#34;https://wiki.tnonline.net/w/Btrfs/Deduplication/Duperemove)&#34;&gt;https://wiki.tnonline.net/w/Btrfs/Deduplication/Duperemove)&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;root@gnu:/mnt/dsk# chrt -i &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; duperemove -A -h -d -r -v -b128k --dedupe-options&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;noblock,same --lookup-extents&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;yes --io-threads&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; var/data/depot 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using 128K blocks
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using hash: murmur3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Gathering file list...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/2031c9c0-076e-11ee-9c12-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/2031c9c0-076e-11ee-9c12-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/2032025a-076e-11ee-9c12-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/2032025a-076e-11ee-9c12-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/cb00f218-076e-11ee-a461-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/cb00f218-076e-11ee-a461-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/cb0142b8-076e-11ee-a461-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/cb0142b8-076e-11ee-a461-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/e89f0f58-076e-11ee-827e-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/0f1a60a6-076f-11ee-a200-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skipping small file /mnt/dsk/var/data/depot/55639ca8-076f-11ee-a315-0242ac110002/metadata.json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; threads &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; file hashing phase
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;1/3&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;33.33%&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; csum: /mnt/dsk/var/data/depot/e89f0f58-076e-11ee-827e-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;2/3&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;66.67%&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; csum: /mnt/dsk/var/data/depot/0f1a60a6-076f-11ee-a200-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;3/3&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;100.00%&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; csum: /mnt/dsk/var/data/depot/55639ca8-076f-11ee-a315-0242ac110002/file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Total files:  &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Total extent hashes: &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Loading only duplicated hashes from hashfile.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Found &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; identical extents.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Simple &lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt; and compare of file data found &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; instances of extents that might benefit from deduplication.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Showing &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt; identical extents of length 209.8M with id 54f11aa1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Start		Filename
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0.0	&lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/e89f0f58-076e-11ee-827e-0242ac110002/file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0.0	&lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/0f1a60a6-076f-11ee-a200-0242ac110002/file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0.0	&lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/55639ca8-076f-11ee-a315-0242ac110002/file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; threads &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; dedupe phase
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0x56351b1f30c0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;1/1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; Try to dedupe extents with id 54f11aa1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0x56351b1f30c0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Add extent &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; file &lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/e89f0f58-076e-11ee-827e-0242ac110002/file&amp;#34;&lt;/span&gt; at offset 0.0 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;3&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0x56351b1f30c0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Add extent &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; file &lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/0f1a60a6-076f-11ee-a200-0242ac110002/file&amp;#34;&lt;/span&gt; at offset 0.0 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;4&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0x56351b1f30c0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Add extent &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; file &lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/55639ca8-076f-11ee-a315-0242ac110002/file&amp;#34;&lt;/span&gt; at offset 0.0 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;5&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0x56351b1f30c0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; Dedupe &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; extents &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;id: 54f11aa1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; with target: &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0.0, 209.8M&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, &lt;span class=&#34;s2&#34;&gt;&amp;#34;/mnt/dsk/var/data/depot/e89f0f58-076e-11ee-827e-0242ac110002/file&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Kernel processed data &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;excludes target files&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;: 419.5M
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Comparison of extent info shows a net change in shared extents of: 629.3M
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Après deduplication :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;df -h .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Filesystem      Size  Used Avail Use% Mounted on
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/dev/loop0        10G  219M  9,3G   3% /mnt/dsk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On a ainsi gagné pas moins de 419.5M !&lt;/p&gt;
&lt;p&gt;Autres points intéressant de &lt;code&gt;Duperemove&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vous n&amp;rsquo;utilisez pas btrfs ou voulez avoir une idée de l&amp;rsquo;espace gagné, il est possible de lancer duperemove en mode détection seulement.&lt;/li&gt;
&lt;li&gt;Changer la taille des blocs (&lt;code&gt;-b&lt;/code&gt;) permet de prendre en compte les fichiers plus petit, par exemple les preview dans
le cas de &lt;em&gt;Tracim&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Duperemove&lt;/code&gt; permet d&amp;rsquo;utiliser un hashfile qui évite de devoir recalculer les fichiers déjà lus,
attention néanmoins à la taille du &lt;a href=&#34;http://markfasheh.github.io/duperemove/duperemove.html#7&#34;&gt;hashfile&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;aller-plus-loin&#34;&gt;Aller plus loin&amp;hellip;&lt;/h2&gt;
&lt;p&gt;La solution &lt;code&gt;Duperemove&lt;/code&gt; se conjugue bien avec le fonctionnement de &lt;em&gt;Tracim&lt;/em&gt;, mais comment peut-on faire autrement ?
Quelles solutions les autres logiciels utilisent pour conserver un historique sans surcharger les disques ?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nextcloud&lt;/strong&gt; : De ce que je comprends de &lt;a href=&#34;https://docs.nextcloud.com/server/20/user_manual/fr/files/version_control.html&#34;&gt;l&amp;rsquo;approche de nextcloud&lt;/a&gt; sur ce genre de problématique, elle consiste à tenter de réduire le nombre de versions sauvegardées
ainsi le versionnage de nextcloud n&amp;rsquo;est à ce sens pas très fiable dans une logique d&amp;rsquo;archivage, une approche hybride à base de version par etiquette pour une gestion semi-automatique associé ou non ne sorte d&amp;rsquo;IA ou d&amp;rsquo;algorithme un peu malin pourrait faire l&amp;rsquo;affaire
afin de limiter les versions stockée tout en gardant l&amp;rsquo;essentiel de l&amp;rsquo;historique.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gestion de version&lt;/strong&gt; : L&amp;rsquo;approche des logiciels de gestion de versions comme &lt;em&gt;git&lt;/em&gt; est intéressante et est clairement optimale en espace de stockage pour du fichier texte. Elle permet réellement de l&amp;rsquo;archivage, de plus le principe de pouvoir associer
un texte à une modification commit, permet de s&amp;rsquo;y retrouvé facilement. Néanmoins l&amp;rsquo;approche ne se conjugue pas très bien avec du stockage de fichier binaire.&lt;/p&gt;
&lt;p&gt;Voili Voilà ! 😀&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🌈 Quelques Astuces de dessins</title>
      <link>https://inkey-art.net/quelques-astuces-de-dessins/</link>
      <pubDate>Sun, 23 Jul 2023 10:38:43 +0200</pubDate>
      
      <guid>https://inkey-art.net/quelques-astuces-de-dessins/</guid>
      <description>&lt;p&gt;J&amp;rsquo;aime beaucoup &lt;a href=&#34;https://dessin.inkey-art.net&#34;&gt;dessiner au crayon de couleurs&lt;/a&gt;.
Voici quelques petites de mes astuces.&lt;/p&gt;
&lt;video controls width=&#34;512&#34;&gt;
 &lt;source src=&#34;https://dessin.inkey-art.net/traditionnel/crayon-de-couleurs-et-aquarelles/crabe-x60.webm&#34; type=&#34;video/webm&#34;&gt;
&lt;/video&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&#34;https://dessin.inkey-art.net/traditionnel/crayon-de-couleurs-et-aquarelles/crabe-x60.webm&#34;&gt;timelapse d&amp;rsquo;un dessin de crabe&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;osez-mélanger-les-outils-médiums&#34;&gt;Osez mélanger les outils (médiums)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Mélanger les outils de dessin peut s&amp;rsquo;avérer très bénéfique&lt;/strong&gt; pour réussir au mieux à réaliser ce que vous souhaitez.
Ainsi pour ma part :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;J&amp;rsquo;aime beaucoup le crayon de couleurs pour faire &lt;strong&gt;les détails&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;J&amp;rsquo;aime beaucoup l&amp;rsquo;aquarelle ou les outils aquarellables pour &lt;strong&gt;faire des fonds&lt;/strong&gt; ou gérer des aplats non-uniforme.&lt;/li&gt;
&lt;li&gt;Pour redonner de la lumière en crayon de couleurs plusieurs options :
&lt;ul&gt;
&lt;li&gt;Pour une lumière légère, &lt;strong&gt;le crayon de couleurs blanc est votre ami&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pour un « sauvetage » de dessin, &lt;strong&gt;il faut mettre les grands moyens&lt;/strong&gt; : blanco ou feutre blanc bien opaque (par exemple: posca).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pourquoi pas des paillettes ? Le crayon graphite peut donner un &lt;strong&gt;effet réfléchissant métallique&lt;/strong&gt; à votre dessin.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;les-soins-intensifs-ça-paye-&#34;&gt;Les soins intensifs, ça paye !&lt;/h3&gt;
&lt;p&gt;N&amp;rsquo;étant pas super soigneux, il m&amp;rsquo;arrive bien souvent de rater des choses dans mes dessins. &lt;strong&gt;Il faut toujours donner
une seconde chance à son dessin&lt;/strong&gt; (ou du moins tenter), faire preuve d&amp;rsquo;un peu d&amp;rsquo;inventivité pour contourner le problème obtenu.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai ainsi sauvé nombre de créations.&lt;/p&gt;
&lt;p&gt;Certains médiums pardonnent plus que d&amp;rsquo;autres, je vous conseille d&amp;rsquo;utiliser les outils les plus adaptés à votre capacité à être soigneux et précis.&lt;/p&gt;
&lt;p&gt;Paradoxalement, il est souvent conseillé de s&amp;rsquo;entrainer sur des outils qui ne pardonnent pas pour apprendre à être juste, mais c&amp;rsquo;est un autre sujet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;cactus.jpg&#34; alt=&#34;Desert Cactus&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://dessin.inkey-art.net/traditionnel/crayon-de-couleurs-et-aquarelles/#1&#34;&gt;dessin de désert avec cactus au crayon de couleur sur fond noir&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;jouer-avec-les-modèles-utilisez-les-comme-tuteur&#34;&gt;Jouer avec les modèles, Utilisez les comme &lt;em&gt;tuteur&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;Il est bien plus facile de dessiner quelque-chose d&amp;rsquo;après modèle que de tête, néanmoins on ne veut pas toujours
reproduire, ainsi, une astuce intéressante est tout simplement de &lt;strong&gt;prendre un modèle comme tuteur&lt;/strong&gt;, rien ne vous interdit
de changer les couleurs, le fond, ainsi que certaines formes (changer un visage, un vêtement, etc.) de votre modèle lors
de votre dessin.&lt;/p&gt;
&lt;p&gt;Vous pouvez aussi faire &lt;strong&gt;une sorte de collage&lt;/strong&gt;, en prenant des reference à droite et à gauche et en les
insérant dans vos scènes.&lt;/p&gt;
&lt;p&gt;Enfin dans ce même ordre d&amp;rsquo;idée, une astuce que j&amp;rsquo;ai découverte grâce à &lt;a href=&#34;https://www.davidrevoy.com/article305/tons-of-potions-part-1-3d&#34;&gt;David Revoy&lt;/a&gt;, est le
fait qu&amp;rsquo;&lt;strong&gt;il est aussi possible de s&amp;rsquo;appuyer sur un rendu 3D pour avoir les bonnes proportions et perspectives&lt;/strong&gt;,
alors certes, je suis encore moins bon en rendu 3D qu&amp;rsquo;en dessin mais :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Réaliser des objets simples sur Blender en quelques clics de souris peut être suffisant&lt;/strong&gt; dans bien des cas pour me servir de modèle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Les rendus 3D sont bien plus facilement accessible aujourd&amp;rsquo;hui&lt;/strong&gt;, quelques pistes :
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Les jeux vidéos&lt;/strong&gt;. Pourquoi pas des captures d&amp;rsquo;écran de Minecraft ? &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Les logiciels d&amp;rsquo;aménagement d&amp;rsquo;intérieur&lt;/strong&gt; : Qui a dit &lt;a href=&#34;https://www.sweethome3d.com/fr/&#34;&gt;Sweet Home 3D&lt;/a&gt; ?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La photogrammétrie&lt;/strong&gt; est aujourd&amp;rsquo;hui accessible à tout le monde ou presque, plus besoin de créer des modèles, s&amp;rsquo;il existe en réalité!&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Les fichiers 3D existants&lt;/strong&gt;, on en trouve pléthore sur le net. Côté paysage, il a des données topographiques qu&amp;rsquo;il est possible de convertir ou d&amp;rsquo;obtenir sous forme de modèle 3D&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ce n&amp;rsquo;est qu&amp;rsquo;un principe général&lt;/strong&gt;, ne vous limitez pas dans vos types de modèle ni dans leur usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bref un modèle n&amp;rsquo;est pas forcément un rendu final à réaliser, ça peut être aussi bien un elements d&amp;rsquo;aide à la création, une sorte de tuteur.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;escargot.jpg&#34; alt=&#34;Escargot&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://dessin.inkey-art.net/traditionnel/crayon-de-couleurs-et-aquarelles/#5&#34;&gt;Escargot&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;jouer-avec-le-hasard-et-le-chaos-pour-linspiration&#34;&gt;Jouer avec le hasard et le chaos pour l&amp;rsquo;inspiration&lt;/h3&gt;
&lt;p&gt;Une source intéressante peut être d&amp;rsquo;utiliser le hasard ou du moins des procédés un peu chaotiques à l&amp;rsquo;image de Jackson Pollock.
C&amp;rsquo;est l&amp;rsquo;idée derrière le logiciel &lt;a href=&#34;http://al.chemy.org/&#34;&gt;Alchemy&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Le plus facile d&amp;rsquo;accès en opensource semble &lt;a href=&#34;https://fr.wikipedia.org/wiki/AliceVision_Meshroom&#34;&gt;Meshroom&lt;/a&gt;. L&amp;rsquo;IGN possède sa &lt;a href=&#34;https://github.com/micmacIGN/InterfaceCEREMA/tree/master&#34;&gt;propre suite&lt;/a&gt; en opensource, mais cela reste moins simple d&amp;rsquo;accès.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;L&amp;rsquo;IGN passe la France au &lt;a href=&#34;https://geoservices.ign.fr/lidarhd&#34;&gt;Lidar&lt;/a&gt;, c&amp;rsquo;est une nouvelle source de modèles 3D qui pourrait s&amp;rsquo;avérer très intéressante.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    <item>
      <title>📷 Mon process de gestion des photos</title>
      <link>https://inkey-art.net/mon-process-de-gestion-des-photos/</link>
      <pubDate>Sat, 22 Jul 2023 22:37:40 +0200</pubDate>
      
      <guid>https://inkey-art.net/mon-process-de-gestion-des-photos/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;J&amp;rsquo;aime beaucoup &lt;a href=&#34;https://photos.inkey-art.net&#34;&gt;prendre des photos&lt;/a&gt;, néanmoins, il n&amp;rsquo;est pas toujours aisé de gérés ces données ensuite.
En plus de 10 ans de photographie numérique, j&amp;rsquo;ai fait évoluer de nombreuses fois mon flux de travail afin de rendre celui-ci le plus fiable et efficace.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;mer-adriatique_925.jpg&#34; alt=&#34;Mer Adriatique&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://photos.inkey-art.net/europe/grece-2011/sur-la-route-de-la-grece/mer-adriatique/#4&#34;&gt;Mer Adriatique, 2011&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;lépineux-problème-des-sauvegardes-en-voyage&#34;&gt;L&amp;rsquo;épineux problème des sauvegardes en voyage&lt;/h3&gt;
&lt;p&gt;Perdre ses photos est une expérience qui peut être douloureuse. Elle m&amp;rsquo;est arrivé une fois en pleine mer adriatique, avec une carte SD m&amp;rsquo;ayant lâché à bord d&amp;rsquo;un ferry.
J&amp;rsquo;ai donc par la suite évalué/testé plusieurs solutions :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Carte SD plus fiable ?&lt;/strong&gt; Je ne connais pas l&amp;rsquo;évolution des procédés technique, mais je m&amp;rsquo;attache à prendre des modèles un minimum qualitatif, Samsung vendait pendant un temps des cartes SD se prétendant plus résistantes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiplications des cartes SD&lt;/strong&gt; : j&amp;rsquo;ai pendant un long moment utilisé un nombre important de cartes de petite taille afin de minimiser le nombre de données
perdu en cas de problème. Le coût des cartes micro-SD de grande capacité étant devenue ridiculement bon marché depuis lors, je n&amp;rsquo;ai pas continué cette méthode.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiplication des appareils&lt;/strong&gt; : involontairement depuis je suis passé à un fonctionnement à deux appareils photos, permettant facilement d&amp;rsquo;alterner des optiques sans risquer trop de problèmes de poussières sur le capteur. Deux appareils signifiant donc 2 cartes SD distinctes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Une sauvegarde sur l&amp;rsquo;appareil photo-même ?&lt;/strong&gt; Certain modèle d&amp;rsquo;appareil haut de gamme permettent effectivement la possibilité de mettre plusieurs cartes, néanmoins je n&amp;rsquo;ai pas le budget.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Une Copie intermédiaire ?&lt;/strong&gt; La solution la plus prometteuse étant d&amp;rsquo;avoir un dispositif de copie intermédiaire, il y a différentes options ;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;un ordinateur portable&lt;/strong&gt; : un peu volumineux, mais si vous en avez besoin, c&amp;rsquo;est le plus simple. On peut coupler ça facilement avec un logiciel pour synchro style &lt;em&gt;phockup&lt;/em&gt; (voir plus bas).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;une carte type raspberry-pi&lt;/strong&gt; avec un programme fait à cet effet, &lt;a href=&#34;https://github.com/outdoorbits/little-backup-box&#34;&gt;litte-backup-box&lt;/a&gt; propose une solution intéressante.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;via son smartphone ?&lt;/strong&gt; Une dernière piste a creusé serait une copie sur smartphone. Il faut un adaptateur usb, reste à savoir quels outils sont possibles pour la copie/synchro ?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;flam-myrdal_473.jpg&#34; alt=&#34;Myrdal&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://photos.inkey-art.net/europe/norvege-2014/rallarvegen/flam-myrdal/#9&#34;&gt;Myrdal, 2014&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;sauvegarde-long-terme&#34;&gt;Sauvegarde long-terme.&lt;/h3&gt;
&lt;p&gt;Ayant pu quelque-peu mitigé les questions des sauvegardes en voyage, il reste la question du stockage à plus long-terme.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai volontairement abandonné :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;les solutions à base de copie sur le cloud&lt;/strong&gt; pour des raisons de confiance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;les solutions de sauvegarde en mode synchronisation bidirectionnelle&lt;/strong&gt; comme &lt;em&gt;syncthing&lt;/em&gt;. Légèrement complexe et avec une gestion des conflits souvent un peu &lt;em&gt;auto-magique&lt;/em&gt;.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Les solutions à base d&amp;rsquo;&lt;em&gt;instantané&lt;/em&gt;&lt;/strong&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. Aussi un peu complexe.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;ai ainsi préféré un modèle très &lt;em&gt;linéaire&lt;/em&gt; et &lt;em&gt;simple&lt;/em&gt; avec des copies &lt;em&gt;pleine&lt;/em&gt; et &lt;em&gt;entière&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ma stratégie est devenue la suivante, une partie du processus n&amp;rsquo;est pas spécifique aux photos :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Stockage des photos via l&amp;rsquo;appareil sur de grandes cartes micro-sd&lt;/strong&gt; (avec adaptateur) dont le contenu n&amp;rsquo;est formaté que quand c&amp;rsquo;est vraiment nécessaire (ça fait une copie de plus au cas où).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stockage primaire sur un NAS&lt;/strong&gt; avec RAID 1 logiciel sans chiffrement sur la partie photos, car je préfère m&amp;rsquo;éviter de m&amp;rsquo;arracher les cheveux si quelque-chose se passe mal là-dessus, cela dit selon la sensibilité du contenu, la réflexion pourrait être amenée à changer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;disque de sauvegarde primaire&lt;/strong&gt; stockée à proximité du NAS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;disques de sauvegardes secondaires&lt;/strong&gt; avec dernière date de synchro noté et stocké à plusieurs endroits géographique (oui, je suis parano).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Quant aux étapes de synchronisations :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Synchronisation &lt;strong&gt;depuis les cartes SD vers le NAS&lt;/strong&gt; via le logiciel &lt;em&gt;phockup&lt;/em&gt; (voir plus loin).&lt;/li&gt;
&lt;li&gt;Synchronisation &lt;strong&gt;entre le NAS et le disque de sauvegarde&lt;/strong&gt; primaire via &lt;em&gt;rsync&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Synchronisation &lt;strong&gt;entre la sauvegarde primaire et les sauvegardes secondaires&lt;/strong&gt; via une &lt;em&gt;baie de disque avec duplicateur de disques&lt;/em&gt; : l&amp;rsquo;intérêt principal étant de ne pas avoir besoin d&amp;rsquo;ordinateur, &amp;ldquo;on lance et on oublie&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;test-noir-et-blanc_2069.jpg&#34; alt=&#34;Champ de lin&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://photos.inkey-art.net/divers/test-noir-et-blanc/#3&#34;&gt;Champ de lin, Noir et blanc, 2015&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;ajout-des-photos-automatisé&#34;&gt;Ajout des photos automatisé&lt;/h3&gt;
&lt;p&gt;Pour la synchro de photos sur mon nas, ayant décidé de ne plus vider systématiquement les cartes SD, j&amp;rsquo;avais du coup besoin d&amp;rsquo;une solution pour gérer plus facilement l&amp;rsquo;ajout des photos dans mon album sans copie, la solution s&amp;rsquo;appelle &lt;a href=&#34;https://github.com/ivandokov/phockup&#34;&gt;phockup&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mon NAS ayant directement un port pour carte micro-sd, je peux synchroniser de cette façon :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo mount /dev/mmcblk1p1  /mnt/sdcard/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;phockup /mnt/sdcard/DCIM/ /home/inkey/Images/Photos/ -y &lt;span class=&#34;c1&#34;&gt;# passage sans changement ou «dry-run»&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;phockup /mnt/sdcard/DCIM/ /home/inkey/Images/Photos/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo umount /dev/mmcblk1p1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Je n&amp;rsquo;ai (à l&amp;rsquo;époque de cet article) pas poussé l&amp;rsquo;automatisation jusqu&amp;rsquo;à lancer automatiquement phockup à la connexion de la carte, mais cela est possible. Il faudrait creuser un peu les possibilités de systemd&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h3 id=&#34;accéder-et-modifié-les-photos-&#34;&gt;Accéder et modifié les photos ?&lt;/h3&gt;
&lt;p&gt;Mon NAS étant ainsi la « source de vérité », il me faut un moyen de pouvoir aisément travailler dessus.
Une solution simple est tout simplement sshfs, ce n&amp;rsquo;est pas le protocole le plus performant, mais combiné avec
le mécanisme de &lt;a href=&#34;https://darktable.gitlab.io/doc/fr/local_copies.html&#34;&gt;copie-locale de &lt;em&gt;darktable&lt;/em&gt;&lt;/a&gt; cela fonctionne plutôt bien.&lt;/p&gt;
&lt;p&gt;Le type d&amp;rsquo;entrée &lt;em&gt;fstab&lt;/em&gt; que j&amp;rsquo;utilise :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshfs#me@mydomain.tld:/home/me/myphotofolder     /home/me/myphotofolder          fuse            port=22,user,noauto,noatime,_netdev     0 0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;napajiri_2117.jpg&#34; alt=&#34;Renne du Père-Noël&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://photos.inkey-art.net/europe/finlande-estonie-2022/rovaniemi-laponie/napajiri/#9&#34;&gt;Renne du Père-Noël, 2022&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;méthode-de-tri-des-photos&#34;&gt;Méthode de tri des photos&lt;/h3&gt;
&lt;p&gt;Trier mes plus de 36000 photos s&amp;rsquo;avère une tâche de prime abord, difficile. Je fais beaucoup de photos et il m&amp;rsquo;arrive parfois de revenir sur d&amp;rsquo;anciennes photos et d&amp;rsquo;y voir un potentiel jusqu&amp;rsquo;alors non-déceler. Ainsi dans mon processus, je ne supprime les photos que quand j&amp;rsquo;ai une vraie certitude qu&amp;rsquo;elles ont ratée, n&amp;rsquo;ayant pas de problème d&amp;rsquo;espace, je conserve ainsi un grand nombre de photos peu intéressant, mais elle reste trié par niveau de qualité.
J&amp;rsquo;utilise &lt;em&gt;Darktable&lt;/em&gt; pour réaliser ce traitement.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;darktable/notations.png&#34; alt=&#34;Intervalle de notation de Darktable&#34;&gt; : Les différentes notations de &lt;em&gt;Darktable&lt;/em&gt; : rejeté, sans étoile, 1 à 5 étoiles.&lt;/p&gt;
&lt;p&gt;Ma stratégie de tri est une sorte d&amp;rsquo;&lt;strong&gt;algorithme&lt;/strong&gt;. Il faut se donner un vague critère pour chaque passage à une étoile supérieure ensuite :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on trie tout et on marque les images comme &lt;strong&gt;rejetés&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;on trie les images non rejetées et on marque la &lt;strong&gt;1ére étoile&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;on trie les images de la 1ére étoile et on marque &lt;strong&gt;la 2de étoile&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;on trie les images de la seconde étoile et on marque &lt;strong&gt;la 3ᵉ étoile&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;… idem jusqu&amp;rsquo;à &lt;strong&gt;la 5ᵉ étoile&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Un cas à décider un peu particulier est celui des images trop similaires, il faut décider à quel niveau on prend la décision de ne plus les classer et choisir la meilleure par comparaisons. &lt;strong&gt;Darktable&lt;/strong&gt; permettant facilement de comparer 2 ou 3 images facilement.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;kathmandou_1549.jpg&#34; alt=&#34;Soirée à Thamel, 2016&#34;&gt;
&lt;em&gt;&lt;a href=&#34;https://photos.inkey-art.net/asie/nepal-hiver-2018-2019/vallee-de-kathmandou/kathmandou/#9&#34;&gt;Soirée à Thamel, 2016&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Pour gérer des modifications bidirectionnelles, je préfère &lt;a href=&#34;https://fr.wikipedia.org/wiki/Unison_(logiciel)&#34;&gt;unison&lt;/a&gt;, qui oblige à être explicite.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;ou &lt;em&gt;snapshot&lt;/em&gt;, voir &lt;a href=&#34;https://fr.wikipedia.org/wiki/Instantan%C3%A9_(informatique)&#34;&gt;ici&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Edit (Février 2024): L&amp;rsquo;automatisation est chose faite, lire &lt;a href=&#34;https://inkey-art.net/sauvegarde-au-branchement-avec-systemd-photos/&#34;&gt;cet article plus récent&lt;/a&gt;,&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    <item>
      <title>💚 Pourquoi j&#39;aime l&#39;Ésperanto… | 💚 Kial mi ŝatas Esperanton…</title>
      <link>https://inkey-art.net/pourquoi-jaime-l%C3%A9speranto-kial-mi-%C5%9Datas-esperanton/</link>
      <pubDate>Sat, 22 Jul 2023 12:09:43 +0200</pubDate>
      
      <guid>https://inkey-art.net/pourquoi-jaime-l%C3%A9speranto-kial-mi-%C5%9Datas-esperanton/</guid>
      <description>&lt;p&gt;J&amp;rsquo;apprends comme passe-temps la langue &lt;a href=&#34;https://fr.wikipedia.org/wiki/Esp%C3%A9ranto&#34;&gt;Éspéranto&lt;/a&gt; via Duolingo, c&amp;rsquo;est une langue étrange :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;construite par &lt;a href=&#34;https://fr.wikipedia.org/wiki/Louis-Lazare_Zamenhof&#34;&gt;Louis-Lazare Zamenhof&lt;/a&gt; en 1887.&lt;/li&gt;
&lt;li&gt;mélange de plusieurs langues tout en ayant ses propres particularités&lt;/li&gt;
&lt;li&gt;voulu comme une langue internationale dès le début.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Elle est très simple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Une lettre = un son.&lt;/li&gt;
&lt;li&gt;Des règles simples.&lt;/li&gt;
&lt;li&gt;Un fonctionnement extrêmement logique.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce qui est amusant d&amp;rsquo;un point de vue d&amp;rsquo;ingénieur, c&amp;rsquo;est de voir les compromis fait par la langue, ainsi
certains mots ont été pioché dans diverses langues avec des choix parfois difficile, entre simplicité et
expressivité.&lt;/p&gt;
&lt;p&gt;Une chose réellement étonnante est l&amp;rsquo;expressivité possible dans le langage son caractère très logique permet
bien plus facilement que dans la plupart des langues de jouer avec les mots, de comprendre toute ou partie du sens d&amp;rsquo;un nouveau
mot et bien d&amp;rsquo;autres choses tout étant peu expérimenté dans le langage. Pour ma part, cela fait, à l&amp;rsquo;heure de cet
article, à peine trois mois que j&amp;rsquo;apprends l&amp;rsquo;Esperanto de façon non intensive et j&amp;rsquo;ai déjà l&amp;rsquo;impression d&amp;rsquo;une certaine maîtrise.&lt;/p&gt;
&lt;p&gt;Les seuls points que je trouve légèrement compliqué en tant que Français au début sont :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La marque de l&amp;rsquo;accusatif que j&amp;rsquo;ai toujours un peu de mal&lt;/li&gt;
&lt;li&gt;Les corrélatifs et tous les petits mots qu&amp;rsquo;il ne m&amp;rsquo;est pas possible de deviner.&lt;/li&gt;
&lt;li&gt;Les cas ou l&amp;rsquo;Esperanto est plus précis que le français et donc ou il n&amp;rsquo;est pas facile de savoir quand/pourquoi utiliser les mots, tel quel les participes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le reste, étant vraiment simple, il faut pratiquer un peu et apprendre du vocabulaire.
Comme dise les Anglais « practice makes perfect » ou plutôt dans notre cas « ekzercado lertigas ».&lt;/p&gt;
&lt;p&gt;Si vous voulez apprendre l&amp;rsquo;Esperanto en ligne, je vous conseille &lt;a href=&#34;https://www.duolingo.com&#34;&gt;Duolingo&lt;/a&gt; et &lt;a href=&#34;https://lernu.net/&#34;&gt;Lernu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gîs la revido ! 👋&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🎮 Créer un jeu de Morpion en ligne : partie 1. Mécanique de Jeu et Rust</title>
      <link>https://inkey-art.net/cr%C3%A9er-un-jeu-de-morpion-en-ligne-partie-1.-m%C3%A9canique-de-jeu-et-rust/</link>
      <pubDate>Fri, 21 Jul 2023 13:05:10 +0200</pubDate>
      
      <guid>https://inkey-art.net/cr%C3%A9er-un-jeu-de-morpion-en-ligne-partie-1.-m%C3%A9canique-de-jeu-et-rust/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Dans le but d&amp;rsquo;apprendre le rust et d&amp;rsquo;autres technologies en m&amp;rsquo;amusant.
J&amp;rsquo;ai décidé de commencer un &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/morpion&#34;&gt;projet de jeux de morpion en rust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;À l&amp;rsquo;instar des &lt;a href=&#34;https://inkey-art.net/mes-g%C3%A9n%C3%A9rateurs-davatars/&#34;&gt;générateurs d&amp;rsquo;avatars&lt;/a&gt;, c&amp;rsquo;est un projet d&amp;rsquo;exploration qui ne va pas droit au but, mais
sert de fil conducteurs à divers problèmes et technologie que j&amp;rsquo;ai envie de tester dans des cas
un minimum réels.&lt;/p&gt;
&lt;h3 id=&#34;les-règles-du-jeu&#34;&gt;Les règles du jeu :&lt;/h3&gt;
&lt;p&gt;Si les jeux de base du &lt;a href=&#34;https://fr.wikipedia.org/wiki/Gomoku&#34;&gt;Gomoku&lt;/a&gt; se fait sur un pavage de 15x15 elements et le gagnant
gagne lors d&amp;rsquo;un 5 à la suite, j&amp;rsquo;envisage que les briques de mon jeu puissent me permettre
un peu de souplesse :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nombre de joueurs possible entre 2 et 10.&lt;/li&gt;
&lt;li&gt;Taille du plateau variable.&lt;/li&gt;
&lt;li&gt;Nombre de coups pour gagner variable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;D&amp;rsquo;autres évolutions sont envisageables :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;variante avec besoin de n fois la suite pour gagner, peut-être jusqu&amp;rsquo;à que la grille soit complête ?&lt;/li&gt;
&lt;li&gt;variante sans gestion de tours.&lt;/li&gt;
&lt;li&gt;etc…&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;poc-rust&#34;&gt;Poc Rust:&lt;/h2&gt;
&lt;p&gt;Pour mon projet, mon idée est de pouvoir me baser sur des 🧱 briques assez génériques pour pouvoir implémenter plein
de variantes facilement.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai ainsi réalisé 2 classes de base :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MorpionBoard&lt;/strong&gt; : le plateau de jeu qui:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;garde le plateau en mémoire.&lt;/li&gt;
&lt;li&gt;contrôle la validité des coups.&lt;/li&gt;
&lt;li&gt;calcule si le jeu est gagné.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Turn&lt;/strong&gt; : Une surcouche d&amp;rsquo;un vecteur permettant d&amp;rsquo;itérer sur les identifiants de joueurs en boucle.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;ai aussi pas mal joué avec les &lt;em&gt;traits&lt;/em&gt; et la &lt;em&gt;généricité&lt;/em&gt; de Rust, c&amp;rsquo;est super agréable d&amp;rsquo;avoir autant de liberté là-dessus,
reste à savoir jusqu&amp;rsquo;où pousser le curseur, en particulier dans un projet perso. On a vite fait de vouloir rendre tout
générique sans cas d&amp;rsquo;usage pertinent derrière.&lt;/p&gt;
&lt;h2 id=&#34;vérifier-la-victoire-&#34;&gt;Vérifier la victoire ?&lt;/h2&gt;
&lt;p&gt;Il existe divers moyens de vérifier la victoire pour un tel jeu, mais j&amp;rsquo;ai trouvé une optimisation particulièrement efficace,
je cherche les segments de n éléments contenant la dernière position jouée, ainsi, je limite ainsi énormément l&amp;rsquo;espace parcouru :&lt;/p&gt;
&lt;p&gt;Je les cherche donc pour chaque direction&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;check_win&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Dimension&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;u8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;HORIZONTAL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;VERTICAL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;DIAG_UP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;DIAG_DOWN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et je cherche pour chaque sens de ces directions le nombre d&amp;rsquo;éléments consécutifs, auquel j&amp;rsquo;ajoute l&amp;rsquo;élément
d&amp;rsquo;origine.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;count_consecutive_in_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Dimension&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;u8&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;count_consecutive_in_way&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;count_consecutive_in_way&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ainsi si j&amp;rsquo;obtiens pour une direction, une longueur égale ou supérieure à la valeur pour gagner, je sais donc que
le dernier coup a été gagnant.&lt;/p&gt;
&lt;p&gt;Ce mécanisme est très efficace.&lt;/p&gt;
&lt;h3 id=&#34;tentative-de-parallélisme&#34;&gt;Tentative de parallélisme&lt;/h3&gt;
&lt;p&gt;Par ailleurs, pour m&amp;rsquo;amuser&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, j&amp;rsquo;ai tenté d&amp;rsquo;aller encore plus loin à l&amp;rsquo;aide des &lt;a href=&#34;https://doc.rust-lang.org/std/thread/fn.scope.html&#34;&gt;scoped threads&lt;/a&gt; de Rust. L&amp;rsquo;idée est
de séparer le travail en plusieurs tâches réalisé séparément, si possible en parallèle grâce à l&amp;rsquo;existence de plusieurs cœurs
sur la machine :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;check_win_multiple_core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Dimension&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;u8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;du&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;thread&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;scope&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spawn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;HORIZONTAL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spawn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;VERTICAL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spawn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;du&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;DIAG_UP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spawn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;check_win_direction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;DIAG_DOWN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;winning_row_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;du&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Mais il s&amp;rsquo;avère que cette solution qui divise le travail en 4 calculs n&amp;rsquo;est pas optimal du tout. Après un test rapide avec
&lt;a href=&#34;https://github.com/bheisler/criterion.rs&#34;&gt;criterion&lt;/a&gt;, le temps explose (ça reste très court cependant).&lt;/p&gt;
&lt;p&gt;En effet, le coût de création des threads est beaucoup trop grand par rapport au coût du parcours de quelques
éléments dans chaque direction. Pour que ça soit intéressant, il faudrait donc beaucoup plus d&amp;rsquo;éléments à parcourir d&amp;rsquo;une
part, mais probablement aussi de quoi pouvoir arrêter les threads dès que l&amp;rsquo;un d&amp;rsquo;entre a fini le travail, une sorte
de « ou optimisé en multicœur » en quelque-sorte.&lt;/p&gt;
&lt;p&gt;La mécanique de scoped threads reste néanmoins super intéressante et facile à mettre en place, il me manque juste une
bonne raison de l&amp;rsquo;utiliser.&lt;/p&gt;
&lt;h2 id=&#34;gestion-des-chaînes-de-caractères&#34;&gt;Gestion des chaînes de caractères&lt;/h2&gt;
&lt;p&gt;La gestion des chaînes de caractères en rust s&amp;rsquo;avère un peu difficile provenant du python.
Il est ainsi impossible d&amp;rsquo;avoir des constantes facilement pour le modèle du format des chaînes avec la macro &lt;em&gt;println!&lt;/em&gt;
car le 1er paramètre est nécessairement une valeur littérale :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mon_text&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;🌷&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pattern&lt;/span&gt;: &lt;span class=&#34;kp&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;--{}--&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;--&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;--&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;🍓&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// --🍓--
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;--&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;--&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mon_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// --🌷--
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pattern&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mon_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// error: format argument must be a string literal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Je ne trouve pas cela super souple.
Après un peu de recherche, j&amp;rsquo;ai finalement contourné pour partie le problème avec une solution, plus complexe, mais plus générique : l&amp;rsquo;&lt;strong&gt;internationalisation&lt;/strong&gt;
via &lt;a href=&#34;https://projectfluent.org/&#34;&gt;fluent&lt;/a&gt;, avec les packages &lt;code&gt;i18n-embed&lt;/code&gt; et &lt;code&gt;i18n-embed-fl&lt;/code&gt; ainsi un peu de code, on peut arriver à faire des choses comme ça :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/i18n/fr/morpion.ftl&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-fluent&#34; data-lang=&#34;fluent&#34;&gt;game-title = Jeu de Morpion
user-turn = Tour du joueur {$name} utilisant le symbole &amp;#39;{$p_char}&amp;#39;:
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;/i18n/eo/morpion.ftl&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-fluent&#34; data-lang=&#34;fluent&#34;&gt;game-title = Ludo de Morpion
user-turn = Vico de la ludanto {$name} kun la simbolo &amp;#39;{$p_char}&amp;#39;:
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;/src/main.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;fl!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;game-title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;println!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;fl!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;user-turn&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;players_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;names&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;player_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p_char&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;format!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;players_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;player_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce n&amp;rsquo;est pas encore parfait (je n&amp;rsquo;aime pas trop les « {} »), mais c&amp;rsquo;est déjà plus pratique, et j&amp;rsquo;ai obtenu, d&amp;rsquo;une pierre, deux coups :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;un mécanisme assez souple pour gérer des chaînes de caractères permettant de séparer un peu le code des jeux, du texte utilisé dans le jeu.&lt;/li&gt;
&lt;li&gt;la possibilité de gérer différentes langues. Dans mon cas, le français, l&amp;rsquo;&lt;a href=&#34;https://inkey-art.net/pourquoi-jaime-l%C3%A9speranto-kial-mi-%C5%9Datas-esperanton/&#34;&gt;espéranto&lt;/a&gt; et l&amp;rsquo;anglais.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;interface-cli&#34;&gt;Interface CLI&lt;/h2&gt;
&lt;p&gt;La première version du projet est toute simple en ligne de commande&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; :&lt;/p&gt;
&lt;video controls width=&#34;512&#34;&gt;
 &lt;source src=&#34;morpion/version_terminal.webm&#34; type=&#34;video/webm&#34;&gt;
&lt;/video&gt;
&lt;p&gt;À suivre…&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;attention, je parle là bien de la &lt;a href=&#34;https://fr.wikipedia.org/wiki/Direction_(g%C3%A9om%C3%A9trie)&#34;&gt;direction&lt;/a&gt;, pas du sens.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Si vous êtes sur des choses un peu sérieuses, éviter ce genre d&amp;rsquo;approche d&amp;rsquo;optimisation préventive, c&amp;rsquo;est la meilleure façon de
perdre du temps sans gagner en performance. Les optimisations sont un sujet sérieux qui doit être réfléchis.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;C&amp;rsquo;est une logique de développement que j&amp;rsquo;ai déjà utilisé pour mon &lt;a href=&#34;https://framagit.org/inkhey_projects/misc/Serpent&#34;&gt;vieux jeu de serpent 🐍&lt;/a&gt; où j&amp;rsquo;ai
d&amp;rsquo;abord réalisé une version ligne de commande peu interactive puis une version ncurse et enfin une version pygame.
Le but étant d&amp;rsquo;apprendre séparément la mécanique de jeu
et la question du moteur. Si vous envisagez de faire des jeux un peu plus sérieux, je ne peux que vous conseiller d&amp;rsquo;utiliser un vrai moteur, tel que &lt;a href=&#34;https://godotengine.org/&#34;&gt;Godot&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🐦 Mes Générateurs d&#39;avatars</title>
      <link>https://inkey-art.net/mes-g%C3%A9n%C3%A9rateurs-davatars/</link>
      <pubDate>Fri, 21 Jul 2023 13:05:10 +0200</pubDate>
      
      <guid>https://inkey-art.net/mes-g%C3%A9n%C3%A9rateurs-davatars/</guid>
      <description>&lt;p&gt;David Revoy, Génial illustrateur de Peeper and Carrot, a lancé avec &lt;a href=&#34;https://www.davidrevoy.com/article590/my-fight-against-cdn-libraries&#34;&gt;cet article&lt;/a&gt;
une flopée d&amp;rsquo;implémentations de générateurs d&amp;rsquo;avatars dans divers langages.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai pour ma part réalisé deux implémentations :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://framagit.org/inkhey_projects/avatar_generator/pioupiou&#34;&gt;Pioupiou&lt;/a&gt;, langage &lt;em&gt;Python&lt;/em&gt; en 2021.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://framagit.org/inkhey_projects/avatar_generator/roucoule&#34;&gt;Roucoule&lt;/a&gt;, langage &lt;em&gt;Rust&lt;/em&gt; en 2023.&lt;/li&gt;
&lt;li&gt;…&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le principe de ce type de génération d&amp;rsquo;avatar en mode &amp;ldquo;sandwich&amp;rdquo;🥪 est très simple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;vous donnez une chaîne de caractère en entrée.&lt;/li&gt;
&lt;li&gt;le programme va décider pour chaque couche de l&amp;rsquo;avatar quel &amp;ldquo;ingrédient&amp;rdquo; prendre à partir de la chaîne donnée.
&lt;ul&gt;
&lt;li&gt;les couches correspondront à des éléments de l&amp;rsquo;image qui seront ensuite appliqué les un sur les autres afin de générer un avatar pseudo-aléatoire&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;avatar/bird.png&#34; alt=&#34;Avatar généré couche par couche&#34;&gt;&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;intérêt de ces projets pour moi est multiple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apprendre plus sur les spécificités du langage.&lt;/li&gt;
&lt;li&gt;Apprendre à faire une librairie &amp;ldquo;propre&amp;rdquo; en mode &amp;ldquo;état de l&amp;rsquo;art&amp;rdquo; en matière d&amp;rsquo;outillage : packaging, CI, linting, etc.&lt;/li&gt;
&lt;li&gt;Servir de point de repère &amp;ldquo;bonne pratique&amp;rdquo; pour les prochains projets notamment, car cela reste des projets assez petits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;N&amp;rsquo;hésitez pas à utiliser ces librairies/y jetez un coup d&amp;rsquo;œil ! 😀&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Une implémentation en &lt;a href=&#34;https://elixir-lang.org/&#34;&gt;Elixir&lt;/a&gt; me plairait bien pour apprendre ce langage.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;le nombre de résultats possible étant
restreint et l&amp;rsquo;algorithme volontairement déterministe pour une entrée donnée, ce n&amp;rsquo;est pas du vrai hasard.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    <item>
      <title>👨‍💻 Quelques utilitaires Gnu/Linux pratiques</title>
      <link>https://inkey-art.net/quelques-utilitaires-gnu/linux-pratiques/</link>
      <pubDate>Mon, 01 May 2023 16:25:45 +0200</pubDate>
      
      <guid>https://inkey-art.net/quelques-utilitaires-gnu/linux-pratiques/</guid>
      <description>&lt;p&gt;Voici quelques utilitaires linux bien pratiques que je me permets de vous présenter brièvement.&lt;/p&gt;
&lt;h3 id=&#34;sftp&#34;&gt;SFTP&lt;/h3&gt;
&lt;p&gt;Compris avec ssh, je trouve sftp particulièrement pratique pour déplacer des fichiers rapidement,
l&amp;rsquo;idée est la suivante :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vous initiez une session sur la machine hôte depuis un répertoire A&lt;/li&gt;
&lt;li&gt;Vous vous déplacez jusqu&amp;rsquo;à un répertoire B à l&amp;rsquo;aide de cd dans la session sftp interactive&lt;/li&gt;
&lt;li&gt;Vous utilisez une des différentes commandes disponibles, les plus communes étant
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;put&lt;/code&gt; pour envoyer depuis A vers B&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get&lt;/code&gt; pour récupérer depuis B vers A&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;il est aussi possible de modifier le répertoire local A à l&amp;rsquo;aide de &lt;code&gt;lls&lt;/code&gt; et de &lt;code&gt;lcd&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bien évidemment l&amp;rsquo;autocomplétion fonctionne, ce qui permet de déplacer efficacement des fichiers à la fois
sans devoir se prendre la tête sur la connaissance des chemins et sans interface graphique.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;cli/sftp.gif&#34; alt=&#34;SFTP en fonctionnement&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;htop&#34;&gt;Htop&lt;/h3&gt;
&lt;p&gt;On ne le présente plus, un bon moniteur de processus, avec
des fonctionnalités de filtrage bien pratique.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;cli/htop.gif&#34; alt=&#34;Htop en fonctionnement&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;ip&#34;&gt;IP&lt;/h3&gt;
&lt;p&gt;Classique de chez classique, pour récupérer les addresses IP de la machine
sans se faire déborder d&amp;rsquo;informations, j&amp;rsquo;utilise ces
paramètres la plupart du temps pour ip (paquet debian iproute2):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;root@867aa82abc92:/# ip -br -c a
&lt;font color=&#34;#06989A&#34;&gt;lo               &lt;/font&gt;UNKNOWN        &lt;font color=&#34;#75507B&#34;&gt;127.0.0.1&lt;/font&gt;/8 &lt;font color=&#34;#3465A4&#34;&gt;::1&lt;/font&gt;/128 
&lt;font color=&#34;#06989A&#34;&gt;tap0             &lt;/font&gt;UNKNOWN        &lt;font color=&#34;#75507B&#34;&gt;10.0.2.100&lt;/font&gt;/24 &lt;font color=&#34;#3465A4&#34;&gt;fe80::4c28:c3ff:fe98:5b16&lt;/font&gt;/64 
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;xkill&#34;&gt;Xkill&lt;/h3&gt;
&lt;p&gt;Pour X11 seulement, je ne sais trop ce qu&amp;rsquo;il en est sur Wayland.
La commande xkill peut s&amp;rsquo;avérer utile pour tuer une fenêtre gelée via la souris en
transformant le pointeur en une sorte de fusil pour processus.😀&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;cli/xkill.gif&#34; alt=&#34;Xkill en fonctionnement&#34;&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🕸 Tracim sur mon NAS, partie 3: Frontal Nginx</title>
      <link>https://inkey-art.net/tracim-sur-mon-nas-partie-3-frontal-nginx/</link>
      <pubDate>Sun, 30 Apr 2023 18:30:23 +0200</pubDate>
      
      <guid>https://inkey-art.net/tracim-sur-mon-nas-partie-3-frontal-nginx/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Le service tracim tourne, mais n&amp;rsquo;est pas accessible. En effet, lors de la dernière configuration, nous avons opté pour
l&amp;rsquo;accessibilité que localement sur la machine sur le port 7070. De plus, pour une raison de sécurité, il nous faut
un accès en https.&lt;/p&gt;
&lt;h3 id=&#34;exemple-de-configuration-nginx-frontal-pour-limage-docker-de-tracim-&#34;&gt;Exemple de configuration nginx frontal pour l&amp;rsquo;image docker de tracim :&lt;/h3&gt;
&lt;p&gt;Voici un exemple de ce à quoi peut ressembler un reverse-proxy pour Tracim dans nginx, à noter quelques points :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;j&amp;rsquo;ai volontairement mis la configuration ssl utilisé dans un fichier &lt;code&gt;common.conf&lt;/code&gt; à part.&lt;/li&gt;
&lt;li&gt;Vous devez bien évidemment ajuster la configuration dns comme il faut pour que votre nom de domaine pointe sur le serveur.&lt;/li&gt;
&lt;li&gt;j&amp;rsquo;ai activé http2 et l&amp;rsquo;ipv6 sur la partie &lt;code&gt;nginx-internet&lt;/code&gt;, notez cependant que le canal &lt;code&gt;tracim-nginx&lt;/code&gt; est en http 1.1 sans ssl et que le buffering du proxy est désactivé, car il produit des dysfonctionnements (utilisation des SSE par Tracim).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;etcnginxsite-availabletracim-&#34;&gt;/etc/nginx/site-available/tracim :&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;upstream&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;tracim_local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;127.0.0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;7070&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kn&#34;&gt;listen&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;443&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http2&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;ssl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kn&#34;&gt;listen&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;[::]:443&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http2&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;ssl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kn&#34;&gt;server_name&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;mysuperwebsite.net&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kn&#34;&gt;include&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;common.conf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kn&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;client_max_body_size&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;300M&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;include&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;proxy_params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;proxy_pass&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;http://tracim_local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;proxy_http_version&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Connection&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;proxy_buffering&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;etcnginxproxy_params&#34;&gt;/etc/nginx/proxy_params:&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;Host&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$http_host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;X-Real-IP&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$remote_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;X-Forwarded-For&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$scheme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;exemple-minimal-de-etcnginxcommonconf&#34;&gt;Exemple minimal de /etc/nginx/common.conf&lt;/h4&gt;
&lt;p&gt;Pour la configuration Nginx du ssl, je vous conseille de la &lt;a href=&#34;https://www.ssllabs.com/ssltest/&#34;&gt;tester&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;ssl_certificate&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/path/vers/moncertif/mysuperwebsite.net/fullchain.pem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/path/vers/moncertif/mysuperwebsite.net/key.pem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## Je vous conseille de vous intéresser aux autres paramètrages de ssl de nginx
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## ainsi qu&amp;#39;au HTTP Strict Transport Security
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour la génération des certificats, une solution simple si vous n&amp;rsquo;avez pas de contrainte complexe est d&amp;rsquo;utiliser Let&amp;rsquo;s Encrypt en mode DNS. &lt;a href=&#34;https://github.com/acmesh-official/acme.sh/wiki/dnsapi&#34;&gt;Je le conseille avec ACME.sh&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;activation-et-utilisation-de-tracim&#34;&gt;Activation et utilisation de tracim&lt;/h3&gt;
&lt;p&gt;Si tout est ok, vous pouvez maintenant activer votre reverse-proxy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo ln -s /etc/nginx/sites-available/tracim /etc/nginx/sites-enabled/tracim
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nginx -t
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl nginx reload
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Et voilà ! un Tracim fonctionnel via Nginx et Podman !&lt;/p&gt;
&lt;h1 id=&#34;heading&#34;&gt;🥳&lt;/h1&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🕸 Tracim sur mon NAS, partie 2: Service Systemd pour conteneur Podman</title>
      <link>https://inkey-art.net/tracim-sur-mon-nas-partie-2-service-systemd-pour-conteneur-podman/</link>
      <pubDate>Sun, 30 Apr 2023 18:30:22 +0200</pubDate>
      
      <guid>https://inkey-art.net/tracim-sur-mon-nas-partie-2-service-systemd-pour-conteneur-podman/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Lors des &lt;a href=&#34;https://inkey-art.net/tracim-sur-mon-nas-partie-1a-g%C3%A9n%C3%A9ration-de-limage-arm64-avec-buildah/&#34;&gt;précédents&lt;/a&gt; &lt;a href=&#34;https://inkey-art.net/tracim-sur-mon-nas-partie-1b-partage-public-dune-image-multiplateforme-avec-buildah/&#34;&gt;articles&lt;/a&gt;, je couvrais le fait de générer une image conteneur pour Tracim, les images sont prêts,
il est temps de les utilisés !&lt;/p&gt;
&lt;h3 id=&#34;mise-en-route-de-limage-avec-podman-et-systemd&#34;&gt;Mise en route de l&amp;rsquo;image avec Podman et Systemd&lt;/h3&gt;
&lt;p&gt;Pour ce faire, je prépare la commande pour lancer le conteneur Tracim avec les bons paramètres, pour
le cas d&amp;rsquo;une configuration très minimal, il est possible de faire comme dans le script donné ci-dessous.&lt;/p&gt;
&lt;p&gt;A notez:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;c&amp;rsquo;est un conteneur en mode utilisateur, il ne demande pas de droits super-utilisateur afin de limiter les risques de sécurité.&lt;/li&gt;
&lt;li&gt;C&amp;rsquo;est une configuration Tracim très basique, qui ne tire par profit du plein potentiel du logiciel.&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;exemple ici demande l&amp;rsquo;existence d&amp;rsquo;un reverse-proxy capable de rediriger le port de sortie 7070 vers l&amp;rsquo;internet, autrement seul le NAS sera capable d&amp;rsquo;accéder au site.&lt;/li&gt;
&lt;li&gt;J&amp;rsquo;ai limité les ressources utilisables par l&amp;rsquo;image via les paramètres cpu et memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman run -d  -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;DATABASE_TYPE=sqlite&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;START_CALDAV=1&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;START_WEBDAV=1&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;TRACIM_WEBSITE__BASE_URL=https://tracim.ndd.tld&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;TRACIM_WEBDAV__BASE_URL=https://tracim.ndd.tld&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;TRACIM_WEBSITE__TITLE=Tracim&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;TRACIM_WEBSITE__DESCRIPTION=Mon espace partagé !&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -e &lt;span class=&#34;s2&#34;&gt;&amp;#34;TRACIM_DEFAULT_LANG=fr&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -p &lt;span class=&#34;s2&#34;&gt;&amp;#34;127.0.0.1:7070:80&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -v &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;//tracim/etc:/etc/tracim&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              -v &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/tracim/var:/var/tracim&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              --cpus&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              --memory&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;2g &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              --name tracim &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;              inkhey/tracim:4.5-no-vtk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pour une gestion un peu plus propre, il est possible de convertir cette configuration en service Systemd de la sorte :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman stop tracim
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman generate systemd -n tracim &amp;gt; ~/.config/systemd/user/tracim.service
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl --user daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl --user &lt;span class=&#34;nb&#34;&gt;enable&lt;/span&gt; tracim
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;systemctl --user start tracim
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Vous avez ainsi un Tracim fonctionnel via Podman donc le cycle de vie est gérable via Systemd, pas mal non ?&lt;/p&gt;
&lt;h3 id=&#34;bonus-convertir-en-fichier-de-configuration-pour-kubernetes&#34;&gt;Bonus : convertir en fichier de configuration pour kubernetes&lt;/h3&gt;
&lt;p&gt;Je n&amp;rsquo;utilise pas personnellement Kubernetes, mais Podman permet facilement de convertir un conteneur existant en
configuration compatible&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman generate kube -f tracim.yml tracim
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On peut aussi démarrer une configuration de type kubernetes :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman play kube ./tracim.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;heading&#34;&gt;🥳&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://inkey-art.net/tracim-sur-mon-nas-partie-3-frontal-nginx/&#34;&gt;La suite&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🕸 Tracim sur mon NAS, partie 1b: Partage public d&#39;une image multiplateforme avec Buildah</title>
      <link>https://inkey-art.net/tracim-sur-mon-nas-partie-1b-partage-public-dune-image-multiplateforme-avec-buildah/</link>
      <pubDate>Sun, 30 Apr 2023 18:30:21 +0200</pubDate>
      
      <guid>https://inkey-art.net/tracim-sur-mon-nas-partie-1b-partage-public-dune-image-multiplateforme-avec-buildah/</guid>
      <description>&lt;h3 id=&#34;une-autre-façon-de-faire-publiez-publiquement-une-image-&#34;&gt;Une autre façon de faire, publiez publiquement une image !&lt;/h3&gt;
&lt;p&gt;Si vous avez lu mon &lt;a href=&#34;https://inkey-art.net/tracim-sur-mon-nas-partie-1a-g%C3%A9n%C3%A9ration-de-limage-arm64-avec-buildah/&#34;&gt;précédent article&lt;/a&gt;
, j&amp;rsquo;expliquais qu&amp;rsquo;il était facile avec Buildah de produire une image pour une plateforme différente.&lt;/p&gt;
&lt;p&gt;Dans cet article-ci, je reviens sur cette procédure, en explorant la possibilité
de tirer plutôt parti du serveur de stockage d&amp;rsquo;image public tout en proposant des images multi-architectures.&lt;/p&gt;
&lt;p&gt;Le principe d&amp;rsquo;une image multi-architecture, est qu&amp;rsquo;avec un même nom, il est possible depuis des systèmes de différente architecture
processeur d&amp;rsquo;utiliser le même nom d&amp;rsquo;image. Il ne s&amp;rsquo;agit pas à proprement parler d&amp;rsquo;image multi-plateforme, mais d&amp;rsquo;un alias unique permettant
à chaque système de récupérer l&amp;rsquo;image compatible.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai pour ce faire suivis attentivement ce &lt;a href=&#34;https://danmanners.com/posts/2022-01-buildah-multi-arch/&#34;&gt;tutoriel&lt;/a&gt;, merci à Dan Manners.
Cet article n&amp;rsquo;est donc qu&amp;rsquo;une application un peu plus concrète de son article.&lt;/p&gt;
&lt;h3 id=&#34;mise-en-application&#34;&gt;Mise en application&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# dépendances nécessaire sous debian&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install podman buildah git qemu-user-static qemu git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On récupère le code nécessaire pour la génération de l&amp;rsquo;image :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone --depth &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; --branch release_04.05.00 https://github.com/tracim/tracim.git tracim
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; tracim//tools_docker/Debian_Uwsgi_ARM64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce qui aboutit en changeant quelques points au script ci-dessous.&lt;/p&gt;
&lt;p&gt;Avant de l&amp;rsquo;utiliser :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Changer le en fonction de votre cas, en particulier la variable &lt;code&gt;USER&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si vous utilisez le docker registry, créer un token d&amp;rsquo;authentification &lt;a href=&#34;https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry&#34;&gt;avec les bons droits&lt;/a&gt; pour pouvoir pousser sur le github registry.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -e
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;TRACIM_VERSION&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;4.5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Set your manifest name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;MANIFEST_NAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;tracim-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;TRACIM_VERSION&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;-no-vtk&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Set the required variables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;BUILD_PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/tmp/tracim/tools_docker/Debian_Uwsgi_ARM64/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;REGISTRY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ghcr.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;USER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;inkhey&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;IMAGE_NAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;tracim&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;IMAGE_TAG&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;TRACIM_VERSION&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;-no-vtk&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;buildah logih &lt;span class=&#34;nv&#34;&gt;$REGISTRY&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Create a multi-architecture manifest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;buildah manifest create &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;MANIFEST_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Build your amd64 architecture container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#buildah bud \&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    --tag &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;REGISTRY&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;USER&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IMAGE_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IMAGE_TAG&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --manifest &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;MANIFEST_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --arch amd64 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;BUILD_PATH&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Build your arm64 architecture container&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;buildah bud &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --tag &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;REGISTRY&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;USER&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IMAGE_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IMAGE_TAG&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --manifest &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;MANIFEST_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --arch arm64 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;BUILD_PATH&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Push the full manifest, with both CPU Architectures&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;buildah manifest push --all &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;MANIFEST_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;docker://&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;REGISTRY&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;USER&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IMAGE_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;IMAGE_TAG&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Les images enfin générées si tout s&amp;rsquo;est bien passé, il est enfin possible d&amp;rsquo;aller les récupérer. Les miennes sont ainsi
disponible &lt;a href=&#34;https://github.com/inkhey/tracim/pkgs/container/tracim/89448326?tag=4.5-no-vtk&#34;&gt;ici&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Vous pouvez ainsi les récupérer sous ce nom : &lt;code&gt;ghcr.io/inkhey/tracim:4.5-no-vtk&lt;/code&gt;que ce soit depuis une machine amd64 ou arm64.&lt;/p&gt;
&lt;h1 id=&#34;heading&#34;&gt;🥳&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://inkey-art.net/tracim-sur-mon-nas-partie-2-service-systemd-pour-conteneur-podman/&#34;&gt;La Suite&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    
    
    <item>
      <title>🕸 Tracim sur mon NAS, partie 1a: Génération de l&#39;image ARM64 avec Buildah</title>
      <link>https://inkey-art.net/tracim-sur-mon-nas-partie-1a-g%C3%A9n%C3%A9ration-de-limage-arm64-avec-buildah/</link>
      <pubDate>Sun, 30 Apr 2023 18:30:20 +0200</pubDate>
      
      <guid>https://inkey-art.net/tracim-sur-mon-nas-partie-1a-g%C3%A9n%C3%A9ration-de-limage-arm64-avec-buildah/</guid>
      <description>&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Podman/Buildah&lt;/em&gt; est une suite logicielle afin de gérer des conteneurs logiciels. C&amp;rsquo;est une alternative à docker, qui a l&amp;rsquo;avantage
de ne pas nécessiter de demon avec les droits root.&lt;/p&gt;
&lt;p&gt;Tracim est un logiciel intéressant permettant de gérer des espaces de collaboration
dans divers cadres. S&amp;rsquo;il est aisé d&amp;rsquo;imaginer des usages professionnels poussés avec ce logiciel,
il est aussi facile du fait de sa modularité de le tester en mode &lt;em&gt;simplifié&lt;/em&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; pour un usage personnel.&lt;/p&gt;
&lt;p&gt;Pour mon usage personnel, j&amp;rsquo;utilise Tracim sur un NAS dont l&amp;rsquo;architecture logicielle est ARM64 et le système d&amp;rsquo;exploitation
est Armbian, dérivée de debian.&lt;/p&gt;
&lt;p&gt;La version actuelle de tracim à l&amp;rsquo;heure de ces lignes est la &lt;a href=&#34;https://github.com/tracim/tracim/releases/tag/release_04.05.00&#34;&gt;4.5.0&lt;/a&gt; sortie le 27 avril 2023.&lt;/p&gt;
&lt;h2 id=&#34;générer-les-images-buildah&#34;&gt;Générer les images (Buildah)&lt;/h2&gt;
&lt;p&gt;Tracim ne fournit actuellement pas d&amp;rsquo;image ARM64 officiel, il faut donc les générer soit même.
Dans cet exemple, je génère l&amp;rsquo;image ARM64 depuis une machine d&amp;rsquo;architecture amd64, j&amp;rsquo;ai ainsi besoin de qemu.&lt;/p&gt;
&lt;p&gt;Sur le système pour générer les images :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install podman buildah git qemu-user-static qemu
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;récupérer-sur-la-dernière-version-stable-de-tracim&#34;&gt;Récupérer sur la dernière version stable de tracim :&lt;/h3&gt;
&lt;p&gt;Récupération de la version 4.5.0 de Tracim :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone --depth &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; --branch release_04.05.00 https://github.com/tracim/tracim.git tracim_stable
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;générer-limage-pour-arm64-avec-qemu-et-buildah&#34;&gt;Générer l&amp;rsquo;image pour ARM64 avec Qemu et Buildah&lt;/h3&gt;
&lt;p&gt;Une image fonctionnelle en ARM64 expérimentale est disponible dans le code source de tracim, la seule différence dans cette version (4.5.0) avec l&amp;rsquo;image officielle est l&amp;rsquo;absence de support
des previews d&amp;rsquo;images 3D, la librairie vtk n&amp;rsquo;étant pas disponible en version compilée pour ARM64.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; tracim_stable/tools_docker/Debian_Uwsgi_ARM64/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;buildah bud &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --tag &lt;span class=&#34;s2&#34;&gt;&amp;#34;algoo/tracim:4.5.0&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --arch arm64 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --build-arg &lt;span class=&#34;nv&#34;&gt;TAG&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;release_04.05.00&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note : la génération peut s&amp;rsquo;avérer longue du fait de l&amp;rsquo;utilisation d&amp;rsquo;une architecture non native.&lt;/p&gt;
&lt;h3 id=&#34;déplacer-limage-entre-2-machines&#34;&gt;Déplacer l&amp;rsquo;image entre 2 machines&lt;/h3&gt;
&lt;p&gt;Sur le système ou l&amp;rsquo;image a été généré :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman save algoo/tracim:4.5.0 &amp;gt; tracim_4.5.0.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On peut ensuite déplacer l&amp;rsquo;archive entre les deux machines via un support tel qu&amp;rsquo;une clé usb ou
tout simplement par le réseau, par exemple via des outils tel que &lt;code&gt;sftp&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Pour importer l&amp;rsquo;image sur le système cible, ne pas oublier d&amp;rsquo;avoir Podman d&amp;rsquo;installé :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install podman
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;podman load &amp;lt; tracim_4.5.0.tar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Il est ainsi possible d&amp;rsquo;utiliser sur mon nas l&amp;rsquo;image &lt;code&gt;algoo/tracim:4.5.0&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;heading&#34;&gt;🥳&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://inkey-art.net/tracim-sur-mon-nas-partie-1b-partage-public-dune-image-multiplateforme-avec-buildah/&#34;&gt;La Suite&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Sans fonctionnalités complexes tels que la recherche avancée avec elasticsearch/opensearch, les notifications mails, etc. la configuration de Tracim est &lt;a href=&#34;https://github.com/tracim/tracim/blob/develop/backend/development.ini.sample&#34;&gt;très fournis&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    
    
    
  </channel>
</rss>
