Planet Asrall

February 16, 2019

Alexandre Bailly

USB Gadget - ethernet à travers USB

Cet article est aussi présent dans mes pages de documentation.
https://docs.nah.re/raspberry_pi/usb-otg-g-ether.html


Avant-propos

Ceci est un petit tutoriel en français, sur l'intégration de g_ether sur un Raspberry PI Zero.

Un minimum de connaissances de GNU/Linux et de la ligne de commande est nécessaire.

Photo d'un Raspberry PI Zero, dans son boîter blanc.

Un Raspberry PI Zero.

Installation de Raspbian

Premier détail : je n'ai pas copié une raspbian lite ou full sur la microSD, parce qu'on n'a pas du tout la même définition de léger.

Du coup, je suis parti sur raspberrypi-ua-netinst https://github.com/FooDeas/raspberrypi-ua-netinst

L'avantage d'une installation en unattended + netinst, c'est que l'on définit les paramètres dans un fichier de configuration, on branche un câble réseau (via un adaptateur micro USB OTG + une carte ethernet USB), on démarre et on laisse tourner.

Une fois l'installation terminée, je me suis connecté sur le Raspberry PI via SSH (toujours via le réseau).

Intégration de g_ether

Maintenant, on peut s'attaquer à l'intégration du gadget USB Ethernet (g_ether).

Se connecter avec le compte root (peu importe la méthode on va modifier des fichiers et installer des trucs)

Ouvrir /boot/config.txt. Ajouter à la fin du fichier, après [all]

#USB G_Ethernet
dtoverlay=dwc2

Si vous lisez des vidéos avec omxplayer et que celui-ci râle avec le message

COMXAudio::Decode timeout

Ajoutez dans le même fichier (/boot/config.txt)

gpu_mem=128

Enregistrer et fermer.

Ouvrir /boot/cmdline.txt

ajoutez à la fin de la commande.

modules-load=dwc2,g_ether

N'insérez surtout pas de saut de ligne.

La commande pourrait ressembler à ça :

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty3 elevator=deadline fsck.repair=yes root=/dev/mmcblk0p2 rootfstype=ext4 rootwait modules-load=dwc2,g_ether quiet logo.nologo loglevel=3 vt.global_cursor_default=0

Ici, j'ai configuré pour que tout soit silencieux, avec aucun message sur la sortie vidéo. Ne copiez pas bêtement la commande sans savoir à quoi correspond quiet ou vt.global_cursor_default=0. Ce n'est pas le but de ce tuto rapide, je ne détaillerai pas à quoi ça correspond.

Enregistrer et fermer le fichier.

Configuration du réseau

Pour éviter de se prendre la tête avec l'attribution de l'adresse IP une fois la carte branchée sur un PC (ou MAC) en USB, j'installe un serveur DHCP qui fera cette tâche automatiquement.

Installer le paquet isc-dhcp-server

apt install isc-dhcp-server

Activer le service (activer, ne pas démarrer tout de suite) avec systemd

systemctl enable isc-dhcp-server

On configurera le serveur DHCP juste après. On va d'abord configurer le réseau pour g_ether.

Ouvrir le fichier /etc/network/interfaces. Y ajouter :

# Ethernet over USB
allow-hotplug usb0
iface usb0 inet static
address 10.10.10.10
netmask 255.255.255.0
broadcast 10.10.10.255
gateway 10.10.10.10

Ici, j'ajoute une interface usb0, qui a une adresse IP 10.10.10.10. Cette IPv4 étant dans les plages réservées pour un usage privé, cela ne posera pas de problème ni de conflit. usb0 sera créé lorsque le raspberry pi sera branché en USB.

Enregistrer et fermer.

Ouvrir maintenant /etc/dhcp/dhcpcd.conf

Supprimer tout le contenu et insérer :

default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
authoritative;
log-facility local7;

subnet 10.10.10.0 netmask 255.255.255.0 {
range 10.10.10.11 10.10.10.20;
option routers 10.10.10.10;
option broadcast-address 10.10.10.255;
default-lease-time 600;
max-lease-time 7200;
option domain-name "local";
}

Les cinq premières lignes sont pour le paramétrage du serveur dhcp, les huit lignes en bas correspondent à la configuration du réseau.

Je définis le réseau comme étant sur 10.10.10.0, s'étendant jusqu'à 10.10.10.255 via le masque réseau.

Je définis ensuite la plage allant de 10.10.10.11 à 10.10.10.20 (ce qui me sera suffisant).

J'indique que le routage se fera sur 10.10.10.10, qui correspond à l'adresse du Raspberry PI (que j'ai défini dans /etc/network/interfaces).

Le reste n'est pas vraiment important (durée des sessions dhcp, nom de domaine local).

Enregistrer et fermer.

Ouvrir maintenant /etc/default/isc-dhcp-server

Décommenter les lignes

DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
DHCPDv4_PID=/var/run/dhcpd.pid

Ajouter usb0 dans INTERFACESv4, comme ceci :

INTERFACESv4="usb0"

Enregistrer et fermer.

Tests

Éteindre le Raspberry PI

sudo poweroff

Tout débrancher, puis brancher un câble micro USB (data, pas charge seule) sur le port "USB" du Raspberry (pas sur "pwr IN"), brancher l'autre côté du câble USB sur un PC.

Photo d'un Raspberry PI Zero avec un câble Micro USD branché sur le port USB.

Branchement du câble micro USB.

Après quelques dizaines de secondes, une interface réseau devrait apparaître (sous Windows, il y ait de fortes chances que le pilote rdnis ne s'installe pas automatiquement, il faudra l'installer manuellement via ajouter un pilote, choisir le pilote, type carte réseau, fabricant Microsoft, sélectionner rdnis ou un truc s'en approchant, répondre oui à l'avertissement comme quoi le pilote n'est peut être pas compatible).

Vérifiez si le Raspberry PI est bien reconnu comme une carte réseau.

Sous Windows

ipconfig /all

Sous Mac OS X et autres BSD

ifconfig

Sous GNU/Linux

ip a

Normalement, quelques lignes indiquant

inet 10.10.10.17/24 brd 10.10.10.255 scope global dynamic noprefixroute enp0s19f2u1

ou

inet 10.10.10.17  netmask 255.255.255.0  broadcast 10.10.10.255

ou un truc indiquant qu'il y a une IP commençant par 10.10.10 devrait s'afficher.

Si c'est le cas, taper

ping 10.10.10.10

S'il y a une réponse, cela signifie que cela fonctionne.

PING 10.10.10.10 (10.10.10.10) 56(84) bytes of data.
64 bytes from 10.10.10.10: icmp_seq=1 ttl=64 time=0.504 ms
64 bytes from 10.10.10.10: icmp_seq=2 ttl=64 time=0.543 ms
64 bytes from 10.10.10.10: icmp_seq=3 ttl=64 time=0.539 ms
64 bytes from 10.10.10.10: icmp_seq=4 ttl=64 time=0.542 ms
^C
--- 10.10.10.10 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 111ms
rtt min/avg/max/mdev = 0.504/0.532/0.543/0.016 ms

Il n'y a plus qu'à se connecter dessus.

ssh pi@10.10.10.10

Si vous avez pu vous connecter via ssh à travers la connection USB, félicitations.

Conclusion

Ce n'est pas très compliqué à mettre en place, le problème étant de réunir les différentes informations éparpillées un peu partout sur le net, et souvent en anglais (ce qui ne me pose pas de problème, mais ce n'est pas le cas de tout le monde).

Remerciements

Un gros merci à Albert, pour m'avoir prêté son Raspberry PI Zero.

by nah at February 16, 2019 04:49 PM

February 12, 2019

Romain Dessort

Marathon Canadien de Ski

Le Marathon Canadien de Ski (MCS) est la plus longue épreuve de ski de fond en Amérique du Nord, 160 km (163,7 km exactement), qui se répartissent en 2 jours soit à peu près 80 km par jour. C'est aussi la plus ancienne épreuve en Amérique, il a été tenu pour la première fois en 1967, lors des 100 ans du Canada. Il s'agit plus d'un évènement populaire que d'une compétition, les skieurs ne sont pas chronométrés et sont là plus pour le plaisir de skier et le défi personnel que la performance. L'évènement attire en moyenne 2000 personnes, venant principalement du Québec, de l'Ontario et du nord-est des États-Unis.

La piste reliait à l'origine les villes de Gatineau et La Chute en longeant plus ou moins la rivière des Outaouais. Montebello était le point central et l'étape intermédiaire. À cause de l'enneigement de plus en plus incertain ces dernières années, il part maintenant d'un peu au sud de Saint-Jovitte (Mont-Tremblant) pour se rendre à La Chute, en faisant un crochet par Montebello, qui reste l'étape intermédiaire. La piste est tracée une seule fois par année pour l'évènement et passe en majorité sur des terres privées.

Pourquoi j'en parle ici ? Ça me titillait depuis que j'en ai entendu parlé en arrivant au Québec, mais cette année je m'y suis inscrit et suis très fier d'avoir skier l'intégralité des 160 km en 2 jours ! Je fais un petit retour sur mon expérience.

Il y plusieurs catégories lors de l'inscription, on peut soit faire le demi-marathon, le marathon entier (Coureur des Bois) ou les sections que l'on veux (Randonneur) (le parcours est divisés en 10 sections de 16 km chacune en moyenne). Jusqu'au dernier moment avant mon inscription, j'ai beaucoup hésité dans quelle catégorie m'inscrire. J'étais plus partant pour faire le marathon entier au début, puis à un moment j'ai douté beaucoup, je n'arrivais pas à m'entrainer autant que je voulais (on a eu un décembre sans neige) et j'ai fini par m'inscrire dans la catégorie Randonneur. Comme ça je me suis dit que si je ne skiais pas les 10 étapes, je ne perdais pas le défi. Le prix a joué aussi, car les frais de participation sont assez cher : 300 $ pour les Coureurs des Bois contre 200 $ pour les Randonneurs. Puisque les Randonneurs peuvent quand même skier l'intégralité du marathon, les 100 $ ne se retrouvent que dans la médaille à la fin, ça ne justifiait pas la différence pour moi. Surtout qu'à cela, il fallait ajouter les frais d'hébergement pour vendredi et samedi (150 $ pour dormir par terre dans les salles de classe de l'école de Papineauville et manger à la cantine de l'école) + plus la navette depuis Montréal (100 $), plus toutes les taxes… Bref ça faisait un sacré budget et faisait cher le kilomètre skié. Mais je dois admettre que c'était toute une organisation sur place vu le nombre de participant et c'était assez bien rodé.

La veille du marathon, j'avais encore changé d'avis et je voulais à tout pris skier les 80 km par jour. Sauf qu'une chose que j'ai appris au dernier moment est que les Randonneurs qui veulent skier les 10 sections sont clairement pénalisés par rapport aux Coureurs des Bois : les Coureurs des Bois partent à 5h, le départ des Randonneurs est à 7h30 et il y a un cutoff à 15h30 pour tout le monde au départ de la dernière section de la journée. Ça laisse beaucoup moins de temps aux Randonneurs ! Donc au final, je me retrouve avec un défi supplémentaire, skier les 4 premières sections de chaque jour plus vite que les Coureurs des Bois pour arriver avant le cutoff de 15h30.

Dans ma tête, c'était donc un défi de 66 km à skier en 8h, pauses comprises, puis les 15 km de la dernière section du jour que je pouvais skier à la vitesse d'un piéton si je serai à bout, ça n'aura plus d'importance. J'ai calculé précisément mes heures de passages aux différents checkpoints. Je devais skier à une vitesse minimum de 9 km/h et pouvais m'arrêter maximum 15 minutes à chaque checkpoint pour refaire le plein d'eau, manger et refarter mes skis si besoin. La veille, j'ai appris par cœur mes heures de passage et j'ai mémorisé le plus de détails possible des cartes des sections (traverses de routes, de lacs, grandes côtes, passages dans les champs) de façon à me donner des points de repères une fois sur la piste pour situer mon avancement ; 80 km c'est long et il est facile de se « perdre » dans les chiffres et d'avoir l'impression de ne pas avancer si dès le départ au matin l'objectif est le 80 ème kilomètre. Voir que j'arrive effectivement à telle place alors que j'en suis qu'au 38 km est très motivant et rassurant à la fois. Et je me prépare ensuite à atteindre le prochain repère, peut-être juste 10 km plus loin. En fait, je me fous complètement du tout dernier kilomètre.

De manière générale, je suis (assez involontairement mais maintenant que j'en ai conscience ça devient moins involontaire) pessimiste concernant mes objectifs, ce qui fait que je les surpasse bien au delà et ça devient une source de motivation plus grande. Dans ce cas si concrètement, mes heures de passage étaient vraiment le minimum, le cas vraiment limite (je skie plus vite que 9 km/h), donc à chaque fois j'arrivais toujours avec 5 ou 10 minutes d'avance sur ce que j'avais en tête. Là encore, ça me rassurait et me motivait pour la section suivante, où je me mettais au défi de maintenir mon avance ou faire encore mieux.

Le premier jour, je suis arrivé à 1h05 avant le cutoff, 1h05 d'avance sur ce que j'avais prévu, et 40 minutes d'avance pour le deuxième jour. J'ai fini la première journée à 16h30 et 16h37 le lendemain, en skiant à peu près 8h à 10,5 km/h de moyenne plus 1h de pause au total. Je skie habituellement entre 10 et 11 km/h et avant le marathon, je doutais être capable de maintenir ma vitesse habituelle sur une aussi grande distance. Mais en faisant des stats par section, je ne constate aucune baisse de vitesse en fin d'épreuve (sauf la dernière section du premier jour où je me ralentissais volontairement pour ne pas me bruler inutilement pour le lendemain). Même, je me sentais bizarrement encore plein d'énergie, en tout cas d'un point de vue mental et cardiaque, mes muscles eux commençaient à fatiguer sérieusement.

Autant j'ai skié plus vite que prévu, autant la durée des pauses passait très rapidement. Le fait est que contrairement à la course à pied, c'est bien moins facile de boire et manger en skiant, avec les bâtons, gants et dragonnes ergonomiques, alors que mon eau est coincée quelque part contre mon ventre pour éviter le gel au lieu d'une simple poche d'eau avec un tuyau comme en trail. Donc je me ravitaillais essentiellement aux checkpoints qui étaient d'ailleurs pas mal bien fourni (eau chaude miellée, soupe, chili, bananes, barres de céréales…).

L'autre chose étaient les conditions de ski assez difficiles : il y a eu plusieurs épisodes de pluie puis du regel la semaine précédent l'évènement et la neige était très transformée. Les 2 jours on a eu un grand beau soleil, bien agréable mais n'améliorant pas les conditions, la température oscillait entre -15 à -3 °C suivant l'avancement de la journée. Bref, des conditions très printanières, la glisse était rapide mais le fartage n'était pas évidant. Malgré une base de liant que j'avais appliqué à chaque fois la veille, le fart de jour ne durait pas longtemps avec les conditions abrasive et je refartais tous les 15 à 20 km en moyenne, et dépendamment de l'évolution de la température (après coup, à des moments j'aurai vraiment du m'arrêter et prendre 5 minutes pour ajuster le fartage au lieu de me fatiguer à skier sans plus aucun kick et me disant que sa attendra le prochain checkpoint). Par contre une chose de vraiment bien, des exposants étaient là à chaque checkpoints pour farter les skis ; j'arrivais, je leur laissais mes skis, je mangeais et buvais un bout puis dès qu'ils avait fini avec mes skis je repartais. Ça me faisait gagner pas mal de temps.

Par rapport à la course à pied, c'est bien plus facile, je ne me verrai pas du tout courir pendant 8h par exemple. Déjà il n'y a pas toute la fatigue du aux chocs à chaque impact, c'est que de la glisse, je peux me reposer en descente (si elles sont pas trop raides) et je peux changer de technique pour reposer plus le haut ou le bas du corps quand l'un ou l'autre fatigue. Je faisais même du pas de patin sur les pistes de motoneige pour varier un peu, preuve que ce n'était pas le cardio mais plus les muscles qui fatiguaient.

Au niveau des paysages traversés, c'était très varié, certaines sections étaient très belles, d'autres moins. On a traversé des pinèdes, des érablières et des forêts de cèdres, des terrains de golf, des champs, passé au travers de fermes, skié le long de routes et dans des vallées, traversé des lacs et des rivières, on a skié dans un tunnel sous l'autoroute… Par moment on était sur des sentiers étroits dans le bois, d'autres fois sur des larges pistes de motoneige.

Finalement je ne regrette pas de m'être inscrit en tant que Randonneur, ça a été un défi supplémentaire par rapport au temps, j'ai pu dormir plus longtemps que les Coureurs des Bois qui se levaient à 3h pour partir à la nuit, et aussi, comme peu de Randonneurs faisaient la première section de la journée, on était qu'un petit groupe de 20/30 personnes à partir au lieu des centaines de Coureurs des Bois qui, eux, partaient tous en même temps et créaient des gros bouchons (de ce qu'on m'a raconté).

D'ailleurs dans la catégorie Coureurs des Bois, il y a une catégorie spéciale pour ceux qui dorment dehors. C'est en fait le défi ultime, skier avec tout son matériel de camping d'hiver et dormir au camp aménagé (avec feu de camp et balles de foin) le samedi soir. Moi personnellement, je ne regrette pas du tout de trouver une douche et un endroit chaud et sec après 80 km de ski. Je m'étais dis à un moment que j'essayerai le camping d'hiver au Québec, mais finalement… ça me tente plus trop !

Bref, le Marathon Canadien de Ski aura été pour moi une superbe expérience, j'en garde plein de bon souvenir et je suis pas mal plus confiant et fier de mes capacités en ski de fond. Presque je m'en veux un peu d'avoir douté de mes capacités au moment de l'inscription !

Départ du jour 2 Dernier checkpoint Médaille

February 12, 2019 11:02 PM

February 11, 2019

Luc Didry

Un dernier merci à mes tipeurs 🙂

Pourquoi un « dernier merci » ?

Et bien… tout simple­ment parce que je vais couper mes pages Tipeee et Libe­ra­pay.

Cela fait plus de deux ans que je reçois des dons pour ce que je fais pour le libre, et ça fait chaud au cœur. Vrai­ment. Énor­mé­ment. Et ça m’a beau­coup motivé à déve­lop­per.

Néan­moins, je consi­dère que je n’ai pas besoin de ces dons, vu que je gagne confor­ta­ble­ment ma vie. De plus, j’avoue, j’éprouve une certaine lassi­tude à parfois me forcer à déve­lop­per pour ne pas lais­ser tomber mes dona­trices et dona­teurs.

Je préfère donc couper mes pages de don.

Si vous souhai­tez faire des dons à d’autres, il y a une chouette dépêche LinuxFr qui liste plein d’as­so­cia­tions qui seraient heureuses de rece­voir des dons. Pis y a le projet Fedi­lab (ancien­ne­ment Masta­lab) qui est chouette : d’un client Masto­don, c’est devenu un client pour plein de service de la fédi­verse, c’est vrai­ment un chouette projet et le déve­lop­pe­ment est très soutenu. Pour les dons, ça se passe ou alors y a la collecte pour que le déve­lop­peur puisse se payer un ordi­na­teur plus costaud pour déve­lop­per dans de bonnes condi­tions.

Ne vous inquié­tez pas, je ne vais pas arrê­ter de faire du libre, mais… disons que je pren­drais sans doute plus mon temps 😉

Et donc… Un dernier merci

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle de janvier. Merci à :

Et un groooooooooooooos merci à tout ceux qui m’ont soutenu pendant ces plus de deux ans. Merci du fond du cœur ♥️


Voici mon bilan de janvier :

Crédits : Photo par Alex Hu sur Unsplash

Parta­ger

by Luc at February 11, 2019 04:04 PM

February 03, 2019

Pierre Boesch

RocketChat : chargement infini sur Firefox

Problème incompréhensible au premier abord : après s'être identifié sur une instance RocketChat, le chargement tourne en boucle. L'un des premiers réflexes est de tester un autre navigateur (Chromium par exemple) : ça fonctionne. L'instance RocketChat n'est pas à remettre en cause…

Du coup ça confirme un problème avec Firefox. Deuxième réflexe : vider le cache web. Non ? Non. Troisième réflexe : redémarrer le navigateur sans les extensions. Peut-être que ça débloquera la situation chez vous ; il ne vous restera donc qu'à désactiver petit à petit les extensions pour trouver la coupable. De mon côté, ça ne marchait quand même pas.

Du coup il ne reste plus qu'à débugger… On ouvre la console du navigateur en étant dans l'onglet de RocketChat : Ctrl + Shift + K puis reload F5. On avance :

TypeError: localStorage is null

Autant dire qu'on trouve tout de suite de quoi il s'agit : le localstorage de Firefox est désactivé. Pour le réactiver :

  • about:config dans la barre de recherche
  • dom.storage.enabled le passer à True

On reload à nouveau RocketChat : on peut à nouveau profiter de sa lourdeur et voir son CPU être bouffé petit à petit :)

by Pierre Boesch at February 03, 2019 11:00 PM

January 31, 2019

Pierre Boesch

Fixer les warnings après l'upgrade vers Pelican 4

Depuis l'upgrade de Pelican 3.7 vers Pelican 4, lors de la génération du html avec make on voit rapidement des warnings liés à certains paramètres.

Le travail sur la rétro-compatibilité étant bien géré par les développeurs, les warnings ne sont pas du tout gênant voir bloquant mais autant les corriger avant de ne plus avoir le choix. De mon côté je n'avais que deux warnings. On va voir comment les fixer.

Premier warning probablement classique :

WARNING: {filename} used for linking to staticcontent pdf/CV_BOESCH_Pierre.pdf in pages/about.md. Use {static} instead

Pour fixer, on édite la page/article en question et on remplace la syntaxe {filename} lié à un contenu statique par une syntaxe plus explicite : {static}

vim content/pages/about.md

-Mon CV est consultable [en cliquant ici]({filename}/pdf/CV_BOESCH_Pierre.pdf).
+Mon CV est consultable [en cliquant ici]({static}/pdf/CV_BOESCH_Pierre.pdf).

Second warning se corrigeant rapidement :

WARNING: %s usage in CATEGORY_FEED_ATOM is deprecated, use {slug} instead.

On grep pour savoir où cette variable est utilisée :

$ grep -ir CATEGORY_FEED_ATOM .
./pelicanconf.py:CATEGORY_FEED_ATOM = None
./publishconf.py:CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'

On ouvre publishconf.py

vim publishconf.py

-CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'
+CATEGORY_FEED_ATOM = 'feeds/{slug}.atom.xml'

C'est tout ! Les warnings d'un upgrade de Pelican 3 vers Pelican 4 sont fixés !

Le changelog complet de Pelican 4 se trouve ici. Et comme d'habitude pour obtenir de l'aide c'est par là.

by Pierre Boesch at January 31, 2019 11:00 PM

Fixer les warnings après l'upgrade de Pelican 4

Depuis l'upgrade de Pelican 3.7 vers Pelican 4, lors de la génération du html avec make on voit rapidement des warnings liés à certains paramètres.

Le travail sur la rétro-compatibilité étant bien géré par les développeurs, les warnings ne sont pas du tout gênant voir bloquant mais autant les corriger avant de ne plus avoir le choix. De mon côté je n'avais que deux warnings. On va voir comment les fixer.

Premier warning probablement classique :

WARNING: {filename} used for linking to staticcontent pdf/CV_BOESCH_Pierre.pdf in pages/about.md. Use {static} instead

Pour fixer, on édite la page/article en question et on remplace la syntaxe {filename} lié à un contenu statique par une syntaxe plus explicite : {static}

vim content/pages/about.md

-Mon CV est consultable [en cliquant ici]({filename}/pdf/CV_BOESCH_Pierre.pdf).
+Mon CV est consultable [en cliquant ici]({static}/pdf/CV_BOESCH_Pierre.pdf).

Second warning se corrigeant rapidement :

WARNING: %s usage in CATEGORY_FEED_ATOM is deprecated, use {slug} instead.

On grep pour savoir où cette variable est utilisée :

$ grep -ir CATEGORY_FEED_ATOM .
./pelicanconf.py:CATEGORY_FEED_ATOM = None
./publishconf.py:CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'

On ouvre publishconf.py

vim publishconf.py

-CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'
+CATEGORY_FEED_ATOM = 'feeds/{slug}.atom.xml'

C'est tout ! Les warnings d'un upgrade de Pelican 3 vers Pelican 4 sont fixés !

Le changelog complet de Pelican 4 se trouve ici. Et comme d'habitude pour obtenir de l'aide c'est par là.

by Pierre Boesch at January 31, 2019 11:00 PM

January 30, 2019

Pierre Boesch

HAProxy : Redirection HTTP en utilisant les maps

Une map est globalement un fichier contenant une structure de keys / values. Si vous avez une liste importante de redirection à faire (un domaine vers un autre, vers URI, etc) il est intéressant de se servir des maps afin de gagner en lisibilité sur la configuration finale de HAProxy. C'est quand même plus sympa d'avoir une ligne de configuration pour 10 domaines que 10 lignes d'acls, non ? :)

Création d'un fichier map

Il faut commencer par créer son premier fichier de map. Personnellement, je les place dans un dossier maps.

mkdir /etc/haproxy/maps

Par convention, j'utilise l'extension .map.

touch /etc/haproxy/maps/domain.map

Maintenant qu'on a notre fichier, il ne reste plus qu'à le remplir…

Les exemples qui vont suivre n'existent pas mais n'hésitez pas à consulter les sites en question ;-)

Redirection d'un domaine vers un second

Prenons le cas le plus classique : redirection de domain.tld vers www.domain.tld

vim /etc/haproxy/maps/domain.map

Admettons que l'on veuille rediriger :

On reprend notre fichier de map crée précédemment et on fait une liste key/value

/etc/haproxy/maps/domain.map

toucher.rectal.digital    www.toucher.rectal.digital
chiffrer.info             www.chiffrer.info

Puis on termine par créer la règle dans la configuration de HAProxy : /etc/haproxy/haproxy.cfg

frontend http
  [...]
  http-request redirect code 301 location https://%[hdr(host),map(/etc/haproxy/maps/domain.map)]%HU if { hdr(host),map(/etc/haproxy/maps/domain.map) -m found }

On dit simplement à HAProxy : si tu trouves le domaine appelé (key) alors redirection (301) vers le domaine que je souhaite (value) en gardant l'URI d'origine (%HU).

Avec cette configuration ça ne marchera que pour un domaine (%hdr(host)). Et si l'on veut rediriger une URI vers un domaine en particulier (#SEO) ?

Redirection d'une URI vers un domaine spécifique

Si l'on souhaite cette fois redirigier :

  • www.chiffrer.info/faq vers faq.chiffrer.info
  • toucher.rectal.digital/crypter vers chiffrer.info/onditpascrypter

En application : /etc/haproxy/maps/path.map

www.chiffrer.info/faq              https://faq.chiffrer.info
toucher.rectal.digital/crypter     https://chiffrer.info/onditpascrypter

/etc/haproxy/haproxy.cfg

frontend http
  [...]
  http-request redirect location %[base,map(/etc/haproxy/maps/path.map)] code 301 if { base,map(/etc/haproxy/maps/path.map) -m found }

Même explication que précédemment. Si l'on test la première redirection mise en place :

$ curl -I www.chiffrer.info/faq
HTTP/1.1 301 Moved Permanently
Content-length: 0
Location: https://faq.chiffrer.info

Redirection à base de regex

Avec les regex on va pouvoir travailler sur des redirections plus complexes.

Si l'on reprend en exemple les deux domaines précédents et que l'on veuille rediriger A vers B en récupérant un ID aléatoire dans l'URI ?

Prenons un cas classique :

www.chiffrer.info/faq?id=1337 vers faq.chiffre.info/1337

La map doit ressembler à ça

^www.chiffrer.info/faq?id=[0-9]+$      faq.chiffre.info/\1

Globalement la regex va matcher le numéro d'id et l'ajouter à la back reference (\1).

Pour ce cas précis, il faut disposer de haproxy 1.7 minimum qui introduit la map map_regm.

Toujours dans le frontend :

http-request redirect location %[base,map_regm(/etc/haproxy/maps/reg.map)] code 301 if { base,map_regm(/etc/haproxy/maps/reg.map) -m found }

Cet exemple n'est pas testé mais ça devrait marcher ;-)

Ressources

by Pierre Boesch at January 30, 2019 11:00 PM

Haproxy - Redirection en utilisant les maps

Une map est globalement un fichier contenant une structure de keys / values. Si vous avez une liste importante de redirection à faire (un domaine vers un autre, vers URI, etc) il est intéressant de se servir des maps afin de gagner en lisibilité sur la configuration finale de haproxy. C'est quand même plus sympa d'avoir une ligne de configuration pour 10 domaines que 10 lignes d'acls, non ? :)

Création d'un fichier map

Il faut commencer par créer son premier fichier de map. Personnellement, je les place dans un dossier maps.

mkdir /etc/haproxy/maps

Par convention, j'utilise l'extension .map.

touch /etc/haproxy/maps/domain.map

Maintenant qu'on a notre fichier, il ne reste plus qu'à le remplir…

Les exemples qui vont suivre n'existent pas mais n'hésitez pas à consulter les sites en question ;-)

Redirection d'un domaine vers un second

Prenons le cas le plus classique : redirection de domain.tld vers www.domain.tld

vim /etc/haproxy/maps/domain.map

Admettons que l'on veuille rediriger :

On reprend notre fichier de map crée précédemment et on fait une liste key/value

/etc/haproxy/maps/domain.map

toucher.rectal.digital    www.toucher.rectal.digital
chiffrer.info             www.chiffrer.info

Puis on termine par créer la règle dans la configuration de haproxy : /etc/haproxy/haproxy.cfg

frontend http
  [...]
  http-request redirect code 301 location https://%[hdr(host),map(/etc/haproxy/maps/domain.map)]%HU if { hdr(host),map(/etc/haproxy/maps/domain.map) -m found }

On dit simplement à haproxy : si tu trouves le domaine appelé (key) alors redirection (301) vers le domaine que je souhaite (value) en gardant l'URI d'origine (%HU).

Avec cette configuration ça ne marchera que pour un domaine (%hdr(host)). Et si l'on veut rediriger une URI vers un domaine en particulier (#SEO) ?

Redirection d'une URI vers un domaine spécifique

Si l'on souhaite cette fois redirigier :

  • www.chiffrer.info/faq vers faq.chiffrer.info
  • toucher.rectal.digital/crypter vers chiffrer.info/onditpascrypter

En application : /etc/haproxy/maps/path.map

www.chiffrer.info/faq              https://faq.chiffrer.info
toucher.rectal.digital/crypter     https://chiffrer.info/onditpascrypter

/etc/haproxy/haproxy.cfg

frontend http
  [...]
  http-request redirect location %[base,map(/etc/haproxy/maps/path.map)] code 301 if { base,map(/etc/haproxy/maps/path.map) -m found }

Même explication que précédemment. Si l'on test la première redirection mise en place :

$ curl -I www.chiffrer.info/faq
HTTP/1.1 301 Moved Permanently
Content-length: 0
Location: https://faq.chiffrer.info

Redirection à base de regex

Avec les regex on va pouvoir travailler sur des redirections plus complexes.

Si l'on reprend en exemple les deux domaines précédents et que l'on veuille rediriger A vers B en récupérant un ID aléatoire dans l'URI ?

Prenons un cas classique :

www.chiffrer.info/faq?id=1337 vers faq.chiffre.info/1337

La map doit ressembler à ça

^www.chiffrer.info/faq?id=[0-9]+$      faq.chiffre.info/\1

Globalement la regex va matcher le numéro d'id et l'ajouter à la back reference (\1).

Pour ce cas précis, il faut disposer de haproxy 1.7 minimum qui introduit la map map_regm.

Toujours dans le frontend :

http-request redirect location %[base,map_regm(/etc/haproxy/maps/reg.map)] code 301 if { base,map_regm(/etc/haproxy/maps/reg.map) -m found }

Cet exemple n'est pas testé mais ça devrait marcher ;-)

Ressources

by Pierre Boesch at January 30, 2019 11:00 PM

January 24, 2019

Romain Dessort

List changed configuration files and restore the maintainer's version

Recently I had to clean one of my server (a virtual machine hosted by Tetaneutral) to make it as close to a fresh install as possible, but without reinstalling it or migrate it somewhere else. It is an old server and it has been installed by hand. Since I now use Ansible to manage my other servers, I wanted to include it to the inventory and apply the same configuration on it.

On Archlinux, I used to use this command which list me all configuration files (in /etc) which have diverged from the version shipped by the package:

$ pacman -Qii | awk '/^MODIFIED/ {print $2}'

I didn't find a simple equivalent way to do it in Debian with dpkg tools, however I found debsums, an extra package that does the job pretty well:

$ debsums -se

I then can restore the package's version by reinstalling the corresponding package with --force-confask option:

# apt install --reinstall -o Dpkg::Options::="--force-confask"

Here is an oneliner to automate the process (careful, it doesn't ask for any confirmation!):

# debsums -se 2>&1 |awk '{print $4}' |xargs -n 1 dpkg -S |awk -F: '{print $1}' |sort -u |xargs apt install --reinstall -o Dpkg::Options::="--force-confask" -o Dpkg::Options::="--force-confnew"

Since xargs doesn't work well with interactive commands, I force the choice by passing both --force-confask and --force-confnew options.

As a conclusion, keep in mind the configuration files added in *.d/ directories won't be listed nor removed, so you still have to clean these directories manually.

January 24, 2019 01:43 AM

January 20, 2019

Florent Peterschmitt

Namasté Népal - #4.2

Article précédent

La suite des photos de montagne, le 23 avril 2017 ^^

photo photo photo

Notre pote singe blanc de la vielle ? Nah, il y en avait tout de même plusieurs ^^

photo photo

La personne en bas à droite c’était mon guide. On parlait tout deux suffisemment d’anglais pour pouvoir discuter de choses et d’autres, de la situation du pays, de sa vie etc…

photo photo photo photo photo photo

On commence à sortir de la forêt où la température était écrasante et l’absence de circulation d’air rendait la marche franchement difficile.

Maintenant c’est tout l’inverse : le vent souffle et il est froid ! Je me suis sévèrement enrhumé à ce moment là d’ailleurs… avec fièvre et tout le tintouin.

photo photo photo

photo photo photo photo photo photo

Sur les prochaines photos, on observe ce qu’il reste de la montagne qui s’est effondrée lors du tremblement de terre du 25 avril 2015 dans le pays.

Un village d’environ 200 habitants a été rasé et beaucoup y sont morts.

photo photo photo

Le village a été reconstruit plus haut et c’est là qu’on passera la nuit.

photo

Article suivant

by Florent Peterschmitt at January 20, 2019 08:30 PM

January 14, 2019

Luc Didry

Instal­ler un serveur Bitwar­den_rs

Avoir des mots de passe solides, c’est bien (et même indis­pen­sable), mais s’en souve­nir… c’est dur. On serait tenté de tout enre­gis­tré dans son navi­ga­teur, avec un mot de passe maître pour stocker les mots de passe de façon chif­frée mais… Fire­fox par exemple a un système de chif­fre­ment par mot de passe maître tout pourri.

Il existe un paquet de gestion­naire de mot de passe libre. Évacuons tous ceux basé sur KeePass ou ses succes­seurs : pour utili­ser ses mots de passe sur un autre PC ou sur son télé­phone, il faut synchro­ni­ser le fichier conte­nant les mots de passe et s’il y a un souci de synchro et que le fichier se retrouve corrom­pu… paf, pastèque !.

J’ai essayé Pass­bolt ou encore l’ap­pli­ca­tion Pass­man de Next­cloud mais quand j’uti­li­sais la sécu­rité maxi­male qu’ils propo­sent… mon Fire­fox plan­tait (oui, quand on me propose des réglages de parano, je les utilise). Sans comp­ter qu’ils ne proposent pas d’ap­pli Android.

Et puis, j’ai testé Bitwar­den. Et c’est pas mal du tout, mais… c’est du C# et ça utilise une base de données SQL Server. Deux trucs Micro­soft.

Bon, passant outre mon aver­sion, j’ai testé. Dans du Docker (quand je vous dis que je suis passé outre mon aver­sion !). C’était pas mal du tout.

Mais en voulant tester le partage de mot de passe (dans l’hy­po­thèse d’une utili­sa­tion chez Frama­soft), j’ai rencon­tré une limi­ta­tion : pour créer une orga­ni­sa­tion (un groupe de personnes qui se partagent des mots de passe) de plus de deux personnes, il faut payer, même quand on héberge soi-même le serveur Bitwar­den. Pourquoi pas. C’est un busi­ness model comme un autre (mais bon, grmpf).

Par contre, les tarifs, c’est un très gros grmpf : 3 dollars par utili­sa­teur et par mois. Pour Frama­soft, cela ferait 3$ * 35 personnes * 12 mois = 1 260$ par an. Y a un autre plan qui pour­rait conve­nir, qui nous revien­drait à 780$ par an. C’est quand même pas négli­geable (surtout pour une asso­cia­tion qui ne vit quasi­ment que de vos dons) alors qu’on héber­ge­rait nous-même le service.

J’avais laissé tombé quand ces derniers jours, une implé­men­ta­tion en Rust de Bitwar­den est passée dans ma time­line Masto­don : https://github.com/dani-garcia/bitwar­den_rs. Et celle-ci n’a pas la limi­ta­tion sur les équipes (mais il encou­rage à donner des sous au projet upstream).

J’ai d’abord testé avec le contai­ner Docker fourni par le déve­lop­peur puis j’ai tenté la compi­la­tion pour voir si ça passait, et ça passe crème !

La grosse diffé­rence, outre la non-limi­ta­tion des orga­ni­sa­tions, c’est que la base de données est, pour l’ins­tant, SQLite. Ce qui peut avoir des consé­quences sur les perfor­mances lorsque la base est très solli­ci­tée.

Ceci dit, Frama­drop tourne toujours avec une base SQLite et ça fonc­tionne bien, et mon instance Lutim, ainsi que Frama­pic ont long­temps utilisé SQLite.

Bref, voyons comment compi­ler et instal­ler cette version de Bitwar­den en Rust.

ATTENTION : allez plutôt voir le tuto­riel sur https://wiki.fiat-tux.fr/admin:logi­ciels:bitwar­den_rs, c’est plus simple pour moi de le main­te­nir sur mon wiki.

Compi­la­tion

On va avoir besoin des back­ports Debian pour instal­ler npm (pour compi­ler l’in­ter­face web) :

echo "deb http://ftp.debian.org/debian stretch-backports main" | sudo tee /etc/apt/sources.list.d/backports.list
sudo apt update

Instal­la­tion des dépen­dances :

sudo apt install pkg-config libssl-dev
sudo apt install -t stretch-backports npm

Instal­la­tion de rustup, qui nous four­nira le compi­la­teur Rust :

curl https://sh.rustup.rs -sSf > rustup.sh

On n’exé­cute pas direct un script tiré du web ! On regarde d’abord s’il ne va pas faire de salo­pe­ries :

vi rustup.sh

On le rend exécu­table :

chmod +x rustup.sh

On installe le compi­la­teur Rust (il sera dans notre $HOME) :

./rustup.sh --default-host x86_64-unknown-linux-gnu --default-toolchain nightly

On source un fichier qui nous permet de l’ap­pe­ler

source $HOME/.cargo/env

Gagnons du temps en clonant le projet bitwar­den_rs et l’in­ter­face web (qu’il faut compi­ler aussi) en même temps .

git clone https://github.com/dani-garcia/bitwarden_rs
git clone https://github.com/bitwarden/web.git web-vault

Compi­la­tion de Bitwar­den_rs :

cd bitwarden_rs
cargo build --release

Le résul­tat de la compi­la­tion est dans bitwarden_rs/target/release/.

Compi­la­tion de l’in­ter­face web :

cd ../web-vault
# On se positionne sur le dernier tag en date
git checkout "$(git tag | tail -n1)"
# Un petit patch pour que ça fonctionne avec notre installation
wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/v2.8.0.patch
# On vérifie le patch
cat v2.8.0.patch
git apply v2.8.0.patch
npm run sub:init
npm install
npm run dist

ATTENTION : on m’a dit que la compi­la­tion de l’in­ter­face web prenait 1,5Gio de RAM, assu­rez-vous que vous en avez assez de libre.

Et on copie l’in­ter­face web dans le dossier où attend le résul­tat de la compi­la­tion de bitwar­den_rs :

cp -a build/ ../bitwarden_rs/target/release/web-vault/

Instal­la­tion

On va instal­ler Bitwar­den_rs dans /opt/bitwarden et on le fera tour­ner avec l’uti­li­sa­teur www-data :

cd ..
sudo rsync -a --info=progress2 bitwarden_rs/target/release/ /opt/bitwarden/
chown -R www-data: /opt/bitwarden

Puis on va créer un service systemd, /etc/systemd/system/bitwarden.service :

[Unit]
Description=Bitwarden Server (Rust Edition)
Documentation=https://github.com/dani-garcia/bitwarden_rs
After=network.target

[Service]
# The user/group bitwarden_rs is run under. the working directory (see below) should allow write and read access to this user/group
User=www-data
Group=www-data
# The location of the .env file for configuration
EnvironmentFile=/etc/bitwarden_rs.env
# The location of the compiled binary
ExecStart=/opt/bitwarden/bitwarden_rs
# Set reasonable connection and process limits
LimitNOFILE=1048576
LimitNPROC=64
# Isolate bitwarden_rs from the rest of the system
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
# Only allow writes to the following directory and set it to the working directory (user and password data are stored here)
WorkingDirectory=/opt/bitwarden/
ReadWriteDirectories=/opt/bitwarden/

[Install]
WantedBy=multi-user.target

Pour l’in­ter­face d’ad­mi­nis­tra­tion, on va créer un token avec :

openssl rand -base64 48

La confi­gu­ra­tion se fait via des variables d’en­vi­ron­ne­ment qu’on va mettre dans /etc/bitwarden_rs.env :

SIGNUPS_ALLOWED=false
WEBSOCKET_ENABLED=true
ADMIN_TOKEN=Un token généré avec `openssl rand -base64 48`
ROCKET_ADDRESS=127.0.0.1
WEBSOCKET_ADDRESS=127.0.0.1
SMTP_HOST=127.0.0.1
SMTP_FROM=bitwarden@example.org
SMTP_PORT=25
SMTP_SSL=false

Vous remarque­rez que je dis à Bitwar­den d’en­voyer les mails via le serveur SMTP local. À vous de faire en sorte qu’il fonc­tionne. Allez voir le wiki du projet pour voir quelles variables vous pour­riez ajou­ter, enle­ver, modi­fier…

Puis :

sudo systemctl daemon-reload
sudo systemctl enable bitwarden
sudo systemctl start bitwarden
sudo systemctl status bitwarden

Nginx

On installe Nginx s’il n’est pas déjà installé :

sudo apt install nginx

Confi­gu­ra­tion du virtual­host :

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name bitwarden.example.org;

    access_log /var/log/nginx/bitwarden.access.log;
    error_log /var/log/nginx/bitwarden.error.log;

    ssl_certificate      /etc/letsencrypt/live/bitwarden.example.org/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/bitwarden.example.org/privkey.pem;

    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:5m;

    ssl_prefer_server_ciphers On;
    ssl_protocols TLSv1.2;
    ssl_ciphers 'EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA';

    ssl_dhparam /etc/ssl/private/dhparam4096.pem;
    add_header Strict-Transport-Security max-age=15768000; # six months
    gzip off;

    if ($https != 'on') {
        rewrite ^/(.*)$ https://bitwarden.example.org/$1 permanent;
    }

    root /var/www/html;

    # Allow large attachments
    client_max_body_size 128M;

    location ^~ '/.well-known/acme-challenge' {
        default_type "text/plain";
        root /var/www/certbot;
    }

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8000;
    }

    location /notifications/hub {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://127.0.0.1:3012;
    }

    location /notifications/hub/negotiate {
        proxy_pass http://127.0.0.1:8000;
    }
}

Pour créer /etc/ssl/private/dhparam4096.pem :

sudo openssl dhparam -out /etc/ssl/private/dhparam4096.pem 4096

Pour le certi­fi­cat Let’s Encrypt, on commente le brol rela­tif à ssl puis :

sudo nginx -t && sudo nginx -s reload
sudo apt install certbot
sudo mkdir /var/www/certbot/
certbot certonly --rsa-key-size 4096 --webroot -w /var/www/certbot/ --agree-tos --text --renew-hook "/usr/sbin/nginx -s reload" -d bitwarden.example.org

Une fois qu’on a le certi­fi­cat, on décom­mente le brol ssl puis :

sudo nginx -t && sudo nginx -s reload

Sauve­garde

Créer le script de sauve­garde /opt/backup_bitwarden.sh :

#!/bin/bash
function bwbackup {
    DATE=$(date '+%a%H')

    # Database
    if [[ ! -d /opt/backup_bitwarden/sqlite-backup/ ]]
    then
        mkdir -p /opt/backup_bitwarden/sqlite-backup/
    fi
    echo ".backup /opt/backup_bitwarden/sqlite-backup/db.${DATE}.sqlite3" | sqlite3 /opt/bitwarden/data/db.sqlite3 2>> /opt/backup_bitwarden/backup.log
    if [[ "$?" -ne "0" ]]
    then
        echo "Something went wrong with bitwarden database backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden database backup" youraddress@mail.example.org
        bwbackup
    fi

    # Files
    if [[ ! -d /opt/backup_bitwarden/files-backup/ ]]
    then
        mkdir -p /opt/backup_bitwarden/files-backup/
    fi
    rsync -a --delete --exclude db.sqlite3 /opt/bitwarden/data/ /opt/backup_bitwarden/files-backup/$DATE/ 2>> /opt/backup_bitwarden/backup.log
    if [[ "$?" -ne "0" ]]
    then
        echo "Something went wrong with bitwarden files backup, please see /opt/backup_bitwarden/backup.log on verity" | mail -s "Bitwarden files backup" youraddress@mail.example.org
        bwbackup
    fi
}
bwbackup

Puis :

sudo chmod +x /opt/backup_bitwarden.sh
sudo mkdir /opt/backup_bitwarden
sudo chown www-data: /opt/backup_bitwarden
sudo apt install sqlite3

Puis, dans le cron de l’uti­li­sa­teur www-data :

42 4 * * * /opt/backup_bitwarden.sh

Logs

J’aime bien avoir mes logs dans un dossier dédié pour ce genre de service.

Dans /etc/rsyslog.d/bitwarden.conf :

if $programname == 'bitwarden_rs' then /var/log/bitwarden/bitwarden.log
if $programname == 'bitwarden_rs' then ~

Dans /etc/logrotate.d/bitwarden :

/var/log/bitwarden/bitwarden.log
{
        rotate 52
        dateext
        weekly
        missingok
        notifempty
        compress
        sharedscripts
        postrotate
                invoke-rc.d rsyslog rotate > /dev/null
        endscript
}

Puis :

sudo mkdir /var/log/bitwarden
sudo chown root:adm /var/log/bitwarden
sudo service rsyslog restart

Fail2­ban

Un fail2­ban qui surveille les logs, ça permet de bloquer les petits malins qui font du brute­force

Dans /etc/fail2ban/filter.d/bitwarden.conf :

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\. Username:.*$
ignoreregex =

Dans /etc/fail2ban/jail.d/bitwarden.local :

[bitwarden]
enabled = true
port = 80,443
filter = bitwarden
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

Pour la page d’ad­min, dans /etc/fail2ban/filter.d/bitwarden-admin.conf :

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Unauthorized Error: Invalid admin token\. IP: <HOST>.*$
ignoreregex =

Dans /etc/fail2ban/jail.d/bitwarden-admin.local :

[bitwarden-admin]
enabled = true
port = 80,443
filter = bitwarden-admin
action = iptables-allports[name=bitwarden]
logpath = /var/log/bitwarden/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

Fina­le­ment :

sudo service fail2ban restart

Conclu­sion

Voilà, vous devriez avoir un serveur Bitwar­den_rs fonc­tion­nel. Plus qu’à aller sur l’in­ter­face web que vous venez de mettre en place ou télé­char­ger les clients et à les utili­ser !

Pour impor­ter vos mots de passe de Fire­fox, il faut passer par une appli­ca­tion pour les expor­ter, puis aller dans les outils de votre client (ou de l’in­ter­face web).

EDIT 15/01/2019 Rempla­ce­ment de la mention de l’ap­pli­ca­tion Next­cloud Pass­words par l’ap­pli­ca­tion Pass­man (je me suis trompé).

EDIT 17/01/2019 Rempla­ce­ment de npm run dist par npm run dist:selfhost dans la compi­la­tion de l’in­ter­face web. Cela désac­tive Google Analy­tics (voir https://github.com/bitwar­den/web/issues/243#issue­comment-412852726)

EDIT 18/01/2019 Rempla­ce­ment de npm run dist:selfhost par npm run dist dans la compi­la­tion de l’in­ter­face web. Google Analy­tics est déjà désac­tivé par le patch. Il semble­rait que j’ai vu passer des requêtes vers Google Analy­tics à cause du cache de mon navi­ga­teur qui gardait une version non patchée.

EDIT 18/01/2019 Ajout d’un aver­tis­se­ment sur la consom­ma­tion de RAM lors de la compi­la­tion de l’in­ter­face web.

Crédits : Photo par Matt Artz sur Unsplash

Parta­ger

by Luc at January 14, 2019 07:02 PM

January 13, 2019

Florent Peterschmitt

Namasté Népal - #4.1

Récapitulatif

Dans l’article précédent j’étais donc à Pokhara et je sortais d’une grotte remplie de chauves-souris. Une fois ressorti j’avais prévu de passer encore une journée sur place, après-demain sera donc le retour vers Kathmandu pour commencer le trekking de la vallée de Langtang.

Le départ est à Syapru Besi, un village à fond pour les touristes venant marcher dans les montagnes. Rien de très étonnant à vrai dire.

L’arrivée était prévue à 4500 mètres d’altitudes, je me suis arrêté à environ 3000 mètres, avec de la fièvre (oui, je suis retombé malade…) et le souffle coupé. Comme quoi il faut s’entraîner avant, oui bien être fumeur : d’après mon guide les fumeurs, même sans expérience de la montagne arrivent à aller au bout. Ce qui est compréhensible vu qu’un fumeur a régulièrement un manque d’oxygène dans les poumons !

J’ai découpé le trek en 4 articles à venir ; les photos sont déjà triées, reste plus qu’à en retoucher quelques unes et à publier.

Et comme toujours, un peu de shell :D

for img in $(find 2* -name "*.*"); do
    echo '![photo](/static/images/nepal2017/'${img}')' >> pics.md
done

22 Avril 2017 - Vallée de Langtang

map-trek

Démarrage à 1600 mètres environ !

photo photo photo photo photo photo photo photo

Sur la gauche de la photo, sur ce flan de montagne effondré, des nids d’abeilles. Elles font un miel qui est récolté.

photo

Premier « singe blanc », qui n’a pas voulu montrer sa tête. Impossible de l’avoir en plus gros, le zoom était déjà à son maximum.

photo photo photo

Arrivé au gîte (guest house) ce pti bonhomme parlait mieux anglais que quand j’avais son âge, et débordait d’énergie ! Il a voulu tester l’appareil photo, je l’ai laissé faire, bon, le résultat était pas probant :D

photo photo

Des rhododendrons !

photo

Soir nuageux.

photo

Matin dégagé.

Article suivant

by Florent Peterschmitt at January 13, 2019 03:15 PM

January 10, 2019

Romain Dessort

Joindre les 2 bouts de la Laurentienne

La région des Laurentides est très riche en pistes de ski nordique datant du siècle dernier, des sentiers historiques tracés en partie par des norvégiens, dont le fameux Jackrabbit, à l'époque où le ski de fond était populaire au Québec. Malheureusement aujourd'hui, beaucoup sont abandonnées, trop méconnues et réduites en morceaux à cause des développements immobilier et des propriétés privées. Découvrir et cartographier ces pistes historiques est devenu ma grande passion, et je skie plus dans le but de répertorier des nouvelles pistes que juste pour le plaisir de skier.

Si il y a un blog de ski nordique que je ne me lasse pas de lire, c'est celui de Barclay. J'ai découvert plusieurs pistes des Laurentides comme ça et c'est toujours intéressant d'avoir régulièrement les conditions des sentiers.

De mon côté jusqu'à présent, je me « contentais » de cartographier les sentiers de ski que je suivais dans OpenStreetMap. La région des Laurentides dans OSM a d'ailleurs explosé depuis quelques années, quelques autres personnes en rajoute aussi, et c'est maintenant clairement la carte la plus complète possible en terme de sentiers de ski (de fond ou de rando nordique). Mais en parler aussi ailleurs est toujours une bonne idée, donc je vais essayer de parler un peu plus de mes sorties ici. En tout cas au moins mes découvertes de pistes moins connues, car je n'aurai pas la motivation d'écrire à chaque fois, et il n'y a peu d'intérêt pour les pistes plus connues ou bien cartographiées.

Voila pour l'introduction, pour revenir à la Laurentienne, il faut retourner à la fin de saison de l'année dernière, j'avais repéré sur la carte du réseau nordique de Morin-Heights une piste qui s'en allait plein ouest, la Laurentienne (#24) puis qui s'arrêtait sans raison au milieu de nulle part. Ça a évidemment titillé ma curiosité et j'étais parti avec pour objectif de voir où elle allait. J'avais réussi à la suivre sur un bon bout au delà de la partie cartographiée, mais j'avais perdu sa trace ensuite dans une érablière et rendu sur le lac Ida. J'avais rebroussé chemin.

Samedi dernier donc, je l'ai prise en partant de Saint-Adolph, en stationnant au lac Louise, là où elle est censée arriver : la carte du réseau de Saint-Adolph montre aussi un début de piste qui a bien l'air de partir dans la bonne direction pour la connecter, mais ils ne l'ont pas cartographiée jusqu'au bout non plus.

À ma grande surprise, la piste était plutôt bien visible sur le terrain, et il y avait même quelques traces de skieurs et de raquetteurs qui m'avaient précédé. Au moins jusqu'à la route de la Montée des Quatres Lacs. Après c'était plus délicat à suivre mais la piste se devinait bien. J'ai pu retrouver l'endroit où je m'étais arrêté l'année dernière, près du lac Ida. La Laurentienne est maintenant complète dans OpenStreetMap !

Par contre des mystères persistent : sur certains sections (un peu avant le lac Ida), j'ai vu des très vieilles balises métalliques indiquant LSD, une autre piste porte déjà ce nom dans le secteur, c'est bizarre. Et après avoir passé la route de la Montée des Quatres Lacs, j'ai vu 2 panneaux dans le même style que ceux utilisés à Morin-Heights indiquant la Picher (#29) et la Dutch-Dash (#27). La Dutch-Dash est le début de la Laurentienne côté Morin-Heights. J'en déduis que ces 2 pistes restent confondues sur un bon bout. Mais après où va-t-elle ? Et la Picher, je n'en ai aucune idée de ce que c'est… Je ne la vois référencée sur aucune carte que j'ai.

Concernant l'allure de la Laurentienne, elle n'est en soit pas très difficile, il y a quelques up and down dans sa partie ouest mais la piste est suffisamment large pour pouvoir manœuvrer en descente. La partie reste essentiellement sur du plat, en passant à travers une belle forêt de cèdres à l'ouest du lac Ida, et longe des zones ruisseau et passe sur des zones marécageuses et des lacs dans sa partie est vers Morin-Heights.

J'étais parti avec l'idée que j'allais devoir débroussailler pas mal la piste, mais elle était assez propre. Il reste quand même quelques coups de scie à donner par-ci par-là si quelqu'un y retourne.

J'en ai aussi profité pour aller explorer la Castor (#6) qui connecte la Laurentienne à la Renard et traverse le lac Saint-Denis. Je me suis arrêté une fois rendu au lac car je voyais bien où est-ce que la Renard commence. C'est intéressant à avoir en tête car ça permet de faire une belle boucle entre Morin-Heights et Saint-Adolph.

January 10, 2019 07:13 PM

January 05, 2019

Romain Dessort

Patinoires de MontrĂŠal et donnĂŠes ouvertes

Dernièrement je me suis amusé à exploiter les données ouvertes que la ville de Montréal maintient sur les conditions de glace des patinoires publiques.

L'état de chaque patinoire est indiqué sur le site de la ville. Un fichier XML mis à jour quasi-quotidiennement durant la saison peut être trouvé ici, les données sont sous licence Creative Common BY 4.0.

L'idée était de pouvoir vérifier les conditions plus simplement que d'ouvrir mon navigateur, en une seule commande. Voici donc patinoires-mtl. Les cas d'usage sont mis en exemple dans le README : lister les patinoires ouvertes, afficher les conditions d'une ou plusieurs patinoires et, bonus, une sous-commande watch qui retourne les conditions seulement si elles ont changées, ce qui me permet d'envoyer ça à mail ou sendxmppet à mettre encron` pour être alerté dès qu'il y a un changement.

Lister les patinoires ouvertes :

$ ./patinoire.py list --open
Skating rink                                          Open
----------------------------------------------------  ----
Patinoire Bleu Blanc Bouge du parc Hayward (PSE)      1
Patinoire Bleu-Blanc-Bouge, Parc Confédération (PSE)  1
Patinoire réfrigérée, Lac aux Castors (PP)            1

Lister les patinoires du Plateau-Mont-Royal :

$ ./patinoire.py list --borough pmr
Skating rink                                           Open
-----------------------------------------------------  ----
Grande patinoire avec bandes, La Fontaine (PSE)        0
Patinoire avec bandes, Baldwin (PSE)                   0
Patinoire avec bandes, Jeanne-Mance (PSE)              0
Patinoire avec bandes, Sir-Wilfrid-Laurier no 1 (PSE)  0
Patinoire avec bandes, Sir-Wilfrid-Laurier no 2 (PSE)  0
Patinoire avec bandes, Sir-Wilfrid-Laurier no 3 (PSE)  0
Patinoire De Gaspé/Bernard (PSE)                       0
Patinoire de patin libre, Baldwin (PPL)                0
Patinoire de patin libre, Jeanne-Mance (PPL)           0
Patinoire de patin libre, Sir-Wilfrid-Laurier (PPL)    0
Patinoire décorative, De Lorimier (PP)                 0
Patinoire décorative, La Fontaine (PP)                 0

Afficher les conditions d'une patinoire en particulier :

$ ./patinoire.py conditions "lac aux castors"
                                            Open  Cleared  Sprayed  Resurfaced  Condition   
------------------------------------------  ----  -------  -------  ----------  ----------  
Patinoire réfrigérée, Lac aux Castors (PP)  1     1        1        1           Excellente 

Et une fonction pratique, pour être notifié d'un changement de condition sur une patinoire :

$ ./patinoire.py watch "lac aux castors"
                                            Open  Cleared  Sprayed  Resurfaced  Condition
------------------------------------------  ----  -------  -------  ----------  ----------
Patinoire réfrigérée, Lac aux Castors (PP)  1     1        1        1           Excellente
Updated on 2018-12-08 09:05:28
$ ./patinoire.py watch "lac aux castors"
$
[a few days later]
$ ./patinoire.py watch "lac aux castors"
                                            Open  Cleared  Sprayed  Resurfaced  Condition
------------------------------------------  ----  -------  -------  ----------  ----------
Patinoire réfrigérée, Lac aux Castors (PP)  1     1        1        1           Bonne
Updated on 2018-12-10 09:03:56

Comme j'adore les cartes, j'ai aussi fait patinoires-mtl-leaflet, qui permet de geolocaliser toutes les patinoires de Montréal sur un fond de carte OpenStreetMap et d'afficher leur état. Bon pour le coup, c'est de nouveau dans le navigateur forcement... La couleur des patinoires est en fonction de leur état. Un aperçu ici : https://univers-libre.net/patinoires-mtl/.

Pour la géolocalisation des patinoires, la ville de Montréal ne fournit aucune données. OpenStreetMap ne contient que très peu de patinoires non plus, et ça allait être compliqué de faire correspondre les noms des patinoires du XML de la ville avec ceux dans OpenStreetMap de toute façon. C'est alors que je suis tombé sur une application Android qui fait à peu près la même chose et qui a un fichier geojson avec la géolocalisation de toutes les patinoires. Rien n'est indiqué concernant la licence ou la provenance de ces données par contre.

L'outil en ligne de commande est en anglais et la carte est en français, ça ne fait aucune cohérence et comme ça tout le monde/personne (n')est content.

Je ne pense pas y faire d'autres modifications à part rajouter probablement la même chose pour les conditions des pistes de ski de fond.

January 05, 2019 02:29 AM

January 04, 2019

Luc Didry

Créer une boutique en ligne avec Word­press

Dans mon précé­dent article, j’évoquais le fait que j’ai ouvert ma boutique en ligne. Je vais expliquer un peu comment j’ai fait pour la mettre en place.

Le logi­ciel de base : Word­press

Pourquoi Word­press et pas Pres­ta­shop ou Magento qui sont des outils dédiés à la vente en ligne ? Plusieurs raisons à cela :

  • je connais déjà bien Word­press, je n’avais pas spécia­le­ment envie de m’enquiqui­ner à instal­ler d’autres trucs ;
  • Word­press, bien que ce soit au départ un moteur de blog, est un CMS que l’on peut tordre dans pas mal de sens. Je me suis dit que j’avais envie de voir si c’était simple d’en faire un site de vente en ligne ;
  • j’ai quand même essayé d’uti­li­ser Pres­ta­shop… sans réus­sir à passer la dernière étape d’ins­tal­la­tion : la mise en place de la base de données tombait en timeout à chaque fois (j’ai pas un énorme serveur et il est déjà bien plein de trucs).

Bref : on commence par instal­ler un Word­press. Je ne vais pas détailler, c’est un sujet fort bien traité sur les Inter­netz.

Les exten­sions

Pour trans­for­mer Word­press en boutique en ligne, il faut instal­ler quelques modules. Mais avant ça, voici ceux que j’ai installé pour la sécu­rité, les perfor­man­ces… :

  • Antis­pam Bee, pour l’an­tis­pam ;
  • iThemes Secu­rity, pour la sécu­rité ;
  • Smush, pour réduire la taille des images ;
  • WP Super Cache, pour les perfor­mances.

Ensuite, des exten­sions pour amélio­rer la boutique, mais pas obli­ga­toires :

  • Contact Form 7, pour le formu­laire de contact ;
  • Google XML Site­maps, pour amélio­rer le réfé­ren­ce­ment ;
  • Masto­don Auto­post, pour pouet­ter auto­ma­tique­ment quand on ajoute un article à la boutique.

Voici les exten­sions pour la boutique elle-même :

  • WooCom­merce, l’ex­ten­sion prin­ci­pale, propo­sée par la boîte qui déve­loppe Word­press, donc ça va, j’ai assez confiance sur la compa­ti­bi­lité ;
  • WooCom­merce Blocks, pour faire fonc­tion­ner WooCom­merce avec le nouvel éditeur de Word­press ;
  • WooS­wipe, pour avoir une gale­rie d’image sur les pages des produits (quand on clique sur l’image pour zoomer, pis pour voir les autres images, vous voyez le genre) ;
  • WooCom­merce Weight Based Ship­ping, pour gérer les frais d’en­voi selon le poids de la commande ;
  • Payment Gate­way Based Fees and Discounts for WooCom­merce, pour pouvoir ajou­ter des frais selon la méthode de paie­ment choi­sie.

Le thème

Il va de soit qu’un thème pour un blog a peu de chance d’al­ler pour faire une boutique. J’ai choisi le thème Shop Isle, que je trouve simple et bien foutu. J’en ai néan­moins fait un thème enfant pour déga­ger ces cochon­ne­ries de google fonts.

Les frais d’en­voi

L’ex­ten­sion « WooCom­merce Weight Based Ship­ping » me permet de défi­nir des frais d’en­voi selon le poids de la commande ainsi que sa desti­na­tion (vous imagi­nez bien qu’en­voyer deux cartes postales en France ne coûte pas le même prix qu’en envoyer 15 dans un autre pays).

Cette exten­sion est parfaite, à l’ex­cep­tion de l’in­ter­face pour choi­sir les pays de desti­na­tion quand on crée les règles : ça va bien quand on ajoute une ou deux desti­na­tions, mais pas quand on doit en sélec­tion­ner 12 (france métro­po­li­taine + DOM/TOM) ou plus (les pays de l’UE).

Person­nel­le­ment, j’ai choisi de faire des frais d’en­voi à prix plus ou moins coûtant : le tarif des timbres, arrondi un peu au-dessus pour faire le prix de l’en­ve­loppe. Je ne dis pas que je ne fais pas un peu de béné­fice dessus, mais ça se compte à coup de centimes.

Le paie­ment

WooCom­merce embarque déjà plusieurs moyens de paie­ments, je dois dire que c’est très bien foutu !

J’ai activé le vire­ment SEPA, parce que ça ne coûte rien, ni à l’en­voyeur, ni au desti­na­taire. Par contre, comme ça prend du temps (le vire­ment prend géné­ra­le­ment 24h pour appa­raître sur les comptes, sans comp­ter que certaines banques mettent plusieurs jours pour accep­ter un nouvel IBAN et permettre des vire­ments vers celui-ci), j’ai ajouté la possi­bi­lité d’uti­li­ser Paypal : ça propose d’uti­li­ser son compte Paypal (et c’est assez répandu pour que ça soit pratique pour un paquet de gens) pour payer ou la carte bancaire. Par contre, ça m’a fait deux blagou­nettes :

  • pour effec­ti­ve­ment pouvoir récu­pé­rer les paie­ments, j’ai du passer mon compte en compte busi­ness. Rien de bien méchant, mais la récu­pé­ra­tion des sous ne fonc­tion­nait pas et rien n’in­diquait sur Paypal que c’était ce qu’il fallait faire (il y avait juste un message d’er­reur complè­te­ment inutile). Une fois mon compte passé en busi­ness, plus de souci ;
  • mais du coup, des frais s’ap­pliquent (pas pour le client, qui paie bien ce que ma boutique lui indiquait, mais pour moi : je ne récu­père pas autant d’argent que ce qu’a payé le client). Comme je ne souhaite pas en être de ma poche, j’ai installé « Payment Gate­way Based Fees and Discounts for WooCom­merce » qui me permet d’ajou­ter le pour­cen­tage (3,4%) et le forfait (0,25€) de la commis­sion lorsqu’on choi­sit Paypal pour payer.

Condi­tions géné­rales de vente

Pour les rédi­ger, j’ai d’abord cher­ché sur le web, et je suis tombé sur https://www.donnees­per­son­nelles.fr/cgv, qui propose carré­ment une exten­sion Word­press. Après l’avoir instal­lée, je me suis contenté de repom­per les CGV qu’elle propo­sait : ça m’a permis, tout d’abord, de les lire, et ensuite de corri­ger des typos.

Après quoi, j’ai désins­tallé l’ex­ten­sion 😁

Conclu­sion

Je ne pense pas qu’il soit néces­saire pour moi de trop détailler le réglage des diffé­rentes exten­sions : les infos se trouvent assez faci­le­ment sur le web, et même si les réglages sont touf­fus, c’est assez intui­tif. La plus grosse partie du temps fut perdue dans la recherche des exten­sions et du thème kivon­bien.

Après quelques tâton­ne­ments, la mise en place de ma boutique fut assez simple. J’es­père que cet article servira à d’autres pour leur éviter de cher­cher autant que moi.

Crédits : Photo par Mike Petrucci sur Unsplash

Parta­ger

by Luc at January 04, 2019 05:09 PM

Merci à mes tipeurs 🙂

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle de décembre.

Merci à :

Voici mon bilan de décembre :

EDIT : j’ai oublié de dire que j’ai bossé sur la réécri­ture de WemaWema en VueJS

Et sinon, grande annonce ! J’ai ouvert ma boutique en ligne !

Bon, pour l’ins­tant, il n’y a qu’un article, une carte postale d’une illus­tra­tion de Linux.pictures. J’avais fait un sondage sur Masto­don il y a quelques mois pour savoir quelle illus­tra­tion impri­mer, et voilà, j’ai enfin pris la peine (et les sous) de faire tirer les cartes postales. Les béné­fices, s’il y en a (vu que je vends à prix coûtant, à quelques arron­dis prêts, y en aura peut-être pas avant long­temps), iront à Linux.pictures (ou un projet libre si je n’ar­rive pas à les contac­ter).

Je compte rajou­ter prochai­ne­ment un recueil de mes mercre­dis fictions relié à la japo­naise par mes soins (vous pouvez voir ce que ça donne sur ce pouet).

Vous pouvez toujours me soute­nir via Duni­ter !

Je remets ici mon expli­ca­tion.

Disclai­mer : je vais peut-être dire des sottises parce que j’ai pas tout compris mais je m’en fous, j’aime bien l’idée

Duni­ter est un projet de crypto-monnaie mais contrai­re­ment au bitcoin où c’est la course à la puis­sance de calcul pour géné­rer la monnaie et deve­nir riche, le but est de créer une monnaie libre (le Ğ1, prononcé comme june en anglais), basée sur une toile de confiance (il faut rece­voir 5 certi­fi­ca­tions pour être membre) et où chacun des membres reçoit tous les jours un divi­dende univer­sel. Je dois dire que je suis assez curieux de ce qu’on peut faire avec un système ressem­blant forte­ment au salaire à vie 😉

C’est pourquoi j’ai créé mon compte et ait fait ce qu’il fallait pour rece­voir mes certi­fi­ca­tions (rencon­trer des gens, tous­sa…). Ma clé publique est :

 2t6NP6Fvvuok2iRWA188C6pGokWAB5Kpf1S1iGtkN9tg

Et comme un projet n’est utile que si on s’en sert, je vous propose de me soute­nir en Ğ1 tout en béné­fi­ciant des mêmes récom­penses que celles présentes sur ma page Tipeee (j’ai arbi­trai­re­ment choisi une parité euro/Ğ1 car je n’ai pas vrai­ment trouvé de page expliquant comment évaluer le cours du Ğ1 en euros, et au final, est-ce vrai­ment néces­saire ? À nous de choi­sir quelle valeur a cette nouvelle monnaie 🙂. Et puis ça me simpli­fie la vie).

Voici donc les diffé­rentes contre­par­ties et leur prix (chaque contre­par­tie comprend celles de tarif infé­rieur) :

  • 1 Ğ1 : vous appa­raî­trez sur la page mensuelle des remer­cie­ments
  • 2 Ğ1 : vous rece­vrez une photo dédi­ca­cée de mon chat
  • 3 Ğ1 : vous rece­vrez 3 stickers repre­nant les logos de Lstu, Lutim et Lufi. De quoi déco­rer son ordi et se la péter en société 😁
  • 5 Ğ1 : un commit vous sera dédié chaque mois (si je déve­loppe suffi­sam­ment pour le nombre de personnes à ce niveau)
  • 15 Ğ1 : vous pouvez me deman­der de bosser en prio­rité sur un bug ou une demande de fonc­tion­na­lité d’un de mes logi­ciels (dans la mesure du faisable, hein).
  • 100 Ğ1 : quand j’au­rais un nouveau projet, vous pour­rez en choi­sir le nom et le logo

Pour en savoir plus sur Duni­ter et Ğ1, je vous propose d’al­ler voir cet article de cgeek : https://blog.cgeek.fr/de-linte­ret-dune-monnaie-libre.html ainsi que la théo­rie rela­tive de la monnaie pour les enfants.

Crédits : Photo par Simon Migaj sur Unsplash

Parta­ger

by Luc at January 04, 2019 04:13 PM

December 24, 2018

Luc Didry

Double merci à mes tipeurs 🙂

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle d’oc­to­bre… et de novembre. Du retard, toujours du retard et encore plus de retard !

Merci à :

Voici mon bilan d’oc­tobre :

Et mon bilan de novembre :

Vous pouvez toujours me soute­nir via Duni­ter !

Je remets ici mon expli­ca­tion.

Disclai­mer : je vais peut-être dire des sottises parce que j’ai pas tout compris mais je m’en fous, j’aime bien l’idée

Duni­ter est un projet de crypto-monnaie mais contrai­re­ment au bitcoin où c’est la course à la puis­sance de calcul pour géné­rer la monnaie et deve­nir riche, le but est de créer une monnaie libre (le Ğ1, prononcé comme june en anglais), basée sur une toile de confiance (il faut rece­voir 5 certi­fi­ca­tions pour être membre) et où chacun des membres reçoit tous les jours un divi­dende univer­sel. Je dois dire que je suis assez curieux de ce qu’on peut faire avec un système ressem­blant forte­ment au salaire à vie 🙂

C’est pourquoi j’ai créé mon compte et ait fait ce qu’il fallait pour rece­voir mes certi­fi­ca­tions (rencon­trer des gens, tous­sa…). Ma clé publique est :

 2t6NP6Fvvuok2iRWA188C6pGokWAB5Kpf1S1iGtkN9tg

Et comme un projet n’est utile que si on s’en sert, je vous propose de me soute­nir en Ğ1 tout en béné­fi­ciant des mêmes récom­penses que celles présentes sur ma page Tipeee (j’ai arbi­trai­re­ment choisi une parité euro/Ğ1 car je n’ai pas vrai­ment trouvé de page expliquant comment évaluer le cours du Ğ1 en euros, et au final, est-ce vrai­ment néces­saire ? À nous de choi­sir quelle valeur a cette nouvelle monnaie 🙂. Et puis ça me simpli­fie la vie).

Voici donc les diffé­rentes contre­par­ties et leur prix (chaque contre­par­tie comprend celles de tarif infé­rieur) :

  • 1 Ğ1 : vous appa­raî­trez sur la page mensuelle des remer­cie­ments
  • 2 Ğ1 : vous rece­vrez une photo dédi­ca­cée de mon chat
  • 3 Ğ1 : vous rece­vrez 3 stickers repre­nant les logos de Lstu, Lutim et Lufi. De quoi déco­rer son ordi et se la péter en société 😁
  • 5 Ğ1 : un commit vous sera dédié chaque mois (si je déve­loppe suffi­sam­ment pour le nombre de personnes à ce niveau)
  • 15 Ğ1 : vous pouvez me deman­der de bosser en prio­rité sur un bug ou une demande de fonc­tion­na­lité d’un de mes logi­ciels (dans la mesure du faisable, hein).
  • 100 Ğ1 : quand j’au­rais un nouveau projet, vous pour­rez en choi­sir le nom et le logo

Pour en savoir plus sur Duni­ter et Ğ1, je vous propose d’al­ler voir cet article de cgeek : https://blog.cgeek.fr/de-linte­ret-dune-monnaie-libre.html ainsi que la théo­rie rela­tive de la monnaie pour les enfants.

Crédits : Photo par Connor Wells sur Unsplash

Parta­ger

by Luc at December 24, 2018 04:21 PM

December 22, 2018

Romain Dessort

Safe paste in terminal

In my daily life of sysadmin, I copy-paste many chunk of text (commands, IP addresses, URLs, file paths, whole scripts or file contents sometimes because it's easier to copy-paste them rather than to scp them). I usually copy them from other servers or from my company's internal documentation (trusted sources). However, I may sometimes follow howtos or read Stackoverflow answers and copy text and commands from those less trusted websites.

I want to talk about how easy one could trick you by replacing copied text in your clipboard or inserting terminal escape sequences so that your shell will run additional and potentially malicious commands. And how I protecting myself against these tricks.

Tricks I have identified

Here is a list of tricks an attacker can use to fool you and make you paste a malicious command in your terminal.

Replacing copied text with Javascript

Dylan Ayrey demonstrates that with a few lines of Javascript, a malicious website can alter your clipboard content. The code runs on key release event (keyboard shortcut or right click) and override clipboard content with the malicious code the attacker wants you to execute.

Obviously this attack doesn't work if you disable Javascript on unstrusted websites, which is by the way always a good idea.

Hiding malicious code with CSS

But even with Javascript disabled it's easy for an attacker to put hidden text in your clipboard. The idea is to put the malicious code in the middle of the displayed command in a <span /> element and apply different CSS properties on it, so that the malicious code isn't visible for the user. For instance make it float and move it away from the viewport, make it transparent, with no height or width…

Here is an interesting article about this attack. It also show how to hide the malicious code once pasted in the victim's terminal so that the victim can't even known he has been p0wned.

What about disabling CSS then?

Inserting non-printable characters

That's no enough since you could have non-printable characters (like backspaces) in raw text. Here is an example (the whole thread is an interesting reading by the way). Basically, the idea is to insert extra characters and a backspace character after each of them to make the code appear inoffensive.

How I protect myself

So what next? What solutions I use to protect myself against those attacks?

Pasting into a text editor: the bad idea

In most shell, I can easily start $EDITOR with ^X^E to edit the current command. But that's totally ineffective since the pasted text can contain ^ESC:!<malicious code> which will work in vim, or simply send the right shortcut to close the editor and get back to the shell.

Shell's bracketed paste mode

This is an elegant solution. Bash (actually readline) can configure the terminal to enclose the pasted text between paste sequences (hence the bracketed paste mode):

enable-bracketed-paste (Off) When set to On, readline will configure the terminal in a way that will enable it to insert each paste into the editing buffer as a single string of charac‐ ters, instead of treating each character as if it had been read from the key‐ board. This can prevent pasted characters from being interpreted as editing commands.

To enable it:

$ echo "set enable-bracketed-paste on" >>~/.inputrc

If you then try to paste multi-lines commands in your terminal, the commands won't be executed unless you press enter. You have a chance to review and edit them before their execution.

But it has two main drawbacks:

  • obviously enabling bracketed paste mode will work on your own computer only, unless you enable it on all your remote servers as well.
  • you may still be vulnerable to code injection if the pasted text contains the bracketed-paste-mode end sequence, whether your terminal automatically filter this sequence or not.

You can test this here.

confirm-paste plugin in URxvt

URxvt has a nice plugin called paste-confirm. It is shipped with URxvt and can be found in its plugin directory (/usr/lib/urxvt/perl/). Once loaded, the plugin will detect multi-lines pastes and will ask you whether to really paste it to the shell or not.

To enable it, simply add it to the plugin list in your ~/.Xdefaults:

URxvt.perl-ext-common: […],confirm-paste

Print your clipboard content before you paste

It's always a good idea to double-check your clipboard content before pasting it somewhere. I sometimes don't remember or I'm not sure about what was my previous selection, and I remember pasting whole file content into my terminal a couple of times…

I now use clipster for my cliboard manager with roficlip. Thus with a simple shortcut I can quickly double-check and select the previous entries in my clipboard.

December 22, 2018 06:13 PM

December 08, 2018

Florent Peterschmitt

Femto Feed

Tous les lecteurs de flux me saoulent :

  • FreshRSS est génial, mais je ne veux pas avoir à installer tout ce qu’il demande. Actuellement mon blog est rendu via des fichiers statiques, je souhaite qu’il en aille de même pour ça.
  • Les services commerciaux comme Feedly ne m’apportent pas grand chose, je n’ai pas besoin des fonctionnalités payantes, et je me suis désinscrit récemment car ils poussent leurs offres payantes comme quelqu’un qui veut vous forcer à avaler un rat mort.
  • Il existe certainement des offres libres et gratuites, mais j’ai une idée très précise de ce que je veux, c’est très simple, alors je l’ai codé.

Femto Feed - Fonctionnalités

  • Récupérer les flux depuis une liste maintenue dans un fichier
  • Générer un fichier HTML rudimentaire avec : date | source | titre et lien

Et… c’est tout. Je le lance via une tâche planifiée et le fichier généré est servi via un serveur web. Fin de l’histoire.

Le nouveau-né s’appelle donc Femto Feed et il est disponible sur gitlab.com et github.com.

En Rust

Avec l’édition 2018 quit vient tout juste de sortir, c’était une raison suffisante pour utiliser ce langage :-P Bon, en vrai, c’est surtout parce que j’aime ça :

  • Typage statique
  • Génériques, et surtout Option et Result
  • Pattern matching
  • Gestion d’erreur sans exceptions
  • Outillage à l’image de ce qui se fait dans le monte Python et/ou Go
  • Move semantic, borrowing… (std::move et unique_ptr en C++ si je ne me trompe pas)

Enjoy !

Toute contribution sera la bienvenue, à partir du moment où on reste dans l’échelle femtomètrique, voir la TODO dans le README du projet.

by Florent Peterschmitt at December 08, 2018 09:00 PM

November 30, 2018

Florent Peterschmitt

La “règle” des 80 colonnes et variantes

Grand débat du jour, faut-il tout limiter à 80 colonnes pour son code et/ou sa documentation ? Et non j’ai rien d’autre à faire un vendredi soir :D

Il est répandu que 80 colonnes pour son code et même du texte, documentation dans le code ou non, c’est bien.

Dans le cas du code, c’est assez court pour éviter de devoir faire défiler le texte à l’horizontale, et de toute façon au de là d’une certaine limite « acceptable » c’est signe d’un code… bof. Pour du texte, cela évite aussi aux yeux de faire de grands sauts entre la fin d’une ligne et le début de la prochaine.

On trouve une réponse historique du côté des cartes performées IBM dont la largeur a été de 80 colonnes (mais pas seulement).

Sauf que les cartes perforées… je n’en ai jamais vu en vrai, alors pourquoi toujours 80 colonnes ?

Marche droit’d’vant toi !!

Cette règle n’est-elle pas un peu trop stricte compte tenu des outils (éditeurs) et supports (écrans) actuels ? Les écrans sont bien plus larges que 80 colonnes de texte taille 13 sur une résolution 1080p et les éditeurs disposent d’outils automatiques pour faire la mise en forme.

L’objectif actuel de limiter le nombre de colonnes dans du code source, ou du texte, est partagé par différents medias : des livres aux pages web, il est toujours désagréable de lire du texte qui n’en fini pas de s’étaler sur toute la largeur de l’écran et il semble donc parfaitement logique de limiter la taille du contenu.

En ce qui concerne le code, même tarif : lire une ligne qui n’en fini pas pose les mêmes problèmes que de lire du texte en bon françoy sur une page web, avec en plus d’horribles conséquences sur la mémorisation de ce qu’il s’y passe.

Le cas du code

if ((bla == truc && op == "bazar" && callMe(withaparam).attribute != someVal) || (urlu == (berlu + mochi) && shift >> it)) {
    patakess();
}

Dans cet exemple on est déjà à 124 colonnes, le blog vous affiche une barre de défilement horizontale, et franchement j’en ai eu marre assez vite. Même avec du code qui veut dire quelque chose, avec de vrais noms de variables explicites, de vrais noms de méthodes etc, c’est très, très chiant.

On préfèrera peut-être quelque chose du genre :

if ((bla == truc && op == "bazar" && callMe(withaparam).attribute != someVal)
    || (urlu == (berlu + mochi) && shift >> it))
{
    patakess();
}

C’est évidemment moins long, ça tient dans les 80 colonnes, on peut accéder à toutes les informations d’un coup et on a assez clairement la séparation des deux conditions ||.

Et pourtant il n’est pas toujours nécessaire d’avoir trouzillions de paramètres/conditions/whatever pour se retrouver avec des lignes aberrantes :

def je_documente_ma_fonction_avec_tous_les_types_de_parametres_dans_le_nom(prout):
    pass

J’ai réellement vu ce genre de cas. Rare, mais quand même…

Parfois même on obtient d’autres aberrations (à mon sens) quand on applique strictement la règle des 80 colonnes (ou toute autre limite) :

func DoStuff() {
    fmt.Println(
        "je suis une belle documentation, je prends soin de moi tous les jours mais " +
        "suis un peu trop longue, on va me concaténer au runtime comme un gros sac " +
        "alors que peut-être ya d’autres moyens de faire ça…"
    )
}

En soit, c’est lisible, mais ajouter des opérations dans un programme pour satisfaire une règle d’affichage pour nous pauvres humains, je trouve cela très exagéré. Et re-oui, c’est du déjà vu. Alors c’est vrai que comme c’est une donnée imutable, il est probable que le compilateur/interpréteur optimise ça… sauf que c’est toujours autant de travail manuel qui doit être réalisé.

Dans tous les cas, limiter manuellement la longueur des lignes de code semble nécessaire afin d’éviter de se perdre ou d’obtenir une indentation moche.

Le cas du texte

Pour moi, le pire du pire est de rédiger du texte (documentation) en appliquant la règle des 80 colonnes à la main.

Quand on écrit du texte, on obtient des paragraphes :

Division d'un texte de prose, d'un discours, d'un chapitre qui apparaît
typographiquement par un alinéa initial. (Dans les renvois, le paragraphe est
noté par le signe §, appelé lui-même « paragraphe ».)

Définition du Larousse

Petite section d'un discours, d'un chapitre. Ce paragraphe se lie mal au
paragraphe précédent.

Une définition du Littré

Et c’est exactement en ce sens que je comprends et utilise les paragraphes : des sections de texte un peu indépendantes des autres, des phrases qui ont un sens une fois regroupées sous un même paragraphe.

En terme de rendu visuel, un paragraphe peut être découpé sans intervention manuelle.

Par exemple, je vais vour reprendre ici la dernière phrase telles que je l’ai écrite :

Et c’est exactement en ce sens que je comprends et utilise les paragraphes : des sections de texte un peu indépendantes des autres, des phrases qui ont un sens une fois regroupées sous un même paragraphe.

Et telle qu’elle me l’est affichée dans le terminal :

Et c’est exactement en ce sens que je comprends et utilise les paragraphes : des 
sections de texte un peu indépendantes des autres, des phrases qui ont un sens une fois 
regroupées sous un même paragraphe.

La ligne fait bien plus que 80 colonnes, mais avec le retour à la ligne automatique on est à l’aise. En plus, comme je change régulièrement les mots utilisés, la mise en forme manuelle est à refaire à chaque relecture. Superbement chiant.

Retour à la ligne automatique, ou word wrap

Les éditeurs proposent tous (ne me citez pas nano… il n’est utile que quand tout le reste a merdé) de faire passer à la ligne automatiquement une ligne trop longue, avec des paramètres variables. On peut même choisir de couper en plein milieu d’un mot ou entre les mots.

On peut aussi demander au word wrap de “physiquement” couper la ligne en insérant un saut de ligne au moment où la ligne devient trop grande.

Bon, j’avais tenté ce paramétrage, au final ça devenait bien souvent complètement n’importe quoi. L’autre frein à ce mode est que lorsqu’on est pas encore fixé sur le texte/code que l’on veut écrire, on se retrouve à supprimer manuellement les sauts de ligne… bonet blanc et blanc bonet en fin de compte.

En revanche la forme « soft » du word wrap, à savoir que le retour à la ligne est une simple astuce d’affichage, me semble bien plus pratique :

  • On laisse chacun gérer sa largeur maximale.
  • On reste concentré sur ce qui est important : écrire son texte, écrire son code. La gestion manuelle des sauts de ligne n’a aucune plus-value dans du texte, et pour du code, la plupart du temps les sauts de ligne ont du sens et on s’arrête avant les 80 colonnes.

Oui, mais non

Je pense que si le word wrap ne fait pas l’unanimité, c’est peut-être que les éditeurs ne supportent pas tous le paramétrage parfait ou ont des comportements par défaut indésirables pour certains utilisateurs.

Par exemple dans Vim, pour avoir un word wrap automatique à ~100 colonnes, j’utilise tmux pour avoir un panneau à droite du texte. C’est pas super, mais en pratique j’ai trèèèèès souvent un second panneau à côté de Vim ou tout simplement un autre buffer Vim, et donc c’est devenu transparent.

Ensuite la navigation d’une ligne à une autre varie selon les utilisateurs. Je préfère qu’une “grande ligne” reste d’un seul morceau plutôt que de la fragmenter, mais ce n’est certainement pas l’avis de tout le monde.

Et puis sans doute d’autres raisons que je n’ai pas trouvé.

Keskonfé ?

Si t’es tout seul avec toi-même, on s’en fout. Le problème se pose lors de la collaboration, et je pense qu’on peut trouver des compromis :

  • Pour le texte : les documentations (README et autres), le word wrap me semble nécessaire, à l’image de ce qui se fait dans Word/LibreOffice.
  • Pour le code : on vote une limite que chacun sera tenu de respecter au mieux : si on choisis 80 est qu’on est à 85 colonnes, on va peut-être éviter de rendre le code moche juste pour respecter la règle.

Et si un compromis (celui-ci ou tout autre évidemment) ne peut être trouvé, il faut quand même que chacun utilise la même méthode : il n’y a rien de pire que d’avoir différentes conventions au sein d’un même fichier ou projet.

by Florent Peterschmitt at November 30, 2018 06:00 PM

October 30, 2018

Luc Didry

Lufi 0.03 est sorti !

Après plus d’un an, voici une nouvelle version de Lufi ! Cette nouvelle version aurait du être l’oc­ca­sion d’une refonte de l’in­ter­face en utili­sant VueJs mais j’ai pris énor­mé­ment de retard sur mon appren­tis­sage de celui-ci, donc ça sera pour la version suivante.

Le déve­lop­pe­ment de la nouvelle version n’a pas pris un an, loin de là, mais comme ce n’est pas le seul logi­ciel que je main­tiens (loin de là), bah voilà.

Vous pouvez tester la nouvelle version sur l’ins­tance de démons­tra­tion : https://demo.lufi.io.

Liste non exhau­sive des chan­ge­ments

Pour les utili­sa­teurs :

  • Amélio­ra­tion de la vitesse au niveau client via l’uti­li­sa­tion de mes plugins Mojo­li­cious GzipS­ta­tic et StaticCache, qui compressent les fichiers statiques et leur adjoint un en-tête de cache navi­ga­teur ;
  • Possi­bi­lité de choi­sir la langue de l’in­ter­face (là où le choix se faisait auto­ma­tique­ment via les préfé­rences du navi­ga­teur) ;
  • Affi­chage de la taille du fichier lors de l’en­voi ;
  • Affi­chage de la taille maxi­male accep­tée des fichiers ;
  • Ajout des traduc­tions en arabe et en alle­mand ;
  • Ajout d’une tâche récur­rente pour provi­sion­ner en avance des adresses de fichier. Pour les utili­sa­teurs, ça se traduit par des pages qui sont envoyées bien plus rapi­de­ment.

Pour la modé­ra­tion :

  • Il y a possi­bi­lité pour l’ad­min de modi­fier un champ en base de données pour bloquer le télé­char­ge­ment d’un fichier, tout en affi­chant la raison (contenu illé­gal, viola­tion des CGU, etc. Les raisons sont confi­gu­rables) au télé­char­geur. Cela n’est pas très pratique (bidouiller en base de données), mais c’est un pas en avant ;
  • Possi­bi­lité de signa­ler simple­ment un fichier aux admins d’une instance.

Pour la sécu­rité :

  • Mise à jour de la biblio­thèque javas­cript de chif­fre­ment SJCL ;
  • Gestion d’une éven­tuelle excep­tion si l’en­tro­pie du navi­ga­teur est trop faible pour géné­rer correc­te­ment une clé de chif­fre­ment ;
  • Ajout de jetons CSRF à la connexion et à la décon­nexion (si l’au­then­ti­fi­ca­tion est utili­sée, bien sûr) ;
  • Ajout de contraintes sur l’en­voi de mail pour éviter de se retrou­ver à envoyer des spams.

Pour les déve­lop­peurs :

  • Utili­sa­tion de Mojo::SQLite à la place d’ORLite pour l’uti­li­sa­tion d’une base SQLite. Ce chan­ge­ment de module me permet de réduire énor­mé­ment le code de la couche d’abs­trac­tion de la base de données : Mojo::SQLite a la même syntaxe que Mojo::Pg, du coup, c’est le même code pour les deux bases de données.
  • Créa­tion et utili­sa­tion de plugins Mojo­li­cious person­nels. Ces modules ne sont pas publiés sur le CPAN car très forte­ment liés à ma manière d’uti­li­ser le frame­work Mojo­li­cious. La publi­ca­tion de modules person­nels sur le CPAN est décon­seillée pour ne pas le polluer, mais Carton, le gestion­naire de dépen­dances que j’uti­lise permet de spéci­fier l’URL de télé­char­ge­ment des modules. Je peux donc utili­ser les tarballs four­nis par Frama­git. L’in­té­rêt de l’uti­li­sa­tion de modules person­nels est de mutua­li­ser le code commun à mes diffé­rents logi­ciels, de ne plus me répé­ter et de réper­cu­ter une correc­tion ou une amélio­ra­tion d’un logi­ciel à un autre bien plus faci­le­ment ;
  • Ajout d’un code de conduite ;
  • Ajout d’une suite de tests, lancée auto­ma­tique­ment à chaque push grâce à l’in­té­gra­tion conti­nue de Gitlab.

Pour les admins :

  • Support de MySQL : comme le code de la couche d’abs­trac­tion a été simpli­fié, il suffit d’uti­li­ser un module possé­dant la même syntaxe que ceux des deux autres bases de données pour ajou­ter le support d’une nouvelle base. Grâce à Mojo::mysql, ça s’est fait très faci­le­ment.
  • Ajout d’une commande pour migrer simple­ment d’une base de données SQLite à un autre type de base.
  • Il y a main­te­nant une option dans la confi­gu­ra­tion pour obli­ger tous les fichiers à être suppri­més après le premier télé­char­ge­ment.
  • Il y a main­te­nant un en-tête Content-Secu­rity-Policy par défaut, qui devrait conve­nir à la plupart des instal­la­tions. Cet en-tête est bien évidem­ment surchar­geable dans la confi­gu­ra­tion.

Hack­péro

Il est à noter que cette version a été présen­tée au Hack­péro qui a eu lieu à Paris le 26 octobre dernier (un genre de hacka­thon spécia­lisé recherche de bugs ou de vulné­ra­bi­li­tés). Je tiens à remer­cier gran­de­ment l’équipe de Bounty Factory qui m’a contacté pour me le propo­ser, ainsi que les bug hunters qui y ont parti­cipé.

Artwork Lufi

Je vous ai déjà présenté l’artwork pour Lutim dans mon article précé­dent. J’avais aussi commandé à Soniop un artwork pour Lufi !

Cliquez pour avoir l’image origi­­nelle (en grande taille)

Comme pour Lutim, c’est en CC-BY-SA (fichier source Photo­shop).

Instal­la­tion

La meilleure façon d’ins­tal­ler Lufi est de suivre les instruc­tions du wiki.

Parta­ger

by Luc at October 30, 2018 05:14 PM

October 25, 2018

Luc Didry

Merci à mes tipeurs 🙂

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle de septembre. Petite forme pour la rentrée, mais je vous rassure, octobre sera un bien meilleur cru 😉

Merci à :

Voici mon bilan de septembre :

  • J’ai bossé sur Lstu :
    • au vu du nombre de spam­meurs/phisheurs qui utilisent Frama.link pour cacher des URLs véro­lées, j’ai du me résoudre à ajou­ter le support de Google Safe Brow­sing (GSB). Pas de panique, les véri­fi­ca­tions sont faites sur une copie locale de la base de Google, donc rien ne filtre vers l’ogre. Cela reste une option : Lstu n’uti­lise pas GSB par défaut. La véri­fi­ca­tion a lieu à la créa­tion d’un raccourci d’URl mais peut égale­ment être effec­tuée via une commande CLI (fort utile pour faire des véri­fi­ca­tions a poste­riori et nettoyer la base de donnée de votre instance).
    • j’ai inté­gré une merge request pour permettre d’uti­li­ser Lstu via Docker. Je ne suis pas un grand fan de Docker, mais si ça peut servir…
  • Commits dédiés

Je ne résiste pas à l’en­vie de vous offrir en avance une superbe illus­tra­tion que j’ai comman­dée à Soniop :

Cliquez pour avoir l’image origi­nelle (en grande taille)

(en avance parce que je l’ai comman­dée en octobre)

Bon, ça a pas été fait avec un logi­ciel libre (source photo­shop), mais c’est libre : libéré sous licence CC-BY-SA. Person­nel­le­ment, je l’ai mise en fond d’écran (sur le PC et sur le télé­phone 😁).

Tcit en a commandé une avec le logo de Frama­soft qu’est super aussi : https://www.devian­tart.com/soniop/art/Commis­sion-Framas­pace-768711643.

Préci­sion : j’ai payé l’illus­tra­tion, mais un tarif plus que raison­nable (mais vrai­ment raison­nable hein !). Contac­tez Soniop si vous souhai­tez comman­der une illus­tra­tion dans le style.

Vous pouvez toujours me soute­nir via Duni­ter !

Je remets ici mon expli­ca­tion.

Disclai­mer : je vais peut-être dire des sottises parce que j’ai pas tout compris mais je m’en fous, j’aime bien l’idée

Duni­ter est un projet de crypto-monnaie mais contrai­re­ment au bitcoin où c’est la course à la puis­sance de calcul pour géné­rer la monnaie et deve­nir riche, le but est de créer une monnaie libre (le Ğ1, prononcé comme june en anglais), basée sur une toile de confiance (il faut rece­voir 5 certi­fi­ca­tions pour être membre) et où chacun des membres reçoit tous les jours un divi­dende univer­sel. Je dois dire que je suis assez curieux de ce qu’on peut faire avec un système ressem­blant forte­ment au salaire à vie 😉

C’est pourquoi j’ai créé mon compte et ait fait ce qu’il fallait pour rece­voir mes certi­fi­ca­tions (rencon­trer des gens, tous­sa…). Ma clé publique est :

 2t6NP6Fvvuok2iRWA188C6pGokWAB5Kpf1S1iGtkN9tg

Et comme un projet n’est utile que si on s’en sert, je vous propose de me soute­nir en Ğ1 tout en béné­fi­ciant des mêmes récom­penses que celles présentes sur ma page Tipeee (j’ai arbi­trai­re­ment choisi une parité euro/Ğ1 car je n’ai pas vrai­ment trouvé de page expliquant comment évaluer le cours du Ğ1 en euros, et au final, est-ce vrai­ment néces­saire ? À nous de choi­sir quelle valeur a cette nouvelle monnaie 🙂. Et puis ça me simpli­fie la vie).

Voici donc les diffé­rentes contre­par­ties et leur prix (chaque contre­par­tie comprend celles de tarif infé­rieur) :

  • 1 Ğ1 : vous appa­raî­trez sur la page mensuelle des remer­cie­ments
  • 2 Ğ1 : vous rece­vrez une photo dédi­ca­cée de mon chat
  • 3 Ğ1 : vous rece­vrez 3 stickers repre­nant les logos de Lstu, Lutim et Lufi. De quoi déco­rer son ordi et se la péter en société 😁
  • 5 Ğ1 : un commit vous sera dédié chaque mois (si je déve­loppe suffi­sam­ment pour le nombre de personnes à ce niveau)
  • 15 Ğ1 : vous pouvez me deman­der de bosser en prio­rité sur un bug ou une demande de fonc­tion­na­lité d’un de mes logi­ciels (dans la mesure du faisable, hein).
  • 100 Ğ1 : quand j’au­rais un nouveau projet, vous pour­rez en choi­sir le nom et le logo

Pour en savoir plus sur Duni­ter et Ğ1, je vous propose d’al­ler voir cet article de cgeek : https://blog.cgeek.fr/de-linte­ret-dune-monnaie-libre.html ainsi que la théo­rie rela­tive de la monnaie pour les enfants.

Crédits : Photo par Nick Fewings sur Unsplash

Parta­ger

by Luc at October 25, 2018 06:21 PM

October 11, 2018

Florent Peterschmitt

Vim Setup

Micro article pour parler de ma configuration Vim, des fois que ça puisse servir à d’autres.

En réalité j’utilise neovim couplé à vim-plug pour la gestion des plugins.

Voici ce dont j’ai besoin :

  • De la complétion pour Python, Go, et parfois Rust
  • Pouvoir lancer un linter sur les fichiers en cours d’édition
  • Afficher les erreurs de compilation, de syntaxe etc…
  • Exécuter des tests depuis l’éditeur
  • Colorisation syntaxique
  • Recherche et ouverture facile de fichiers à la SublimeText

Tout ça je l’ai avec cette conf.

La doc d’installation est en haut du fichier.

Les principaux modules que j’utilise sont :

  • YouCompleteMe pour la complétion
  • ALE pour la syntaxe et certaines commandes pour corriger des imports en python, nettoyer les fins de ligne etc…
  • FZF et le plugin vim pour chercher des fichiers, dans les fichiers etc…
  • GutenTags, couplé à FZF pour chercher les fonctions, classes ou toute définition supportée par universal ctags
  • vim-go pour Go
  • Vimagit pour maniper Git directement dans un buffer dédié
  • GitGutter pour voir les lignes modifiées/ajoutées etc…

Les autres plugins sont principalement des aides, que j’utilise assez peu en fin de compte.

Alors c’est pas parfait, j’aimerais bien avoir des raccourcis pour lancer les tests en ayant le curseur dans le bloc de code de test par exemple, ce genre de trucs. Je me débrouille autrement, notemment avec watchngo, de fabrication maison ^^

Have fun !

by Florent Peterschmitt at October 11, 2018 05:00 PM

September 15, 2018

Luc Didry

Merci à mes tipeurs :-)

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle d’août.

Merci à :

Voici mon bilan d’août :

Vous pouvez toujours me soute­nir via Duni­ter !

Je remets ici mon expli­ca­tion.

Disclai­mer : je vais peut-être dire des sottises parce que j’ai pas tout compris mais je m’en fous, j’aime bien l’idée

Duni­ter est un projet de crypto-monnaie mais contrai­re­ment au bitcoin où c’est la course à la puis­sance de calcul pour géné­rer la monnaie et deve­nir riche, le but est de créer une monnaie libre (le Ğ1, prononcé comme june en anglais), basée sur une toile de confiance (il faut rece­voir 5 certi­fi­ca­tions pour être membre) et où chacun des membres reçoit tous les jours un divi­dende univer­sel. Je dois dire que je suis assez curieux de ce qu’on peut faire avec un système ressem­blant forte­ment au salaire à vie 🙂

C’est pourquoi j’ai créé mon compte et ait fait ce qu’il fallait pour rece­voir mes certi­fi­ca­tions (rencon­trer des gens, tous­sa…). Ma clé publique est :

 2t6NP6Fvvuok2iRWA188C6pGokWAB5Kpf1S1iGtkN9tg

Et comme un projet n’est utile que si on s’en sert, je vous propose de me soute­nir en Ğ1 tout en béné­fi­ciant des mêmes récom­penses que celles présentes sur ma page Tipeee (j’ai arbi­trai­re­ment choisi une parité euro/Ğ1 car je n’ai pas vrai­ment trouvé de page expliquant comment évaluer le cours du Ğ1 en euros, et au final, est-ce vrai­ment néces­saire ? À nous de choi­sir quelle valeur a cette nouvelle monnaie 🙂. Et puis ça me simpli­fie la vie).

Voici donc les diffé­rentes contre­par­ties et leur prix (chaque contre­par­tie comprend celles de tarif infé­rieur) :

  • 1 Ğ1 : vous appa­raî­trez sur la page mensuelle des remer­cie­ments
  • 2 Ğ1 : vous rece­vrez une photo dédi­ca­cée de mon chat
  • 3 Ğ1 : vous rece­vrez 3 stickers repre­nant les logos de Lstu, Lutim et Lufi. De quoi déco­rer son ordi et se la péter en société 😁
  • 5 Ğ1 : un commit vous sera dédié chaque mois (si je déve­loppe suffi­sam­ment pour le nombre de personnes à ce niveau)
  • 15 Ğ1 : vous pouvez me deman­der de bosser en prio­rité sur un bug ou une demande de fonc­tion­na­lité d’un de mes logi­ciels (dans la mesure du faisable, hein).
  • 100 Ğ1 : quand j’au­rais un nouveau projet, vous pour­rez en choi­sir le nom et le logo

Pour en savoir plus sur Duni­ter et Ğ1, je vous propose d’al­ler voir cet article de cgeek : https://blog.cgeek.fr/de-linte­ret-dune-monnaie-libre.html ainsi que la théo­rie rela­tive de la monnaie pour les enfants.

Crédits : Photo par Tim Marshal sur Unsplash

Parta­ger

by Luc at September 15, 2018 12:38 PM

August 22, 2018

Luc Didry

Hey ! C’est le Ray’s day !

Pour le Ray’s day, je lance un concours avec tirage au sort pour gagner un recueil de mes mercre­dis fiction, relié à la japo­naise avec mes petites mains.

Lais­sez-moi votre nom/pseudo/whate­ver ainsi qu’une adresse mail et je vous contac­te­rai si vous avez gagné 🙂

Le nom/pseudo/whate­ver du gagnant sera annoncé sur mon compte masto­don ainsi qu’ici, sur mon blog.

Le formu­laire est sur https://frama­forms.org/concours-pour-le-rays-day-1534924436 ou direc­te­ment embarqué ci-dessous.

Parta­ger

by Luc at August 22, 2018 08:26 AM

August 11, 2018

Luc Didry

Double merci à mes tipeurs :-)

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle de juin… et de juillet. Du retard, toujours du retard et encore plus de retard !

Merci à :

Aparté : j’ar­rête de propo­ser de me soute­nir en bitcoins car le bitcoin est une catas­trophe écolo­gique et je ne souhaite pas caution­ner ça. J’ai donc vidé mon porte­feuille bitcoin. J’ai mis du temps à le faire pour deux raisons : d’abord, je ne pense pas souvent à mon porte­feuille bitcoin, ensui­te… l’ap­pât du gain. Faut pas se mentir, quand on voit comme le bitcoin peut grim­per, ça fait rêver de voir combien on peut gagner. Du coup, je me trans­for­mais en un spécu­la­teur de la pire espèce. Quand je m’en suis rendu compte, j’ai décidé d’ar­rê­ter. À noter que la Ğ1, si c’est une crypto-monnaie repo­sant sur une block­chain comme le bitcoin, ne présente pas les mêmes défauts : de par le divi­dende univer­sel qui est distri­bué à tous et qui augmente avec la toile de confiance, la thésau­ri­sa­tion ne sert pas à grand-chose, et la preuve de travail de la Ğ1 est beau­coup moins consom­ma­trice de ressources que le bitcoin.

Voici mon bilan de juin :

Et mon bilan de juillet :

Vous pouvez toujours me soute­nir via Duni­ter !

Je remets ici mon expli­ca­tion.

Disclai­mer : je vais peut-être dire des sottises parce que j’ai pas tout compris mais je m’en fous, j’aime bien l’idée

Duni­ter est un projet de crypto-monnaie mais contrai­re­ment au bitcoin où c’est la course à la puis­sance de calcul pour géné­rer la monnaie et deve­nir riche, le but est de créer une monnaie libre (le Ğ1, prononcé comme june en anglais), basée sur une toile de confiance (il faut rece­voir 5 certi­fi­ca­tions pour être membre) et où chacun des membres reçoit tous les jours un divi­dende univer­sel. Je dois dire que je suis assez curieux de ce qu’on peut faire avec un système ressem­blant forte­ment au salaire à vie 🙂

C’est pourquoi j’ai créé mon compte et ait fait ce qu’il fallait pour rece­voir mes certi­fi­ca­tions (rencon­trer des gens, tous­sa…). Ma clé publique est :

 2t6NP6Fvvuok2iRWA188C6pGokWAB5Kpf1S1iGtkN9tg

Et comme un projet n’est utile que si on s’en sert, je vous propose de me soute­nir en Ğ1 tout en béné­fi­ciant des mêmes récom­penses que celles présentes sur ma page Tipeee (j’ai arbi­trai­re­ment choisi une parité euro/Ğ1 car je n’ai pas vrai­ment trouvé de page expliquant comment évaluer le cours du Ğ1 en euros, et au final, est-ce vrai­ment néces­saire ? À nous de choi­sir quelle valeur a cette nouvelle monnaie 🙂. Et puis ça me simpli­fie la vie).

Voici donc les diffé­rentes contre­par­ties et leur prix (chaque contre­par­tie comprend celles de tarif infé­rieur) :

  • 1 Ğ1 : vous appa­raî­trez sur la page mensuelle des remer­cie­ments
  • 2 Ğ1 : vous rece­vrez une photo dédi­ca­cée de mon chat
  • 3 Ğ1 : vous rece­vrez 3 stickers repre­nant les logos de Lstu, Lutim et Lufi. De quoi déco­rer son ordi et se la péter en société 😁
  • 5 Ğ1 : un commit vous sera dédié chaque mois (si je déve­loppe suffi­sam­ment pour le nombre de personnes à ce niveau)
  • 15 Ğ1 : vous pouvez me deman­der de bosser en prio­rité sur un bug ou une demande de fonc­tion­na­lité d’un de mes logi­ciels (dans la mesure du faisable, hein).
  • 100 Ğ1 : quand j’au­rais un nouveau projet, vous pour­rez en choi­sir le nom et le logo

Pour en savoir plus sur Duni­ter et Ğ1, je vous propose d’al­ler voir cet article de cgeek : https://blog.cgeek.fr/de-linte­ret-dune-monnaie-libre.html ainsi que la théo­rie rela­tive de la monnaie pour les enfants.

Crédits : Photo par Connor Wells sur Unsplash

Parta­ger

by Luc at August 11, 2018 09:20 AM

July 25, 2018

Luc Didry

Retrou­vez mes confé­rences en vidéos sur PeerTube !

Juste un p’tit mot rapide pour dire que j’ai mis les vidéos des confé­rences que j’ai pu donner à droite à gauche sur PeerTube (celles que j’ai retrou­vées sur le net tout du moins).

Ça se passe sur https://aperi.tube/accounts/luc/videos, et pour vous abon­ner à mon compte via Masto­don ou autre service fédéré qui sait le faire, mon compte est @luc@a­peri.tube.

NB : https://aperi.tube n’est pas à moi (même si j’en gère le système), donc pas la peine de me deman­der un compte dessus, désolé :/

Crédits : Photo par Tim Marshal sur Unsplash

Parta­ger

by Luc at July 25, 2018 07:58 PM

July 01, 2018

Romain Dessort

Rando-voyage dans l'ouest du Canada

Je pars aujourd'hui pour un voyage de 4 mois à la découverte de l'ouest canadien, en Colombie-Britanique principalement, un peu d'Alberta et peut-être aussi au Yukon si j'ai le temps et qu'une opportunité se présente.

Je vais essayer de publier mes photos et un récit au fur et à mesure de mon périple, mais je ne promets rien, je n'aurai pas souvent accès à Internet et encore moins à un ordinateur. Ça se passera ici (flux Atom).

July 01, 2018 12:57 PM

June 30, 2018

Luc Didry

Merci à mes tipeurs :-)

Le 14 juillet 2016, j’ai lancé mes pages Tipeee et Libe­ra­pay.

La récom­pense de base est l’ap­pa­ri­tion sur une page mensuelle de remer­cie­ments… voici celle de mai (juste à temps pour pas faire une double page de remer­cie­ments demain) !

Merci à :

Voici mon bilan de mai :

Vous pouvez toujours me soute­nir via Duni­ter !

Je remets ici mon expli­ca­tion.

Disclai­mer : je vais peut-être dire des sottises parce que j’ai pas tout compris mais je m’en fous, j’aime bien l’idée

Duni­ter est un projet de crypto-monnaie mais contrai­re­ment au bitcoin où c’est la course à la puis­sance de calcul pour géné­rer la monnaie et deve­nir riche, le but est de créer une monnaie libre (le Ğ1, prononcé comme june en anglais), basée sur une toile de confiance (il faut rece­voir 5 certi­fi­ca­tions pour être membre) et où chacun des membres reçoit tous les jours un divi­dende univer­sel. Je dois dire que je suis assez curieux de ce qu’on peut faire avec un système ressem­blant forte­ment au salaire à vie 🙂

C’est pourquoi j’ai créé mon compte et ait fait ce qu’il fallait pour rece­voir mes certi­fi­ca­tions (rencon­trer des gens, tous­sa…). Ma clé publique est :

 2t6NP6Fvvuok2iRWA188C6pGokWAB5Kpf1S1iGtkN9tg

Et comme un projet n’est utile que si on s’en sert, je vous propose de me soute­nir en Ğ1 tout en béné­fi­ciant des mêmes récom­penses que celles présentes sur ma page Tipeee (j’ai arbi­trai­re­ment choisi une parité euro/Ğ1 car je n’ai pas vrai­ment trouvé de page expliquant comment évaluer le cours du Ğ1 en euros, et au final, est-ce vrai­ment néces­saire ? À nous de choi­sir quelle valeur a cette nouvelle monnaie 🙂. Et puis ça me simpli­fie la vie).

Voici donc les diffé­rentes contre­par­ties et leur prix (chaque contre­par­tie comprend celles de tarif infé­rieur) :

  • 1 Ğ1 : vous appa­raî­trez sur la page mensuelle des remer­cie­ments
  • 2 Ğ1 : vous rece­vrez une photo dédi­ca­cée de mon chat
  • 3 Ğ1 : vous rece­vrez 3 stickers repre­nant les logos de Lstu, Lutim et Lufi. De quoi déco­rer son ordi et se la péter en société 😁
  • 5 Ğ1 : un commit vous sera dédié chaque mois (si je déve­loppe suffi­sam­ment pour le nombre de personnes à ce niveau)
  • 15 Ğ1 : vous pouvez me deman­der de bosser en prio­rité sur un bug ou une demande de fonc­tion­na­lité d’un de mes logi­ciels (dans la mesure du faisable, hein).
  • 100 Ğ1 : quand j’au­rais un nouveau projet, vous pour­rez en choi­sir le nom et le logo

Pour en savoir plus sur Duni­ter et Ğ1, je vous propose d’al­ler voir cet article de cgeek : https://blog.cgeek.fr/de-linte­ret-dune-monnaie-libre.html ainsi que la théo­rie rela­tive de la monnaie pour les enfants.

PS : j’ai aussi une adresse bitcoin si vous souhai­tez me soute­nir par ce biais

Crédits : Photo par Tim Marshal sur Unsplash

Parta­ger

by Luc at June 30, 2018 09:37 PM

June 24, 2018

Florent Peterschmitt

Namasté Népal - #3.2

Plus d’un an après le dernier article sur le sujet… alala ^^'

Et comme d’habitude, un peut de shell pour corriger les images :

for i in $(find . -namae *.jpeg); do
    convert $i -auto-orient /tmp/out.jpeg
    mv /tmp/out.jpeg $i
done

Article précédent

Vadrouille - 17 Avril… 2017, hein :D

L’objectif était de visiter le musée Gurkha la grotte « Mahendra », où je me suis rendu compte après coup avoir été correctement plumé… ah bah on est touriste ou on ne l’est pas ^_^ !

Voici donc les photos prises pendant le trajet.

photo

photo

photo

Bindabasini Temple

Endroit un peu en hauteur, vent frais. Je n’ai pas pris beaucoup de photos car j’ai une vidéo du lieu, trop lourde pour être postée ici malheureusement. J’aurais dû y penser, c’est trop tard maintenant !

photo

photo

photo

Musée Gurkha

Étant très mauvais historien, je préfère encore vous rediriger vers la page wikipedia sur les Gurkhas plutôt que de tout recopier :)

Pour faire simple, les Gurkhas sont des unités armées britanniques, entraînées sur place.

photo

photo

photo

Visite officielle et rumeurs…

photo

photo

Mousquets Martini Henry et India Pattern

photo

photo

Moderne et toujours présent

photo

photo

photo

En allant vers la grotte

photo

À l’intérieur de la grotte, à l’entrée, on trouve une roche ayant l’apparence d’une trompe d’éléphant, rapport à Ganesh, le dieu à tête d’éléphant. Peu de touristes sont présents ici, les personnes se bouscules pour faire une brève prière et s’attirer la bonne fortune.

Ce qui n’empêche pas l’endroit d’être jonché de bouteilles en plastique.

photo

Le guide m’emmène vers le reste de la grotte, où seuls les touristes vont. Il avoue lui-même que les touristes Indiens ne sont pas respectueux des lieus et qu’il ne souhaite pas que cette partie soit publiquement accessible.

Bon par contre, vous remarquerez que j’ai honteusement dérangé ces charmantes chauves-souris…

photo

photo

photo

photo

photo

À la sortie de la grotte, c’est là que le plumage a eu lieu. En grand champion, j’ai confondu, à l’orale, “1000” et “100” en anglais : le guide a annoncé 8000 roupies, j’ai compris 800. Résultat j’y ai laissé 80€ au lieu de 8 pour la visite… évidemment le guide n’allait pas refuser, et il a eu bien raison d’essayer !

En somme, une journée bien physique, crapahuter dans la grotte c’était quand même assez chouette, et puis surtout il y faisait bien frais :D

Article suivant

by Florent Peterschmitt at June 24, 2018 04:00 PM