<![CDATA[Johackim - Hacker indépendant]]>https://johackim.comGatsbyJSMon, 26 Jul 2021 11:58:46 GMT<![CDATA[Résumé du livre Make de Pieter Levels]]>https://johackim.com/make-pieter-levelshttps://johackim.com/make-pieter-levelsSun, 18 Jul 2021 19:21:58 GMT<h2 id="tldr">TL;DR</h2><h3 id="idee"><a href="/soon" title="Idée">Idée</a></h3><p>Trouver une idée basée sur vos propres problèmes.</p><h3 id="construire">Construire</h3><p>Créez votre idée avec les outils que vous connaissez déjà, ne déléguer pas la construction. Construisez uniquement les fonctionnalités de base dans un premier temps.</p><h3 id="lancement"><a href="/soon" title="Lancement">Lancement</a></h3><p>Lancer tôt et à plusieurs reprises. Lancer sur des sites populaires (ex: Product Hunt, Hacker News, The Next Web, Reddit, Forbes).</p><p>Trouvez votre audience spécifique, ne jouer pas aux grosses startup qui veulent changer le monde.</p><h3 id="grandir">Grandir</h3><p>Grandissez organiquement. Un bon produit est un produit que les gens veulent réellement et qui est meilleur que le reste. Vous n&#x27;avez pas besoin de publicité.</p><p>Ne recrutez pas avant que les revenues ne suivent. Faites les choses vous-même.</p><h3 id="monetisez">Monétisez</h3><p>Monétisez votre produit en demandant aux utilisateurs de l&#x27;argent. Ne vendez pas leurs données et ne mettez pas de la publicité partout.</p><h3 id="automatisez">Automatisez</h3><p>Automatisez en écrivant des programmes qui font le travail pour vous. Automatisez seulement si le temps sauvé en vaut la peine.</p><p>Si c&#x27;est trop dur à automatiser, recrutez quelqu’un, et laissez-le travailler de manière la plus autonome possible.</p><h2 id="vous-aurez-besoin-de-perseverance-et-de-chance">Vous aurez besoin de persévérance et de chance</h2><p>Vous allez probablement devoir créer 10 à 30 produits pendant 1 à 3 ans avant d&#x27;avoir quelque chose qui fonctionne.</p><p>Vous construisez quelque chose et regardez ce qui colle.</p><p>Le succès d&#x27;un produit provient beaucoup de la chance et du timing.</p><h2 id="pratiquer">Pratiquer</h2><p>Lire le livre ne sera pas utile. Pratiquez ! Et plus important, &quot;shipez&quot; !</p><h2 id="faire-des-preventes">Faire des préventes</h2><p>Pieter Levels à créé un Typeform qui fait office de landing page et a demandé $22.</p><div data-testid="general-observer" class="mdx-embed"><div style="height:0;width:100%"></div></div><p>Il a créé le livre sur un google docs en mode &quot;Building in public&quot; et demander les retours des clients qui ont acheté le livre en pré-vente.</p><h2 id="resolvez-vos-propres-problemes">Résolvez vos propres problèmes</h2><p>Observé vos challenges du quotidien, sélectionnez les plus gros, et aidez à les gens à le résoudre aussi.</p><p>Votre problème pourrait être celui d&#x27;autres personnes.</p><p>Lorsque Pieter voyageait dans plusieurs pays, en tant que digital nomade, il ne savait pas quel pays était cher, pas cher, avec ou sans wifi, etc...</p><p>Il s&#x27;est avéré que c&#x27;était le cas de plein d&#x27;autres personnes.</p><p><mark class="font-bold">Vous êtes le plus grand expert de vos propres problèmes</mark>. C&#x27;est plus compliqué de créer une application médicale en tant que non-docteur que de développer une application pour des développeurs par exemple.</p><blockquote><p>We knew what people wanted because we were the target market. Founder of Boosted Boards.</p></blockquote><p><strong>Les startups conseillent de &quot;parler aux clients pour trouver leurs problèmes&quot;, c&#x27;est bien, mais vous travaillez toujours d&#x27;un point de vue extérieur plutôt que du vôtre.</strong></p><h2 id="toujours-demarrer-part-le-probleme-et-non-de-la-solution">Toujours démarrer part le problème et non de la solution</h2><p>Si vous résolver un problème qui n&#x27;existe pas, cela peut-être technologiquement sexy, mais vous n&#x27;aurez pas d&#x27;utilisateurs.</p><p>Le problème doit toujours venir en premier, pas la technologie, ni la solution.</p><h2 id="pour-devenir-gros-commencez-petit">Pour devenir gros, commencez petit</h2><p><a href="/soon" title="Niche">Les niches</a> sont des segments de marché spécifiques qui sont suffisamment peu profonds pour être facilement accessibles et qui ne comptent pas beaucoup d&#x27;acteurs.</p><p>C&#x27;est un excellent point de départ car leur valeur économique est trop faible pour intéresser les grandes entreprises.</p><p>Aucune grosse entreprise à commencé gros :</p><ul><li>Facebook a démarré avec une application &quot;Hot or Not&quot;</li><li>Amazon a démarré en vendant des livres</li><li>Etc...</li></ul><p>Si vous avez uniquement 1000 personnes qui payent votre produit 83,33€/mois, vous avez un revenu récurrent de 1 000 000€ de revenu annuel.</p><h2 id="comment-faire-1-000-000€-">Comment faire 1 000 000€ ?</h2><ul><li>Créez un produit à 5,000€ pour 200 personnes</li><li>Créez un produit à 2,000€ pour 500 personnes</li><li>Créez un produit à 1,000€ pour 1,000 personnes</li><li>Créez un produit à 200€ pour 5,000 personnes</li><li>Créez un produit à 100€ pour 10,000 personnes</li><li>Créez un produit à 10€ pour 100,000 personnes</li></ul><p>ou</p><ul><li>Créez un abonnement à 167€ / mois pour 500 personnes pendant 1 an</li><li>Créez un abonnement à 83€ / mois pour 1,000 personnes pendant 1 an</li><li>Créez un abonnement à 42€ / mois pour 2,000 personnes pendant 1 an</li><li>Créez un abonnement à 17€ / mois pour 5,000 personnes pendant 1 an</li><li>Créez un abonnement à 9€ / mois pour 10,000 personnes pendant 1 an</li></ul><h2 id="demarrez-avec-une-micro-niche">Démarrez avec une micro niche</h2><p>Imaginez que vous souhaitez créer un logiciel de réservation pour les coiffeurs. Il y a probablement des millions de coiffeurs dans le monde.</p><p>Allez plus loin en créant un logiciel qui se focus uniquement sur les coiffeurs qui font des coiffures africaines. Ce qui doit probablement être des dizaines de milliers de coiffeurs dans le monde.</p><p>Si vous réussissez à capter 10% de 10 000 coiffeurs, à savoir 1000 client, et qu&#x27;ils paient environ 83€ par mois, cela vous rapporte 1 000 000€ par an.</p><h2 id="dune-mico-niche-a-une-multi-niche">D&#x27;une mico-niche à une multi-niche</h2><p>Il vaut mieux commencer par une niche comme une application de réservation pour coiffeurs africains et partir après sur le marché des coiffeurs asiatiques que l&#x27;inverse.</p><p>Vous aurez moins de mal à déceler les résistances à l&#x27;adoption de votre solution et vous pouvez plus facilement faire marche arrière dans ce sens là.</p><h2 id="dune-multi-niche-a-des-marches-adjacents">D&#x27;une multi-niche à des marchés adjacents</h2><p>Supposons que vous détenez tout le marché des réservations pour salon de coiffure. Vous pouvez peut-être envisager de passer par le marché des salons de manucure ou de tatouage.</p><h2 id="creer-une-liste-didee">Créer une liste d&#x27;idée</h2><p>Concept &gt; Promising &gt; Building &gt; Success &gt; Fail</p><p><img src="https://i.imgur.com/JWuNnca.jpg"/></p><h2 id="ne-travaillez-pas-en-groupe-dans-un-premier-temps">Ne travaillez pas en groupe dans un premier temps</h2><p>Il est inutile de débattre de la viabilité d&#x27;une idée à plusieurs.</p><p>Il suffit juste de construire un prototype et de le faire valider par son marché.</p><p><mark class="font-bold">Seul le marché à la réponse, personne d&#x27;autre</mark>.</p><h2 id="les-idees-ne-valent-rien-du-tout">Les idées ne valent rien du tout</h2><p><code>Business = Idée x exécution</code></p><p>Une idée ne vaut rien seule.</p><p>Mauvaise idée = 0<br/> Bonne idée = 10<br/> Excellente idée = 20</p><p>Aucune exécution = 0<br/> Bonne exécution = 100,000€<br/> Excellente exécution = 1,000,000€</p><p>Une excellente idée sans exécution vaudra toujours zéro, tandis qui une bonne idée avec une bonne exécution peut valoir +100,000€.</p><p>Ne pas partager votre idée est stupide parce qu&#x27;elle reste dans votre tête.</p><h2 id="construisez-rapidement-et-simplement">Construisez rapidement et simplement</h2><p>Le but est d&#x27;éviter de rester coincé dans la boucle infernale des brainstormings et de commencer la création le plus rapidement possible.</p><p>Le plus vite vous dévoiler votre produit, le plus vite vous vérifiez si les gens veulent l&#x27;utiliser.</p><p>Dans un premier temps, faites les choses vous-même (DIY) plutôt que de déléguer.</p><h2 id="ne-soyez-pas-obsede-par-les-outils">Ne soyez pas obsédé par les outils</h2><p>Tous les outils, frameworks ou langages de programmation ne sont qu&#x27;une perte de temps qui vous éloigne de <strong>votre objectif : construire et vendre votre produit</strong>.</p><h2 id="lancement-1">Lancement</h2><p>Il ya plusieurs manières de lancer son produit :</p><ul><li>Sur des plateformes comme <a href="https://www.producthunt.com/">Product Hunt</a>, <a href="https://news.ycombinator.com/">Hacker News</a> ou <a href="https://www.reddit.com/">Reddit</a>, <a href="https://betalist.com/">BetaList</a></li><li>Par le biais de la presse</li><li>Par le biais de l&#x27;audience d&#x27;une autre personne</li></ul><p>Le lancement est utile pour avoir beaucoup de personnes qui utilisent notre application afin que l&#x27;on puisse apprendre de leurs usages, réparer les bugs, développer de nouvelles fonctionnalités et faire en sorte qu&#x27;ils restent utiliser notre application.</p><blockquote><p>Une landing page avec un champ d&#x27;inscription pour rentré un e-mail n&#x27;est pas un produit, c&#x27;est une landing page.</p></blockquote><p>Assurez-vous d&#x27;avoir une seule fonctionnalité et qui fonctionne correctement.</p><p>Et si vous demandez l&#x27;adresse e-mail d&#x27;un visiteur. Proposer quelque chose de valeur et pas simplement un &quot;inscrivez-vous à ma newsletter&quot;.</p><p><mark class="font-bold">Lancez là où votre audience se trouve</mark>.</p><h2 id="lancer-sur-product-hunt">Lancer sur Product Hunt</h2><p><strong>Vous devez lancer à 00:00:01 PST</strong>.</p><p>Le fuseau horaire de Product Hunt est San Francisco (fuseau horaire PST) et son système de vote est réinitialisé à minuit.</p><p><strong>Utiliser le nom de votre application</strong> (avec le numéro de version si il s&#x27;agit d&#x27;une mise à jour. </p><p><strong>Ajoutez un bon slogan</strong> (#copywriting).</p><p><strong>Ajoutez 8 à 16 screenshots (en haute résolution) des fonctionnalités principales de votre application</strong>.</p><p>Si possible, ajoutez une vidéo de présentation de votre produit de 30 secondes.</p><p>Une fois lancé :</p><p><strong>Ajoutez immédiatement un commentaire sur Product Hunt</strong> avec une introduction de qui vous êtes, pourquoi vous avez créé votre produit et quel est votre plan futur (<a href="https://www.producthunt.com/posts/hoodmaps">exemple</a>).</p><p><img src="https://i.imgur.com/7YX0P3Y.jpg" alt="Commentaire Product Hunt"/></p><p><strong>Envoyer un Tweet, Post Facebook/Instagram ou un email à votre communauté</strong> pour informé de votre lancement.</p><p>Et <strong>répondez à tous les commentaires</strong> sur Product Hunt et sur vos réseaux.</p><h2 id="lancer-sur-hacker-news">Lancer sur Hacker News</h2><p>Hacker News est beaucoup plus compliqué que Product Hunt.</p><p>C&#x27;est très compliqué d&#x27;apparaitre sur la première page (front page) de Hacker News.</p><p>Par exemple, si votre post reçoit trop de commentaires par rapport au nombre de vote il sera automatiquement supprimé.</p><p><strong>Le titre est très important</strong> :</p><p>Eviter les titres comme : &quot;Petsy.com - The best food delivery for pets&quot;.</p><p>Préférez un titre comme : &quot;Show HN: I made a sPite that lets you subscribe to pet food delivery&quot;.</p><p>Votre post sera ajouté sur la &quot;new page&quot; dans un premier temps, si vous <strong>demandez à 5 personnes d&#x27;upvoter votre post la première heure</strong>, elle aura peut être des chances d&#x27;arriver sur la &quot;Front page&quot;.</p><h2 id="etre-publie-dans-la-presse">Être publié dans la presse</h2><p><strong>Evitez les adresses email en mode &quot;trou noir&quot;</strong> comme <a href="mailto:tips@thenextweb.com">tips@thenextweb.com</a>.</p><p><strong>Tentez de trouver un journaliste en particulier qui correspond à votre niche</strong>.</p><p><strong>Evitez les e-mails trop long et vague qui ne vont pas droit au but</strong>.</p><h2 id="faites-de-chaque-fonctionnalite-une-opportunite-de-lancement">Faites de chaque fonctionnalité une opportunité de lancement</h2><p>Faites une promotion à chaque fois que vous lancez une nouvelle fonctionnalité.</p><p>Même si vous avez déjà lancé il y a longtemps, les gens aiment voir des améliorations.</p><h2 id="si-vous-navez-plus-de-motivation-vendez-le-automatisez-le-ou-tuez-le">Si vous n&#x27;avez plus de motivation, vendez-le, automatisez-le ou tuez-le</h2><p>Si votre idée fonctionne, mais qu&#x27;elle ne vous motive plus, vous pouvez soit recruter des personnes et automatiser le plus de choses possible soit vendre votre projet.</p><h2 id="grandissez-organiquement">Grandissez organiquement</h2><p>Sur le long terme, il est préférable de grandir de manière organique que d&#x27;utiliser de la pub ou des techniques de growth hacking à deux balles.</p><p><strong>Faites des lancements tous les 3 mois</strong> avec un promotion en vendant les nouvelles fonctionnalitées.</p><p>Ex : sur Product Hunt, avec les numéros de version (2.0, 3.0, etc...).</p><p><strong>Racontez des histoires</strong> plutôt que de parler uniquement des nouvelles fonctionnalités.</p><p>N&#x27;oubliez pas d&#x27;analyser les metrics lors de votre lancement pour vérifier si les utilisateurs provenant d&#x27;une source en particulier utilisent ou non l&#x27;application.</p><p>Et le meilleur moyen de grandir est simplement de <strong>créer un produit utile et génial selon les besoins existants de son audience</strong>.</p><h2 id="la-monetisation-est-la-validation">==La monétisation est la validation==</h2><blockquote><p>What I mean is, if you have 1,000 people using your product actively, don&#x27;t expect more than 5% to pay for it. Probably fewer. So your paying customer base is fewer than 50 people.</p></blockquote><p>Ajoutez un bouton &quot;Acheter&quot;, si les utilisateurs cliquent dessus, affichez une modal de paiement où ils peuvent renseigner leurs coordonnées bancaires.</p><p>Si votre produit n&#x27;est pas terminé, affichez un message &quot;Désolé, nous n&#x27;avons pas débité votre carte mais merci de votre intérêt. Notre produit n&#x27;est pas encore prêt, mais nous vous préviendrons quand il le sera&quot;.</p><p><strong>Note personnelle</strong> : Donnez-leur une réduction pour leur prochain achat.</p><p>De cette façon, vous pouvez estimer les revenus que vous pourriez avoir.</p><blockquote><p>An app without monetization is a charity. An app with monetization is a business.</p></blockquote><h2 id="les-business-modeles">Les business modèles</h2><p><strong>Limitez certaines fonctionnalitées à des utilisateurs</strong> (Pay-per-feature) :</p><p>Analysez les fonctionnalités de votre application les plus utilisé et ajoutez une popup &quot;Pour utiliser cette fonctionnalité, veuillez mettre à jour votre compte&quot;.</p><p><strong>Publicités natives</strong> :</p><p>Utiliser des publicités natives au lieu d&#x27;utiliser des publicités Google AdSense toutes moches qui ne rapporte pas grand-chose.</p><p><strong>Parrainages</strong> :</p><p>Demandez à des compagnies de sponsoriser votre projet en ajoutant leur logo sur votre site pour un montant mensuel.</p><p><strong>Patreon</strong> :</p><p>Recevez le support des fans de votre travail via la plateforme <a href="https://www.patreon.com/">Patreon</a>.</p><p><strong>Abonnements</strong> :</p><p>De la même manière qu&#x27;un abonnement a Netflix. Demandez à vos utilisateurs de payer un revenue récurrent mensuel ou annuel pour utiliser votre application.</p><p>L&#x27;objectif est de les garder le plus longtemps en évitant le churn (les personnes qui se désinscrivent).</p><p><strong>Communauté</strong> :</p><p>Une communauté peut être sous la forme d&#x27;un forum, d&#x27;un chat, réseau social ou rencontres physiques.</p><p>Plus vous avez de personnes dans votre communauté, plus elle devient précieuse, et plus vous pouvez monétiser plus cher.</p><p>C&#x27;est un moyen de garder les utilisateurs sur son site ; construire une communauté.</p><h2 id="eviter-dembaucher-construisez-des-robots">Eviter d&#x27;embaucher, construisez des robots</h2><p>Les humains sont complexes et moins rapides que des robots. La plupart des tâches peuvent être automatisées.</p><h2 id="nautomatisez-pas-si-ca-nen-vaut-pas-le-coup">N&#x27;automatisez pas si ça n&#x27;en vaut pas le coup</h2><p>Si le temps passé à automatiser une tâche est plus long que la tâche elle-même, cela ne vaut pas le coup d&#x27;automatiser.</p><p>Et si c&#x27;est trop long et/ou trop complexe a automatiser, déléguer.</p><h2 id="le-test-du-bus">Le test du bus</h2><p>« Une expérience qui explore l&#x27;impact de la perte d&#x27;une personne : si un individu particulièrement habilité dans une organisation est heurté par un bus, l&#x27;organisation en souffrira-t-elle grandement ? Si oui, le test échoue. Sinon, le test est réussi. »</p><p>Demandez-vous si vous passez le test, si ce n&#x27;est pas le cas, automatisez.</p><h2 id="listez-vos-taches-recurrentes-et-automatisez-les">Listez vos tâches récurrentes et automatisez-les</h2><p>Pendant une semaine, listez toutes les tâches récurrentes qui prennent du temps; ordonnez-les par facilité d&#x27;automatisation et commencez à automatiser.</p><p>Si des tâches sont trop difficiles à automatiser, recruter un prestataire et automatiser les interactions entre lui et votre business.</p><![CDATA[Travailler en Deep Work sur Linux]]>https://johackim.com/travailler-en-deep-work-sur-linuxhttps://johackim.com/travailler-en-deep-work-sur-linuxSun, 18 Jul 2021 19:21:58 GMT<p>Pour travailler en Deep Work sur Linux, je me suis créé <a href="https://github.com/johackim/dotfiles/blob/master/bin/lock">un script maison</a>.</p><p>Ce script a pour but de m&#x27;empêcher d&#x27;avoir à des sites (ex: Youtube, Twitter, ect...) et applications spécifiques (Signal, Mailspring, etc...) qui m&#x27;empêche d&#x27;être productif.</p><p>L&#x27;avantage de ce script, c&#x27;est qu&#x27;il m&#x27;empêche aussi de débloquer l&#x27;accès avec le compte root.</p><p>Ajoutez les sites et les applications que vous souhaitez bloquer à l&#x27;intérieur du script dans les variables <code>DOMAINS</code> et <code>APPS</code>.</p><p><strong>ATTENTION : Les commandes suivantes bloquera votre accès au groupe sudo pendant 1 heure, veuillez utiliser ce script uniquement en connaissance de cause</strong>.</p><p>Puis exécuter le script avec la commande suivante pour :</p><pre><code class="language-bash">sudo -E lock </code></pre><p>Vous pouvez choisir le nombre d&#x27;heures :</p><pre><code class="language-bash">sudo -E lock 3 # Travailler en deep work pendant 3 heures </code></pre><p>Si vous voulez savoir combien de temps il reste avant de pouvoir réutiliser votre ordinateur, vous pouvez taper la commande <code>lock status</code>.</p><p>Et n&#x27;oubliez pas d&#x27;ajouter la commande <code>lock reset</code> dans une tâche cron qui s&#x27;exécute chaque minute pour pouvoir vous débloquer l&#x27;accès automatiquement.</p><pre><code class="language-crontab">* * * * * lock reset </code></pre><![CDATA[Comment créer un thème Obsidian ?]]>https://johackim.com/creer-un-theme-obsidianhttps://johackim.com/creer-un-theme-obsidianSun, 11 Jul 2021 09:50:48 GMT<p>Pour créer un thème dans <a href="/obsidian" title="Obsidian">Obsidian</a>, il vous faut simplement créer un fichier CSS <code>nomdutheme.css</code> dans le dossier <code>.obsidian/themes</code> de votre Vault Obsidian.</p><p>Exemple :</p><pre><code class="language-css">/* vault/.obsidian/themes/darkyan.css */ .theme-light, .theme-dark { --background-primary: #111827; --background-primary-alt: #111827; --background-secondary: #1F2937; --background-secondary-alt: #1F2937; --text-normal: #D1D5DB; --text-faint: #D1D5DB; --text-title-h1: #D1D5DB; --text-title-h2: #D1D5DB; --text-title-h3: #D1D5DB; --text-title-h4: #D1D5DB; --text-title-h5: #D1D5DB; --text-title-h6: #D1D5DB; --text-highlight-bg: #374151; --text-link: #D1D5DB; --text-a-hover: #D1D5DB; --inline-code: #D1D5DB; --code-block: #D1D5DB; --text-a: #D1D5DB; --interactive-accent: #00AAAD; --text-accent: #00AAAD; --text-accent-hover: #00AAAD; --text-on-accent: #D1D5DB; --interactive-accent-rgb: #D1D5DB; --interactive-accent-hover: #00AAAD; --vim-cursor: #D1D5DB; --pre-code: #000000; --interactive-before: #374151; --background-modifier-border: #374151; --text-selection: #374151; --text-faint: #4B5563; } </code></pre><p>Une fois le fichier créé, vous pouvez utiliser votre thème depuis Settings -&gt; Appearance -&gt; Themes -&gt; Theme -&gt; Darkyan.</p><p>J&#x27;ai récemment créé un thème, vous pouvez l&#x27;utiliser en vous rendant sur le dépôt Github <a href="https://github.com/johackim/obsidian-darkyan/">johackim/obsidian-darkyan</a>.</p><p><img src="https://raw.githubusercontent.com/johackim/obsidian-darkyan/master/screenshot.png" alt="Obsidian Theme"/></p><p><img src="https://raw.githubusercontent.com/johackim/obsidian-darkyan/master/screenshot2.png" alt="Graph viewer"/></p><p>Pour publier son thème dans les thèmes de la communauté d&#x27;Obsidian, créez une pull request sur le dépôt <a href="https://github.com/obsidianmd/obsidian-releases/pull/356">obsidianmd/obsidian-releases</a>.</p><p>Une fois la pull request accepté, il apparaitra dans la liste des thèmes d&#x27;Obsidian dans Settings -&gt; Appearance -&gt; Themes -&gt; Community themes.</p><![CDATA[Démarrer une application GUI avec SSH]]>https://johackim.com/demarrer-une-application-gui-avec-sshhttps://johackim.com/demarrer-une-application-gui-avec-sshSun, 11 Jul 2021 09:50:48 GMT<p>Pour démarrer une application graphique à distance via SSH, commencez par ajouter le paramètre <code>X11Forwarding yes</code> au fichier <code>/etc/ssh/sshd_config</code> de votre serveur.</p><p>Redémarrer votre serveur SSH :</p><pre><code class="language-bash">sudo systemctl restart sshd </code></pre><p>Puis connectez-vous à votre serveur via une commande SSH avec le paramètre <code>-X</code> :</p><pre><code class="language-bash">ssh -X &lt;user&gt;@&lt;ip&gt; </code></pre><p>Démarrez l&#x27;application GUI que vous souhaitez (ex: <a href="https://obsidian.md">Obsidian</a>) :</p><pre><code class="language-bash">obsidian </code></pre><p>Maintenant vous avez accès à une application graphique distante directement depuis votre machine hôte 😀🎉.</p><![CDATA[Démarrer un serveur HTTP en ligne de commande]]>https://johackim.com/demarrer-un-serveur-http-en-ligne-de-commandehttps://johackim.com/demarrer-un-serveur-http-en-ligne-de-commandeMon, 05 Jul 2021 16:31:18 GMT<p>Il existe plusieurs façons de démarrer un serveur HTTP en ligne de commande.</p><p>En python :</p><pre><code class="language-bash">python3 -m http.server 5000 </code></pre><p>En PHP :</p><pre><code class="language-bash">php -S 0.0.0.0:5000 </code></pre><p>En Nodejs :</p><pre><code class="language-bash">npm i -g http-server http-server -p 5000 # ou npm i -g serve serve </code></pre><p>Avec webfsd :</p><pre><code class="language-bash">webfsd -F -p 5000 </code></pre><p>Références :</p><ul><li><a href="https://gist.github.com/willurd/5720255">https://gist.github.com/willurd/5720255</a></li></ul><![CDATA[Générer dynamiquement des images avec node-canvas]]>https://johackim.com/generer-dynamiquement-des-images-avec-node-canvashttps://johackim.com/generer-dynamiquement-des-images-avec-node-canvasMon, 05 Jul 2021 16:31:18 GMT<p>Pour générer des images de manière dynamique en Nodejs, il existe la librairie <code>node-canvas</code> :</p><pre><code class="language-bash">npm i -D canvas canvas-txt </code></pre><pre><code class="language-js">// script.js const fs = require(&#x27;fs&#x27;); const { createCanvas } = require(&#x27;canvas&#x27;); const { default: canvasTxt } = require(&#x27;canvas-txt&#x27;); const createImage = (text, path = &#x27;image.jpg&#x27;, width = 1600, height = 900) =&gt; { const canvas = createCanvas(width, height); const ctx = canvas.getContext(&#x27;2d&#x27;); ctx.fillStyle = &#x27;#101827&#x27;; ctx.fillRect(0, 0, width, height); canvasTxt.fontSize = 72; canvasTxt.fontWeight = 500; canvasTxt.font = &#x27;Roboto&#x27;; canvasTxt.align = &#x27;center&#x27;; canvasTxt.vAlign = &#x27;middle&#x27;; ctx.fillStyle = &#x27;#E5E7EB&#x27;; canvasTxt.drawText(ctx, text, 0, canvas.height / 4, canvas.width - 10, canvas.height / 2); const buffer = canvas.toBuffer(&#x27;image/jpeg&#x27;); fs.writeFileSync(path, buffer); }; createImage(&#x27;Hello World!&#x27;); </code></pre><p>Lorsque j&#x27;exécute ce script (<code>node script.js</code>), une image avec un fond gris et un texte blanc &quot;Hello World!&quot; sera créée.</p><p>C&#x27;est cette librairie que j&#x27;utilise pour générer automatiquement toutes les previews de mon <a href="https://johackim.com">Digital Garden</a>.</p><![CDATA[Créer un ebook à partir d'un fichier markown]]>https://johackim.com/creer-un-ebook-a-partir-d'un-fichier-markownhttps://johackim.com/creer-un-ebook-a-partir-d'un-fichier-markownSun, 27 Jun 2021 19:19:19 GMT<p>Pour créer un ebook à partir d&#x27;un fichier markdown, il est possible d&#x27;utiliser Pandoc sur Linux.</p><h2 id="installation-de-pandoc-sur-linux">Installation de Pandoc sur Linux</h2><p>Sur Ubuntu et Debian :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -y pandoc texlive texlive-latex-extra </code></pre><p>Sur Arch Linux :</p><pre><code class="language-bash">pacman -S --noconfirm pandoc texlive-bin texlive-core </code></pre><h2 id="creation-dun-ebook-au-format-epub">Création d&#x27;un ebook au format epub</h2><pre><code class="language-bash">pandoc input.md -o output.epub </code></pre><h2 id="creation-dun-ebook-au-format-pdf">Création d&#x27;un ebook au format pdf</h2><pre><code class="language-bash">pandoc input.md -o output.pdf </code></pre><h2 id="creation-dun-ebook-au-format-mobi">Création d&#x27;un ebook au format mobi</h2><pre><code class="language-bash">pandoc input.md -o output.mobi </code></pre><h2 id="creation-dun-ebook-avec-docker">Création d&#x27;un ebook avec Docker</h2><pre><code class="language-bash">docker run -it -v $PWD:/mnt pandoc/core input.md -o /mnt/output.mobi </code></pre><h2 id="ajouter-une-cover">Ajouter une cover</h2><p>Pour ajouter une cover :</p><pre><code class="language-bash">pandoc input.md --epub-cover-image cover.png -o output.epub </code></pre><![CDATA[Créer un fichier .gitignore automatiquement]]>https://johackim.com/creer-un-fichier-.gitignorehttps://johackim.com/creer-un-fichier-.gitignoreSun, 27 Jun 2021 19:19:19 GMT<p>Pour créer un fichier <code>.gitignore</code> rapidement, il existe le service <a href="https://gitignore.io/">gitignore.io</a>.</p><pre><code class="language-bash"># .bashrc gi () { curl -L &quot;https://www.gitignore.io/api/$@&quot; } </code></pre><p>À chaque fois que je souhaite créer un fichier <code>.gitignore</code>, pour un projet Nodejs par exemple, j&#x27;exécute la commande suivante :</p><pre><code class="language-bash">gi node &gt; .gitignore </code></pre><![CDATA[Extraire les sous-titres d'une vidéo YouTube]]>https://johackim.com/extraire-les-sous-titres-d'une-video-youtubehttps://johackim.com/extraire-les-sous-titres-d'une-video-youtubeSun, 27 Jun 2021 19:19:19 GMT<p>Pour extraire les sous-titres d&#x27;une vidéo YouTube, vous pouvez vous rendre sur le site <a href="https://savesubs.com/">https://savesubs.com/</a> et insérer l&#x27;URL de votre vidéo.</p><p>Ce service vous retournera un fichier <code>.srt</code> ou <code>.txt</code> de votre vidéo.</p><![CDATA[Installer facilement Arch Linux avec Anarchy Installer]]>https://johackim.com/installer-arch-linux-avec-anarchy-installerhttps://johackim.com/installer-arch-linux-avec-anarchy-installerSun, 27 Jun 2021 19:19:19 GMT<p>Anarchy Installer (anciennement Anarchy Linux) est un programme d&#x27;installation qui aide à configurer, à personnaliser et installer un système d&#x27;exploitation basé sur Arch Linux.</p><p>Le programme d&#x27;installation fournit un accès rapide à plusieurs environnements de bureau et à des configurations personnalisées.</p><p>Pour l&#x27;installer : </p><ol><li>Téléchargez <a href="https://gitlab.com/anarchyinstaller/installer/-/releases">le fichier ISO</a></li><li>Créez une clé USB bootable avec la commande <code>dd</code> ou avec <a href="https://www.balena.io/etcher/">Etcher</a></li></ol><pre><code class="language-bash">dd if=anarchy-1.3.3-x86_64.iso of=/dev/sdx status=progress conv=sync </code></pre><ol start="3"><li>Bootez la clé USB sur votre ordinateur et suivez les instructions 😉</li></ol><![CDATA[Mon processus de prise de notes]]>https://johackim.com/mon-processus-de-prise-de-noteshttps://johackim.com/mon-processus-de-prise-de-notesSun, 27 Jun 2021 19:19:19 GMT<p>Lorsque je prend des notes, j&#x27;utilise en partie la méthode <a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">Zettelkasten</a>.</p><p>Dès que j&#x27;ai des idées qui me viennent en tête, je prend des <a href="/notes-temporaires" title="Notes temporaires">notes temporaires</a> dans un fichier <a href="/soon" title="Markdown">Markdown</a> <code>inbox.md</code> dans <a href="/obsidian" title="Obsidian">Obsidian</a>.</p><p>Si je lis un livre, un article ou écoute un podcast, je rédige avec mes propres mots une <a href="/notes-litteraires" title="Notes littéraires">note littéraire</a> de tout ce qui m&#x27;intéresse dans le contenu.</p><p>Une fois la <a href="/notes-litteraires" title="Notes littéraires">note littéraire</a> terminé, je la divise en plusieurs <a href="/notes-permanentes" title="Notes permanentes">notes permanentes</a> (et <a href="/note-atomique" title="Note atomique">atomique</a>).</p><div class="mermaid" data-processed="true"><svg id="mermaid-1627299627832" width="100%" xmlns="http://www.w3.org/2000/svg" xmlnsXLink="http://www.w3.org/1999/xlink" height="142" style="max-width:339.875px" viewBox="0 0 339.875 142"><style>#mermaid-1627299627832{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-1627299627832 .error-icon{fill:#552222;}#mermaid-1627299627832 .error-text{fill:#552222;stroke:#552222;}#mermaid-1627299627832 .edge-thickness-normal{stroke-width:2px;}#mermaid-1627299627832 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1627299627832 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1627299627832 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1627299627832 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1627299627832 .marker{fill:#333333;stroke:#333333;}#mermaid-1627299627832 .marker.cross{stroke:#333333;}#mermaid-1627299627832 svg{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:16px;}#mermaid-1627299627832 .label{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;color:#333;}#mermaid-1627299627832 .cluster-label text{fill:#333;}#mermaid-1627299627832 .cluster-label span{color:#333;}#mermaid-1627299627832 .label text,#mermaid-1627299627832 span{fill:#333;color:#333;}#mermaid-1627299627832 .node rect,#mermaid-1627299627832 .node circle,#mermaid-1627299627832 .node ellipse,#mermaid-1627299627832 .node polygon,#mermaid-1627299627832 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-1627299627832 .node .label{text-align:center;}#mermaid-1627299627832 .node.clickable{cursor:pointer;}#mermaid-1627299627832 .arrowheadPath{fill:#333333;}#mermaid-1627299627832 .edgePath .path{stroke:#333333;stroke-width:1.5px;}#mermaid-1627299627832 .flowchart-link{stroke:#333333;fill:none;}#mermaid-1627299627832 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-1627299627832 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-1627299627832 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-1627299627832 .cluster text{fill:#333;}#mermaid-1627299627832 .cluster span{color:#333;}#mermaid-1627299627832 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:12px;background:hsl(80,100%,96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1627299627832:root{--mermaid-font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;}</style><g><g class="output"><g class="clusters"></g><g class="edgePaths"><g class="edgePath LS-Temporaire LE-Permanente" id="L-Temporaire-Permanente" style="opacity:1"><path class="path" d="M83.359375,46L83.359375,50.166666666666664C83.359375,54.333333333333336,83.359375,62.666666666666664,92.21058238636363,71C101.06178977272727,79.33333333333333,118.76420454545455,87.66666666666667,127.61541193181817,91.83333333333333L136.4666193181818,96" marker-end="url(#arrowhead8)" style="fill:none"></path><defs><marker id="arrowhead8" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker></defs></g><g class="edgePath LS-Littéraire LE-Permanente" id="L-Littéraire-Permanente" style="opacity:1"><path class="path" d="M270.296875,46L270.296875,50.166666666666664C270.296875,54.333333333333336,270.296875,62.666666666666664,261.4456676136364,71C252.59446022727275,79.33333333333333,234.89204545454547,87.66666666666667,226.04083806818184,91.83333333333333L217.1896306818182,96" marker-end="url(#arrowhead9)" style="fill:none"></path><defs><marker id="arrowhead9" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker></defs></g></g><g class="edgeLabels"><g class="edgeLabel" transform="" style="opacity:1"><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span id="L-L-Temporaire-Permanente" class="edgeLabel L-LS-Temporaire&#x27; L-LE-Permanente"></span></div></foreignObject></g></g><g class="edgeLabel" transform="" style="opacity:1"><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span id="L-L-Littéraire-Permanente" class="edgeLabel L-LS-Littéraire&#x27; L-LE-Permanente"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="flowchart-Temporaire-4" transform="translate(83.359375,27)" style="opacity:1"><rect rx="0" ry="0" x="-75.359375" y="-19" width="150.71875" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-65.359375,-9)"><foreignObject width="130.71875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Notes temporaires</div></foreignObject></g></g></g><g class="node default" id="flowchart-Permanente-5" transform="translate(176.828125,115)" style="opacity:1"><rect rx="0" ry="0" x="-71.8203125" y="-19" width="143.640625" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-61.8203125,-9)"><foreignObject width="123.640625" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Note permanente</div></foreignObject></g></g></g><g class="node default" id="flowchart-Littéraire-6" transform="translate(270.296875,27)" style="opacity:1"><rect rx="0" ry="0" x="-61.578125" y="-19" width="123.15625" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-51.578125,-9)"><foreignObject width="103.15625" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Notes littéraire</div></foreignObject></g></g></g></g></g></g></svg></div><p>Ce sur quoi mon processus diffère de la méthode <a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">Zettelkasten</a>, c&#x27;est que je transforme directement mes notes littéraires en plusieurs notes permanentes sans garder le contenu d&#x27;origine de la note littéraire pour ne pas avoir de duplications dans mon <a href="/hacklab" title="Hacklab">Second cerveau</a>.</p><p>J&#x27;ajoute quand même les références du contenu d&#x27;origine (URLs, page d&#x27;un livre, timecode d&#x27;une vidéo ou d&#x27;un podcast, etc...) pour avoir une trace des contenus originellement consommées.</p><p>Je me suis donné <strong>5 règles à respecter lorsque je prends des notes</strong> :</p><ol><li>Une note permanente <strong>ne doit pas dépasser une page</strong>.</li><li><strong>Ne jamais copier-coller</strong> un contenu.</li><li><strong>Utiliser ses propres mots</strong> pour rédiger une note.</li><li>Toujours renseigner les <strong>références</strong> d&#x27;une note.</li><li><strong>Une note = Un concept</strong>.</li></ol><![CDATA[Note atomique]]>https://johackim.com/note-atomiquehttps://johackim.com/note-atomiqueSun, 27 Jun 2021 19:19:19 GMT<p>Principe d&#x27;atomicité : regroupez les éléments qui appartiennent ensemble dans une seule note, attribuez-lui un identifiant, mais limitez son contenu à ce seul sujet.</p><p>La plupart des notes devraient essayer de ne pas dépasser une page - si elles le font, envisagez de les diviser.</p><p><mark class="font-bold">Une idée doit être égale à une note</mark>.</p><p>Références :</p><ul><li><a href="https://publish.obsidian.md/lyt-kit/Umami/Guiding+Principles+of+PKM">https://publish.obsidian.md/lyt-kit/Umami/Guiding+Principles+of+PKM</a></li><li><a href="https://zettelkasten.de/posts/overview/">https://zettelkasten.de/posts/overview/</a></li></ul><![CDATA[Notes littéraires]]>https://johackim.com/notes-litteraireshttps://johackim.com/notes-litterairesSun, 27 Jun 2021 19:19:19 GMT<p><strong>Une note littéraire est essentiellement une note que vous avez créée à partir d&#x27;un contenu que vous avez consommé (livres, articles, vidéos, films, podcasts, formations, discussions, etc...).</strong></p><p>Notez ce que vous ne voulez pas oublier ou ce que vous pensez pouvoir utiliser dans votre propre réflexion ou vos écrits.</p><p>Soyez bref, soyez extrêmement sélectif et utilisez vos propres mots.</p><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul><![CDATA[Notes permanentes]]>https://johackim.com/notes-permanenteshttps://johackim.com/notes-permanentesSun, 27 Jun 2021 19:19:19 GMT<p>Parcourez vos notes <a href="/notes-temporaires" title="Notes temporaires">temporaires</a> et <a href="/notes-litteraires" title="Notes littéraires">littéraires</a> et réfléchissez à la manière dont elles se rapportent à ce qui est pertinent pour vos propres recherches, réflexions ou intérêts.</p><p>L&#x27;idée n&#x27;est pas de collecter, mais de développer des idées, des arguments et des discussions.</p><p><strong>Rédigez une note pour chaque idée et écrivez comme si vous écriviez pour quelqu&#x27;un d&#x27;autre : utilisez des phrases complètes, indiquez vos sources, faites des références et essayez d&#x27;être aussi précis, clair et bref que possible.</strong></p><p>Jetez les notes éphémères et placez les notes littéraires dans votre <strong>système de référence</strong>. Vous pouvez les oublier maintenant. Tout ce qui compte, c&#x27;est ce qui se trouve dans la <strong>boite à chaussure</strong> des notes permanentes.</p><p><strong>Ajoutez vos nouvelles notes permanentes dans votre boîte à chaussure</strong>. Placez chaque note derrière une note associée (si elle ne se rapporte à aucune note existante, ajoutez-la à la toute fin).</p><p>Optionnellement, vous pouvez également :</p><ul><li>Ajouter des liens vers (et depuis) les notes associées.</li><li>Les ajouter à un «<strong>index</strong>» - un type spécial de note qui sert de «table des matières» et de point d&#x27;entrée pour un sujet important, y compris une collection triée de liens sur le sujet.</li></ul><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul><![CDATA[Notes temporaires]]>https://johackim.com/notes-temporaireshttps://johackim.com/notes-temporairesSun, 27 Jun 2021 19:19:19 GMT<p><strong>Ayez toujours quelque chose à portée de main avec lequel écrire pour capturer chaque idée qui vous vient à l&#x27;esprit</strong>. Ne vous préoccupez pas trop de la manière dont vous écrivez ou du support sur lequel vous écrivez.</p><p>Il s&#x27;agit de notes éphémères, de simples rappels de ce que vous avez en tête. Elles ne doivent pas vous distraire. <strong>Mettez-les dans un seul endroit, que vous définissez comme votre boîte de réception, et traitez-les plus tard</strong>.</p><p>Personnellement, j&#x27;ai 3 manières de prendre des note temporaires :</p><ol><li>Les &quot;Messages enregistrés&quot; de Telegram ou Signal quand je n&#x27;ai pas accès à mon PC.</li><li>Mon Rocketbook quand je suis sur mon bureau.</li><li>Un fichier markdown inbox.md dans Obisidian où je note tout ce qui me traverse l&#x27;esprit.</li></ol><p>Si vos pensées sont déjà triées et que vous avez le temps, vous pouvez sauter cette étape et écrire directement votre idée sous forme de note permanente.</p><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul><![CDATA[Supprimer l'espace libre d'un disque dur avec Linux]]>https://johackim.com/supprimer-l'espace-libre-d'un-disque-dur-avec-linuxhttps://johackim.com/supprimer-l'espace-libre-d'un-disque-dur-avec-linuxSun, 27 Jun 2021 19:19:19 GMT<p>Lorsqu&#x27;un fichier est supprimé, son contenu peut toujours être laissé dans le système de fichiers, à moins qu&#x27;il ne soit explicitement écrasé par autre chose.</p><p>Pour supprimer l&#x27;espace libre de son disque dur sur Linux, il existe la suite d&#x27;outils <a href="https://doc.ubuntu-fr.org/secure-delete">secure-delete</a> :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -y secure-delete </code></pre><p><code>srm</code> - Supprime en toute sécurité un fichier existant<br/> <code>smem</code> - Supprime en toute sécurité les traces d&#x27;un fichier dans la RAM<br/> <code>sfill</code> - Supprime tout l&#x27;espace libre de votre disque dur<br/> <code>sswap</code> - Supprime toutes les données du SWAP</p><p>Dans notre cas, la commande qui nous intéresse c&#x27;est <code>sfill</code> :</p><pre><code class="language-bash">sfill -f -v &lt;mountpoint&gt; </code></pre><p>Et pour ceux qui utilisent Arch Linux comme moi, vous pouvez utiliser la commande suivante :</p><pre><code class="language-bash">dd if=/dev/zero of=hugefile; sync; rm hugefile; sync </code></pre><p>Références :</p><ul><li><a href="https://wiki.archlinux.org/title/Securely_wipe_disk">https://wiki.archlinux.org/title/Securely_wipe_disk</a></li></ul><![CDATA[Tester les touches de son clavier sur Linux]]>https://johackim.com/tester-les-touches-de-son-clavier-sur-linuxhttps://johackim.com/tester-les-touches-de-son-clavier-sur-linuxSun, 27 Jun 2021 19:19:19 GMT<p>Pour tester et vérifier que les touches de son clavier fonctionne correctement, il existe un outil sur Linux du nom de <code>xev</code>, pour l&#x27;installer, exécutez la commande suivante :</p><pre><code class="language-bash">apt update &amp;&amp; apt -yq install xorg-xev </code></pre><p>Pour le lancer :</p><pre><code class="language-bash">xev </code></pre><p>Appuyez ensuite sur les touches de votre clavier pour vérifier si votre ordinateur les prend bien en compte.</p><![CDATA[Bloquer toutes les connexions entrantes avec iptables]]>https://johackim.com/bloquer-toutes-les-connexions-entrantes-avec-iptableshttps://johackim.com/bloquer-toutes-les-connexions-entrantes-avec-iptablesMon, 07 Jun 2021 20:36:50 GMT<p>Pour bloquer toutes les connexion entrantes avec iptables à l&#x27;exception des ports SSH et du protocole ICMP, voici les commandes à exécuter :</p><h2 id="vider-toutes-les-regles-iptables">Vider toutes les règles iptables</h2><pre><code class="language-bash">iptables -F iptables -F -t mangle iptables -F -t nat iptables -X iptables -X -t mangle iptables -X -t nat </code></pre><h2 id="bloquer-toutes-les-connexions-entrantes">Bloquer toutes les connexions entrantes</h2><pre><code class="language-bash">iptables -P INPUT DROP iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT </code></pre><h2 id="autoriser-les-connexions-provenant-de-linterface-de-loopback">Autoriser les connexions provenant de l&#x27;interface de loopback</h2><pre><code class="language-bash">iptables -A INPUT -i lo -j ACCEPT </code></pre><h2 id="autoriser-le-protocole-icmp">Autoriser le protocole icmp</h2><pre><code class="language-bash">iptables -A INPUT -p icmp -j ACCEPT </code></pre><h2 id="autoriser-le-port-22">Autoriser le port 22</h2><pre><code class="language-bash">iptables -A INPUT -p tcp --dport 22 -j ACCEPT </code></pre><h2 id="autoriser-toutes-les-connexions-sortantes">Autoriser toutes les connexions sortantes</h2><pre><code class="language-bash">iptables -P OUTPUT ACCEPT </code></pre><![CDATA[Créer un flux RSS avec Gatsby]]>https://johackim.com/creer-un-flux-rss-avec-gatsbyhttps://johackim.com/creer-un-flux-rss-avec-gatsbyMon, 07 Jun 2021 20:36:50 GMT<p>Pour créer un flux RSS avec Gatsby, installez le plugin <code>gatsby-plugin-feed</code> :</p><pre><code class="language-bash">npm install gatsby-plugin-feed </code></pre><p>Puis, ajoutez au fichier <code>gatsby-config.js</code> la configuration suivante :</p><pre><code class="language-js">// gatsby-config.js module.exports = { plugins: [ { resolve: `gatsby-plugin-feed`, }, ], }; </code></pre><![CDATA[Créer une bar de progression de lecture sur Gatsby]]>https://johackim.com/creer-une-bar-de-progression-de-lecture-sur-gatsbyhttps://johackim.com/creer-une-bar-de-progression-de-lecture-sur-gatsbyMon, 07 Jun 2021 20:36:50 GMT<p>Il existe <a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-page-progress/">un plugin Gatsby</a> qui permet d&#x27;automatiquement ajouter une bar de progression de lecture :</p><pre><code class="language-bash">npm i -D gatsby-plugin-page-progress </code></pre><pre><code class="language-javascript">// gatsby-config.js { resolve: &#x27;gatsby-plugin-page-progress&#x27;, options: { height: 3, prependToBody: false, color: &#x27;#4A5563&#x27;, footerHeight: 500, headerHeight: 0, }, }, </code></pre><![CDATA[Gérer les workspaces avec Terraform]]>https://johackim.com/gerer-les-workspaces-avec-terraformhttps://johackim.com/gerer-les-workspaces-avec-terraformMon, 07 Jun 2021 20:36:50 GMT<p>Terraform donne la possibilité de gérer facilement des espaces de travail :</p><h2 id="creer-un-workspace">Créer un workspace</h2><pre><code class="language-bash">terraform workspace new &lt;name&gt; </code></pre><p>Vous pouvez par exemple créer 2 espaces de travail <code>dev</code> et <code>prod</code> pour effectuer vos tests sur l&#x27;infructure de <code>dev</code> avant d&#x27;appliquer des changement sur l&#x27;infrastructure de <code>prod</code> :</p><pre><code class="language-bash">terraform workspace new dev terraform workspace new prod </code></pre><h2 id="selectionner-un-workspace">Sélectionner un workspace</h2><pre><code class="language-bash">terraform workspace select &lt;name&gt; </code></pre><h2 id="supprimer-un-workspace">Supprimer un workspace</h2><pre><code class="language-bash">terraform workspace delete &lt;name&gt; </code></pre><h2 id="lister-les-workspaces">Lister les workspaces</h2><pre><code class="language-bash">terraform workspace list </code></pre><![CDATA[Gérer un stockage Zapier avec cURL]]>https://johackim.com/gerer-un-stockage-zapier-avec-curlhttps://johackim.com/gerer-un-stockage-zapier-avec-curlMon, 07 Jun 2021 20:36:50 GMT<p>Zapier permet de stocker et de récupérer des données dans un mini-espace de stockage appelé <a href="https://zapier.com/help/doc/how-get-started-storage-zapier">Storage by Zapier</a>.</p><p>Personnellement, je me sers de cet espace de stockage pour stocker les données provenant des tâches Zapier, exemple : une liste de tweets qui s&#x27;autopublie sur Twitter.</p><p>Il est possible de récupérer le contenu d&#x27;un stockage Zapier avec une simple commande Linux curl :</p><pre><code class="language-bash">curl -s https://store.zapier.com/api/records\?secret\=&lt;uuid_secret_key&gt; </code></pre><p>Et pour ajouter des données à un stockage Zapier :</p><pre><code class="language-bash">curl -s -X POST -H &quot;Content-Type: application/json&quot; -d &#x27;{&quot;list&quot;: [&quot;item1&quot;, &quot;item2&quot;]}&#x27; https://store.zapier.com/api/records\?secret\=&lt;uuid_secret_key&gt; </code></pre><![CDATA[IPTV]]>https://johackim.com/iptvhttps://johackim.com/iptvMon, 07 Jun 2021 20:36:50 GMT<p>L’Internet Protocol TeleVision ou, IPTV, est le fait d’accéder à des chaines de télévision avec internet. Ce qui permet ’avoir accès à la télévision sur un ordinateur ou smartphone.</p><![CDATA[Initialiser eslint sur un projet JavaScript]]>https://johackim.com/initialiser-eslint-sur-un-projet-javascripthttps://johackim.com/initialiser-eslint-sur-un-projet-javascriptMon, 07 Jun 2021 20:36:50 GMT<p>Pour initialiser eslint sur un projet JavaScript il existe la commande suivante :</p><pre><code class="language-bash">npx eslint --init </code></pre><p>Personnellement j&#x27;ajoute les règles suivantes au fichier <code>.eslintrc</code> :</p><pre><code class="language-js">// .eslintrc &quot;rules&quot;: { &quot;indent&quot;: [2, 4, { &quot;SwitchCase&quot;: 1 }], &quot;max-len&quot;: [0], &quot;import/no-extraneous-dependencies&quot;: [0] &quot;react/jsx-filename-extension&quot;: [&quot;warn&quot;, { &quot;extensions&quot;: [&quot;.js&quot;, &quot;.jsx&quot;] }], &quot;react/jsx-indent-props&quot;: [2, 4], &quot;react/prop-types&quot;: [0], &quot;object-curly-newline&quot;: [0], &quot;react/no-unescaped-entities&quot;: [0] } </code></pre><![CDATA[Inspecter toutes les couches d'une image Docker]]>https://johackim.com/inspecter-toutes-les-couches-d'une-image-dockerhttps://johackim.com/inspecter-toutes-les-couches-d'une-image-dockerMon, 07 Jun 2021 20:36:50 GMT<p>Pour inspecter toutes les couches d&#x27;une image <a href="/docker" title="Docker">Docker</a>, il existe la commande suivante :</p><pre><code class="language-bash">docker history --no-trunc &lt;image&gt; </code></pre><![CDATA[Intégrer Tailwind CSS à gatsby]]>https://johackim.com/integrer-tailwind-css-a-gatsbyhttps://johackim.com/integrer-tailwind-css-a-gatsbyMon, 07 Jun 2021 20:36:50 GMT<p>Pour intégrer Tailwind CSS dans Gatsby, installez les packages npm suivants :</p><pre><code class="language-bash">npm i -D tailwindcss autoprefixer postcss </code></pre><p>Créez le fichier de configuration tailwind :</p><pre><code class="language-javascript">// tailwind.config.js module.exports = { purge: false, darkMode: &#x27;class&#x27;, theme: { extend: {}, }, variants: { extend: {}, }, plugins: [], }; </code></pre><p>Créez le fichier de configuration postcss <code>postcss.config.js</code> :</p><pre><code class="language-javascript">// postcss.config.js module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, }; </code></pre><p>Puis créez un fichier <code>style.css</code> à intégrer dans le fichier <code>gatsby-browser.js</code> :</p><pre><code class="language-css">/* src/style.css */ @tailwind base; @tailwind components; @tailwind utilities; </code></pre><pre><code class="language-js">// gatsby-browser.js import &#x27;./src/style.css&#x27;; </code></pre><p>Vous pouvez à présent utiliser Tailwind CSS partout dans votre code :</p><pre><code class="language-js">// src/pages/index.js import React from &#x27;react&#x27;; const IndexPage = () =&gt; ( &lt;p className=&quot;text-red-800&quot;&gt;Hello world!&lt;/p&gt; ); export default IndexPage; </code></pre><![CDATA[Kodi]]>https://johackim.com/kodihttps://johackim.com/kodiMon, 07 Jun 2021 20:36:50 GMT<p>Kodi (anciennement XBMC) est un lecteur multimédia libre qui tourne nativement sur les systèmes d’exploitation BSD, Raspbian, GNU/Linux, Mac OS X, Microsoft Windows, Android et iOS.</p><h2 id="installer-un-depot-sur-kodi">Installer un dépôt sur Kodi</h2><p>Un dépôt ou repository regroupe une sélection d&#x27;extensions (ou add-ons), que vous pouvez installer directement depuis l&#x27;application Kodi. Vous n&#x27;avez donc pas besoin de chercher add-on par add-on, tout est regroupé dans un dépôt ou repository.</p><p>Le plus connu de tous c&#x27;est <a href="https://superrepo.org/">SuperRepo</a> qui compte pas moins de 5000 add-ons.</p><p>Pour ajouter un dépôt :</p><ol><li>Rendez-vous dans Système (la petite icône engrenage en haut à gauche)</li><li>Dans gestionnaire de fichiers</li><li>Appuyer sur &quot;Ajouter une source&quot;</li><li>Ajouter l&#x27;adresse : <a href="http://srp.nu">http://srp.nu</a> là où il y a marqué &quot;aucun&quot;, et donnez lui un nom (ex: &quot;SuperRepo&quot;).</li><li>Rendez-vous ensuite dans Système -&gt; Extensions</li><li>Appuyer sur &quot;Installer depuis un fichier zip&quot;</li><li>Selectionnez votre source précédemment nommé &quot;SuperRepo&quot; -&gt; Krypton -&gt; all -&gt; superrepo.kodi.krypton.all-0.7.04.zip</li></ol><p>Voilà ! Maintenant vous pouvez parcourir toutes les extensions et prendre celles dont vous avez besoin depuis le menu Système -&gt; Extensions -&gt; Installer depuis un dépôt -&gt; SuperRepo.</p><p>Cette installation fonctionne avec SuperRepo de la même façon que n&#x27;importe quel autre dépôt ;).</p><![CDATA[Kopia]]>https://johackim.com/kopiahttps://johackim.com/kopiaMon, 07 Jun 2021 20:36:50 GMT<p><a href="https://github.com/kopia/kopia">Kopia</a> est un logiciel de sauvegarde disponible sur Windows, macOS et Linux.</p><p>Pour initialiser un dépôt :</p><pre><code class="language-bash">kopia repository create s3 --bucket=&lt;bucket&gt; --access-key=&lt;access_key&gt; --secret-access-key=&lt;secret_key&gt; --endpoint &lt;endpoint&gt; </code></pre><p>Pour créer une sauvegarde :</p><pre><code class="language-bash">kopia snapshot create &lt;dossier|fichier&gt; </code></pre><p>Pour monter un dépôt :</p><pre><code class="language-bash">kopia mount all &lt;dossier&gt; kopia mount &lt;snapshot_id&gt; &lt;dossier&gt; </code></pre><p>Pour se déconnecter d&#x27;un dépôt :</p><pre><code class="language-bash">kopia repository disconnect </code></pre><p>Pour se connecter à un dépôt :</p><pre><code class="language-bash">kopia repository connect s3 --bucket=&lt;bucket&gt; --access-key=&lt;access_key&gt; --secret-access-key=&lt;secret_key&gt; --endpoint &lt;endpoint&gt; </code></pre><p>Pour lister les sauvegardes :</p><pre><code class="language-bash">kopia snapshot list </code></pre><p>Pour lister les fichier d&#x27;une sauvegarde :</p><pre><code class="language-bash">kapia ls -l &lt;snpashot_id&gt; </code></pre><p>Pour supprimer une sauvegarde :</p><pre><code class="language-bash">kopia snapshot delete &lt;snapshot_id&gt; --delete </code></pre><p>Pour changer le type de compression :</p><pre><code class="language-bash">kopia policy set --global --compression=pgzip </code></pre><![CDATA[Mes films préférés]]>https://johackim.com/mes-films-prefereshttps://johackim.com/mes-films-preferesMon, 07 Jun 2021 20:36:50 GMT<ul><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=448.html">Retour vers le futur</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=27070.html">Le seigneur des anneaux</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=19776.html">Matrix</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=135564.html">Limitless</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=234023.html">Le fondateur</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=222858.html">Night Call</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=233140.html">Molly&#x27;s Game</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=140005.html">Le stratège</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=147912.html">The Social Network</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=198371.html">The Imitation Game</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=190918.html">Django Unchained</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=54098.html">À la recherche du bonheur</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=12475.html">American History X</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=363.html">Good Will Hunting</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=138673.html">Warrior</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=11736.html">Les évadés</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=47422.html">N&#x27;oublie jamais</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=115362.html">The Dark Knight</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=256661.html">Green Book</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=21189.html">Fight Club</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=4307.html">La Grande Vadrouille</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=134316.html">Good Morning England</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=225953.html">Whiplash</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=15282.html">Un air de famille</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=271682.html">Avengement</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=190267.html">Argo</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=123837.html">Wanted</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=28771.html">Phone Game</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=21608.html">American Pie</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=45361.html">Le jour d&#x27;après</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=25744.html">Memento</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=191696.html">Capitaine Phillips</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=126169.html">Taken</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=261322.html">L&#x27;intervention</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=217882.html">Gone Girl</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=46943.html">Le Dernier Samouraï</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=108998.html">Le prestige</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=262396.html">LE MANS 66</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=127524.html">Le Loup de Wall Street</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=192826.html">Gold</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=196253.html">War Dogs</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=227900.html">The big short</a></li><li><a href="https://www.allocine.fr/film/fichefilm_gen_cfilm=29298.html">Chevalier</a></li></ul><![CDATA[Mes jeux préférés]]>https://johackim.com/mes-jeux-prefereshttps://johackim.com/mes-jeux-preferesMon, 07 Jun 2021 20:36:50 GMT<ul><li><a href="https://www.jeuxvideo.com/jeux/pc/00020794-mount-blade.htm">Mount &amp; blade</a></li><li><a href="https://www.jeuxvideo.com/jeux/add-on/jeu-113394/">Age of empire</a></li><li><a href="https://www.tibosoftware.com/bad-toys.htm">Bad Toys 3D</a></li><li><a href="https://www.jeuxvideo.com/jeux/pc/00000439-goblins-3.htm">Goblins</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-55671/">Need for Speed : Conduite en Etat de Liberté</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-55623/">MDK</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-79254/">Hotline Miami</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-1056648/">Microsoft Flight Simulator</a></li><li><a href="https://www.jeuxvideo.com/jeux/pc/00000639-monster-truck-madness.htm">Monster Truck Madness</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-74347/">Jedi Knight II</a></li><li><a href="https://www.jeuxvideo.com/jeux/pc/jeu-766834/">Adibou</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-65185/">Far Cry 2</a></li><li><a href="https://www.jeuxvideo.com/jeux/pc/00000572-les-incroyables-machines-du-professeur-tim.htm">Professeur TIM</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-65346/">Skate</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-57067/">Grand Theft Auto 2</a></li><li><a href="https://www.jeuxvideo.com/jeux/pc/00000653-motocross-madness.htm">Motocross Madness</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-55676/">NHL 99</a></li><li><a href="https://www.jeuxvideo.com/jeux/jeu-55421/">Fifa 99</a></li></ul><![CDATA[Mes séries préférés]]>https://johackim.com/mes-series-prefereshttps://johackim.com/mes-series-preferesMon, 07 Jun 2021 20:36:50 GMT<ul><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=17966.html">Mr. Robot</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=3517.html">Breaking Bad</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=17907.html">Le bureau des légendes</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=10855.html">Black mirror</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=7663.html">House of cards</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=446.html">How I met your mother</a></li><li><a href="httpicals://www.allocine.fr/series/ficheserie_gen_cserie=21504.html">La Casa de Papel</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=10214.html">Vikings</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=20328.html">Dark</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=11701.html">Silicon Valley</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=7157.html">Game of thrones</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=30.html">The Wire</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=7330.html">The Walking Dead</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=19156.html">Stranger Things</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=669.html">H</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=23024.html">Sex Education</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=24940.html">How To Sell Drugs Online Fast</a></li><li><a href="https://www.allocine.fr/series/ficheserie_gen_cserie=21143.html">Atypical</a></li></ul><![CDATA[Rclone]]>https://johackim.com/rclonehttps://johackim.com/rcloneMon, 07 Jun 2021 20:36:50 GMT<p><a href="https://rclone.org/">Rclone</a> est un outil de backups open-source disponible sur Linux, macOS et Windows.</p><p>Pour configurer rclone :</p><pre><code class="language-bash">rclone config </code></pre><p>Pour configurer un stockage chiffré</p><pre><code class="language-bash">rclone config # Choisir &quot;crypt&quot; (11) comme type de stockage </code></pre><p>Pour monter un répertoire :</p><pre><code class="language-bash">rclone mount &lt;remote&gt;:/ &lt;folder&gt; </code></pre><p>Pour monter un répertoire avec un meilleur accès en lecture :</p><pre><code class="language-bash">rclone mount --vfs-cache-mode full &lt;remote&gt;:/ &lt;folder&gt; </code></pre><p>Copier des données d&#x27;un dossier à une source :</p><pre><code class="language-bash">rclone copy --progress &lt;folder&gt; &lt;remote&gt;:/ </code></pre><p>Copier des données d&#x27;une source à une autre :</p><pre><code class="language-bash">rclone copy --progress &lt;source&gt;:/ &lt;dest&gt;:/ </code></pre><p>Synchroniser deux souces avec les mêmes fichiers :</p><pre><code class="language-bash">rclone sync --progress &lt;source&gt;:/ &lt;remote&gt;:/ </code></pre><p>Voir tous les buckets :</p><pre><code class="language-bash">rclone lsd &lt;remote&gt;: </code></pre><p>Chiffrer la configuration rclone :</p><pre><code class="language-bash">rclone config # Set configuration password </code></pre><p>Vérifie les fichiers dans la correspondance source et destination :</p><pre><code class="language-bash">rclone check &lt;source&gt;:/ &lt;dest&gt;:/ </code></pre><p>Récupérer un fichier anciennement versionné dans un bucket B2 chez backblaze :</p><pre><code class="language-bash">rclone ls --b2-versions &lt;remote&gt;: rclone copy --progress --b2-versions &lt;remote&gt;:&lt;file&gt; . </code></pre><p>Supprimer les anciennes versions d&#x27;un fichier versionné dans un bucket B2 chez backblaze :</p><pre><code class="language-bash">rclone cleanup --b2-versions backblaze-crypt:/file.txt </code></pre><![CDATA[Regarder toutes les chaines de télévision gratuitement depuis son ordinateur]]>https://johackim.com/regarder-la-television-avec-kodihttps://johackim.com/regarder-la-television-avec-kodiMon, 07 Jun 2021 20:36:50 GMT<p>Pour regarder la télévision avec Kodi il existe un addon <a href="/iptv" title="IPTV">IPTV</a> du nom de <a href="https://kodi.wiki/view/Add-on:PVR_IPTV_Simple_Client">PVR IPTV Simple Client</a>.</p><p>Pour l&#x27;installer, <a href="/kodi#installer-un-depot-sur-kodi" title="Kodi">ajouter le dépôt SuperRepo</a> puis installer l&#x27;addon PVR IPTV Simple Client.</p><p>Une fois l&#x27;addon installé, configurez l&#x27;extension via Système -&gt; Extensions -&gt; Mes extensions -&gt; Client enregisteur vidéo -&gt; PVR IPTV Simple Client -&gt; Configurer.</p><p>Ajoutez l&#x27;URL de la liste de chaînes françaises M3U suivante : <a href="https://raw.githubusercontent.com/iptv-org/iptv/master/channels/fr.m3u">https://raw.githubusercontent.com/iptv-org/iptv/master/channels/fr.m3u</a></p><p>Redémarrez Kodi et accédez à toutes vos chaînes de télévision dans TV.</p><p>Pour accéder à d&#x27;autres chaînes que celle de la France, rendez-vous <a href="https://github.com/iptv-org/iptv/">sur ce dépôt Github</a> ou sur <a href="https://docs.google.com/spreadsheets/d/137Yw178ruq_v7_33al_B1PoGPyuGCANDNhLnDGXdrVg/">ce Spreadsheet</a>.</p><p>Et si vous ne trouvez pas une chaine, vous pouvez vous inscrire <a href="/vie-privee/comment-detenir-un-compte-google-anonyme" title="Compte Google anonyme">avec un compte gmail</a> sur le service <a href="https://bestbuyiptv.store/user/registration/register.html">bestbuyiptv</a> qui donne accès à une période d&#x27;essai gratuite de 24H.</p><![CDATA[Sauvegardes]]>https://johackim.com/sauvegardeshttps://johackim.com/sauvegardesMon, 07 Jun 2021 20:36:50 GMT<ul><li><a href="/types-de-sauvegarde" title="Types de sauvegarde">Types de sauvegarde</a></li><li><a href="/restic" title="Restic">Restic</a></li><li><a href="/soon" title="Borg">Borg</a></li><li><a href="/rclone" title="Rclone">Rclone</a></li><li><a href="/kopia" title="Kopia">Kopia</a></li></ul><![CDATA[Tester la vitesse d'écriture d'un disque dur sur Linux]]>https://johackim.com/tester-la-vitesse-d'ecriture-d'un-disque-dur-sur-linuxhttps://johackim.com/tester-la-vitesse-d'ecriture-d'un-disque-dur-sur-linuxMon, 07 Jun 2021 20:36:50 GMT<p>Pour tester la vitesse d&#x27;écriture d&#x27;un disque dur sur Linux, il existe une commande installé nativement sur la plus part des distributions Linux qui s&#x27;appelle <code>dd</code>.</p><pre><code class="language-bash">$ dd if=/dev/zero of=1g.bin bs=1G count=1 # 1+0 records in # 1+0 records out # 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 3.38203 s, 317 MB/s </code></pre><p>Dans ce cas présent, la vitesse d&#x27;écriture du disque dur est de 317 MB/s.</p><![CDATA[Les différents types de sauvegarde]]>https://johackim.com/types-de-sauvegardehttps://johackim.com/types-de-sauvegardeMon, 07 Jun 2021 20:36:50 GMT<h2 id="sauvegarde-complete">Sauvegarde complète</h2><p>Une sauvegarde complète est une copie totale de l&#x27;ensemble des données.</p><p>Chaque fois que vous effectuez une sauvegarde complète, vous stockez entièrement et une nouvelle fois la source de données.</p><h2 id="sauvegarde-incrementale">Sauvegarde incrémentale</h2><p>La sauvegarde incrémentale effectue d&#x27;abord une première copie complète de toutes vos données et chaque sauvegarde qui vient après permet d&#x27;enregistrer les modifications apportées depuis la dernière sauvegarde.</p><p>Contrairement à la sauvegarde complète, la sauvegarde incrémentale est très rapide à réaliser, mais plus lente à la restauration. Elle possède aussi l&#x27;avantage d&#x27;utiliser peu de quantité de stockage. Ce sera cette méthode que vous utiliserez avec la plupart des systèmes de stockage en ligne.</p><h2 id="sauvegarde-differentielle">Sauvegarde différentielle</h2><p>Une sauvegarde différentielle est une sauvegarde cumulative de tous les fichiers modifiés depuis la dernière sauvegarde.</p><p>Comme avec la sauvegarde incrémentale, la différentielle va effectuer une copie initiale et complète de tous vos fichiers et dossiers. Mais les prochaines sauvegardes vont permettre de stocker tous les changements apportés depuis votre dernière sauvegarde complète.</p><p>Ce type de sauvegarde permet d&#x27;enregistrer les données plus rapidement que la sauvegarde complète et demande aussi moins d&#x27;espace. Quant à la restauration, elle est plus rapide que celle de la sauvegarde incrémentale qui nécessite moins d&#x27;espace de stockage.</p><h2 id="sauvegarde-mirroir">Sauvegarde mirroir</h2><p>La sauvegarde miroir réalise une copie conforme des fichiers de votre système. Elle s&#x27;effectue ponctuellement et prend en compte l&#x27;ensemble des données sources telles qu&#x27;elles existaient lors de la dernière sauvegarde.</p><p>Ce procédé a l&#x27;avantage de proposer une restauration rapide et ne contient pas de fichiers anciens ou obsolètes.</p><p><a href="https://www.netexplorer.fr/blog/quels-sont-les-differents-types-de-sauvegardes">Source</a></p><![CDATA[Créer un script de parsing avec puppeteer]]>https://johackim.com/creer-un-script-de-parsing-avec-puppeteerhttps://johackim.com/creer-un-script-de-parsing-avec-puppeteerMon, 07 Jun 2021 20:36:50 GMT<p>Si vous souhaitez parser un site internet, il existe <a href="https://github.com/puppeteer/puppeteer">puppeteer</a>.</p><pre><code class="language-bash">npm i puppeteer </code></pre><p>Voici un exemple de script nodejs pour prendre un screenshot d&#x27;un site internet avec puppeteer :</p><pre><code class="language-js">#!/bin/node const puppeteer = require(&#x27;puppeteer&#x27;); (async () =&gt; { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(&#x27;https://johackim.com&#x27;); await page.screenshot({ path: &#x27;example.png&#x27; }); await browser.close(); })(); </code></pre><p>Vous pouvez reprendre l&#x27;URL d&#x27;une video intégré sur un site :</p><pre><code class="language-js">const url = await page.$eval(&#x27;video&#x27;, (a) =&gt; a.getAttribute(&#x27;src&#x27;)); </code></pre><p>Intégrer avec <code>youtube-dl</code>, vous pouvez enregistrer la vidéo en question :</p><pre><code class="language-js">await execSync(`youtube-dl -o &quot;${filePath}&quot; -f &#x27;best[ext=mp4]&#x27; ${url}`, { stdio: &#x27;inherit&#x27; }); </code></pre><p>Ou vous connecter automatiquement sur un site en remplissant automatiquement les champs <code>email</code> et <code>password</code> et sauvegarder le cookie dans un fichier :</p><pre><code class="language-js">await page.focus(&#x27;input#email&#x27;); await page.keyboard.type(email); await page.focus(&#x27;input#password&#x27;); await page.keyboard.type(password); await page.click(&#x27;.container form button[type=submit]&#x27;); await page.waitForSelector(&#x27;.logged-in&#x27;); const cookies = await page.cookies(); await page.setCookie(...cookies); fs.writeFileSync(&#x27;cookie.json&#x27;, JSON.stringify(cookies, null, 2)); </code></pre><![CDATA[Ajouter le support de la syntaxe markdown d'Obsidian dans Gatsby]]>https://johackim.com/ajouter-le-support-de-la-syntaxe-markdown-d'obsidian-dans-gatsbyhttps://johackim.com/ajouter-le-support-de-la-syntaxe-markdown-d'obsidian-dans-gatsbyMon, 31 May 2021 16:00:14 GMT<p>Les fichiers markdown dans <a href="/obsidian" title="Obsidian">Obsidian</a> peuvent avoir une syntaxe spéciale propre à Obsidian :</p><ul><li><a href="/soon" title="Internal link">Internal link</a></li><li><a href="/soon" title="With custom text">With custom text</a></li><li><a href="/soon#heading" title="Internal link">Internal link</a></li><li><a href="/soon#heading" title="With custom text">With custom text</a></li><li><a href="/soon" title="Embed note">Embed note</a></li><li><a href="/soon#heading" title="Embed note">Embed note</a></li></ul><undefined>Cette syntaxe permet de relier des notes entre elles via des liens bidirectionnels (<a href="/soon" title="Internal link">Internal link</a>).</undefined><p>Pour ajouter le support de ces liens, j&#x27;ai créé un plugin <a href="https://github.com/johackim/gatsby-remark-obsidian">gatsby-remark-obsidian</a>.</p><p>Vous pouvez intégrer ce plugin avec Remark ou MDX :</p><pre><code class="language-javascript">// gatsby-config.js plugins: [ { resolve: &quot;gatsby-transformer-remark&quot;, options: { plugins: [ { resolve: &#x27;gatsby-remark-obsidian&#x27;, }, ] } }, ], </code></pre><p>Si vous utilisez MDX :</p><pre><code class="language-javascript">// gatsby-config.js plugins: [ { resolve: &#x27;gatsby-plugin-mdx&#x27;, options: { extensions: [&#x27;.md&#x27;], gatsbyRemarkPlugins: [ { resolve: &#x27;gatsby-remark-obsidian&#x27;, }, ], }, }, ], </code></pre><![CDATA[Créer une table des matières des fichiers markdown avec Gatsby]]>https://johackim.com/creer-une-table-des-matieres-des-fichiers-markdown-avec-gatsbyhttps://johackim.com/creer-une-table-des-matieres-des-fichiers-markdown-avec-gatsbyMon, 31 May 2021 16:00:14 GMT<p>Après avoir <a href="/initialiser-un-projet-gatsby" title="Initialiser un projet Gatsby">Initialiser un projet Gatsby</a> et <a href="/importer-ses-notes-markdown-dans-gatsby" title="Importer ses notes markdown dans Gatsby">importer vos fichiers markdown</a>, vous pouvez créer automatiquement la table des matière d&#x27;un fichier markdown dans Gatsby.</p><pre><code class="language-javascript">// gatsby-node.js exports.createPages = async ({ actions, graphql, reporter }) =&gt; { const { createPage } = actions; const result = await graphql(` { allMarkdownRemark { edges { node { id html headings { value depth } parent { ... on File { name } } } } } } `); if (result.errors) { reporter.panicOnBuild(&#x27;Error while running GraphQL query.&#x27;); return; } const markdowns = result.data.allMarkdownRemark.edges; const noteTemplate = require.resolve(&#x27;./src/templates/noteTemplate.js&#x27;); markdowns.forEach(({ node }) =&gt; { const { id, html, headings } = node; createPage({ path: `/${node.parent.name}`, component: noteTemplate, context: { id, html, headings }, }); }); }; </code></pre><pre><code class="language-javascript">// src/components/toc.js import React from &#x27;react&#x27;; import { Link } from &#x27;gatsby&#x27;; import slugify from &#x27;slugify&#x27;; export default ({ headings = [], depthMin = 1, className = &#x27;&#x27; }) =&gt; { if (!headings.length) return false; return ( &lt;ul className={className}&gt; {headings.filter(({ depth }) =&gt; depth &gt;= depthMin).map(({ value }) =&gt; { const id = slugify(value, { lower: true, strict: true }); return ( &lt;li key={value}&gt; &lt;Link to={`#${id}`} title={value}&gt; {value} &lt;/Link&gt; &lt;/li&gt; ); })} &lt;/ul&gt; ); }; </code></pre><pre><code class="language-js">// src/templates/noteTemplate.js import React from &#x27;react&#x27;; import Toc from &#x27;../components/toc&#x27;; export default function Template({ pageContext }) { const { html, headings } = pageContext; return ( &lt;&gt; &lt;Toc headings={headings} depthMin={2} /&gt; &lt;div dangerouslySetInnerHTML={{ __html: html }} /&gt; &lt;/&gt; ); } </code></pre><p>Pour créer automatiquement les id sur chaque header, il existe le plugin <a href="https://www.gatsbyjs.com/plugins/gatsby-remark-autolink-headers/">gatsby-remark-autolink-headers</a> :</p><pre><code class="language-npm">npm i -D gatsby-remark-autolink-headers </code></pre><pre><code class="language-javascript">// gatsby-config.js module.exports = { plugins: [ { resolve: &#x27;gatsby-source-filesystem&#x27;, options: { path: &#x27;./content&#x27;, }, }, { resolve: &#x27;gatsby-transformer-remark&#x27;, options: { plugins: [ { resolve: &#x27;gatsby-remark-autolink-headers&#x27;, options: { icon: false, }, }, ], }, }, ], }; </code></pre><![CDATA[Importer ses notes markdown dans Gatsby]]>https://johackim.com/importer-ses-notes-markdown-dans-gatsbyhttps://johackim.com/importer-ses-notes-markdown-dans-gatsbyMon, 31 May 2021 16:00:14 GMT<p>Après avoir <a href="/initialiser-un-projet-gatsby" title="Initialiser un projet Gatsby">Initialiser un projet Gatsby</a>, créez un dossier <code>content</code> qui va contenir toutes vos notes au format markdown (ex: <code>content/hello-world.md</code>).</p><p><strong>NOTE</strong> : Vous pouvez ouvrir se dossier avec Obsidian ou n&#x27;importe quel editeur de fichier markdown pour éditer vos notes.</p><p>Importez et configurez le package <code>gatsby-source-filesystem</code> &amp; <code>gatsby-transformer-remark</code> pour pouvoir detecter vos fichiers markdown dans Gatsby :</p><pre><code class="language-bash">npm i -D gatsby-source-filesystem gatsby-transformer-remark </code></pre><pre><code class="language-javascript">// gatsby-config.js module.exports = { plugins: [ { resolve: &#x27;gatsby-source-filesystem&#x27;, options: { path: &#x27;./content&#x27;, }, }, { resolve: &#x27;gatsby-transformer-remark&#x27;, }, ], }; </code></pre><p>Créez le fichier gatsby-node.js avec la configuration si dessous pour pouvoir créer des pages pour chacune de vos notes markdown :</p><pre><code class="language-js">// gatsby-node.js exports.createPages = async ({ actions, graphql, reporter }) =&gt; { const { createPage } = actions; const result = await graphql(` { allMarkdownRemark { edges { node { id html parent { ... on File { name } } } } } } `); if (result.errors) { reporter.panicOnBuild(&#x27;Error while running GraphQL query.&#x27;); return; } const markdowns = result.data.allMarkdownRemark.edges; const noteTemplate = require.resolve(&#x27;./src/templates/noteTemplate.js&#x27;); markdowns.forEach(({ node }) =&gt; { const { id, html } = node; createPage({ path: `/${node.parent.name}`, component: noteTemplate, context: { id, html }, }); }); }; </code></pre><pre><code class="language-js">// src/templates/noteTemplate.js import React from &#x27;react&#x27;; export default function Template({ pageContext }) { const { html } = pageContext; return &lt;div dangerouslySetInnerHTML={{ __html: html }} /&gt;; } </code></pre><p>Si vous avez une note <code>hello-world.md</code> dans votre dossier <code>content</code> et que vous vous rendez à l&#x27;adresse http://localhost:8000/hello-world, cela devrait afficher le contenu de votre fichier markdown. </p><![CDATA[Initialiser un projet Gatsby]]>https://johackim.com/initialiser-un-projet-gatsbyhttps://johackim.com/initialiser-un-projet-gatsbyMon, 31 May 2021 16:00:14 GMT<p>Pour initialiser un projet Gatsby, il suffit d&#x27;installer <a href="https://nodejs.org">node.js</a> puis exécuter cette commande :</p><pre><code class="language-bash">npm install --save gatsby </code></pre><p>Une fois installé, vous pouvez démarrer Gatsby :</p><pre><code class="language-bash">./node_modules/.bin/gatsby develop </code></pre><p>Ajoutez les lignes suivantes dans votre fichier <code>package.json</code> afin d&#x27;avoir accès aux commandes gatsby plus facilement :</p><pre><code class="language-json">&quot;scripts&quot;: { &quot;build&quot;: &quot;gatsby build&quot;, &quot;start&quot;: &quot;gatsby develop&quot;, &quot;serve&quot;: &quot;gatsby serve&quot;, &quot;clean&quot;: &quot;gatsby clean&quot; } </code></pre><p>Vous pouvez à présent exécuter la commande <code>npm start</code> pour démarrer Gatsby.</p><![CDATA[Créer un digital garden de A à Z avec Gatsby et Obsidian]]>https://johackim.com/creer-un-digital-gardenhttps://johackim.com/creer-un-digital-gardenMon, 31 May 2021 15:50:46 GMT<h2 id="i-initialiser-un-projet-gatsby">I. Initialiser un projet Gatsby</h2><p><p>Pour initialiser un projet Gatsby, il suffit d&#x27;installer <a href="https://nodejs.org">node.js</a> puis exécuter cette commande :</p><pre><code class="language-bash">npm install --save gatsby </code></pre><p>Une fois installé, vous pouvez démarrer Gatsby :</p><pre><code class="language-bash">./node_modules/.bin/gatsby develop </code></pre><p>Ajoutez les lignes suivantes dans votre fichier <code>package.json</code> afin d&#x27;avoir accès aux commandes gatsby plus facilement :</p><pre><code class="language-json">&quot;scripts&quot;: { &quot;build&quot;: &quot;gatsby build&quot;, &quot;start&quot;: &quot;gatsby develop&quot;, &quot;serve&quot;: &quot;gatsby serve&quot;, &quot;clean&quot;: &quot;gatsby clean&quot; } </code></pre><p>Vous pouvez à présent exécuter la commande <code>npm start</code> pour démarrer Gatsby.</p></p><h2 id="ii-importer-ses-notes-markdown">II. Importer ses notes markdown</h2><p><p>Après avoir <a href="/initialiser-un-projet-gatsby" title="Initialiser un projet Gatsby">Initialiser un projet Gatsby</a>, créez un dossier <code>content</code> qui va contenir toutes vos notes au format markdown (ex: <code>content/hello-world.md</code>).</p><p><strong>NOTE</strong> : Vous pouvez ouvrir se dossier avec Obsidian ou n&#x27;importe quel editeur de fichier markdown pour éditer vos notes.</p><p>Importez et configurez le package <code>gatsby-source-filesystem</code> &amp; <code>gatsby-transformer-remark</code> pour pouvoir detecter vos fichiers markdown dans Gatsby :</p><pre><code class="language-bash">npm i -D gatsby-source-filesystem gatsby-transformer-remark </code></pre><pre><code class="language-javascript">// gatsby-config.js module.exports = { plugins: [ { resolve: &#x27;gatsby-source-filesystem&#x27;, options: { path: &#x27;./content&#x27;, }, }, { resolve: &#x27;gatsby-transformer-remark&#x27;, }, ], }; </code></pre><p>Créez le fichier gatsby-node.js avec la configuration si dessous pour pouvoir créer des pages pour chacune de vos notes markdown :</p><pre><code class="language-js">// gatsby-node.js exports.createPages = async ({ actions, graphql, reporter }) =&gt; { const { createPage } = actions; const result = await graphql(` { allMarkdownRemark { edges { node { id html parent { ... on File { name } } } } } } `); if (result.errors) { reporter.panicOnBuild(&#x27;Error while running GraphQL query.&#x27;); return; } const markdowns = result.data.allMarkdownRemark.edges; const noteTemplate = require.resolve(&#x27;./src/templates/noteTemplate.js&#x27;); markdowns.forEach(({ node }) =&gt; { const { id, html } = node; createPage({ path: `/${node.parent.name}`, component: noteTemplate, context: { id, html }, }); }); }; </code></pre><pre><code class="language-js">// src/templates/noteTemplate.js import React from &#x27;react&#x27;; export default function Template({ pageContext }) { const { html } = pageContext; return &lt;div dangerouslySetInnerHTML={{ __html: html }} /&gt;; } </code></pre><p>Si vous avez une note <code>hello-world.md</code> dans votre dossier <code>content</code> et que vous vous rendez à l&#x27;adresse http://localhost:8000/hello-world, cela devrait afficher le contenu de votre fichier markdown. </p></p><h2 id="iii-ajouter-le-support-de-la-syntaxe-markdown-dobsidian">III. Ajouter le support de la syntaxe markdown d&#x27;Obsidian</h2><p><p>Les fichiers markdown dans <a href="/obsidian" title="Obsidian">Obsidian</a> peuvent avoir une syntaxe spéciale propre à Obsidian :</p><ul><li><a href="/soon" title="Internal link">Internal link</a></li><li><a href="/soon" title="With custom text">With custom text</a></li><li><a href="/soon#heading" title="Internal link">Internal link</a></li><li><a href="/soon#heading" title="With custom text">With custom text</a></li><li><a href="/soon" title="Embed note">Embed note</a></li><li><a href="/soon#heading" title="Embed note">Embed note</a></li></ul><undefined>Cette syntaxe permet de relier des notes entre elles via des liens bidirectionnels (<a href="/soon" title="Internal link">Internal link</a>).</undefined><p>Pour ajouter le support de ces liens, j&#x27;ai créé un plugin <a href="https://github.com/johackim/gatsby-remark-obsidian">gatsby-remark-obsidian</a>.</p><p>Vous pouvez intégrer ce plugin avec Remark ou MDX :</p><pre><code class="language-javascript">// gatsby-config.js plugins: [ { resolve: &quot;gatsby-transformer-remark&quot;, options: { plugins: [ { resolve: &#x27;gatsby-remark-obsidian&#x27;, }, ] } }, ], </code></pre><p>Si vous utilisez MDX :</p><pre><code class="language-javascript">// gatsby-config.js plugins: [ { resolve: &#x27;gatsby-plugin-mdx&#x27;, options: { extensions: [&#x27;.md&#x27;], gatsbyRemarkPlugins: [ { resolve: &#x27;gatsby-remark-obsidian&#x27;, }, ], }, }, ], </code></pre></p><h2 id="iv-creer-un-graph-viewer-comme-obsidian">IV. Créer un Graph Viewer comme Obsidian</h2><p><p>Pour <a href="https://johackim.com/explore">créer un Graph Viewer comme Obsidian dans Gatsby</a> et afficher visuellement les liens des fichiers markdowns, il existe la librairie <a href="https://github.com/visjs/vis-network">vis-network</a> :</p><pre><code class="language-bash">npm i -D react-graph-vis gatsby-source-filesystem gatsby-transformer-remark gatsby-transformer-markdown-references </code></pre><pre><code class="language-javascript">// gatsby-config.js module.exports = { plugins: [ { resolve: &#x27;gatsby-source-filesystem&#x27;, options: { path: &#x27;./content&#x27;, }, }, { resolve: &#x27;gatsby-transformer-remark&#x27;, }, { resolve: &#x27;gatsby-transformer-markdown-references&#x27;, options: { types: [&#x27;MarkdownRemark&#x27;], }, }, ], }; </code></pre><p>Créez la page <code>index.js</code> et le composant <code>graph.js</code>.</p><pre><code class="language-javascript">// src/pages/index.js import React from &#x27;react&#x27;; import { graphql } from &#x27;gatsby&#x27;; import Graph from &#x27;../components/graph&#x27;; const IndexPage = ({ data: { allMarkdownRemark } }) =&gt; { const nodes = allMarkdownRemark.edges.map(({ node }) =&gt; node); return ( &lt;div style={{ height: &#x27;100vh&#x27; }}&gt; &lt;Graph nodes={nodes} /&gt;; &lt;/div&gt; ); }; export const query = graphql` { allMarkdownRemark { edges { node { id parent { ... on File { name } } inboundReferences { ... on MarkdownRemark { parent { ... on File { id name } } } } outboundReferences { ... on MarkdownRemark { parent { ... on File { id name } } } } } } } } `; export default IndexPage; </code></pre><pre><code class="language-javascript">// src/components/graph.js import React, { useState } from &#x27;react&#x27;; import Graph from &#x27;react-graph-vis&#x27;; import { navigate } from &#x27;gatsby&#x27;; export default ({ nodes = [] }) =&gt; { const [network, setNetwork] = useState(); const sizes = { DEFAULT: 10, MEDIUM: 20, LARGE: 30 }; const graph = { nodes: [], edges: [] }; const options = { nodes: { color: &#x27;#000&#x27;, font: { color: &#x27;#000&#x27; }, shape: &#x27;dot&#x27;, size: 10, widthConstraint: { maximum: 300 }, }, layout: { hierarchical: false, }, edges: { color: &#x27;#000&#x27;, arrows: { to: { enabled: false } }, }, interaction: { hover: true, tooltipDelay: 3000000, }, physics: { enabled: true, solver: &#x27;repulsion&#x27;, repulsion: { nodeDistance: 200, }, }, }; const computeSize = (refs) =&gt; { if (refs &gt;= 5) return sizes.MEDIUM; if (refs &gt;= 10) return sizes.LARGE; return sizes.DEFAULT; }; const createVisNode = (node) =&gt; { let size = sizes.DEFAULT; if (node.inboundReferences &amp;&amp; node.outboundReferences) { size = computeSize(node.inboundReferences.length + node.outboundReferences.length); } return { id: node.parent.name, name: node.parent.name, size, url: `/${node.parent.name}`, label: node.parent.name, title: node.parent.name, }; }; nodes.forEach((node) =&gt; { const { inboundReferences, outboundReferences } = node; graph.nodes.push(createVisNode(node)); inboundReferences.forEach((inboundReference) =&gt; { graph.edges.push({ from: inboundReference.parent.name, to: node.parent.name }); if (nodes.length === 1) { graph.nodes.push(createVisNode(inboundReference)); } }); outboundReferences.forEach((outboundReference) =&gt; { graph.edges.push({ from: node.parent.name, to: outboundReference.parent.name }); if (nodes.length === 1) { graph.nodes.push(createVisNode(outboundReference)); } }); }); graph.nodes = [...new Set(graph.nodes)]; const events = { click: (event) =&gt; { const selectedNode = graph.nodes.find((node) =&gt; node.id === event.nodes[0]); if (selectedNode) { const { url } = selectedNode; navigate(url); } }, blurEdge: () =&gt; { network.canvas.body.container.style.cursor = &#x27;default&#x27;; }, blurNode: () =&gt; { network.canvas.body.container.style.cursor = &#x27;default&#x27;; }, hoverNode: () =&gt; { network.canvas.body.container.style.cursor = &#x27;pointer&#x27;; }, }; return ( &lt;Graph graph={graph} events={events} getNetwork={(n) =&gt; setNetwork(n)} options={options} /&gt; ); }; </code></pre><p>À présent, si vous créer deux fichier markdowns, ils seront afficher dans votre Graph Viewer :</p><pre><code class="language-markdown">&lt;!-- content/note1.md --&gt; Hello [[note2]] </code></pre><pre><code class="language-markdown">&lt;!-- content/note2.md --&gt; Hello world! </code></pre></p><h2 id="v-creer-automatiquement-une-table-des-matieres-des-fichiers-markdown">V. Créer automatiquement une table des matières des fichiers markdown</h2><p><p>Après avoir <a href="/initialiser-un-projet-gatsby" title="Initialiser un projet Gatsby">Initialiser un projet Gatsby</a> et <a href="/importer-ses-notes-markdown-dans-gatsby" title="Importer ses notes markdown dans Gatsby">importer vos fichiers markdown</a>, vous pouvez créer automatiquement la table des matière d&#x27;un fichier markdown dans Gatsby.</p><pre><code class="language-javascript">// gatsby-node.js exports.createPages = async ({ actions, graphql, reporter }) =&gt; { const { createPage } = actions; const result = await graphql(` { allMarkdownRemark { edges { node { id html headings { value depth } parent { ... on File { name } } } } } } `); if (result.errors) { reporter.panicOnBuild(&#x27;Error while running GraphQL query.&#x27;); return; } const markdowns = result.data.allMarkdownRemark.edges; const noteTemplate = require.resolve(&#x27;./src/templates/noteTemplate.js&#x27;); markdowns.forEach(({ node }) =&gt; { const { id, html, headings } = node; createPage({ path: `/${node.parent.name}`, component: noteTemplate, context: { id, html, headings }, }); }); }; </code></pre><pre><code class="language-javascript">// src/components/toc.js import React from &#x27;react&#x27;; import { Link } from &#x27;gatsby&#x27;; import slugify from &#x27;slugify&#x27;; export default ({ headings = [], depthMin = 1, className = &#x27;&#x27; }) =&gt; { if (!headings.length) return false; return ( &lt;ul className={className}&gt; {headings.filter(({ depth }) =&gt; depth &gt;= depthMin).map(({ value }) =&gt; { const id = slugify(value, { lower: true, strict: true }); return ( &lt;li key={value}&gt; &lt;Link to={`#${id}`} title={value}&gt; {value} &lt;/Link&gt; &lt;/li&gt; ); })} &lt;/ul&gt; ); }; </code></pre><pre><code class="language-js">// src/templates/noteTemplate.js import React from &#x27;react&#x27;; import Toc from &#x27;../components/toc&#x27;; export default function Template({ pageContext }) { const { html, headings } = pageContext; return ( &lt;&gt; &lt;Toc headings={headings} depthMin={2} /&gt; &lt;div dangerouslySetInnerHTML={{ __html: html }} /&gt; &lt;/&gt; ); } </code></pre><p>Pour créer automatiquement les id sur chaque header, il existe le plugin <a href="https://www.gatsbyjs.com/plugins/gatsby-remark-autolink-headers/">gatsby-remark-autolink-headers</a> :</p><pre><code class="language-npm">npm i -D gatsby-remark-autolink-headers </code></pre><pre><code class="language-javascript">// gatsby-config.js module.exports = { plugins: [ { resolve: &#x27;gatsby-source-filesystem&#x27;, options: { path: &#x27;./content&#x27;, }, }, { resolve: &#x27;gatsby-transformer-remark&#x27;, options: { plugins: [ { resolve: &#x27;gatsby-remark-autolink-headers&#x27;, options: { icon: false, }, }, ], }, }, ], }; </code></pre></p><h2 id="vi-ameliorer-le-seo-de-votre-digital-garden">VI. Améliorer le SEO de votre digital garden</h2><p><p>Pour améliorer le SEO d&#x27;un site Gatsby, il existe le plugin <code>helmet</code> qui permet d&#x27;overrider les balises meta de votre site :</p><pre><code class="language-bash">npm i -D react-helmet </code></pre><p>Ensuite, créez le fichier <code>src/component/seo.js</code> qui génerera toutes les balises meta nécessaires pour un bon référencement :</p><pre><code class="language-javascript">// src/components/seo.js import React from &#x27;react&#x27;; import Helmet from &#x27;react-helmet&#x27;; import { useLocation } from &#x27;@reach/router&#x27;; import { useStaticQuery, graphql } from &#x27;gatsby&#x27;; export default ({ title, image, description, article, datePublished, dateModified, tags = [], meta = [] }) =&gt; { const location = useLocation(); const { site } = useStaticQuery(graphql` query { site { siteMetadata { title lang logo description author twitter siteUrl siteName } } } `); const defaultTitle = site.siteMetadata?.title; const defaultDescription = site.siteMetadata?.description; return ( &lt;Helmet htmlAttributes={{ lang: site.siteMetadata.lang }} title={title || defaultTitle} meta={[ { name: &#x27;description&#x27;, content: description || defaultDescription, }, { property: &#x27;og:url&#x27;, content: location.href, }, { property: &#x27;og:site_name&#x27;, content: site.siteMetadata.siteName, }, { property: &#x27;og:title&#x27;, content: title || defaultTitle, }, { property: &#x27;og:description&#x27;, content: description || defaultDescription, }, { property: &#x27;og:type&#x27;, content: article ? &#x27;article&#x27; : &#x27;website&#x27;, }, ...(image ? [{ property: &#x27;og:image&#x27;, content: image, }] : []), ...(tags ? tags.map((tag) =&gt; ({ property: &#x27;article:tag&#x27;, content: tag, })) : []), { name: &#x27;twitter:title&#x27;, content: title || defaultTitle, }, { name: &#x27;twitter:creator&#x27;, content: site.siteMetadata.twitter, }, { name: &#x27;twitter:site&#x27;, content: site.siteMetadata.twitter, }, { name: &#x27;twitter:description&#x27;, content: description || defaultDescription, }, ...(image ? [{ name: &#x27;twitter:image&#x27;, content: image, }, { name: &#x27;twitter:card&#x27;, content: &#x27;summary_large_image&#x27;, }] : [{ name: &#x27;twitter:card&#x27;, content: &#x27;summary&#x27;, }]), ].concat(meta)} &gt; &lt;script type=&quot;application/ld+json&quot;&gt; {JSON.stringify({ &#x27;@context&#x27;: &#x27;https://schema.org&#x27;, &#x27;@type&#x27;: article ? &#x27;Article&#x27; : &#x27;WebSite&#x27;, mainEntityOfPage: { &#x27;@type&#x27;: &#x27;WebPage&#x27;, &#x27;@id&#x27;: site.siteMetadata?.siteUrl, }, url: location.href, headline: title || defaultTitle, author: { &#x27;@type&#x27;: &#x27;Person&#x27;, name: site.siteMetadata.author, }, publisher: { &#x27;@type&#x27;: &#x27;Organization&#x27;, name: site.siteMetadata.author, url: site.siteMetadata?.siteUrl, logo: { &#x27;@type&#x27;: &#x27;ImageObject&#x27;, url: site.siteMetadata.logo, }, }, description: description || defaultDescription, ...(image &amp;&amp; { image }), ...(dateModified &amp;&amp; { dateModified }), ...(datePublished &amp;&amp; { datePublished }), })} &lt;/script&gt; &lt;/Helmet&gt; ); }; </code></pre><p>Vous pouvez gérer les données par défault de votre site dans le fichier <code>gatsby-config.js</code> :</p><pre><code class="language-js">// gatsby-config.js module.exports = { siteMetadata: { title: &#x27;Website Title&#x27;, siteName: &#x27;Website Name&#x27;, description: &#x27;Description&#x27;, author: &#x27;author&#x27;, twitter: &#x27;@author&#x27;, logo: &#x27;http://example.com/logo.png&#x27;, lang: &#x27;fr&#x27;, siteUrl: &#x27;https://example.com&#x27;, } }; </code></pre><p>Vous pouvez Intégrer le composant <code>SEO</code> dans la page de votre choix (ex: <code>index.js</code>) :</p><pre><code class="language-js">// src/pages/index.js import React from &#x27;react&#x27;; import SEO from &#x27;../components/seo&#x27;; const IndexPage = () =&gt; ( &lt;&gt; &lt;SEO /&gt; &lt;p className=&quot;text-red-800&quot;&gt;Hello world!&lt;/p&gt; &lt;/&gt; ); export default IndexPage; </code></pre><p>Pour remplacer les balises meta par défaut, vous pouvez ajouter des propriétés au composant <code>&lt;SEO /&gt;</code> :</p><pre><code class="language-jsx">&lt;SEO title=&quot;title&quot; description=&quot;description&quot; image=&quot;https://example.com/image.png&quot; dateModified=&quot;2020-01-01T08:00:00.000Z&quot; datePublished=&quot;2020-01-01T08:00:00.000Z&quot; tags={[&quot;tag1&quot;, &quot;tag2&quot;]} article={true} /&gt; </code></pre></p><![CDATA[Contourner la protection Cloudflare]]>https://johackim.com/contourner-la-protection-cloudflarehttps://johackim.com/contourner-la-protection-cloudflareSun, 30 May 2021 19:50:38 GMT<p><a href="https://github.com/FlareSolverr/FlareSolverr">FlareSolverr</a> est un serveur proxy pour contourner la protection Cloudflare.</p><p><strong>NOTE</strong> : Pour l&#x27;instant, aucun des solveurs de captcha ne fonctionne. Vous pouvez vérifier l&#x27;état d&#x27;avancement <a href="https://github.com/FlareSolverr/FlareSolverr/issues">sur Github</a>.</p><p>Pour le démarrer avec <a href="/docker" title="Docker">Docker</a> :</p><pre><code class="language-bash">docker run -p 8191:8191 -e LOG_LEVEL=info ghcr.io/flaresolverr/flaresolverr:latest </code></pre><p>FlareSolverr peut être personnalisé pour résoudre les captchas automatiquement en définissant la variable d&#x27;environnement <code>CAPTCHA_SOLVER</code> avec le nom de l&#x27;un des resolvers (<code>hcaptcha-solver</code> ou <code>harvester</code>), exemple :</p><pre><code class="language-bash">docker run -p 8191:8191 -e LOG_LEVEL=info -e CAPTCHA_SOLVER=hcaptcha-solver ghcr.io/flaresolverr/flaresolverr:latest </code></pre><p>Pour utiliser FlareSolverr, envoyez une requête curl :</p><pre><code class="language-bash">curl -L -X POST &#x27;http://localhost:8191/v1&#x27; \ -H &#x27;Content-Type: application/json&#x27; \ --data-raw &#x27;{ &quot;cmd&quot;: &quot;request.get&quot;, &quot;url&quot;:&quot;http://yggtorrent.li/&quot;, &quot;userAgent&quot;: &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleW...&quot;, &quot;maxTimeout&quot;: 60000 }&#x27; </code></pre><![CDATA[Créer un service Docker avec plusieurs replicas]]>https://johackim.com/creer-un-service-docker-avec-plusieurs-replicashttps://johackim.com/creer-un-service-docker-avec-plusieurs-replicasSun, 30 May 2021 19:50:38 GMT<p>Il est possible de créer plusieurs conteneurs dans un seul service Docker. Ces conteneurs sont appelé des replicas.</p><div class="mermaid" data-processed="true"><svg id="mermaid-1627299625547" width="100%" xmlns="http://www.w3.org/2000/svg" xmlnsXLink="http://www.w3.org/1999/xlink" height="142" style="max-width:413.5px" viewBox="0 0 413.5 142"><style>#mermaid-1627299625547{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-1627299625547 .error-icon{fill:#552222;}#mermaid-1627299625547 .error-text{fill:#552222;stroke:#552222;}#mermaid-1627299625547 .edge-thickness-normal{stroke-width:2px;}#mermaid-1627299625547 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1627299625547 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1627299625547 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1627299625547 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1627299625547 .marker{fill:#333333;stroke:#333333;}#mermaid-1627299625547 .marker.cross{stroke:#333333;}#mermaid-1627299625547 svg{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:16px;}#mermaid-1627299625547 .label{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;color:#333;}#mermaid-1627299625547 .cluster-label text{fill:#333;}#mermaid-1627299625547 .cluster-label span{color:#333;}#mermaid-1627299625547 .label text,#mermaid-1627299625547 span{fill:#333;color:#333;}#mermaid-1627299625547 .node rect,#mermaid-1627299625547 .node circle,#mermaid-1627299625547 .node ellipse,#mermaid-1627299625547 .node polygon,#mermaid-1627299625547 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-1627299625547 .node .label{text-align:center;}#mermaid-1627299625547 .node.clickable{cursor:pointer;}#mermaid-1627299625547 .arrowheadPath{fill:#333333;}#mermaid-1627299625547 .edgePath .path{stroke:#333333;stroke-width:1.5px;}#mermaid-1627299625547 .flowchart-link{stroke:#333333;fill:none;}#mermaid-1627299625547 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-1627299625547 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-1627299625547 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-1627299625547 .cluster text{fill:#333;}#mermaid-1627299625547 .cluster span{color:#333;}#mermaid-1627299625547 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:12px;background:hsl(80,100%,96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1627299625547:root{--mermaid-font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;}</style><g><g class="output"><g class="clusters"></g><g class="edgePaths"><g class="edgePath LS-Service LE-Conteneur1" id="L-Service-Conteneur1" style="opacity:1"><path class="path" d="M176.7421875,37.660542883682524L157.62369791666666,43.21711906973544C138.50520833333334,48.77369525578835,100.26822916666667,59.88684762789418,81.14973958333333,69.61009048061375C62.03125,79.33333333333333,62.03125,87.66666666666667,62.03125,91.83333333333333L62.03125,96" marker-end="url(#arrowhead9)" style="fill:none"></path><defs><marker id="arrowhead9" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker></defs></g><g class="edgePath LS-Service LE-Conteneur2" id="L-Service-Conteneur2" style="opacity:1"><path class="path" d="M213.421875,46L213.421875,50.166666666666664C213.421875,54.333333333333336,213.421875,62.666666666666664,213.421875,71C213.421875,79.33333333333333,213.421875,87.66666666666667,213.421875,91.83333333333333L213.421875,96" marker-end="url(#arrowhead10)" style="fill:none"></path><defs><marker id="arrowhead10" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker></defs></g><g class="edgePath LS-Service LE-Conteneur3" id="L-Service-Conteneur3" style="opacity:1"><path class="path" d="M250.1015625,38.1520190023753L268.1080729166667,43.62668250197942C286.1145833333333,49.10134600158353,322.1276041666667,60.05067300079177,340.1341145833333,69.69200316706255C358.140625,79.33333333333333,358.140625,87.66666666666667,358.140625,91.83333333333333L358.140625,96" marker-end="url(#arrowhead11)" style="fill:none;stroke-width:2px;stroke-dasharray:3"></path><defs><marker id="arrowhead11" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowheadPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker></defs></g></g><g class="edgeLabels"><g class="edgeLabel" transform="" style="opacity:1"><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span id="L-L-Service-Conteneur1" class="edgeLabel L-LS-Service&#x27; L-LE-Conteneur1"></span></div></foreignObject></g></g><g class="edgeLabel" transform="" style="opacity:1"><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span id="L-L-Service-Conteneur2" class="edgeLabel L-LS-Service&#x27; L-LE-Conteneur2"></span></div></foreignObject></g></g><g class="edgeLabel" transform="" style="opacity:1"><g transform="translate(0,0)" class="label"><rect rx="0" ry="0" width="0" height="0"></rect><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span id="L-L-Service-Conteneur3" class="edgeLabel L-LS-Service&#x27; L-LE-Conteneur3"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="flowchart-Service-6" transform="translate(213.421875,27)" style="opacity:1"><rect rx="0" ry="0" x="-36.6796875" y="-19" width="73.359375" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-26.6796875,-9)"><foreignObject width="53.359375" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Service</div></foreignObject></g></g></g><g class="node default" id="flowchart-Conteneur1-7" transform="translate(62.03125,115)" style="opacity:1"><rect rx="0" ry="0" x="-54.03125" y="-19" width="108.0625" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-44.03125,-9)"><foreignObject width="88.0625" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Conteneur 1</div></foreignObject></g></g></g><g class="node default" id="flowchart-Conteneur2-9" transform="translate(213.421875,115)" style="opacity:1"><rect rx="0" ry="0" x="-47.359375" y="-19" width="94.71875" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-37.359375,-9)"><foreignObject width="74.71875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Conteneur</div></foreignObject></g></g></g><g class="node default" id="flowchart-Conteneur3-11" transform="translate(358.140625,115)" style="opacity:1"><rect rx="0" ry="0" x="-47.359375" y="-19" width="94.71875" height="38" class="label-container"></rect><g class="label" transform="translate(0,0)"><g transform="translate(-37.359375,-9)"><foreignObject width="74.71875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap">Conteneur</div></foreignObject></g></g></g></g></g></g></svg></div><p>La commande suivante aura pour objectif de créer 3 replicas basé sur l&#x27;image Docker ghost :</p><pre><code class="language-bash">docker service create --replicas 3 ghost </code></pre><p>Si on exécute la commande <code>docker ps -a</code>, on remarquera l&#x27;apparition de 3 conteneurs ghost.</p><![CDATA[Créer un service Docker]]>https://johackim.com/creer-un-service-dockerhttps://johackim.com/creer-un-service-dockerSun, 30 May 2021 19:50:38 GMT<p>Pour créer un service, il suffit d&#x27;exécuter une commande <code>docker service create</code> :</p><pre><code class="language-bash">docker service create -p published=2368,target=2368,mode=host ghost </code></pre><p>Vous pouvez accéder à votre application Ghost à l&#x27;adresse : http://localhost:2368</p><![CDATA[Détruire l'infrastructure]]>https://johackim.com/detruire-l'infrastructurehttps://johackim.com/detruire-l'infrastructureSun, 30 May 2021 19:50:38 GMT<p>Pour détruire une infrastructure géré par Terraform :</p><pre><code class="language-bash">terraform destroy </code></pre><![CDATA[Héberger un site sur le réseau IPFS]]>https://johackim.com/ipfshttps://johackim.com/ipfsSun, 30 May 2021 19:50:38 GMT<p>IPFS est un système de fichiers interplanétaire </p><p>InterPlanetary File System (ou IPFS, système de fichier inter-planétaire) est un protocole et un réseau peer-to-peer pour le stockage et le partage de données dans un système de fichiers distribué.</p><h2 id="heberger-un-site-sur-ipfs">Héberger un site sur IPFS</h2><p>Voici 6 étapes à suivre pour héberger un site sur le réseau peer-to-peer IPFS :</p><ol><li>Télécharger et démarrer l&#x27;application <a href="https://github.com/ipfs/ipfs-desktop#install">ipfs-desktop</a></li><li>Importer un dossier <code>test</code> avec un fichier <code>index.html</code> dans l&#x27;onglet &quot;Files&quot;</li><li>Récupérer un lien de partage ou le hash (CID) en effectuant un clic droit sur le dossier</li><li>Activer l&#x27;extension <a href="https://github.com/ipfs/ipfs-companion">ipfs-companion</a> sur votre navigateur</li><li>Rendez-vous sur une passerelle ipfs comme ipfs.io ou cloudflare-ipfs.com pour accéder à votre site : <code>https://ipfs.io/ipfs/&lt;votre_hash_ici&gt;</code> </li></ol><h2 id="relier-un-nom-de-domaine-a-un-site-web-heberge-sur-ipfs">Relier un nom de domaine à un site web hébergé sur IPFS</h2><p>Vous pouvez utiliser une passerelle (Gateway Provider) comme <a href="https://www.cloudflare.com/distributed-web-gateway/">Cloudflare</a> pour relier un nom de domaine.</p><ul><li>Créez une zone DNS CNAME <code>votre.site</code> qui pointe sur <code>www.cloudflare-ipfs.com.</code></li><li>Créez une zone DNS TXT <code>_dnslink.your.website</code> avec la valeur <code>dnslink=/ipfs/&lt;votre_hash_ici&gt;</code></li><li>Ajoutez votre nom de domaine sur <a href="https://www.cloudflare.com/distributed-web-gateway/">le site de Cloudflare</a> dans la partie &quot;Connecting Your Website&quot; (tout en bas de la page) et appuyez sur &quot;Submit&quot;.</li></ul><p>Plus de details sur <a href="https://developers.cloudflare.com/distributed-web/ipfs-gateway/connecting-website#connecting-to-cloudflares-gateway">la documentation de cloudflare</a>.</p><p>Références :</p><ul><li><a href="https://fr.wikipedia.org/wiki/InterPlanetary_File_System">https://fr.wikipedia.org/wiki/InterPlanetary_File_System</a></li><li><a href="https://developers.cloudflare.com/distributed-web/ipfs-gateway">https://developers.cloudflare.com/distributed-web/ipfs-gateway</a></li></ul><![CDATA[Initialiser terraform]]>https://johackim.com/initialiser-terraformhttps://johackim.com/initialiser-terraformSun, 30 May 2021 19:50:38 GMT<p>Pour initialiser terraform, créez un fichier <code>main.tf</code>, exemple :</p><pre><code class="language-json">// main.tf terraform { required_providers { docker = { source = &quot;kreuzwerker/docker&quot; } } } resource &quot;docker_image&quot; &quot;image_id&quot; { name = &quot;ghost:latest&quot; } </code></pre><p>Cet exemple demande l&#x27;utilisation de Docker sur notre machine hôte, n&#x27;oubliez pas d&#x27;<a href="/installer-docker" title="Installer Docker">installer Docker</a>.</p><p>Puis exécutez la commande suivante :</p><pre><code class="language-bash">terraform init </code></pre><![CDATA[Jackett - Un méta-moteur de torrents bien pratique]]>https://johackim.com/jacketthttps://johackim.com/jackettSun, 30 May 2021 19:50:38 GMT<p>Jackett est un métamoteur de torrents open-source. Il peut être intégrer dans des outils de recherche de torrent comme qBittorrent par exemple.</p><p>Pour l&#x27;installer avec <a href="/docker" title="Docker">Docker</a>, exécutez la commande suivante :</p><pre><code class="language-bash">docker run -d --name jackett --restart=always -v ~/.jackett/config:/config -v ~/.jackett/downloads:/downloads -p 9117:9117 linuxserver/jackett </code></pre><p>Vous pouvez ensuite vous rendre à l&#x27;adresse http://localhost:9117/ pour ajouter des Trackers torrent.</p><p>Vous pouvez aussi paramétrer <a href="/contourner-la-protection-cloudflare" title="Contourner la protection Cloudflare">un proxy pour contourner cloudflare</a> si besoin.</p><![CDATA[Augmentez automatiquement son ratio sur les sites de torrent]]>https://johackim.com/joalhttps://johackim.com/joalSun, 30 May 2021 19:50:38 GMT<p>Joal est un outil pour augmenter automatiquement son ratio sur les sites de torrent.</p><p><strong>NOTE</strong> : N&#x27;utilisez cet outil UNIQUEMENT en cas d&#x27;extrème nécessité car cela nuit au principe de partage.</p><p>Pour l&#x27;installer, commencez par télécharger <a href="https://github.com/anthonyraymond/joal/releases/download/2.1.24/joal.tar.gz">les fichiers de configurations</a> nécessaires à l&#x27;utilisation de Joal :</p><pre><code class="language-bash">export VERSION=2.1.24 mkdir ~/.joal wget -O ~/.joal/joal.tar.gz https://github.com/anthonyraymond/joal/releases/download/$VERSION/joal.tar.gz tar xvf ~/.joal/joal.tar.gz -C ~/.joal </code></pre><pre><code class="language-json">// ~/.joal/config.json { &quot;minUploadRate&quot; : 10000, &quot;maxUploadRate&quot; : 10000, &quot;simultaneousSeed&quot; : 5, &quot;client&quot; : &quot;qbittorrent-4.2.5.client&quot;, &quot;keepTorrentWithZeroLeechers&quot; : true } </code></pre><p>Puis lancez la commande <a href="/docker" title="Docker">Docker</a> suivante pour démarrer Joal :</p><pre><code class="language-bash">docker run -d \ -p 8080:8080 \ -v ~/.joal:/data \ --name=&quot;joal&quot; \ anthonyraymond/joal \ --joal-conf=&quot;/data&quot; \ --spring.main.web-environment=true \ --server.port=&quot;8080&quot; \ --joal.ui.path.prefix=&quot;SECRET_PATH&quot; \ --joal.ui.secret-token=&quot;SECRET_TOKEN&quot; \ --restart=always </code></pre><p>Accéder à l&#x27;adresse http://localhost:8080/SECRET_PATH/ui/#/ puis cliquez sur le bouton &quot;Change connection settings&quot; pour renseigner les paramètres suivants :</p><ul><li>Path Prefix -&gt; SECRET_PATH</li><li>Secret Token -&gt; SECRET_TOKEN</li></ul><p>Enfin, ajoutez un fichier torrent de tracker à l&#x27;aide du bouton &quot;+&quot; vert en bas à droite et attendez jusqu&#x27;à atteindre le ratio qui vous convient.</p><![CDATA[Mettre à jour l'infrastructure]]>https://johackim.com/mettre-a-jour-l'infrastructurehttps://johackim.com/mettre-a-jour-l'infrastructureSun, 30 May 2021 19:50:38 GMT<p>Pour mettre à jour l&#x27;infrastructure :</p><pre><code class="language-bash">terraform apply </code></pre><![CDATA[Regarder la méteo depuis un terminal]]>https://johackim.com/regarder-la-meteo-depuis-un-terminalhttps://johackim.com/regarder-la-meteo-depuis-un-terminalSun, 30 May 2021 19:50:38 GMT<p>Pour regarder la météo depuis un terminal, il existe le projet Github <a href="https://github.com/chubin/wttr.in">wttr.in</a> qui permet de consulter la méteo de sa ville avec une simple commande curl depuis un terminal Linux, Mac ou Windows.</p><p>Exemple pour la ville de Paris :</p><pre><code class="language-bash">curl http://wttr.in/Paris </code></pre><p>Pour mettre la langue en français :</p><pre><code class="language-bash">curl http://wttr.in/Paris\?lang\=fr </code></pre><p>Pour supprimer le message de fin :</p><pre><code class="language-bash">curl http://wttr.in/Paris\?lang\=fr\&amp;F </code></pre><p>Vous pouvez ajouter un alias dans votre fichier <code>.bashrc</code> ou <code>.zshrc</code> :</p><pre><code class="language-bash">alias meteo=&quot;curl http://wttr.in/Paris\?lang\=fr\&amp;F&quot; </code></pre><p>Comme ça, vous pouvez à tout moment connaitre la météo en tapant la commande <code>meteo</code> dans votre terminal.</p><![CDATA[Télecharger les vidéos de l'espace membre d'un site]]>https://johackim.com/telecharger-les-videos-de-l'espace-membre-d'un-sitehttps://johackim.com/telecharger-les-videos-de-l'espace-membre-d'un-siteSun, 30 May 2021 19:50:38 GMT<p>Pour télecharger les vidéos de l&#x27;espace membre d&#x27;un site, il suffit de se connecter au site, de reprendre le cookie puis d&#x27;utiliser <a href="https://github.com/ytdl-org/youtube-dl">youtube-dl</a> ou <a href="https://mrs0m30n3.github.io/youtube-dl-gui/">youtube-dl-gui</a> pour télécharger les vidéos que vous souhaitez.</p><ol><li><p>Installez l&#x27;extension Firefox <a href="https://addons.mozilla.org/en-US/firefox/addon/cookies-txt/">cookies.txt</a> ou l&#x27;extension Chrome <a href="https://chrome.google.com/webstore/detail/get-cookiestxt/bgaddhkoddajcdgocldbbfleckgcbcid">Get cookies.txt</a>.</p></li><li><p>Connectez vous à l&#x27;espace membre du site en question.</p></li><li><p>Installez <code>youtube-dl</code> et exécutez la commande suivante :</p></li></ol><pre><code class="language-bash">youtube-dl --cookies cookies.txt -f hd_mp4-720p &lt;url&gt; </code></pre><p>Si il y a beaucoup de vidéos, vous pouvez parser le site afin de reprendre toutes les URLs dans un fichier texte (ex: <code>links.txt</code>) puis exécuter la commande suivante :</p><pre><code class="language-bash">for link in $(cat links.txt); do youtube-dl --cookie cookies.txt $link; done; </code></pre><p>Il est aussi possible de coupler <code>youtube-dl</code> avec <a href="/creer-un-script-de-parsing-avec-puppeteer" title="Créer un script de parsing avec puppeteer">Puppeteer</a> pour parser et télécharger toutes les vidéo de l&#x27;espace membre d&#x27;un site internet automatiquement.</p><![CDATA[Bypasser les raccourcisseurs d'URL comme bitly]]>https://johackim.com/universal-bypasshttps://johackim.com/universal-bypassSun, 30 May 2021 19:50:38 GMT<p><a href="https://github.com/Sainan/Universal-Bypass">Universal Bypass</a> est une extension open-source pour navigateur qui permet de d&#x27;outrepasser les redirections des liens généré par les raccourcisseurs d&#x27;url comme bitly.</p><p>L&#x27;extension est disponible sur les navigateurs <a href="https://addons.mozilla.org/en-US/firefox/addon/universal-bypass/">Firefox</a>, <a href="https://github.com/Sainan/Universal-Bypass/releases/download/13.15.2/Universal.Bypass.for.Chromium-based.browsers.zip">Chrome</a> et <a href="https://microsoftedge.microsoft.com/addons/detail/universal-bypass/ckiidekccfgninkobmmofopbbdgdclgg">Edge</a>.</p><p>Ça peut être utile pour des services qui nous font passer par plusieurs redirections à la suite pour pouvoir accéder à un contenu en ligne comme certain débrideurs (ex: <a href="https://leechpremium.link/index.php">LeechPremium</a>).</p><![CDATA[ClamAV - Un logiciel de sécurité pour détecter les malwares]]>https://johackim.com/clamavhttps://johackim.com/clamavTue, 18 May 2021 21:17:59 GMT<p><a href="https://github.com/Cisco-Talos/clamav-devel">Clam AntiVirus</a> (ClamAV) est logiciel de sécurité pour détecter les malwares.</p><p>ClamAV est l&#x27;un des rares antivirus disponible sous GNU/Linux et MacOS. Les virus ciblés sont majoritairement des virus s&#x27;attaquant au système d&#x27;exploitation Windows.</p><p>Pour l&#x27;installer sur Debian ou Ubuntu :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -y clamav </code></pre><p>Pour mettre à jour sa base de donnée :</p><pre><code class="language-bash">freshclam </code></pre><p>Pour scanner un fichier, un répertoire ou tout le système de fichier :</p><pre><code class="language-bash">clamscan &lt;file&gt; clamscan --recursive --infected &lt;folder&gt; clamscan --recursive --infected --exclude-dir=&#x27;^/sys|^/dev&#x27; / </code></pre><p>Pour executé ClamAV en tâche de fond vous pouvez exécutez la commande suivante :</p><pre><code class="language-bash">clamd </code></pre><![CDATA[DPI]]>https://johackim.com/dpihttps://johackim.com/dpiTue, 18 May 2021 21:17:59 GMT<p>L&#x27;inspection profonde de paquets ou <strong>DPI</strong> (deep packet inspection) est une technique utilisée par certaines organisations ou gouvernements (ex: la Chine), pour analyser, identifier et filtrer le trafic Internet de manière profonde. C&#x27;est par ce moyen qu&#x27;un pays comme la chine censure tous les citoyens en interdisant l&#x27;utilisation de VPNs pour contrôler et limiter la population à l&#x27;utilisation de leurs applications et réseaux internes (Baidu, WeChat, ect...).</p><![CDATA[Hardening]]>https://johackim.com/hardeninghttps://johackim.com/hardeningTue, 18 May 2021 21:17:59 GMT<p>Le durcissement (ou <strong>hardening</strong> en anglais) est un processus destiné à sécuriser un système en réduisant le plus possible sa surface d&#x27;attaque.</p><p>Pour ça, on supprime tout ce qui n&#x27;est pas indispensable :</p><ul><li>Utilisateurs et droits inutiles</li><li>Mots de passe par défaut</li><li>Bibliothèques logicielles inutiles</li><li>Fichiers de configurations inutiles</li><li>Services inutiles</li><li>etc...</li></ul><p>Pour ça il existe des outils comme <a href="https://github.com/CISOfy/lynis">lynis</a> pour analyser son système et fournir des conseils pour le renforcer (<code>lynis audit system</code>).</p><p>Pour automatiser ce processus d&#x27;hardening sur un serveur Ubuntu ou Debian il est possible d&#x27;utiliser Ansible avec le dépot <a href="https://github.com/dev-sec/ansible-collection-hardening/">ansible-collection-hardening</a> :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -yq python3-pip &amp;&amp; pip3 install ansible ansible-galaxy collection install devsec.hardening </code></pre><pre><code class="language-yaml"># playbook.yml - hosts: localhost collections: - devsec.hardening roles: - os_hardening </code></pre><pre><code class="language-bash">ansible-playbook playbook.yml </code></pre><![CDATA[IDS]]>https://johackim.com/idshttps://johackim.com/idsTue, 18 May 2021 21:17:59 GMT<p>Un <strong>système de détection d&#x27;intrusion</strong> (ou <strong>IDS</strong> : Intrusion Detection System) est un logiciel utilisé pour monitorer et détecter les activités anormales ou suspectes sur un réseau ou un système de fichier.</p><p>De manière générale, il existe 2 types d&#x27;IDS ;</p><ol><li><p>Les Systèmes de détection d&#x27;intrusion réseau (ou <strong>NIDS</strong> : Network Intrusion Detection System) ; ceux qui analysent le trafic réseau entrant.</p></li><li><p>Les Systèmes de détection d&#x27;intrusion hôtes (ou <strong>HIDS</strong> : Host-based Intrusion Detection System) ; ceux qui analysent les systèmes de fichier.</p></li></ol><p>Concernant les <strong>méthodes de détection d&#x27;intrusion</strong>, elles sont généralement classifiées en deux catégories :</p><ul><li><p><strong>Détection basée sur les signatures</strong> : l&#x27;IDS basé sur les signatures surveille les paquets dans le réseau et les compare avec des modèles d&#x27;attaque préconfigurés et prédéterminés appelés signatures.</p></li><li><p><strong>Détection basée sur les anomalies</strong> : l&#x27;IDS basé sur des anomalies surveillera le trafic réseau et le comparera à une base de référence établie. La ligne de base identifiera ce qui est «normal» pour ce réseau - quel type de bande passante est généralement utilisé et quels protocoles sont utilisés.</p></li></ul><p>Les IDS les plus populaires sont :</p><ul><li><a href="https://github.com/snort3/snort3">Snort</a></li><li><a href="https://github.com/OISF/suricata">Suricata</a></li><li><a href="https://github.com/fail2ban/fail2ban">fail2ban</a></li><li><a href="https://github.com/zeek/zeek">Zeek</a></li><li><a href="https://github.com/ossec/ossec-hids">OSSEC</a></li><li><a href="https://github.com/wazuh/wazuh">Wazuh</a></li></ul><p>Il existe aussi des distributions qui intègrent un IDS :</p><ul><li><a href="https://github.com/Security-Onion-Solutions/securityonion">Security Onion</a></li><li><a href="https://github.com/StamusNetworks/SELKS">SELKS</a></li></ul><![CDATA[IPS]]>https://johackim.com/ipshttps://johackim.com/ipsTue, 18 May 2021 21:17:59 GMT<p>Un <strong>système de prévention d&#x27;intrusion</strong> (ou <strong>IPS</strong> : Intrusion Prevention System), également appelé système de détection et de prévention des intrusions (ou <strong>IDPS</strong> : <strong>intrusion detection and prevention systems</strong>), est un logiciel pour détecter et bloquer les activités anormales ou suspecte sur un réseau ou un système de fichier.</p><p>De manière générale, il existe 2 types d&#x27;IPS ;</p><ol><li><p>Les Systèmes de prévention d&#x27;intrusion réseaux (ou <strong>NIPS</strong> : Network Intrusion Prevention System) ; ceux qui détecte et bloque le trafic réseau entrant suspect.</p></li><li><p>Les Systèmes de prévention d&#x27;intrusion hôtes (ou <strong>HIPS</strong> : Host-based Intrusion Prevention System) ; ceux qui analyse et bloque les comportements suspect sur un système de fichier.</p></li></ol><p>Contrairement aux <a href="/ids" title="IDS">systèmes de détection d&#x27;intrusion</a> qui se contentent d&#x27;analyser des données pour émettre des alertes, les IPS (ou IDPS) sont des outils permettant de bloquer une attaque.</p><![CDATA[MasterPassword]]>https://johackim.com/masterpasswordhttps://johackim.com/masterpasswordTue, 18 May 2021 21:17:59 GMT<p><a href="https://www.masterpasswordapp.com/">MasterPassword</a> est une <strong>application de mot de passe</strong> qui ne stocke aucun mot de passe, il contient un algorithme pour <strong>créer des mots de passe uniques de manière reproductible</strong>.</p><p><strong>Vous retenez uniquement un seul mot de passe et l&#x27;algorithme se charge du reste.</strong></p><p>Exemple : si vous voulez générer/retrouver le mot de passe de votre compte Twitter, vous devez renseigner 3 informations dans l&#x27;application :</p><ol><li>Votre Identifiant Twitter (ex: johackim)</li><li>L&#x27;URL ou le nom de l&#x27;application (ex: twitter.com)</li><li>Votre MasterPassword (ex: mym@sterp@ssw0rd)</li></ol><p>Et cela vous génère un mot de passe unique basé sur ces 3 informations que vous pouvez utiliser en tant que mot de passe Twitter.</p><p><strong>Aucun mot de passe n&#x27;est stocké nulle part</strong>. Cela évite de se faire voler ou de perdre son mot de passe. À condition de ne jamais oublier son MasterPassword.</p><p>Il existe une version web, Linux, Mac, Windows, iOS et Android.</p><![CDATA[Pare-feu]]>https://johackim.com/pare-feuhttps://johackim.com/pare-feuTue, 18 May 2021 21:17:59 GMT<p>Un pare-feu (ou firewall) est un logiciel ou matériel de sécurité permettant d&#x27;autoriser ou bloquer le trafic entrant et/ou sortant d&#x27;un réseau.</p><p>Les pare-feu open-source les plus populaires sont :</p><ul><li><a href="https://www.pfsense.org/">pfSense</a></li><li><a href="https://opnsense.org/">OPNSense</a></li><li><a href="https://github.com/crowdsecurity/crowdsec">CrowdSec</a></li><li><a href="https://doc.ubuntu-fr.org/iptables">iptables</a></li><li><a href="https://doc.ubuntu-fr.org/ufw">ufw</a></li></ul><![CDATA[Démarrer un conteneur Docker]]>https://johackim.com/demarrer-un-conteneur-dockerhttps://johackim.com/demarrer-un-conteneur-dockerTue, 18 May 2021 12:40:12 GMT<p>Pour démarrer un conteneur Docker, basé sur l&#x27;image Docker <a href="https://ghost.org/">Ghost</a> par exemple, il suffit d&#x27;exécuter la commande suivante :</p><pre><code class="language-bash">docker run --name ghost -p 2368:2368 ghost </code></pre><p>Rendez-vous sur http://localhost:2368 pour accèder à une application Ghost fraichement installé.</p><![CDATA[Ajouter un node à un cluster Docker Swarm]]>https://johackim.com/ajouter-un-node-a-un-cluster-docker-swarmhttps://johackim.com/ajouter-un-node-a-un-cluster-docker-swarmMon, 17 May 2021 17:32:25 GMT<p>Un node peut être configuré en tant que <strong>manager</strong> ou <strong>worker</strong> :</p><ul><li><p>Les <strong>managers</strong> s&#x27;occupent de gérer l&#x27;état du cluster et de la répartition des tâches entre les workers.</p></li><li><p>Les <strong>workers</strong> acceptent les tâches des managers et les exécutent.</p></li></ul><p>Pour ajouter un node manager ou worker :</p><pre><code class="language-bash">docker swarm join-token worker # Ajout d&#x27;un node worker docker swarm join-token manager # Ajout d&#x27;un node manager </code></pre><p>La commande précédente affichera une commande <code>docker swarm join</code> à exécuter sur le serveur que vous souhaitez ajouter à votre cluster Docker Swarm :</p><pre><code class="language-bash">docker swarm join --token &lt;token&gt; &lt;ip&gt;:2377 </code></pre><![CDATA[Créer un volume Docker]]>https://johackim.com/creer-un-volume-dockerhttps://johackim.com/creer-un-volume-dockerMon, 17 May 2021 17:32:25 GMT<p>Afin de concerver les données d&#x27;un conteneur sur notre machine hôte, il est possible de créer des volumes Docker :</p><pre><code class="language-bash">docker run -v $PWD/ghost:/var/lib/ghost/content -p 2368:2368 ghost </code></pre><p>Dans cet exemple, les données seront sauvegardé dans le dossier <code>ghost</code> à l&#x27;endroit où est éxecuté la commande.</p><p>Si on n&#x27;oublie de spécifier le volume, les données de notre conteneur seront définitivement perdu à la suppression du conteneur.</p><![CDATA[Docker Swarm]]>https://johackim.com/docker-swarmhttps://johackim.com/docker-swarmMon, 17 May 2021 17:32:25 GMT<p>Docker Swarm est un <strong>orchestrateur</strong> qui exécute, coordonne et gère automatiquement le cycle de vie des conteneurs Docker.</p><p>Il permet de répartir les conteneurs Docker selon l&#x27;utilisation des ressources (CPU, RAM, ect...) de chaque serveur.</p><![CDATA[Docker]]>https://johackim.com/dockerhttps://johackim.com/dockerMon, 17 May 2021 17:32:25 GMT<p><a href="https://www.docker.com">Docker</a> est un logiciel open-source (disponible sur Linux, Mac et Windows) qui permet de lancer facilement des applications dans des conteneurs logiciels.</p><p><strong>C&#x27;est un outil qui peut empaqueter une application et ses dépendances dans un conteneur isolé, qui pourra être exécuté sur n&#x27;importe quel serveur.</strong></p><p><strong>Il ne s&#x27;agit pas de virtualisation</strong>, mais de conteneurisation, une forme beaucoup plus légère qui s&#x27;appuie sur certaines parties de la machine hôte pour son fonctionnement.</p><![CDATA[Entrer à l'intérieur d'un conteneur Docker]]>https://johackim.com/entrer-a-l'interieur-d'un-conteneur-dockerhttps://johackim.com/entrer-a-l'interieur-d'un-conteneur-dockerMon, 17 May 2021 17:32:25 GMT<p>Pour entrer à l&#x27;intérieur d&#x27;un conteneur vous pouvez exécuter la commande :</p><pre><code class="language-bash">docker exec -it &lt;nom_du_conteneur&gt; /bin/bash </code></pre><p>Exemple :</p><pre><code class="language-bash">docker exec -it ghost bash </code></pre><![CDATA[GlusterFS]]>https://johackim.com/glusterfshttps://johackim.com/glusterfsMon, 17 May 2021 17:32:25 GMT<p><strong>GlusterFS</strong> est <a href="/soon" title="Système de fichiers distribué">Système de fichiers distribué</a> qui peut évoluer de manière progressive pour stocker plusieurs pétaoctets de données.</p><p>Pour installer un serveur GlusterFS :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -yq glusterfs-server systemctl enable --now glusterd </code></pre><p>Pour créer un volume de donnée <code>/mnt/glusterfs</code> :</p><pre><code class="language-bash">gluster volume create vol01 transport tcp &quot;127.0.0.1:/mnt/glusterfs&quot; force gluster volume start vol01 </code></pre><p>Pour accéder au volume de donnée depuis d&#x27;autres serveurs :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -yq glusterfs-client </code></pre><pre><code class="language-bash">echo &quot;127.0.0.1:/vol01 /mnt/data glusterfs defaults,_netdev 0 0&quot; &gt;&gt; /etc/fstab mount -a </code></pre><p>PS: N&#x27;oubliez pas de modifier l&#x27;adresse ip <code>127.0.0.1</code> par l&#x27;adresse ip interne de votre serveur (ex: <code>10.12.180.210</code>).</p><![CDATA[Initialiser un cluster Docker Swarm]]>https://johackim.com/initialiser-un-cluster-docker-swarmhttps://johackim.com/initialiser-un-cluster-docker-swarmMon, 17 May 2021 17:32:25 GMT<p>Pour initialiser un cluster Docker Swarm, exécutez cette commande :</p><pre><code class="language-bash">docker swarm init </code></pre><p>Si vous exécutez la commande <code>docker node ls</code>, vous allez voir que votre serveur est à présent un node de votre cluster Docker Swarm.</p><![CDATA[Installer Docker]]>https://johackim.com/installer-dockerhttps://johackim.com/installer-dockerMon, 17 May 2021 17:32:25 GMT<p>Pour installer <a href="https://www.docker.com/">docker</a> sur un serveur Linux (Ubuntu ou Debian), il suffit d&#x27;exécuter cette commande :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -yq docker.io </code></pre><p>Il existe aussi une <a href="https://docs.docker.com/docker-for-windows/install/">installation pour Windows</a> et une <a href="https://docs.docker.com/docker-for-mac/install/">installation pour Mac</a>.</p><![CDATA[Installer Grafana et Prometheus avec Docker Swarm]]>https://johackim.com/installer-grafana-et-prometheus-avec-docker-swarmhttps://johackim.com/installer-grafana-et-prometheus-avec-docker-swarmMon, 17 May 2021 17:32:25 GMT<p>Pour monitorer une infrastructure, il existe Grafana et Prometheus.</p><p>Prometheus se chargera de collecter les données (CPU, RAM, DISK, etc..) des différents serveurs, et Grafana les affichera sur un dashboard.</p><p>Installer <a href="/docker-swarm" title="Docker Swarm">Docker Swarm</a> et <a href="/traefik" title="Traefik">Traefik</a> puis créez et démarrez la stack Docker <code>monitoring.yml</code> :</p><pre><code class="language-yaml"># monitoring.yml version: &#x27;3.8&#x27; services: prometheus: image: prom/prometheus:v2.27.0 entrypoint: /bin/sh -c &#x27;/bin/sh -c &quot;$${@}&quot;&#x27; command: - /bin/sh - -c - | chown -R 65534:root /prometheus wget --no-cache -qnc https://raw.githubusercontent.com/johackim/stacks/v2/configs/prometheus.yml -O /etc/prometheus/prometheus.yml prometheus --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/prometheus \ --storage.tsdb.retention.time=7d \ --web.console.libraries=/usr/share/prometheus/console_libraries \ --web.console.templates=/usr/share/prometheus/consoles \ --web.route-prefix=/prometheus \ --web.external-url=${SCHEME:-http}://${DOMAIN:-grafana.localhost}/prometheus volumes: - ${VOLUME_PATH}prometheus:/prometheus - ${VOLUME_PATH}config:/etc/prometheus/ deploy: labels: - traefik.enable=true - traefik.http.routers.grafana-prom-${NUMBER:-1}.rule=Host(`${DOMAIN:-grafana.localhost}`) &amp;&amp; PathPrefix(`/prometheus/`) - traefik.http.routers.grafana-prom-${NUMBER:-1}.entrypoints=${SCHEME:-http} - traefik.http.routers.grafana-prom-${NUMBER:-1}.service=grafana-prom-${NUMBER:-1} - traefik.http.routers.grafana-prom-${NUMBER:-1}.tls.certresolver=letsencrypt - traefik.http.services.grafana-prom-${NUMBER:-1}.loadbalancer.server.port=9090 - traefik.http.routers.grafana-prom-${NUMBER:-1}.middlewares=grafana-prom-${NUMBER:-1}-auth - traefik.http.middlewares.grafana-prom-${NUMBER:-1}-auth.basicauth.users=${PROMETHEUS_USER:-admin}:${PROMETHEUS_PASSWORD:-htpasswd} networks: - internal - traefik grafana: image: grafana/grafana:7.5.6 user: root environment: - GF_SMTP_ENABLED=true - GF_SMTP_FROM_ADDRESS=${SMTP_FROM:-noreply@ethibox.fr} - GF_SMTP_HOST=${SMTP_HOST:-mail.service.host:587} - GF_SMTP_PASSWORD=${SMTP_PASSWORD:-myp@ssw0rd} - GF_SMTP_USER=${SMTP_USERNAME:-noreply@ethibox.fr} - GF_SERVER_ROOT_URL=${SCHEME:-http}://${DOMAIN:-grafana.localhost} volumes: - ${VOLUME_PATH}grafana:/var/lib/grafana deploy: labels: - traefik.enable=true - traefik.http.routers.grafana-${NUMBER:-1}.rule=Host(`${DOMAIN:-grafana.localhost}`) - traefik.http.routers.grafana-${NUMBER:-1}.entrypoints=${SCHEME:-http} - traefik.http.routers.grafana-${NUMBER:-1}.service=grafana-${NUMBER:-1} - traefik.http.routers.grafana-${NUMBER:-1}.tls.certresolver=letsencrypt - traefik.http.services.grafana-${NUMBER:-1}.loadbalancer.server.port=3000 networks: - internal - traefik cadvisor: image: gcr.io/cadvisor/cadvisor:v0.37.5 command: -docker_only=true volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro deploy: mode: global networks: - internal node-exporter: image: prom/node-exporter:v1.1.2 hostname: &quot;{{.Node.Hostname}}&quot; volumes: - /sys:/host/sys:ro - /:/rootfs:ro - /proc:/host/proc:ro - /etc/hostname:/etc/hostname - /mnt:/mnt:ro environment: - NODE_ID={{.Node.ID}} command: - &#x27;--path.sysfs=/host/sys&#x27; - &#x27;--path.procfs=/host/proc&#x27; - &#x27;--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)&#x27; - &#x27;--no-collector.ipvs&#x27; deploy: mode: global resources: limits: memory: 128M reservations: memory: 64M networks: - internal volumes: config: grafana: prometheus: networks: internal: driver: overlay attachable: true traefik: external: true name: traefik-net </code></pre><p>PS: Si vous souhaitez accéder à Grafana en http plutôt qu&#x27;en https, commentez la ligne <code>traefik.http.routers.grafana.tls.certresolver=letsencrypt</code>.</p><pre><code class="language-bash">docker stack deploy -c monitoring.yml monitoring </code></pre><p>Une fois installé vous pouvez vous rendre sur <a href="http://grafana.localhost">http://grafana.localhost</a> avec les identifiants <code>admin:admin</code> et ajoutez prometheus en tant que Data Source :</p><p><a href="/soon" title="Add prometheus Data Source on Grafana.mp4">Add prometheus Data Source on Grafana.mp4</a></p><p>Vous pouvez ensuite ajouter un dashboard pour monitorer vos serveurs (Conteneurs, CPU, RAM, stockage, etc...).</p><p>Voici <a href="https://directus.johackim.com/assets/70becb16-7d80-4e38-a500-8555ecfe7532?download">mon Dashboard</a> si vous souhaitez vous en inspirer.</p><![CDATA[Installer Terraform]]>https://johackim.com/installer-terraformhttps://johackim.com/installer-terraformMon, 17 May 2021 17:32:25 GMT<p>Pour installer Terraform, rendez-vous sur <a href="https://www.terraform.io/downloads.html">la page de téléchargement</a>.</p><p>Téléchargez et installez le fichier adapté à votre système d&#x27;exploitation (Linux, Mac ou Windows).</p><p>Exemple pour linux :</p><pre><code class="language-bash">wget https://releases.hashicorp.com/terraform/0.15.3/terraform_0.15.3_linux_amd64.zip unzip terraform_0.15.3_linux_amd64.zip sudo mv terraform /usr/local/bin </code></pre><pre><code class="language-bash">terraform -version # Terraform v0.15.3 </code></pre><![CDATA[Installer Traefik avec Docker Swarm]]>https://johackim.com/installer-traefik-avec-docker-swarmhttps://johackim.com/installer-traefik-avec-docker-swarmMon, 17 May 2021 17:32:25 GMT<p>Pour installer Traefik avec <a href="/docker-swarm" title="Docker Swarm">Docker Swarm</a>, on créer une stack Docker <code>traefik.yml</code> :</p><pre><code class="language-yaml"># traefik.yml version: &#x27;3.8&#x27; services: traefik: image: traefik:${VERSION:-2.4.8} command: - --providers.docker - --providers.docker.network=traefik-net - --providers.docker.exposedByDefault=false - --providers.docker.swarmMode=true - --providers.docker.endpoint=unix:///var/run/docker.sock - --entrypoints.http.address=:80 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro ports: - {target: 80, published: 80, mode: host, protocol: tcp} networks: default: external: true name: traefik-net </code></pre><p>On créer un réseau docker :</p><pre><code class="language-bash">docker network create --driver=overlay traefik-net </code></pre><p>On déploie traefik :</p><pre><code class="language-bash">docker stack deploy -c traefik.yml traefik </code></pre><p>Il est à présent possible de déployer une application (ex: Ghost) avec un nom de domaine associé (ex: ghost.localhost) :</p><pre><code class="language-bash">docker service create --network traefik-net \ -l traefik.enable=true \ -l traefik.http.routers.my-container.rule=&#x27;Host(`ghost.localhost`)&#x27; \ -l traefik.http.services.my-service.loadbalancer.server.port=2368 ghost </code></pre><p>Vous pouvez accédez à votre application en vous rendant sur <a href="http://ghost.localhost">http://ghost.localhost</a>.</p><![CDATA[Installer Traefik avec Docker]]>https://johackim.com/installer-traefik-avec-dockerhttps://johackim.com/installer-traefik-avec-dockerMon, 17 May 2021 17:32:25 GMT<p>Il est possible d&#x27;installer Traefik avec Docker avec la commande suivante :</p><pre><code class="language-bash">docker run -p 80:80 \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ traefik:2.4.8 --providers.docker=true </code></pre><p>Une fois installé vous pouvez relié une application à un nom de domaine (ex: ghost.localhost) :</p><pre><code class="language-bash">docker run -l traefik.http.routers.container.rule=&#x27;Host(`ghost.localhost`)&#x27; ghost </code></pre><p>Vous pouvez accédez à votre application en vous rendant sur <a href="http://ghost.localhost">http://ghost.localhost</a>.</p><![CDATA[Lister les conteneurs Docker]]>https://johackim.com/lister-les-conteneurs-dockerhttps://johackim.com/lister-les-conteneurs-dockerMon, 17 May 2021 17:32:25 GMT<p>Pour lister les conteneurs Docker, exécutez la commande suivante :</p><pre><code class="language-bash">docker ps -a </code></pre><![CDATA[Restic]]>https://johackim.com/restichttps://johackim.com/resticMon, 17 May 2021 17:32:25 GMT<p>Pour sauvegarder des données sous Linux, il existe <a href="https://github.com/restic/restic">restic</a> en tant que logiciel de backups.</p><p>Restic peut sauvegarder des données sur différent backends :</p><ul><li>Buckets S3 (minio, scaleway, AWS, etc...)</li><li>SFTP</li><li>Local</li><li>Etc...</li></ul><p>Et si vous souhaitez plus de <a href="https://rclone.org/#providers">backends</a> (Nextcloud, Dropbox, OVH, etc...), il est possible de coupler restic avec <a href="/rclone" title="Rclone">Rclone</a>.</p><p>Pour installer restic sous Debian ou Ubuntu :</p><pre><code class="language-bash">apt update &amp;&amp; apt install -y restic </code></pre><p>Voici un exemple avec une sauvegarde du dossier <code>~/</code> vers un bucket S3 <code>test</code> de chez Scaleway :</p><pre><code class="language-bash"># /root/.restic AWS_ACCESS_KEY_ID=&lt;AWS_ACCESS_KEY_ID&gt; AWS_SECRET_ACCESS_KEY=&lt;AWS_SECRET_ACCESS_KEY&gt; </code></pre><pre><code class="language-bash">restic -r s3:s3.fr-par.scw.cloud/test init </code></pre><pre><code class="language-bash">restic -r s3:s3.fr-par.scw.cloud/test backup ~/ </code></pre><p>Il est possible de facilement automatiser la sauvegarde via une tâche cron :</p><pre><code class="language-cron"># Sauvegarde du dossier ~/ chaque jour à minuit 0 0 * * * RESTIC_PASSWORD=PASS restic -r s3:s3.fr-par.scw.cloud/test backup ~/ </code></pre><p>Pour monter une sauvegarde restic sur un dossier :</p><pre><code class="language-bash">restic -r &lt;remote&gt; mount &lt;folder&gt; </code></pre><p>Pour libérer de l&#x27;espace :</p><pre><code class="language-bash">restic -r &lt;remote&gt; forget --keep-within 30d restic -r &lt;remote&gt; prune </code></pre><![CDATA[Service Docker]]>https://johackim.com/service-dockerhttps://johackim.com/service-dockerMon, 17 May 2021 17:32:25 GMT<p>Pour déployer des conteneurs dans un cluster <a href="/docker-swarm" title="Docker Swarm">Docker Swarm</a>, il faut créer des <strong>services Docker</strong>.</p><p>Les services permettent de définir un état souhaité pour une application que Docker Swarm prendra soin de gérer tout seul.</p><p>Si un conteneur d&#x27;un service s&#x27;arrête, il sera automatiquement relancer.</p><p>Il existe deux types de services :</p><ul><li><p>Les <strong>services répliqués</strong> ; vous spécifiez le nombre de réplicas que vous souhaitez, et ils seront attribués aux nœuds disponibles.</p></li><li><p>Les <strong>services globaux</strong> ; un seul réplica sera attribué sur chaque noeud.</p></li></ul><p>Le mode de réplication par défaut d&#x27;un service est répliqué. Pour déployer un service global, vous devez passer l&#x27;indicateur <code>--mode global</code> à la commande <code>docker service create</code>.</p><![CDATA[Stack Docker]]>https://johackim.com/stack-dockerhttps://johackim.com/stack-dockerMon, 17 May 2021 17:32:25 GMT<p>Pour créer une <strong>stack Docker</strong>, il suffit de créer un fichier YAML qui contient les détails des services Docker à démarrer (image, volumes, ports, labels, etc...) :</p><pre><code class="language-yaml"># ghost.yml version: &#x27;3.8&#x27; services: web: image: ghost:latest ports: - {target: 2368, published: 2368, mode: host} </code></pre><p>On peut démarrer la stack <code>ghost.yml</code> avec la commande suivante :</p><pre><code class="language-bash">docker stack deploy -c ghost.yml ghost </code></pre><p>Vous pouvez accéder à votre application Ghost à l&#x27;adresse : http://localhost:2368</p><p>Il est aussi possible de télécharger et d&#x27;exécuter une stack Docker via une seule ligne de commande :</p><pre><code class="language-bash">docker stack deploy -c &lt;(curl -so - https://raw.githubusercontent.com/ethibox/stacks/master/etherpad.yml) etherpad </code></pre><![CDATA[Supprimer un conteneur Docker]]>https://johackim.com/supprimer-un-conteneur-dockerhttps://johackim.com/supprimer-un-conteneur-dockerMon, 17 May 2021 17:32:25 GMT<p>Si vous souhaitez supprimer un conteneur, exécutez la commande :</p><pre><code class="language-bash">docker rm -f &lt;nom_du_conteneur&gt; </code></pre><p>Exemple :</p><pre><code class="language-bash">docker rm -f ghost </code></pre><![CDATA[Terraform]]>https://johackim.com/terraformhttps://johackim.com/terraformMon, 17 May 2021 17:32:25 GMT<p>Terraform est un logiciel open-source pour construire, modifier et versionner une infrastructure de manière sûre et efficace.</p><p>C&#x27;est un outil infrastructure as code.</p><p>Vous utilisez des fichiers de configuration au format .tf (HashiCorp) pour décrire les composants que vous souhaitez avoir dans votre infrastructure et Terraform s&#x27;occupe de générer un plan d&#x27;exécution et de l&#x27;exécuter.</p><p>Terraform supporte un grand nombre de <a href="https://registry.terraform.io/search/providers">fournisseurs d&#x27;infrastructure cloud</a> : </p><ul><li><a href="https://registry.terraform.io/providers/scaleway/scaleway/latest/docs">Scaleway</a></li><li><a href="https://registry.terraform.io/providers/ovh/ovh/latest/docs">OVH</a></li><li><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs">AWS</a></li><li><a href="https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs">OpenStack</a></li><li><a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs">Azure</a></li><li><a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs">GCP</a></li><li>ect...</li></ul><![CDATA[Traefik et Let's Encrypt]]>https://johackim.com/traefik-et-let's-encrypthttps://johackim.com/traefik-et-let's-encryptMon, 17 May 2021 17:32:25 GMT<p>Pour générer des certificats SSL, rien de mieux que Let&#x27;s Encrypt pour effectuer automatiquement cette tâche.</p><p>En rendant publiquement accessible les ports 80 et 443, <a href="/traefik" title="Traefik">Traefik</a> va automatiquement communiquer avec Let&#x27;s Encrypt pour générer automatiquement des certificats SSL à chaque fois qu&#x27;un nouveau nom de domaine est relié à une application.</p><h2 id="verifiez-que-vos-ports-80-et-443-sont-accessibles-publiquement">Vérifiez que vos ports 80 et 443 sont accessibles publiquement</h2><p>Avant de lancer Traefik, n&#x27;oubliez pas de vérifiez si vos ports 80 et 443 sont bien accessible depuis l&#x27;extérieur de votre réseau pour que Let&#x27;s Encrypt puisse communiquer avec votre serveur Traefik.</p><p>Utilisez la commande <code>curl https://ipv4.am.i.mullvad.net/port/80</code> (depuis votre serveur) ou <a href="https://canyouseeme.org/">https://canyouseeme.org/</a> pour vérifier.</p><h2 id="creez-une-zone-dns-de-type-a">Créez une zone DNS de type A</h2><p>Créez une zone DNS de type A vers l&#x27;adresse IP publique de votre serveur, exemple : <code>ghost.example.com</code> -&gt; <code>IN A 9.9.9.9</code>.</p><p>Pour ça, passez par le registraire de votre nom de domaine (ex: <a href="https://www.ovh.com/fr/">OVH</a>, <a href="https://www.gandi.net/fr">Gandi</a>, <a href="https://www.godaddy.com/fr-fr">GoDaddy</a> ou <a href="https://www.ionos.fr/domaine/noms-de-domaine">1&amp;1</a>).</p><h2 id="demarrez-traefik-avec-docker-swarm-et-lets-encrypt">Démarrez Traefik avec Docker Swarm et Let&#x27;s Encrypt</h2><p>Démarrez Traefik :</p><pre><code class="language-yaml">version: &#x27;3.8&#x27; services: traefik: image: traefik:${VERSION:-2.4.8} command: - --providers.docker - --providers.docker.network=traefik-net - --providers.docker.exposedByDefault=false - --providers.docker.swarmMode=true - --providers.docker.endpoint=unix:///var/run/docker.sock - --entrypoints.http.address=:80 - --entrypoints.https.address=:443 - --entrypoints.http.http.redirections.entryPoint.to=https - --entrypoints.http.http.redirections.entryPoint.scheme=https - --entrypoints.http.http.redirections.entrypoint.permanent=true - --certificatesresolvers.letsencrypt.acme.tlschallenge=true - --certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL:-noreply@ethibox.fr} - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json volumes: - ${VOLUME_PATH}letsencrypt:/letsencrypt - /var/run/docker.sock:/var/run/docker.sock:ro ports: - {target: 80, published: 80, mode: host, protocol: tcp} - {target: 443, published: 443, mode: host, protocol: tcp} volumes: letsencrypt: networks: default: external: true name: traefik-net </code></pre><pre><code class="language-bash">docker stack deploy -c traefik.yml traefik </code></pre><p>Créer une application avec un nom de domaine que vous disposez (ex: ghost.example.com) :</p><pre><code class="language-bash">docker service create --network traefik-net \ -l traefik.enable=true \ -l traefik.http.routers.my-container.rule=&#x27;Host(`ghost.example.com`)&#x27; \ -l traefik.http.services.my-service.loadbalancer.server.port=2368 ghost </code></pre><p>Un certificat est automatiquement généré et vous pouvez à présent accéder à votre application avec le protocole HTTPS : <code>https://ghost.example.com</code>.</p><![CDATA[Traefik]]>https://johackim.com/traefikhttps://johackim.com/traefikMon, 17 May 2021 17:32:25 GMT<p>Pour rendre accessible plusieurs applications web à partir d&#x27;un seul point d&#x27;entrée, il existe Traefik en tant que reverse proxy.</p><p>Grâce à Traefik, chaque requête HTTP provenant d&#x27;un client web (ex: Firefox, Chrome) sera automatiquement rediriger vers la bonne application.</p><![CDATA[Ma stack technique]]>https://johackim.com/ma-stack-techniquehttps://johackim.com/ma-stack-techniqueTue, 11 May 2021 13:05:19 GMT<h2 id="front-end">Front-end</h2><ul><li>React</li><li>Gatsby</li><li>Recoil</li><li>Tailwind CSS</li><li>Webpack</li></ul><h2 id="back-end">Back-end</h2><ul><li>Node.js</li><li>GraphQL</li><li>Prisma</li><li>Express.js</li></ul><h2 id="testing">Testing</h2><ul><li>Jest</li><li>Cypress</li></ul><h2 id="devops">Devops</h2><ul><li>Docker</li><li>Docker swarm</li><li>Kubernetes</li><li>Traefik</li><li>Ansible</li><li>Terraform</li><li>Github workflow</li><li>Grafana</li><li>Prometheus</li><li>Jenkins</li><li>RabbitMQ</li></ul><h2 id="systeme">Système</h2><ul><li>Arch Linux</li><li>zsh</li><li>i3</li><li>vim</li><li>rxvt</li><li>tmux</li><li><a href="https://github.com/johackim/dotfiles">dotfiles</a></li></ul><![CDATA[Les 6 étapes à suivre minutieusement pour détenir un compte Facebook anonyme]]>https://johackim.com/compte-facebook-anonymehttps://johackim.com/compte-facebook-anonymeTue, 11 May 2021 12:20:05 GMT<p>Détenir un compte Facebook anonyme est beaucoup plus complexe qu&#x27;<a href="/vie-privee/comment-detenir-un-compte-google-anonyme" title="Compte Google anonyme">avoir un compte Google anonyme</a>.</p><p>Voici les étapes à suivre :</p><ol><li><strong>Générez une photo de profil</strong></li></ol><p>Téléchargez une photo sur <a href="http://thispersondoesnotexist.com/">ce générateur de photo de profil</a>, cropez l&#x27;image et changez sa couleur, son orientation et sa taille.</p><ol start="2"><li><strong><a href="https://bit.ly/3qjDB1H">Générez un faux nom</a></strong></li><li><strong>Créez-vous un compte e-mail</strong> sur <a href="https://protonmail.com/">Protonmail</a>.</li><li><strong>Utilisez une adresse IP résidentielle</strong></li></ol><p>Ne passez pas par un VPN et vérifier la qualité de votre IP sur un service comme <a href="https://scamalytics.com/">scamalytics</a> avant de vous inscrire.</p><ol start="5"><li><strong>Rendez-vous sur <a href="https://m.facebook.com/">la version mobile de Facebook</a></strong> (de préférence avec le navigateur d&#x27;un smartphone -&gt; Opera)</li><li><strong>Inscrivez-vous</strong> avec les informations précédemment générées (Photo, E-mail, faux nom).</li></ol><p>Si vous ne passez pas minutieusement par toutes ses étapes, Facebook va stopper votre compte et vous demander une carte d&#x27;identité.</p><p>C&#x27;est le seul moyen que j&#x27;ai trouvé pour disposer d&#x27;un compte Facebook.</p><p>PS: Après inscription, pensez à effectuer des actions qu&#x27;un utilisateur lambda ferait ; liker, commenter, s&#x27;abonner à des pages, ect...</p><p>Références :</p><ul><li><a href="https://onehack.us/t/create-unlimited-facebook-accounts-without-mobile-numbers/54518">https://onehack.us/t/create-unlimited-facebook-accounts-without-mobile-numbers/54518</a></li></ul><![CDATA[Guide obsidian]]>https://johackim.com/obsidianhttps://johackim.com/obsidianTue, 11 May 2021 12:20:05 GMT<p><a href="https://obsidian.md/">Obsdidian</a> est une application de prise de notes comme <a href="https://evernote.com/">Evernote</a>, <a href="https://www.notion.so/">Notion</a> et <a href="https://bear.app/">Bear</a>, mais se distingue en introduisant une nouvelle façon d&#x27;organiser et de prendre vos notes.</p><ul><li>Les <strong>Backlinks</strong> - permettant de relier les notes entre elles.</li><li>Un <strong>Graph Viewer</strong> - pour découvrir et associer des notes et des topics.</li></ul><p>Et contrairement à <a href="https://roamresearch.com/">Roam Research</a>, Obsidian est <strong>gratuit</strong> et garde les <strong>données en local sur son ordinateur</strong>.</p><p>Ainsi, vous pouvez sauvegarder/synchroniser toutes vos données sur votre NAS ou solutions cloud (ex: Nextcloud).</p><p>Il est disponible sur Mac, Windows ou Linux (et bientôt sur Android et iOS).</p><h2 id="syntaxe-dobsidian">Syntaxe d&#x27;Obsidian</h2><p>Obsidian utilise <a href="/soon" title="Markdown">la syntaxe Markdown</a> par défaut avec quelques spécificités supplémentaires :</p><ul><li><undefined><a href="/soon" title="Linking Note">Linking Note</a> : Créer un lien vers une autre note</undefined></li><li><undefined><a href="/soon" title="Link Name">Link Name</a> : Créer un lien avec un nom personnalisé</undefined></li><li><undefined><a href="/soon#heading" title="Linking Note">Linking Note</a> : Créer un lien vers un titre d&#x27;une autre note</undefined></li><li><code>![[Linking Note^]]</code> : Intégrer un bloc d&#x27;une autre note</li><li><undefined><a href="/soon" title="Filename">Filename</a> : Intégrer une autre note</undefined></li><li><code>#tag</code> : Créer un tag</li><li><code>#nested/tag</code> : Créer un sous-tag</li><li><code>[^Ref]</code> et <code>[^Ref]: Footnote text.</code> : Créer une note de bas de page</li><li><code>^[Footnote text]</code> : Créer une note de bas de page en une ligne</li><li><p><mark class="font-bold">highlight</mark> : Créer un texte surligné</p></li><li><code>aliases: [Alias1, Alias2]</code> : Créer un alias (à ajouter dans le frontmatter)</li><li><code>- [ ] Task list</code> : Créer une tâche</li><li><code>- [x] Task list</code> : Cochez une tâche</li></ul><h2 id="raccourcis-clavier">Raccourcis clavier</h2><ul><li><code>CTRL+E</code> : Basculer entre le mode édition et visualisation.</li><li><code>CTRL+O</code> : Changer de fichier rapidement</li><li><code>CTRL+MAJ+F</code> : Activer le mode recherche</li><li><code>CTRL+P</code> : Exécuter une commande</li><li><code>CTRL+G</code> : Afficher le Graph viewer</li><li><code>CTRL+,</code> : Afficher les paramètres d&#x27;Obsidian</li></ul><h2 id="fonctionnalites-avancees">Fonctionnalités avancées</h2><ul><li><strong>Mermaid</strong> : Obsidian est compatible avec <a href="https://github.com/mermaid-js/mermaid">Mermaid</a>, ce qui vous permet de créer des diagrammes dans vos notes.</li><li><strong>Workspaces</strong> : Vous pouvez créer des espaces de travail avec des configurations différentes.</li><li><strong>Templates</strong> : Vous pouvez créer des templates réutilisables.</li><li><strong>Daily notes</strong> : Obsidian permet de créer rapidement des notes journalières à partir d&#x27;un template.</li><li><strong>Publish</strong> : Vous pouvez publier vos notes publiquement sur un site.</li></ul><h2 id="plugins">Plugins</h2><p>Obsidian offre la possiblité d&#x27;étendre ses fonctionnalités avec des plugins :</p><ul><li><a href="https://github.com/lynchjames/obsidian-mind-map">Mindmap</a></li><li><a href="https://github.com/mgmeyers/obsidian-kanban">Kanban</a></li><li><a href="https://github.com/tgrosinger/advanced-tables-obsidian">Avanced-tables</a></li><li><a href="https://github.com/lynchjames/note-refactor-obsidian">Note-refactor</a></li><li><a href="https://github.com/avirut/obsidian-metatemplates">Metatemplates</a></li><li><a href="https://github.com/pyrochlore/obsidian-tracker">Tracker</a></li></ul><h2 id="creer-un-theme-obsidian">Créer un thème Obsidian</h2><p><p>Pour créer un thème dans <a href="/obsidian" title="Obsidian">Obsidian</a>, il vous faut simplement créer un fichier CSS <code>nomdutheme.css</code> dans le dossier <code>.obsidian/themes</code> de votre Vault Obsidian.</p><p>Exemple :</p><pre><code class="language-css">/* vault/.obsidian/themes/darkyan.css */ .theme-light, .theme-dark { --background-primary: #111827; --background-primary-alt: #111827; --background-secondary: #1F2937; --background-secondary-alt: #1F2937; --text-normal: #D1D5DB; --text-faint: #D1D5DB; --text-title-h1: #D1D5DB; --text-title-h2: #D1D5DB; --text-title-h3: #D1D5DB; --text-title-h4: #D1D5DB; --text-title-h5: #D1D5DB; --text-title-h6: #D1D5DB; --text-highlight-bg: #374151; --text-link: #D1D5DB; --text-a-hover: #D1D5DB; --inline-code: #D1D5DB; --code-block: #D1D5DB; --text-a: #D1D5DB; --interactive-accent: #00AAAD; --text-accent: #00AAAD; --text-accent-hover: #00AAAD; --text-on-accent: #D1D5DB; --interactive-accent-rgb: #D1D5DB; --interactive-accent-hover: #00AAAD; --vim-cursor: #D1D5DB; --pre-code: #000000; --interactive-before: #374151; --background-modifier-border: #374151; --text-selection: #374151; --text-faint: #4B5563; } </code></pre><p>Une fois le fichier créé, vous pouvez utiliser votre thème depuis Settings -&gt; Appearance -&gt; Themes -&gt; Theme -&gt; Darkyan.</p><p>J&#x27;ai récemment créé un thème, vous pouvez l&#x27;utiliser en vous rendant sur le dépôt Github <a href="https://github.com/johackim/obsidian-darkyan/">johackim/obsidian-darkyan</a>.</p><p><img src="https://raw.githubusercontent.com/johackim/obsidian-darkyan/master/screenshot.png" alt="Obsidian Theme"/></p><p><img src="https://raw.githubusercontent.com/johackim/obsidian-darkyan/master/screenshot2.png" alt="Graph viewer"/></p><p>Pour publier son thème dans les thèmes de la communauté d&#x27;Obsidian, créez une pull request sur le dépôt <a href="https://github.com/obsidianmd/obsidian-releases/pull/356">obsidianmd/obsidian-releases</a>.</p><p>Une fois la pull request accepté, il apparaitra dans la liste des thèmes d&#x27;Obsidian dans Settings -&gt; Appearance -&gt; Themes -&gt; Community themes.</p></p><h2 id="securite">Sécurité</h2><p>D&#x27;un point de vue sécurité, voilà ce qui est affiché sur la page d&#x27;accueil d&#x27;Obsidian :</p><pre><code class="language-text">À notre époque où les services de cloud computing peuvent fermer, être rachetés ou changer de politique de confidentialité à tout moment, la dernière chose que vous voulez est un format propriétaire et un verrouillage des données. Avec Obsidian, vos données se trouvent dans un dossier local. Ne laissez plus jamais le travail de votre vie pris en otage dans le cloud. Le format Markdown en texte brut vous donne également une interopérabilité inégalée pour utiliser n&#x27;importe quel type de synchronisation, de chiffrage ou de traitement de données qui fonctionne avec des fichiers en texte brut. </code></pre><hr/><p>Références :</p><ul><li><a href="https://www.youtube.com/watch?v=QgbLb6QCK88&amp;list=PL3NaIVgSlAVLHty1-NuvPa9V0b0UwbzBd">Linking Your Thinking - Obsidian for Beginners</a></li><li><a href="https://www.keepproductive.com/obsidian-made-simple">Keep Productive - Obsidian Made Simple</a></li><li><a href="https://www.youtube.com/watch?v=Zawx-N3-iko">Prendre de bonnes notes dans OBSIDIAN - ZETTELKASTEN dans obsidian</a></li></ul><![CDATA[Installer un serveur minecraft avec Docker]]>https://johackim.com/installer-un-serveur-minecraft-avec-dockerhttps://johackim.com/installer-un-serveur-minecraft-avec-dockerTue, 04 May 2021 08:50:00 GMT<p>Une fois <a href="/docker" title="Docker">Docker</a> installé avec la commande <code>apt update &amp;&amp; apt install -yq docker.io</code>.</p><p>On lance notre conteneur docker minecraft :</p><pre><code class="language-bash">docker run -d -e EULA=true -e MEMORY=4G -p 25565:25565 -v ~/minecraft:/data --name minecraft -v /etc/localtime:/etc/localtime:ro itzg/minecraft-server </code></pre><p>Vous pouvez à présent accéder à votre serveur Minecraft en renseignant l&#x27;adresse IP de votre serveur suivi du port, exemple : <code>127.0.0.1:25565</code>.</p><p>PS: N&#x27;oubliez pas de configurer votre pare-feu pour permettre l&#x27;accès au port <code>25565</code>.</p><h2 id="executer-des-commandes-minecraft">Exécuter des commandes Minecraft</h2><p>Pour exécuter une commande Minecraft (ex: <code>/op &lt;username&gt;</code>) : </p><pre><code class="language-bash">docker exec -it minecraft rcon-cli </code></pre><p>Vous pouvez ensuite taper toutes les commandes que vous souhaitez.</p><p>Voici la <a href="https://minecraft.gamepedia.com/Commands#List_and_summary_of_commands">liste des commandes Minecraft</a>.</p><h2 id="faire-une-sauvegarde">Faire une sauvegarde</h2><p>Pour faire une sauvegarde, c&#x27;est très simple. Il suffit de copier-coller le dossier Minecraft là ou on le souhaite (ex: Nextcloud, NAS, etc...) 😀</p><![CDATA[38 Façons de renforcer un titre]]>https://johackim.com/38-facons-de-renforcer-un-titrehttps://johackim.com/38-facons-de-renforcer-un-titreWed, 28 Apr 2021 10:52:22 GMT<h2 id="1-exprimer-la-promesse-en-termes-de-mesure">1. Exprimer la promesse en termes de mesure</h2><ul><li>« 20.000 micbofiltres dans la viceroy »</li><li>« J&#x27;ai perdu trente kilos... »</li><li>« Qui à deja vu une plante donner 17.000 fleurs ? »</li></ul><h2 id="2-exprimer-la-promesse-en-termes-de-rapidite">2. Exprimer la promesse en termes de rapidité</h2><ul><li>« Sentez-vous mieux rapidement »</li><li>« En deux secondes, l&#x27;aspirine bayer commence à se dissoudre dans votre verre »</li></ul><h2 id="3-exprimer-la-promesse-sous-forme-de-comparaison">3. Exprimer la promesse sous forme de comparaison</h2><ul><li>« Une lessive six fois plus blanche »</li><li>« Coute 300 $ de moins que tous les autres modeles comparables »</li></ul><h2 id="4-employer-une-metaphore">4. Employer une métaphore</h2><ul><li>« Bannit les maux de tete »</li><li>« Fait fondre ces vilains kilos »</li></ul><h2 id="5-faire-appel-aux-sens-du-client-potentiel">5. Faire appel aux sens du client potentiel</h2><ul><li>« Goute frais cueilli »</li><li>« Une peau qu&#x27;on aime toucher »</li></ul><h2 id="6-en-faire-la-demonstration-au-moyen-dun-exemple">6. En faire la démonstration au moyen d’un exemple</h2><ul><li>« Le verre de papier mono resiste meme à jack lamotta, un lutteur de 80 kilos »</li><li>« A 100 kilometres heure, le seul bruit qu&#x27;on entend dans une rolls-royce est celui de la pendule electrique »</li></ul><h2 id="7-etre-spectaculaire">7. Etre spectaculaire</h2><ul><li>« Voici 50 $ de plus marie !{ je gagne beaucoup d&#x27;argent maintenant ! »</li><li>« Les rires fusaient quand je me suis assis au piano, mais quand j&#x27;ai commence à jouer... »</li></ul><h2 id="8-utiliser-un-paradoxe">8. Utiliser un paradoxe</h2><ul><li>« Comment un coiffeur chauve à reussi a sauver mes cheveux »</li><li>« Gagnez aux courses en choisissant les perdants »</li></ul><h2 id="9-eliminer-danciennes-limitations">9. Eliminer d&#x27;anciennes limitations</h2><ul><li>« Guerit les hemorroides sans chirurgie »</li><li>« Vous ne respirez pas de poussiere en le faisant avec lewyt ! »</li></ul><h2 id="10-associer-le-produit-a-des-valeurs-ou-des-gens-avec-lesquels-le-client-potentiel-desire-sidentifier">10. Associer le produit à des valeurs ou des gens avec lesquels le client potentiel désire s&#x27;identifier</h2><ul><li>« Mickey mantle affirme : les camels ne me donnent jamais mal à la gorge »</li><li>« Neuf decorateurs sur dix utilisent les tapis wundaweave pour la longevite a bas prix »</li></ul><h2 id="11-exprimer-en-detail-tout-ce-que-fait-votre-produit">11. Exprimer en détail tout ce que fait votre produit</h2><ul><li>« Maintenant ! le soulagement en quelques secondes de cinq troubles de l&#x27;estomac causes par l&#x27;hyperacidite »</li><li>« Soulage instantanement la congestion des 7 sinus »</li></ul><h2 id="12-utiliser-la-forme-interrogative">12. Utiliser la forme interrogative</h2><ul><li>« Qui veut une lessive plus blanche sans travailler dur ? »</li><li>« Aimeriez-vous gagner 25 $ de plus par semaine ? »</li></ul><h2 id="13-donner-des-renseignements-sur-la-facon-datteindre-le-but-promis">13. Donner des renseignements sur la façon d’atteindre le but promis</h2><ul><li>« Comment se faire des amis et influencer les gens »</li><li>« Voici comment se debarrasser rapidement de ses boutons »</li></ul><h2 id="14-faire-appel-a-lautorite">14. Faire appel à l’autorité</h2><ul><li>« L&#x27;expert en mecanique vous dit comment eviter les reparations de moteur »</li><li>« Voici ce que font les medecins quand ils ne se sentent pas bien »</li></ul><h2 id="15-exposer-la-situation-avant-et-apres">15. Exposer la situation avant et après</h2><ul><li>« Avant coldene, un enfant se remettait d&#x27;un rhume apres cinq jours de douleur, d&#x27;eternuements, de reniflements et de pleurs. »</li><li>« Avec coldene, un enfant se remet d&#x27;un rhume en cinq jours »</li></ul><h2 id="16-insister-sur-la-nouveaute-du-produit">16. Insister sur la nouveauté du produit</h2><ul><li>« Introduisant les bougies missile guidey »</li><li>« Maintenant, chromez sans chaleur, electricite ou equipement »</li></ul><h2 id="17-insister-sur-lexclusivite">17. insister sur l&#x27;exclusivité</h2><ul><li>« Les seuls agneaux persans d&#x27;origine a 389,40$ »</li><li>« Seul glem utilise le gl-70 pour garder les dents propres toute la journee apres un seul brossage »</li></ul><h2 id="18-mettre-le-client-potentiel-au-defi">18. Mettre le client potentiel au défi</h2><ul><li>« Laquelle des jumelles a une toni ? Laquelle une permanente à 15 $ ? »</li><li>« Un colorant capillaire tellement naturel que seul son coiffeur le sait »</li></ul><h2 id="19-exprimer-le-resultat-sous-forme-dexemple">19. Exprimer le résultat sous forme d&#x27;exemple</h2><ul><li>« Regarde maman ! Pas de caries ! »</li><li>« Est-ce possible ? J&#x27;ai un rhume ! »</li></ul><h2 id="20-condenser-et-substituer-votre-produit-a-celui-quil-remplace">20. Condenser et substituer votre produit à celui qu&#x27;il remplace</h2><ul><li>« Maintenant ! un changement de segment et de piston dans un petit tube »</li><li>« Versez-vous un nouveau moteur »</li></ul><h2 id="21-utiliser-un-symbole-qui-remplace-lenonce-direct-en-le-comparant-a-une-realite-parallele">21. Utiliser un symbole qui remplace l&#x27;énoncé direct en le comparant à une réalité parallèle</h2><ul><li>« A partir de mardi prochain, l&#x27;ocean atlantique sera cino fois moins long à traverser »</li></ul><h2 id="22-faire-un-lien-entre-le-produit-et-son-mecanisme-de-fonctionnement">22. Faire un lien entre le produit et son mécanisme de fonctionnement</h2><ul><li>« Fait fondre la graisse »</li><li>« Retourne les vapeurs d&#x27;echappement dans votre moteur »</li></ul><h2 id="23-etonner-le-lecteur-en-contredisant-ce-quil-croit-etre-le-mecanisme-de-fonctionnement-du-produit">23. Etonner le lecteur en contredisant ce qu&#x27;il croit être le mécanisme de fonctionnement du produit</h2><ul><li>« Frappez la balle à l&#x27;autre bout du champ avec la main droite, » dit tommy armour.</li></ul><h2 id="24-faire-un-lien-entre-le-besoin-et-la-solution-que-vous-proposez">24. Faire un lien entre le besoin et la solution que vous proposez</h2><ul><li>« Il n&#x27;y à qu&#x27;une solution à un probleme de publicite : trouver l&#x27;homme 1! »</li></ul><h2 id="25-fournir-des-renseignements-dans-la-publicite-elle-meme">25. Fournir des renseignements dans la publicité elle-même</h2><ul><li>« Pourquoi les hommes craquent... »</li><li>« Ce que tout le monde devrait savoir au sujet des valeurs mobilieres. »</li></ul><h2 id="26-transformer-le-besoin-ou-la-solution-en-une-histoire">26. Transformer le besoin ou la solution en une histoire</h2><ul><li>«Tante marie qui ne s&#x27;est jamais mariee... »</li><li>«Elle commande encore : une salade de poulet, s.v.p. »</li></ul><h2 id="27-identifier-le-probleme-ou-le-besoin-en-lui-donnant-un-nom">27. Identifier le problème ou le besoin en lui donnant un nom</h2><ul><li>« Quand la lourdeur de l&#x27;apres-midi vous frappe, prenez alka-seltzer. »</li></ul><h2 id="28-prevenir-le-lecteur-des-problemes-qui-surgiront-sil-nutilise-pas-le-produit">28. Prévenir le lecteur des problèmes qui surgiront s&#x27;il n&#x27;utilise pas le produit</h2><ul><li>« N&#x27;investissez pas un cent de votre argent sans avoir consulte ce guide »</li></ul><h2 id="29-insister-sur-votre-promesse-en-la-divisant-en-deux-phrases-ou-en-la-repetant">29. Insister sur votre promesse en la divisant en deux phrases ou en la répétant</h2><ul><li>« Un homme auquel on peut faire confiance. c&#x27;est l&#x27;homme de kloper ! »</li><li>« Personne, absolument personne n&#x27;a de meilleurs prix que gimbel »</li></ul><h2 id="30-montrer-a-quel-point-votre-promesse-est-simple-a-atteindre-ceci-en-incluant-une-limitation-facile-a-depasser">30. Montrer à quel point votre promesse est simple à atteindre, ceci en incluant une limitation facile à dépasser</h2><ul><li>« Si vous pouvez compter jusqu&#x27;à onze, vous pouvez augmenter votre vitesse et vos performances à volonté »</li></ul><h2 id="31-exposer-la-difference-dans-votre-accroche">31. Exposer la différence dans votre accroche</h2><ul><li>« La différence entre de l&#x27;essence premium (de première qualité) et d&#x27;autres essences se trouve directement dans les additifs »</li></ul><h2 id="32-buipieritire-votre-lecteur-en-lui-faisant-realiser-que-des-limitations-qui-existaient-auparavant-sont-desormais-inexistantes">32. Buipieritiré votre lecteur en lui faisant réaliser que des limitations qui existaient auparavant sont désormais inexistantes</h2><ul><li>« Voyez ce qui arrive quand vous vous écrasez avec un</li><li>« hartman DC-8 »? Absolument rien! »</li></ul><h2 id="33-sadresser-aux-personnes-qui-ne-peuvent-pas-acheter-votre-produit">33. S&#x27;adresser aux personnes qui ne peuvent pas acheter votre produit</h2><ul><li>« Si vous avez déjà pris vos vacances, ne lisez pas ceci. Ça vous brisera le coeur »</li></ul><h2 id="34-sadresser-directement-a-votre-prospect">34. S&#x27;adresser directement à votre prospect</h2><ul><li>« À l&#x27;homme qui ne vise rien de plus bas que la présidence de l&#x27;entreprise où il travaille »</li></ul><h2 id="35-dramatiser-sur-la-difficulte-que-cela-a-represente-de-creer-une-telle-promesse">35. Dramatiser sur la difficulté que cela a représenté de créer une telle promesse</h2><ul><li>« Quand Jens a terminé de créer ce support pour bougies, nous avons carrément dû réinventé une toute nouvelle sorte de bougies »</li></ul><h2 id="36-positionner-votre-promesse-ou-votre-accroche-comme-etant-«-trop-formidable-»">36. Positionner votre promesse ou votre accroche comme étant « trop formidable »</h2><ul><li>« C&#x27;est immoral de faire de l&#x27;argent si facilement »</li></ul><h2 id="37-mettre-au-defi-les-croyances-limitantes-actuelles-de-vos-prospects">37. Mettre au défi les croyances limitantes actuelles de vos prospects</h2><ul><li>« Vous êtes deux fois plus intelligent que vous ne le pensez »</li></ul><h2 id="38-transformer-votre-accroche-en-une-question-avec-reponse">38. Transformer votre accroche en une question avec réponse</h2><ul><li>« Vous ne savez pas ce qu&#x27;il y a sous le capot de votre voiture et vous ne vous en souciez pas tant que votre voiture roule bien. Mais à qui devriez-vous faire appel si ce n&#x27;est pas le cas?... Quelqu&#x27;un qui s&#x27;en soucie — United Delco. »</li></ul><p>Références :</p><ul><li><a href="https://amzn.to/3kT23nt">Breakthrough Advertising - Eugene Schwartz</a></li></ul><![CDATA[Comment mieux organiser ses notes avec la méthode Zettelkasten]]>https://johackim.com/how-to-take-smart-notes-sonke-ahrenshttps://johackim.com/how-to-take-smart-notes-sonke-ahrensWed, 28 Apr 2021 10:52:22 GMT<p>Le livre <strong><a href="https://amzn.to/3mXQP36">How to Take Smart Notes</a></strong> de Sönke Ahrens est une introduction à la <strong>méthode de prise de note</strong> allemande <strong>Zettelkasten</strong> (aussi appelé la méthode <strong>slip-box</strong> en anglais ou <strong>boite à chaussure</strong> en français) développée par Niklas Luhmann.</p><p>Il s&#x27;agit d&#x27;<strong>un moyen efficace d&#x27;organiser ses notes</strong>. Cette méthode encourage à <strong>créer des liens entre nos notes individuelles</strong>, ce qui soutient la pensée créative et aide à faire avancer nos idées.</p><blockquote><p>« Notes aren’t a record of my thinking process. They are my thinking process. » Richard Feynman<sup id="fnref-1"><a href="#fn-1" class="footnote-ref">1</a></sup></p></blockquote><p>Luhmann avait deux boîtes en bois : <strong>une boîte bibliographique</strong>, qui contenait les références et de brèves notes sur le contenu de la littérature qu&#x27;il lisait, et <strong>une boîte principale</strong> qui contenait les idées et les théories qu&#x27;il recueillait en réponse à ce qu&#x27;il lisait. Les notes étaient écrites sur des fiches et conservées dans des boîtes en bois.</p><p>Luhmann a trois types de notes qui entrent dans ses boîtes : les <strong>notes temporaires</strong>, les <strong>notes littéraires</strong> et les <strong>notes permanentes</strong>.</p><h2 id="notes-temporaires">Notes temporaires</h2><p><p><strong>Ayez toujours quelque chose à portée de main avec lequel écrire pour capturer chaque idée qui vous vient à l&#x27;esprit</strong>. Ne vous préoccupez pas trop de la manière dont vous écrivez ou du support sur lequel vous écrivez.</p><p>Il s&#x27;agit de notes éphémères, de simples rappels de ce que vous avez en tête. Elles ne doivent pas vous distraire. <strong>Mettez-les dans un seul endroit, que vous définissez comme votre boîte de réception, et traitez-les plus tard</strong>.</p><p>Personnellement, j&#x27;ai 3 manières de prendre des note temporaires :</p><ol><li>Les &quot;Messages enregistrés&quot; de Telegram ou Signal quand je n&#x27;ai pas accès à mon PC.</li><li>Mon Rocketbook quand je suis sur mon bureau.</li><li>Un fichier markdown inbox.md dans Obisidian où je note tout ce qui me traverse l&#x27;esprit.</li></ol><p>Si vos pensées sont déjà triées et que vous avez le temps, vous pouvez sauter cette étape et écrire directement votre idée sous forme de note permanente.</p><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul></p><h2 id="notes-litteraires">Notes littéraires</h2><p><p><strong>Une note littéraire est essentiellement une note que vous avez créée à partir d&#x27;un contenu que vous avez consommé (livres, articles, vidéos, films, podcasts, formations, discussions, etc...).</strong></p><p>Notez ce que vous ne voulez pas oublier ou ce que vous pensez pouvoir utiliser dans votre propre réflexion ou vos écrits.</p><p>Soyez bref, soyez extrêmement sélectif et utilisez vos propres mots.</p><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul></p><h2 id="notes-permanentes">Notes permanentes</h2><p><p>Parcourez vos notes <a href="/notes-temporaires" title="Notes temporaires">temporaires</a> et <a href="/notes-litteraires" title="Notes littéraires">littéraires</a> et réfléchissez à la manière dont elles se rapportent à ce qui est pertinent pour vos propres recherches, réflexions ou intérêts.</p><p>L&#x27;idée n&#x27;est pas de collecter, mais de développer des idées, des arguments et des discussions.</p><p><strong>Rédigez une note pour chaque idée et écrivez comme si vous écriviez pour quelqu&#x27;un d&#x27;autre : utilisez des phrases complètes, indiquez vos sources, faites des références et essayez d&#x27;être aussi précis, clair et bref que possible.</strong></p><p>Jetez les notes éphémères et placez les notes littéraires dans votre <strong>système de référence</strong>. Vous pouvez les oublier maintenant. Tout ce qui compte, c&#x27;est ce qui se trouve dans la <strong>boite à chaussure</strong> des notes permanentes.</p><p><strong>Ajoutez vos nouvelles notes permanentes dans votre boîte à chaussure</strong>. Placez chaque note derrière une note associée (si elle ne se rapporte à aucune note existante, ajoutez-la à la toute fin).</p><p>Optionnellement, vous pouvez également :</p><ul><li>Ajouter des liens vers (et depuis) les notes associées.</li><li>Les ajouter à un «<strong>index</strong>» - un type spécial de note qui sert de «table des matières» et de point d&#x27;entrée pour un sujet important, y compris une collection triée de liens sur le sujet.</li></ul><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul></p><h2 id="outils-a-utiliser-avec-la-methode-zettelkasten">Outils à utiliser avec la méthode Zettelkasten</h2><p><p>Concernant les outils à utiliser, <strong>un stylo</strong>, <strong>des feuilles</strong> et <strong>des boites à chaussure</strong> peuvent suffire.</p><p>À titre personnel, j&#x27;utilise <a href="/obsidian" title="Obsidian">Obsidian</a> en tant qu&#x27;<strong>éditeur</strong> et <a href="https://calibre-ebook.com/">Calibre</a> en tant que <strong>système de gestion des références</strong>.</p><p>Mais il existe plein d&#x27;autres logiciels :</p><ul><li><a href="https://www.zotero.org/">Zotero</a></li><li><a href="https://github.com/Zettelkasten-Team/Zettelkasten">Zettelkasten</a></li><li><a href="https://evernote.com/">Evernote</a></li><li><a href="https://bear.app/">Bear Notes</a></li><li><a href="https://www.notion.so/">Notion</a></li><li><a href="https://roamresearch.com/">Roam Research</a></li></ul><p>Références :</p><ul><li><a href="/how-to-take-smart-notes-sonke-ahrens" title="How to Take Smart Notes - Sönke Ahrens">How to Take Smart Notes - Sönke Ahrens</a></li></ul></p><p>Références :</p><ul><li><a href="https://vimeo.com/275530205">Sonke Ahrens - How to Take Smart Notes NEWCRAFTS Conferences</a></li><li><a href="https://www.nateliason.com/blog/smart-notes">How to Take Smart Notes: A Step-by-Step Guide</a></li><li><a href="https://fortelabs.co/blog/how-to-take-smart-notes/">10 Principles to Revolutionize Your Note-Taking and Writing</a></li><li><a href="https://aliabdaal.com/book-notes/how-to-take-smart-notes/">How to Take Smart Notes - Book Summary and Notes</a></li><li><a href="https://jeancharleskurdali.com/comment-jai-construit-mon-second-cerveau-en-moins-dun-mois-zettelkasten/">Comment j’ai construit mon second cerveau en quelques semaines avec la méthode Zettelkasten</a></li><li><a href="https://school.atomicthinking.fr/cours">La méthode Atomic Thinking</a></li><li><a href="https://eliottmeunier.com/how-to-take-smart-notes-sonke-ahrens/">Résumé du livre How to Take Smart Notes</a></li><li><a href="https://www.youtube.com/watch?v=5Cqp9aUqq9s">Prendre et organiser ses NOTES dans un CARNET - Zettelkasten</a></li><li><a href="https://www.youtube.com/watch?v=rOSZOCoqOo8">Zettelkasten Note-Taking Method: Simply Explained</a></li></ul><div class="footnotes"><hr/><ol><li id="fn-1">Genius: The Life And Science of Richard Feynman (page 409).<a href="#fnref-1" class="footnote-backref">↩</a></li></ol></div><![CDATA[Comment mieux concevoir ses notes avec la synthétisation progressive]]>https://johackim.com/synthetisation-progressivehttps://johackim.com/synthetisation-progressiveWed, 28 Apr 2021 10:52:22 GMT<p>La synthétisation progressive (ou <a href="https://fortelabs.co/blog/progressive-summarization-a-practical-technique-for-designing-discoverable-notes/">Progressive Summarization</a> en anglais) est une technique pour mieux concevoir ses notes afin de les rendre plus accessibles et compréhensibles.</p><p>Inventé en 2017 par Tiago Forte, le processus ressemble à quelque chose comme ça :</p><ul><li>Couche 1 : Notes</li><li>Couche 2 : <strong>Passages en gras</strong></li><li><p>Couche 3 : <mark class="font-bold">Passages soulignés</mark></p></li><li>Couche 4 : Mini-sommaire</li><li>Couche 5 : Remix</li></ul><p>Chaque note est traitée par plusieurs passages si nécessaire.</p><p><img src="https://i.imgur.com/dyQtFqv.jpeg" alt="Progressive Summarization"/></p><h2 id="compression-vs-contexte">Compression VS contexte</h2><p>Pour qu&#x27;une note puisse être <strong>accessible</strong>, il faut qu&#x27;elle soit petite, simple et facile à digérer. Pour ce faire, nous utilisons la <strong>compression</strong> : nous créons des résumés très condensés, sans le superflu.</p><p>Mais nous voulons aussi que nos notes soient <strong>compréhensibles</strong>. Cela implique d&#x27;inclure tout le <strong>contexte</strong> : les détails, les exemples et les sources citées pour s&#x27;assurer que rien ne passe à travers les mailles du filet.</p><p>Si l&#x27;on compresse trop une note, c&#x27;est-à-dire si l&#x27;on fait un résumé trop bref, on perd le contexte et la note perd tout son sens.</p><p>Est si on va trop loin dans la direction opposée. Si nous rendons une chose totalement compréhensible, en d&#x27;autres termes, si nous incluons chaque petit détail et chaque élément de contexte, elle perd sa capacité d&#x27;<strong>accessibilité</strong>.</p><h2 id="couche-1--notes">Couche 1 : Notes</h2><p>La couche 1 est le contenu à apporter initialement dans un programme de prise de notes (Notion, Obsidian, Evernote...). Il n&#x27;y a pas de critères explicites sur ce qui doit être conservé. Capturez simplement tout ce qui vous semble perspicace, intéressant ou utile.</p><h2 id="couche-2--passages-en-gras">Couche 2 : Passages en gras</h2><p>La couche 2 est le premier round d&#x27;une véritable synthétisation, dans lequel on met en gras que les meilleures parties des passages que l&#x27;on a importés. Là encore, il n&#x27;y a pas de critères explicites. Recherchez les mots clés, les expressions clés et les phrases clés qui, selon vous, représentent le noyau ou l&#x27;essence de l&#x27;idée discutée.</p><h2 id="couche-3--passages-soulignes">Couche 3 : Passages soulignés</h2><p>Pour la 3ème couche, on passe au surlignage les meilleurs passages en gras, afin de pouvoir distinguer le petit nombre de passages surlignés parmi tous les passages en gras. Cette fois, on recherche le &quot;meilleur du meilleur&quot;, en ne surlignant que ce qui est vraiment unique ou précieux.</p><h2 id="couche-4--mini-sommaire">Couche 4 : Mini-sommaire</h2><p>Pour la couche 4, on résume encore, mais on va au-delà de la mise en évidence des mots, pour enregistrer les siens. On résume les couches 2 et 3 dans un mini-sommaire informel en haut de la note, en rappelant les points clés avec nos propres mots.</p><p>Notez que toutes les couches précédentes sont conservées dans leur contexte, ce qui vous donne la liberté de laisser des choses de côté sans craindre de les perdre.</p><h2 id="couche-5--remix">Couche 5 : Remix</h2><p>Et enfin, on remixe le tout. On y ajoute notre propre personnalité et notre créativité en transformant nos notes en autre chose (sketch notes, un épisode de podcast, un article de blog, un tweet, une vidéo YouTube, etc...).</p><hr/><p>Références :</p><ul><li><a href="https://fortelabs.co/blog/progressive-summarization-a-practical-technique-for-designing-discoverable-notes/">Progressive Summarization - Forte Labs</a></li><li><a href="https://jamesstuber.com/progressive-summarization-a-waste/">Is Progressive Summarization a Waste of Time?</a></li></ul><![CDATA[Résumé du livre The One Thing de Garry Keller]]>https://johackim.com/the-one-thing-garry-kellerhttps://johackim.com/the-one-thing-garry-kellerWed, 28 Apr 2021 10:52:22 GMT<p><a href="https://www.placedeslibraires.fr/livre/9782379350474-the-one-thing-gary-keller/">The One Thing</a> est un livre de productivité écrit par Garry Keller en 2013.</p><p>L&#x27;idée clé du livre est de se concentrer sur cette question : <mark class="font-bold">Quelle est l&#x27;UNIQUE chose que vous pouvez faire, de telle sorte qu&#x27;en la faisant, tout le reste deviendra plus facile ou inutile ?</mark>.</p><blockquote><p>« Quand on court après deux lièvres à la fois, on n&#x27;en attrape aucun. » Proverbe Russe</p></blockquote><h2 id="leffet-domino">L&#x27;effet domino</h2><p>Un domino est capable de renverser un autre domino 50% plus grand.</p><p>Si vous commencez avec un domino de 5 centimètres et que vous augmentez la taille de chaque domino de 50% =&gt; Le 57ème domino couvrirait presque la distance entre la terre et la lune.</p><p><img src="https://i.imgur.com/ih6FgiE.png" alt="Dominos - Une progression géométrique"/></p><p>Il existe un domino pour chaque domaine de notre vie (<strong>santé, sport, travail, amour, philosophie, relations, finances, ect...</strong>).</p><p><mark class="font-bold">Lorsque vous vous fixez un objectif, trouvez et focalisez-vous sur le premier domino. Celui qui fera tomber tous les autres. Concentrez-vous dessus jusqu&#x27;à le renversé.</mark></p><p>Chaque domino renversé rendra le suivant plus simple à faire tomber, à condition qu&#x27;ils soient correctement alignés.</p><p><strong>Réalignez de temps en temps vos dominos en phase avec celui que vous voulez atteindre.</strong></p><p>Et n&#x27;oubliez pas qu&#x27;il est physiquement impossible de faire tomber le dernier domino sans faire tomber les précédents.</p><p>Vous ne pouvez pas griller les étapes.</p><h2 id="la-question-essentielle">La question essentielle</h2><p>Pourquoi se concentrer sur une question alors que c’est la réponse que l’on cherche ?</p><p>Les réponses naissent des questions, et la qualité de toute réponse dépend directement de la justesse de la question.</p><p><strong>Posez la mauvaise question, vous obtiendrez la mauvaise réponse</strong>.</p><p>Posez la question la plus puissante possible, et la réponse peut changer votre vie.</p><p>La question essentielle rassemble toutes les questions possibles en une seule :</p><p><mark class="font-bold">Quelle est la chose ESSENTIELLE que je peux faire de telle sorte qu’en la faisant tout le reste deviendra plus simple voire inutile ?</mark>.</p><p>Utilisez-la dès le réveil et tout au long de la journée. Elle vous recentre sur votre tâche la plus importante, chaque fois que vous en avez besoin. Elle vous aide aussi à trouver « <strong>l’action-levier</strong> », <strong>le premier domino</strong>.</p><p>Quelle est la chose ESSENTIELLE que je peux faire maintenant pour [ce que vous voulez], de telle sorte qu’en la faisant tout le reste deviendra plus simple voire inutile ?</p><p><mark class="font-bold">Tant que je n’ai pas fait l’ESSENTIEL, tout le reste est une distraction.</mark></p><h2 id="pensez-grand-et-specifique">Pensez grand et spécifique</h2><p><img src="https://i.imgur.com/I5QoWKE.jpg" alt="Matrice de la Grande Question"/></p><p>Lorsque vous posez la question ESSENTIELLE, pensez grand et spécifique (un objectif important avec des chiffres concrets et un délai) pour indiquer où vous voulez aller.</p><p>Exemple :</p><ul><li><strong>Petit &amp; Spécifique</strong> : « Que puis-je faire pour augmenter les ventes de 5% cette année  ? »</li><li><strong>Petit &amp; Large</strong> : « Que puis-je faire pour augmenter les ventes ? »</li><li><strong>Grand &amp; Large</strong> : « Que puis-je faire pour doubler les ventes  ? »</li><li><strong>Grand &amp; Spécifique</strong> : « Que puis-je faire pour doubler les ventes en six mois ? »</li></ul><h2 id="construire-un-bunker">Construire un bunker</h2><p>Trouvez un endroit où travailler, loin des interruptions et des distractions. Si vous avez un bureau, accrochez une pancarte « Ne pas déranger ». Si les murs sont en verre, installez des stores. Si vous travaillez en open space, demandez l’autorisation d’ouvrir un paravent. Si nécessaire, allez ailleurs.</p><p>L’immortel Ernest Hemingway respectait un emploi du temps strict pour son écriture, qui commençait chaque matin à 7 heures dans sa chambre.</p><p>Le mortel mais très talentueux auteur Dan Heath « acheta un vieil ordinateur portable, effaça tous ses navigateurs, et pour faire bonne mesure, effaça ses réseaux sans fil », et il apportait cette « machine antédiluvienne » dans un café pour éviter les distractions.</p><p>Entre ces deux extrêmes, vous trouverez certainement une pièce vide avec une porte qui ferme.</p><h2 id="bloquer-du-temps-pour-lessentiel">Bloquer du temps pour l’essentiel</h2><p>Dans A Geography of Time, Robert Levine fait remarquer que la plupart des gens travaillent à l’heure de l’horloge (« Il est cinq heures, à demain  ! ») tandis que d’autres travaillent à l’heure de la tâche (« J’aurai fini de travailler quand mon travail sera fini »). </p><p>Réfléchissez. Un fermier ne pointe pas à heures fixes. Il rentre chez lui quand il a fini de traire les vaches. Tout métier axé sur les résultats fonctionne de la même façon. </p><p><strong>Les gens les plus productifs sont à l’heure de leur tâche. Ils ne s’arrêtent pas avant d’avoir accompli l’ESSENTIEL.</strong></p><p><strong>Bloquez quatre heures par jour.</strong> C’est un minimum, si vous pouvez y consacrer plus de temps, faites-le.</p><h2 id="decouper-son-objectif">Découper son objectif</h2><p>Le secret pour avancer, c’est de se mettre en route. Le secret pour se mettre en route, c’est de <mark class="font-bold">fractionner les tâches écrasantes</mark> devant nous pour les transformer en petites tâches abordables, puis de s’atteler à la première.</p><h2 id="soyez-responsable-de-vos-resultats">Soyez responsable de vos résultats</h2><p>Accepter les conséquences de ses actions, se considérer comme seul responsable de ses résultats, est la méthode la plus efficace pour se rapprocher du succès.</p><p>Face aux aléas de la vie, vous avez le choix entre devenir l&#x27;acteur de votre vie ou sa victime.</p><h2 id="ecrivez-et-partagez-vos-objectifs">Écrivez et partagez vos objectifs</h2><p>En 2008, le Dr. Gail Matthews, de l’université dominicaine de Californie, a recruté 267 participants, venus d’un large éventail de professions (avocats, comptables, bénévoles, commerciaux, etc.) et de nationalités. Ceux qui écrivaient leurs objectifs avaient 39,5% de chances en plus de les accomplir. <mark class="font-bold">Écrire ses objectifs</mark> et sa priorité essentielle est la dernière étape pour vivre sa priorité.</p><p>Les individus qui écrivent leurs objectifs et soumettent des rapports ou des mémos d’évolution avaient 76,7% de chances supplémentaires d’atteindre leur objectif. Écrire vos objectifs, c’est efficace. <mark class="font-bold">Partager vos progrès</mark> avec quelqu’un de manière régulière, ne serait-ce qu’un ami, peut vous rendre deux fois plus efficace.</p><p>Références :</p><ul><li><a href="https://www.dominican.edu/sites/default/files/2020-02/gailmatthews-harvard-goals-researchsummary.pdf">https://www.dominican.edu/sites/default/files/2020-02/gailmatthews-harvard-goals-researchsummary.pdf</a></li></ul><h2 id="lobjectif-futur-est-lie-a-la-priorite-presente">L’objectif futur est lié à la priorité présente</h2><p>Comme <strong>une poupée russe</strong>, votre ESSENTIEL « immédiat » se trouve à l&#x27;intérieur de votre ESSENTIEL de la semaine, qui se trouve à l&#x27;intérieur de votre ESSENTIEL du mois....</p><p><img src="https://i.imgur.com/Qe8RmPD.png"/></p><p>C&#x27;est ainsi qu&#x27;une petite chose peut mener à une grande chose.</p><p>Choisissez une direction, commencez à la suivre pour voir si elle vous convient. La clarté de vision vient avec le temps, et si ce n&#x27;est pas la bonne voie, vous pourrez toujours changer d&#x27;avis. À vous de construire votre vie.</p><![CDATA[Mon hacklab]]>https://johackim.com/hacklabhttps://johackim.com/hacklabFri, 16 Apr 2021 10:50:31 GMT<p>Inspiré par le concept des <a href="/soon" title="Digital Garden">digital gardens</a>, <a href="https://www.buildingasecondbrain.com/">Building a Second Brain</a> et <a href="https://www.linkingyourthinking.com/">Linking Your Thinking</a>, je me suis créé un hacklab ; un <strong>espace d&#x27;expérimentation</strong> où je recense et partage toutes mes <strong>idées</strong>, <strong>découvertes</strong> et <strong>notes personnelles</strong>.</p><p>Une sorte de <strong>laboratoire</strong> où j&#x27;expérimente tout un tas de sujets.</p><p>Un <strong>second cerveau</strong> où je stocke tous mes <strong>modèles mentaux</strong>.</p><p>C&#x27;est ici que je partage mes <strong>méthodes de réflexions</strong>.</p><p><em>Il ne s&#x27;agit pas d&#x27;un blog traditionnel où je publie de simples articles.</em></p><h2 id="visualisation-de-mon-hacklab">Visualisation de mon hacklab</h2><div class="mermaid" data-processed="true"><svg id="mermaid-1627299625927" width="100%" xmlns="http://www.w3.org/2000/svg" xmlnsXLink="http://www.w3.org/1999/xlink" height="700" style="max-width:922.859375px" viewBox="0 0 922.859375 700"><style>#mermaid-1627299625927{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-1627299625927 .error-icon{fill:#552222;}#mermaid-1627299625927 .error-text{fill:#552222;stroke:#552222;}#mermaid-1627299625927 .edge-thickness-normal{stroke-width:2px;}#mermaid-1627299625927 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1627299625927 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1627299625927 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1627299625927 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1627299625927 .marker{fill:#333333;stroke:#333333;}#mermaid-1627299625927 .marker.cross{stroke:#333333;}#mermaid-1627299625927 svg{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:16px;}#mermaid-1627299625927 .label{font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;color:#333;}#mermaid-1627299625927 .cluster-label text{fill:#333;}#mermaid-1627299625927 .cluster-label span{color:#333;}#mermaid-1627299625927 .label text,#mermaid-1627299625927 span{fill:#333;color:#333;}#mermaid-1627299625927 .node rect,#mermaid-1627299625927 .node circle,#mermaid-1627299625927 .node ellipse,#mermaid-1627299625927 .node polygon,#mermaid-1627299625927 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-1627299625927 .node .label{text-align:center;}#mermaid-1627299625927 .node.clickable{cursor:pointer;}#mermaid-1627299625927 .arrowheadPath{fill:#333333;}#mermaid-1627299625927 .edgePath .path{stroke:#333333;stroke-width:1.5px;}#mermaid-1627299625927 .flowchart-link{stroke:#333333;fill:none;}#mermaid-1627299625927 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-1627299625927 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-1627299625927 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-1627299625927 .cluster text{fill:#333;}#mermaid-1627299625927 .cluster span{color:#333;}#mermaid-1627299625927 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;font-size:12px;background:hsl(80,100%,96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1627299625927:root{--mermaid-font-family:&quot;trebuchet ms&quot;,verdana,arial,sans-serif;}</style><g transform="translate(0, 0)"><marker id="flowchart-pointEnd" class="marker flowchart" viewBox="0 0 10 10" refX="9" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker><marker id="flowchart-pointStart" class="marker flowchart" viewBox="0 0 10 10" refX="0" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1, 0"></path></marker><marker id="flowchart-circleEnd" class="marker flowchart" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1, 0"></circle></marker><marker id="flowchart-circleStart" class="marker flowchart" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width:1;stroke-dasharray:1, 0"></circle></marker><marker id="flowchart-crossEnd" class="marker cross flowchart" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1, 0"></path></marker><marker id="flowchart-crossStart" class="marker cross flowchart" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width:2;stroke-dasharray:1, 0"></path></marker><g class="root"><g class="clusters"><g class="cluster default" id="subGraph2"><rect rx="0" ry="0" x="153.9296875" y="526" width="640.9375" height="166"></rect><g class="cluster-label" transform="translate(402.796875, 531)"><foreignObject width="143.203125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Système de partage</span></div></foreignObject></g></g><g class="cluster default" id="subGraph1"><rect rx="0" ry="0" x="226.1875" y="325" width="626.765625" height="83"></rect><g class="cluster-label" transform="translate(449.734375, 330)"><foreignObject width="179.671875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Le coeur de mon hacklab</span></div></foreignObject></g></g><g class="cluster default" id="subGraph0"><rect rx="0" ry="0" x="8" y="8" width="906.859375" height="267"></rect><g class="cluster-label" transform="translate(338.5078125, 13)"><foreignObject width="245.84375" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Système de capture d&#x27;informations</span></div></foreignObject></g></g></g><g class="edgePaths"><path d="M233.0859375,66L233.0859375,91L233.0859375,116" id="L-News-Mailbrew-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-News LE-Mailbrew" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M233.0859375,149L233.0859375,183L338.41015625,218.62894785043306" id="L-Mailbrew-Mailspring-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Mailbrew LE-Mailspring" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M538.0390625,66L538.0390625,91L538.0390625,116" id="L-Kindle-Readwise-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Kindle LE-Readwise" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M538.0390625,149L538.0390625,183L426.33203125,219.23870166369727" id="L-Readwise-Mailspring-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Readwise LE-Mailspring" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M755.265625,66L755.265625,91L755.265625,116" id="L-Moi-Telegram-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Moi LE-Telegram" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M382.37109375,250L382.37109375,275L382.37109375,300L382.37109375,325L447.80078125,350" id="L-Mailspring-Obsidian-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Mailspring LE-Obsidian" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M755.265625,149L755.265625,183L755.265625,233.5L755.265625,275L755.265625,300L755.265625,325L596.0600527108434,350" id="L-Telegram-Obsidian-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Telegram LE-Obsidian" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M416.5604292168675,383L303.796875,408L303.796875,433L303.796875,467L303.796875,501L303.796875,526L303.796875,551" id="L-Obsidian-Gatsby-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Obsidian LE-Gatsby" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M500.1165286144578,383L513.953125,408L513.953125,433L513.953125,467L513.953125,501L513.953125,526L513.953125,551" id="L-Obsidian-Newsletter-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Obsidian LE-Newsletter" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M567.9460655120482,383L684.5546875,408L684.5546875,433L684.5546875,467L684.5546875,501L684.5546875,526L684.5546875,551" id="L-Obsidian-Twitter-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Obsidian LE-Twitter" style="fill:none" marker-end="url(#flowchart-pointEnd)"></path><path d="M303.796875,584L303.796875,609L303.796875,634" id="L-Gatsby-SEO-0" class="edge-thickness-normal edge-pattern-solid flowchart-link LS-Gatsby LE-SEO" style="fill:none" marker-start="url(#flowchart-pointStart)" marker-end="url(#flowchart-pointEnd)"></path></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(233.0859375, 183)"><g class="label" transform="translate(-24.015625, -9)"><foreignObject width="48.03125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel">1x/jour</span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(538.0390625, 183)"><g class="label" transform="translate(-24.015625, -9)"><foreignObject width="48.03125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel">1x/jour</span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(303.796875, 467)"><g class="label" transform="translate(-40.9140625, -9)"><foreignObject width="81.828125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel">1x/semaine</span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(513.953125, 467)"><g class="label" transform="translate(-40.9140625, -9)"><foreignObject width="81.828125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel">1x/semaine</span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(684.5546875, 467)"><g class="label" transform="translate(-40.9140625, -9)"><foreignObject width="81.828125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel">3x/semaine</span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default default" id="flowchart-Gatsby-38" transform="translate(303.796875, 567.5)"><rect class="basic label-container" rx="0" ry="0" x="-114.8671875" y="-16.5" width="229.734375" height="33"></rect><g class="label" transform="translate(-107.3671875, -9)"><foreignObject width="214.734375" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">johackim.com (Gatsby + RSS)</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Newsletter-40" transform="translate(513.953125, 567.5)"><rect class="basic label-container" rx="0" ry="0" x="-45.2890625" y="-16.5" width="90.578125" height="33"></rect><g class="label" transform="translate(-37.7890625, -9)"><foreignObject width="75.578125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Newsletter</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Twitter-42" transform="translate(684.5546875, 567.5)"><rect class="basic label-container" rx="0" ry="0" x="-75.3125" y="-16.5" width="150.625" height="33"></rect><g class="label" transform="translate(-67.8125, -9)"><foreignObject width="135.625" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Twitter + Mastodon</span></div></foreignObject></g></g><g class="node default default" id="flowchart-SEO-44" transform="translate(303.796875, 650.5)"><rect class="basic label-container" rx="0" ry="0" x="-109.765625" y="-16.5" width="219.53125" height="33"></rect><g class="label" transform="translate(-102.265625, -9)"><foreignObject width="204.53125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">SEO (Moteurs de recherche)</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Obsidian-34" transform="translate(490.984375, 366.5)"><rect class="basic label-container" rx="0" ry="0" x="-111.09375" y="-16.5" width="222.1875" height="33"></rect><g class="label" transform="translate(-103.59375, -9)"><foreignObject width="207.1875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Obsidian (fichiers markdown)</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Mailbrew-24" transform="translate(233.0859375, 132.5)"><rect class="basic label-container" rx="0" ry="0" x="-39.5078125" y="-16.5" width="79.015625" height="33"></rect><g class="label" transform="translate(-32.0078125, -9)"><foreignObject width="64.015625" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Mailbrew</span></div></foreignObject></g></g><g class="node default default" id="flowchart-News-23" transform="translate(233.0859375, 49.5)"><rect class="basic label-container" rx="0" ry="0" x="-190.0859375" y="-16.5" width="380.171875" height="33"></rect><g class="label" transform="translate(-182.5859375, -9)"><foreignObject width="365.171875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">News (RSS,Podcasts,YouTube,Newsletters,Twitter)</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Mailspring-26" transform="translate(382.37109375, 233.5)"><rect class="basic label-container" rx="0" ry="0" x="-43.9609375" y="-16.5" width="87.921875" height="33"></rect><g class="label" transform="translate(-36.4609375, -9)"><foreignObject width="72.921875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Mailspring</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Readwise-28" transform="translate(538.0390625, 132.5)"><rect class="basic label-container" rx="0" ry="0" x="-42.6328125" y="-16.5" width="85.265625" height="33"></rect><g class="label" transform="translate(-35.1328125, -9)"><foreignObject width="70.265625" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Readwise</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Kindle-27" transform="translate(538.0390625, 49.5)"><rect class="basic label-container" rx="0" ry="0" x="-64.8671875" y="-16.5" width="129.734375" height="33"></rect><g class="label" transform="translate(-57.3671875, -9)"><foreignObject width="114.734375" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Liseuse (Kindle)</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Telegram-32" transform="translate(755.265625, 132.5)"><rect class="basic label-container" style="stroke:#FFF;stroke-width:1px;stroke-dasharray:5" rx="0" ry="0" x="-124.59375" y="-16.5" width="249.1875" height="33"></rect><g class="label" transform="translate(-117.09375, -9)"><foreignObject width="234.1875" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Wallabag, Rocketbook, Telegram</span></div></foreignObject></g></g><g class="node default default" id="flowchart-Moi-31" transform="translate(755.265625, 49.5)"><rect class="basic label-container" rx="0" ry="0" x="-20.390625" y="-16.5" width="40.78125" height="33"></rect><g class="label" transform="translate(-12.890625, -9)"><foreignObject width="25.78125" height="18"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;white-space:nowrap"><span class="nodeLabel">Moi</span></div></foreignObject></g></g></g></g></g></svg></div><h2 id="mon-systeme-de-capture-dinformations">Mon système de capture d&#x27;informations</h2><p>C&#x27;est à cet endroit que je capture toutes les informations (RSS, Newsletters, Tweets, Vidéos YouTube, etc...).</p><p>Je ne consulte mon actualité qu&#x27;une fois par jour à l&#x27;aide de <strong>mailbrew</strong> qui m&#x27;envoie un résumé de tous les blogs et newsletters que je suis.</p><p>Cela m&#x27;évite de scroller sans cesse mes flux d&#x27;actualités tout au long de la journée comme un blaireau ^^.</p><h2 id="le-coeur-de-mon-hacklab">Le coeur de mon hacklab</h2><p>C&#x27;est à cet endroit que je créer et sauvegarde toutes les informations qui me semblent pertinentes.</p><p>Il s&#x27;agit d&#x27;un ensemble de fichiers texte bruts au format <strong>markdown</strong> reliés entre eux par des <strong>liens bidirectionnels</strong>.</p><p>Ces fichiers peuvent être consultés avec n&#x27;importe quel éditeur de texte.</p><p>Personnellement, j&#x27;utilise vim et/ou <a href="/obsidian" title="Obsidian">Obsidian</a>.</p><p>L&#x27;ensemble est versionnée avec <a href="https://github.com/git/git">git</a> et sauvegardé chaque jour sur un serveur externe.</p><h2 id="mon-systeme-de-partage">Mon système de partage</h2><p><strong>J&#x27;automatise chaque semaine le partage de mon hacklab.</strong></p><p>Tous mes écrits sont automatiquement créés, gérées et publiés par <a href="/creer-un-digital-garden" title="Créer un digital garden de A à Z avec Gatsby et Obsidian">Gatsby et Obsidian</a>.</p><p>Un récapitulatif est envoyé chaque semaine sur <a href="https://johackim.com/#subscribe">ma newsletter</a>.</p><![CDATA[Améliorer le SEO de Gatsby]]>https://johackim.com/ameliorer-le-seo-de-gatsbyhttps://johackim.com/ameliorer-le-seo-de-gatsbyMon, 12 Apr 2021 15:44:01 GMT<p>Pour améliorer le SEO d&#x27;un site Gatsby, il existe le plugin <code>helmet</code> qui permet d&#x27;overrider les balises meta de votre site :</p><pre><code class="language-bash">npm i -D react-helmet </code></pre><p>Ensuite, créez le fichier <code>src/component/seo.js</code> qui génerera toutes les balises meta nécessaires pour un bon référencement :</p><pre><code class="language-javascript">// src/components/seo.js import React from &#x27;react&#x27;; import Helmet from &#x27;react-helmet&#x27;; import { useLocation } from &#x27;@reach/router&#x27;; import { useStaticQuery, graphql } from &#x27;gatsby&#x27;; export default ({ title, image, description, article, datePublished, dateModified, tags = [], meta = [] }) =&gt; { const location = useLocation(); const { site } = useStaticQuery(graphql` query { site { siteMetadata { title lang logo description author twitter siteUrl siteName } } } `); const defaultTitle = site.siteMetadata?.title; const defaultDescription = site.siteMetadata?.description; return ( &lt;Helmet htmlAttributes={{ lang: site.siteMetadata.lang }} title={title || defaultTitle} meta={[ { name: &#x27;description&#x27;, content: description || defaultDescription, }, { property: &#x27;og:url&#x27;, content: location.href, }, { property: &#x27;og:site_name&#x27;, content: site.siteMetadata.siteName, }, { property: &#x27;og:title&#x27;, content: title || defaultTitle, }, { property: &#x27;og:description&#x27;, content: description || defaultDescription, }, { property: &#x27;og:type&#x27;, content: article ? &#x27;article&#x27; : &#x27;website&#x27;, }, ...(image ? [{ property: &#x27;og:image&#x27;, content: image, }] : []), ...(tags ? tags.map((tag) =&gt; ({ property: &#x27;article:tag&#x27;, content: tag, })) : []), { name: &#x27;twitter:title&#x27;, content: title || defaultTitle, }, { name: &#x27;twitter:creator&#x27;, content: site.siteMetadata.twitter, }, { name: &#x27;twitter:site&#x27;, content: site.siteMetadata.twitter, }, { name: &#x27;twitter:description&#x27;, content: description || defaultDescription, }, ...(image ? [{ name: &#x27;twitter:image&#x27;, content: image, }, { name: &#x27;twitter:card&#x27;, content: &#x27;summary_large_image&#x27;, }] : [{ name: &#x27;twitter:card&#x27;, content: &#x27;summary&#x27;, }]), ].concat(meta)} &gt; &lt;script type=&quot;application/ld+json&quot;&gt; {JSON.stringify({ &#x27;@context&#x27;: &#x27;https://schema.org&#x27;, &#x27;@type&#x27;: article ? &#x27;Article&#x27; : &#x27;WebSite&#x27;, mainEntityOfPage: { &#x27;@type&#x27;: &#x27;WebPage&#x27;, &#x27;@id&#x27;: site.siteMetadata?.siteUrl, }, url: location.href, headline: title || defaultTitle, author: { &#x27;@type&#x27;: &#x27;Person&#x27;, name: site.siteMetadata.author, }, publisher: { &#x27;@type&#x27;: &#x27;Organization&#x27;, name: site.siteMetadata.author, url: site.siteMetadata?.siteUrl, logo: { &#x27;@type&#x27;: &#x27;ImageObject&#x27;, url: site.siteMetadata.logo, }, }, description: description || defaultDescription, ...(image &amp;&amp; { image }), ...(dateModified &amp;&amp; { dateModified }), ...(datePublished &amp;&amp; { datePublished }), })} &lt;/script&gt; &lt;/Helmet&gt; ); }; </code></pre><p>Vous pouvez gérer les données par défault de votre site dans le fichier <code>gatsby-config.js</code> :</p><pre><code class="language-js">// gatsby-config.js module.exports = { siteMetadata: { title: &#x27;Website Title&#x27;, siteName: &#x27;Website Name&#x27;, description: &#x27;Description&#x27;, author: &#x27;author&#x27;, twitter: &#x27;@author&#x27;, logo: &#x27;http://example.com/logo.png&#x27;, lang: &#x27;fr&#x27;, siteUrl: &#x27;https://example.com&#x27;, } }; </code></pre><p>Vous pouvez Intégrer le composant <code>SEO</code> dans la page de votre choix (ex: <code>index.js</code>) :</p><pre><code class="language-js">// src/pages/index.js import React from &#x27;react&#x27;; import SEO from &#x27;../components/seo&#x27;; const IndexPage = () =&gt; ( &lt;&gt; &lt;SEO /&gt; &lt;p className=&quot;text-red-800&quot;&gt;Hello world!&lt;/p&gt; &lt;/&gt; ); export default IndexPage; </code></pre><p>Pour remplacer les balises meta par défaut, vous pouvez ajouter des propriétés au composant <code>&lt;SEO /&gt;</code> :</p><pre><code class="language-jsx">&lt;SEO title=&quot;title&quot; description=&quot;description&quot; image=&quot;https://example.com/image.png&quot; dateModified=&quot;2020-01-01T08:00:00.000Z&quot; datePublished=&quot;2020-01-01T08:00:00.000Z&quot; tags={[&quot;tag1&quot;, &quot;tag2&quot;]} article={true} /&gt; </code></pre>