guide : écrire un greffon pour SàT

goffi 06/07/2016, 19:12 dév tutoriel jabber-xmpp projet GNU-Linux planet-libre SàT Libre

Cela fait plusieurs fois qu’on me demande comment contribuer à SàT, le projet étant conséquent il n’est pas facile d’accès. Aussi voici un article d’introduction pour l’écriture d’un greffon pour le backend.

Il est très utile d’avoir lu l'article d’introduction sur l’architecture de SàT avant. L’intérêt de faire un greffon backend est qu’il fonctionnera avec tous les frontaux, autrement dit sur le web, sur le bureau, sur appareils portables (bientôt) voire en ligne de commande ou autre.

Nous allons faire un classique « Salut à Toi le monde ! » bien connu des développeurs.

avant de commencer, quelques remarques en vrac

Quelques remarques et notions utiles à savoir, ne vous inquiétez pas si vous ne comprenez pas tout du premier coup :

  • SàT est actuellement en Python 2, le passage à Python 3 ayant été bloqué principalement par Twisted jusqu’ici. Mais les choses ont beaucoup avancé récemment, et Twisted fonctionne désormais partiellement avec Python 3, la partie XMPP est aussi en cours de portage, et le passage à Python 3 pourra être envisagé pour SàT 0.8 (après la version « grand public » donc).

  • le style de code suit à peu près les conventions de la PEP 8, mais pas entièrement. En particulier les noms de méthodes utilisent le CamelCase pour rester cohérent avec le code de Twisted, et la limite des 80 caractères n’est pas respectée (il n’est pas impossible que cela change dans le futur), vous aurez plus de détails sur le wiki (notez bien la partie sur les docstrings).

  • le backend de SàT est entièrement asynchrone, en utilisant Twisted. C’est probablement le plus difficile à appréhender pour un débutant, et vous pouvez commencer en regardant comment font les autres parties du code pour comprendre les grandes lignes. La chose la plus importante à retenir est qu’il ne faut jamais faire de code « bloquant », c’est-à-dire long à s’exécuter, car ça bloquera tout le backend. S’il est indispensable de bloquer pour une raison ou une autre (un module tiers à utiliser par exemple), vous devrez utiliser des processus séparés. La documentation sur le site mentionné est relativement fournie quand vous vous sentirez d’approfondir le domaine…

  • la hierarchie du code (src) est actuellement comme suit:

    • bridge gère la communication avec les frontaux, c’est l'IPC (actuellement D-Bus mais d’autres options sont possibles)
    • core contient comme son nom l’indique le cœur du backend (le « Service » SàT, le client XMPP, les constantes, les exceptions spécifiques à SàT, la gestion des logs et de la traduction)
    • memory gère tout ce qui est conservation des données que ce soit en mémoire vive ou sur disque (via Sqlite pour le moment, mais d’autres options sont possibles)
    • plugins contient… les greffons, c’est à eux que l’on va s’intéresser par la suite
    • stdui contient les interfaces XMLUI de base (nous reparlerons de XMLUI plus bas)
    • test est le répertoire où sont comme vous vous en doutez les tests unitaires ou autre.
    • tmp est une hiérarchie que nous avons dû créer pour mettre du code temporaire destiné à être intégré par des projets tiers que nous utilisons, en particulier Wokkel à l’heure actuelle
    • tools est la hiérarchie un peu « fourre-tout » pour les choses utiles, en particulier XMLUI et les triggers dont nous reparlerons plus tard. La sous-hiérarchie « common » contient les modules utilisés/ables à la fois par le backend et les frontaux.
    • twisted enfin est uniquement utilisé pour l’intégration à Twisted
    • on parle souvent de profil ( profile en anglais et dans le code) qui correspond à un compte XMPP. En mode mono-utilisateur (Primitivus ou Cagou par exemple), cela peut correspondre à plusieurs comptes d’un même utilisateur (par exemple j’ai un profil jabberfr et un autre libervia.org pour mes 2 comptes correspondant). En mode multi-utilisateur (avec Libervia par exemple), cela correspond à des comptes d’utilisateurs différents.
    • à la notion de « profile » s’ajoute celle de « profile_key ». C’est en fait en mot clef qui indique un profil à utiliser (vous les trouverez dans les constantes avec PROF_KEY_XXX). En particulier PROF_KEY_DEFAULT indique d’utiliser le profil par défaut, et PROF_KEY_NONE indique une valeur non renseignée qui provoquera une exception si elle est utilisée avec getClient (voir plus bas).
    • dans les classes, on utilise souvent un attribut « host » (self.host la plupart du temps), qui correspond à l’instance du service SàT, et qui permet d'accéder à beaucoup de choses (le « bridge », la partie « memory », etc).
    • dans les méthodes, vous verrez souvent les paramètres « client » ou « profile ». « profile » correspond au nom du profil dont on a parlé plus haut, et client à l’instance du client XMPP et donc à la session associée à ce profil. On passe du profil au client en faisant « host.getClient(profile) » et du client au profil en faisant « client.profile ». Avant « profile » était systématiquement utilisé et placé en dernier paramètre (avec une valeur par défaut de C.PROF_KEY_NONE qui indique une valeur non renseignée). Désormais il a été décidé de toujours utiliser client comme premier argument, et profile uniquement quand c’est nécessaire (à l’entrée ou la sortie du « bridge » par exemple), aussi le code passe petit à petit à la nouvelle convention, et vous pouvez voir les 2 cas.
    • en début de fichier, il est souvent utile de faire ces imports :
        python from sat.core.constants import Const as C
        from sat.core.i18n import _, D
        from sat.core.log import getLogger log = getLogger( **name** )
        from sat.core import exceptions

La première ligne permet d’accéder aux constantes, avec C pour que ça reste court et lisible. La seconde importe la fonction gettext « _ » qui traduit le texte dans la langue locale au moment de son utilisation, et « D_  » qui indique qu’un texte est à traduire, mais que la traduction aura lieu plus tard dynamiquement (utile pour un menu par exemple, qu’on peut traduire différemment selon les profils). Les 2 suivantes instancient un loggeur qu’on peut utiliser assez classiquement avec log.[niveau](message), par exemple log.debug(u"mon message de debug") Enfin la dernière ligne permet d’utiliser les exceptions spécifiques à SàT, vous pouvez lire le code du module idoine pour plus d’infos.

Avec tout ça on a l’essentiel pour s’attaquer au code.

création du fichier et déclaration du plugin

La première chose à faire est de créer un fichier python dans le répertoire plugins et dont le nom commence par "plugin_". De tels fichiers sont automatiquement importés par le backend au démarrage, et à terme il devrait être possible de les mettre ailleurs (par exemple dans un dossier personnel) et de les télécharger et installer automatiquement. Vous constaterez que les greffons existant sont nommés avec leur type puis leur nom, et que ceux qui implémentent des XEPs prennent le nom de la XEP (par exemple plugin_xep_0045.py ).

Nous allons maintenant déclarer le greffon, pour celà nous utilisons une variable (un dictionnaire) nommée PLUGIN_INFO et placée en début de fichier. Voici un exemple d’en-tête avec celui du greffon XEP-0045 (le salon de groupe MUC) :

    PLUGIN_INFO = {
    "name": "XEP-0045 Plugin",
    "import_name": "XEP-0045",
    "type": "XEP",
    "protocols": ["XEP-0045"],
    "dependencies": [],
    "recommendations": [C.TEXT_CMDS],
    "main": "XEP_0045",
    "handler": "yes",
    "description": _(u"""Implementation of Multi-User Chat""")
}

  

voici les informations données:

  • name  : nom « lisible par un humain » donné au greffon
  • import_name  : nom court utilisé pour référencer ce greffon par ailleurs (depuis d’autres greffons par exemple) pour accéder à ce greffon par la suite, vous pourrez utiliser host.plugins[ nom d'import ], ainsi ici vous pourrez faire host.plugins["XEP-0045"]
  • type  : une information sur ce que qui est implémenté ; est-ce une XEP (type "XEP"), ou expérimentation (type "EXP") ? L’information n’est pas encore utilisée, mais elle devrait permettre de filtrer les greffons à l’avenir, quand ils seront téléchargeables depuis un dépôt. Les types courants ont leur constante de la forme PLUG_TYPE_*
  • protocols  : une liste de protocoles implémenté le cas échéant. Les XEP sont toujours référencées sous la forme XEP-0xxx avec « XEP » en majuscules.
  • dependencies  : autres greffons indispensables pour faire fonctionner celui-ci. C'est une liste de noms correspondant au « import_name » voulus. Ces greffons seront importés avant celui en cours, et s’ils ne sont pas disponibles l'import échouera
  • recommendations  : greffons non indispensable pour faire fonctionner celui en cours, mais qui apportent des améliorations si présents. Fonctionne de la même manière que dependencies sauf que l'import n’échouera pas si ces greffons ne sont pas disponibles
  • main  : classe principale du greffon, c’est cette classe qui sera instanciée à l'import et qu’on référencera en faisant host.plugins[XXX]
  • handler  : s’il vaut "yes", indique que le greffon va réagir à des requêtes XML particulières, toute autre valeur indique le contraire. Nous reparlerons des handlers plus tard
  • description : texte décrivant ce que fait le greffon. Vous remarquerez la présence du _() qui est utilisé pour la traduction (gettext)

Pour notre greffon que nous allons mettre dans un fichier plugin_misc_salut_le_monde.py placé dans src/plugins, nous allons utiliser le code suivant :

    #!/usr/bin/env python2
# -*- coding: utf-8 -*-

from sat.core.constants import Const as C
from sat.core.i18n import _
from sat.core.log import getLogger
log = getLogger(__name__)

PLUGIN_INFO = {
    "name": u"Salut le monde",
    "import_name": "SALUT_MONDE",
    "type": C.PLUG_TYPE_MISC,
    "main": "Salut",
    "handler": "no",
    "description": _(u"""Plugin to learn basic concepts of SàT""")
}


class Salut(object):

    def __init__(self, host):
        log.info(_(u"Salut à Toi le monde !"))

  

C'est à peu près le greffon le plus simple que vous puissiez faire. En lançant SàT, vous devriez voir quelque chose similaire à ceci dans les logs :

    2016-07-05 19:15:31+0200 [-] [sat.core.sat_main] importing plugin: Salut le monde
2016-07-05 19:15:31+0200 [-] [sat.plugins.plugin_misc_salut_le_monde] Salut à Toi le monde !

  

XMLUI

Bon tout ça c’est bien gentil, mais il serait quand même sympa d’avoir notre message sur les frontaux.

Comme vous le savez, SàT est multi-frontaux, autrement dit un message peut être affiché sur Libervia (interface web), sur Primitivus (interface console), (bientôt) sur Cagou (interface bureau/appareils portatifs) ou encore dans Emacs avec l’interface « Sententia ». Tous ces frontaux affichent les informations différemment : qui avec du texte directement, qui en HTML, qui via un cadriciel graphique, etc. Il serait ennuyant de devoir refaire l’affichage de l’interface pour chaque frontal, aussi nous avons créé un mini langage XML qui permet de décrire une interface de manière générique : XMLUI. C’est un langage descriptif simple et qui reste volontairement de haut niveau pour que le frontal affiche l’information comme il l’entend. On décrit des choses comme des textes, des JID, ou des listes.

XMLUI contient 2 classes « mères » principales : un widget (texte ou mot de passe par exemple), et un « container » (conteneur) qui dispose les widgets d’une certaine façon (verticalement, 2 par 2, en liste, etc). Vous pouvez lire le code gérant cela dans tools.xml_tools.

La création d’une interface se veut assez simple, et xml_tools contient des méthodes pour aider. Par exemple, l’interface suivante utilisée dans l'UI standard pour le gestionnaire de profils (dans stdui.ui_profile_manager) permet de demander un mot de passe si nécessaire :

    form_ui = xml_tools.XMLUI("form", title=D_('Profile password for {}').format(profile), submit_id='')
form_ui.addPassword('profile_password', value='')
d = xml_tools.deferredUI(self.host, form_ui, chained=True)
d.addCallback(self._authenticateProfile, profile)
return {'xmlui': form_ui.toXml()}

  

Rien de bien compliqué. Quelques remarques sur ce code :

  • on utilise D_ pour le titre, car il peut être traduit différemment d’un profil à l’autre
  • une UI XML peut être soumise (c.-à-d. un résultat est envoyé par le frontal au backend, le mot de passe par exemple), et la méthode appelée dans le backend retourne un dictionnaire. Si celui-ci est vide, le dialogue est fini, s’il retourne une nouvelle interface avec la clef « xmlui », celle-ci sera affichée.
  • pour soumettre une interface on peut soit enregistrer une callback via host.registerCallback (l’identifiant retourné sera utilisé avec submit_id au moment de la création de l'UI), soit utiliser une XMLUI « déferrée » comme ici, ce qui permet d’utiliser le mécanisme de Deferred de Twisted, submit_id doit dans ce cas être une chaîne vide.

Pour notre greffon de test, nous n’avons pas besoin de quelque chose nécessitant une réponse, nous pouvons utiliser la méthode xml_tools.note qui facilite les choses.

Pour utiliser une XMLUI, il y a plusieurs méthodes : création d’une callback via un menu par exemple, ou envoi d’un signal aux frontaux pour leur indiquer qu’il faut afficher l’interface, c’est ce que nous allons faire ici avec la méthode host.actionNew  :

    host.actionNew({"xmlui": xml_tools.note(u"Salut à Toi le monde !").toXml()}, profile=profile)

  

Remarquez le toXml() nécessaire pour convertir l'UI XML en texte utilisable à travers le bridge.

Nous avons presque notre greffon qui affiche un message, mais il y a encore un problème à régler : le greffon est importé au chargement du backend, un moment où les frontaux ne sont pas encore actifs, aussi nous ne pouvons pas afficher le message dans l'__init__, il serait envoyé dans le vide.

La solution est simple : nous allons afficher le message quand le profil est connecté. Dans ce cas, la méthode profileConnected, si elle existe, est appelé pour chaque greffon, avec pour seul argument le nom de profil.

Notre code devient donc :

    #!/usr/bin/env python2
# -*- coding: utf-8 -*-

from sat.core.constants import Const as C
from sat.core.i18n import _
from sat.core.log import getLogger
log = getLogger(__name__)
from sat.tools import xml_tools

PLUGIN_INFO = {
    "name": u"Salut le monde",
    "import_name": "SALUT_MONDE",
    "type": C.PLUG_TYPE_MISC,
    "main": "Salut",
    "handler": "no",
    "description": _(u"""Plugin to learn basic concepts of SàT""")
}


class Salut(object):

    def __init__(self, host):
        self.host = host
        log.info(_(u"Salut à Toi le monde !"))

    def profileConnected(self, profile):
        msg = u"Salut à vous {} et le monde !".format(profile)
        self.host.actionNew({"xmlui": xml_tools.note(msg).toXml()}, profile=profile)

  

En lançant Primitivus, voici ce que l’on voit :

résultat avec Primitivus

…et avec Libervia :

résultat avec Libervia

Vous aurez un message équivalent sur les autres frontaux.

À savoir également

Nous n’irons pas plus loin pour ce premier guide afin de ne pas être trop indigeste, mais il peut être utile d’expliquer succinctement d’autre éléments :

  • il y a des paramètres que vous pouvez utiliser pour configurer votre greffon. Ils sont déclarés en XML, et il existe 2 types : « general » pour un paramètre global du backend (par exemple le port d’un serveur), et « individual » pour les paramètres qui changent avec les profils, ce qui est le cas le plus courant (par exemple le JID est un paramètre individuel).

  • il y a un mécanisme de menus qui permettent d’associer une action (souvent un XMLUI) à un menu. Il y a plusieurs types de menus (regardez les constantes C.MENU_*) : C.MENU_GLOBAL sera le menu principal, tandis que C.MENU_JID_CONTEXT sera utilisé en cliquant sur un jid (un contact par exemple).

  • si votre greffon gère une tâche longue quelconque (par exemple un transfert de fichier), il y a un mécanisme pour gérer les progressions, regardez les méthodes progress* pour avoir une idée de leur fonctionnement

  • autre notion importante : la limite de sécurité. Il s’agit d’un simple entier qui indique si une méthode peut être utilisée en environnement restreint ou pas. Pour un frontal utilisé par un simple utilisateur ça n’est a priori pas utilisé, mais un frontal multi-utilisateur comme Libervia, ça permet de limiter ce qui peut être changé (le port d’un serveur ne doit pas être changé tandis que la syntaxe favorite peut l’être par exemple). Vous trouverez des explications sur le wiki.

  • si votre greffon réagit au XML qui passe (ce qui est probablement — mais pas forcément — le cas si vous implémentez une XEP), il agit en « handler » et doit déclarer « "handler": "yes" » dans PLUGIN_INFO. Au moment de l'import, la méthode getHandler sera appelée et elle doit retourner l'instance à utiliser. Pour gérer « disco », votre classe doit implémenter wokkel.disco.IDisco et les méthodes getDiscoInfo et getDiscoItems, référez-vous au code des différents greffons pour bien comprendre.

  • enfin les triggers permettent de modifier le comportement de SàT (du cœur ou d’un plugin), ce sont des méthodes qui sont appelées à certains endroits (d’autres projets parlent parfois de « hook »). Ils peuvent être utilisés par exemple pour modifier un message (le greffon OTR les utilise pour chiffrer le contenu). Il ne faut les utiliser que si nécessaire, car ils compliquent un peu la lecture du code.

Et bien entendu, vous pouvez toujours venir chercher de l’aide sur le salon MUC de SàT : sat@chat.jabberfr.org.

À vos claviers ! Et n’oubliez pas de nous faire signe si vous vous lancez dans quelque chose :)

P.-S. : les morceaux de codes ne sont pas mis en couleurs à l’heure actuelle, j’envisage de faire un greffon pour intégrer pygments, mais pour le moment la priorité est le développement de Cagou.

Émission radio sur la vie privée et Salut à Toi

goffi 25/06/2017, 19:08 SàT radio interview jabber-xmpp seenthis planet-libre Libre

Radio Prague vient de mettre en ligne une émission d'environ 10 min sur la vie privée où j'ai été interviewé pour parler de Salut à Toi.

Je suis vraiment content de l'émission qui est claire, bien expliquée, et pas trop technique . la journaliste a très bien compris le projet (ce qui n'est pas évident, il faut bien le reconnaître), et a fait du beau travail.

Vous pouvez l'écouter et la lire ici : http://www.radio.cz/fr/rubrique/panorama/la-disparition-de-la-vie-privee-nest-pas-inevitable

À écouter et faire circuler si le thème et/ou le projet vous intéressent. Comme indiqué dans lémission nous avons beaucoup de mal à nous faire connaître, aussi ce genre de chose nous aide bien.

Il y a beaucoup de choses qui ont avancé pour la version 0.7 à venir qui sera la première version dite « grand public » (comprendre, installable sans trop de difficultés et utilisable au jour le jour). J'espère trouver le temps de faire des articles pour expliquer les nouveautés comme un cadriciel (framework) web asynchrone/basé sur XMPP, la gestion des évenements ou encore des tickets (donc en décentralisé et basé sur XMPP). Si tout va bien une bêta est à attendre pendant l'été ou à la rentrée, ça sera l'occasion de s'organiser pour faciliter les contributions et mises en production.

À bientôt…

E

edhelas 27/08/2017, 22:02

J

jnanar 28/08/2017, 06:03

Salut à Toi 0.6.1

goffi 12/07/2016, 23:36 seenthis jabber-xmpp projet GNU-Linux planet-libre SàT Libre

Salut à tous,

la version 0.6.1 de Salut à Toi vient de sortir, et elle est conséquente malgré son numéro de version mineur. La prochaine version — qui est déjà bien entamée — sera la version « grand public » que nous annonçons depuis des années, autrement dit une version que nous voulons suffisamment stable pour être utilisée au quotidien, et suffisamment facile à installer pour être disponible pour un large public.

Vous pouvez toujours vous référer au journal des modifications (changelog) ou au dépôt pour avoir le détail, mais voici quelques unes des nouveautés et corrections principales :

  • plugin d'import extensible avec « importeurs » pour Dotclear et DokuWiki. Notez bien que grâce à l’utilisation des standards, ça peut vous être utile même si vous n’utilisez pas SàT pour afficher votre blog (c’est compatible avec Movim par exemple)
  • en plus de l'import Dotclear, la syntaxe wiki Dotclear est également disponible avec SàT désormais, elle vient s’ajouter à Markdown et XHTML.
  • inscription automatique à un flux PubSub pour les nouveaux comptes, ce qui évite d'arriver sur une page vide
  • MAM (XEP-0313) est implémentée pour PubSub, ce qui permet de remonter dans les articles et de faire des recherches de manière beaucoup plus souple et puissante. Notez que MAM n’est pas encore disponible pour la messagerie instantanée, ce sera le cas pour la 0.7
  • meilleure détection de la version du dépôt utilisée
  • jp (l’interface en ligne de commande) a désormais une option --output qui permet de spécifier le format de sortie (par exemple du JSON ce qui permet de facilement parser le résultat avec une autre commande). C’est encore peu utilisé mais la base est là.
  • jp : nouvelles commandes pour importer un blog (import), (ré-)éditer un nouveau/ancien billet (edit) ou voir l’aperçu mis à jour en temps réel (preview). Pour plus d’infos, référez-vous au billet d’explication qui montre comment publier sur votre blog avec Vim ou autre
  • jp : des nouvelles commandes également pour la gestion du roster, qui permettent de l’afficher (get), d’avoir des statistiques (stats) ou de le nettoyer (purge)
  • jp : la commande « message » a été déplacée vers « message send » par cohérence avec les autres commandes, et parce qu’un « message get » est à prévoir
  • jp : les codes de retour utilisent maintenant des constantes, afin qu’ils soient plus utiles
  • Primitivus (interface console) : détection d’un « coller » (une validation est nécessaire dans ce cas, ce qui évite l’envoi accidentel d’un mauvais message comme un mot de passe copié peu avant) et gestion du mode « bracketed paste »
  • Libervia (interface web) : une nouvelle option « allow_registration » permet de désactiver la création de nouveaux comptes, pratique si vous êtes seul sur votre instance, ou si vous créez les comptes par vos propres moyens
  • Libervia : affichage d’un message avec compteur en cas de perte de connexion avec le serveur
  • Libervia : utilisation d’une nouvelle favicon avec un compteur de notifications visible
  • Libervia : correction de la connexion avec un compte (jid) extérieur. Cette fonctionnalité très demandée nous avait causé de gros problèmes à la sortie de la 0.6.0, ils devraient être désormais réglés.
  • Libervia : il est maintenant possible de rediriger les pages ou d'intégrer un répertoire local dans Libervia. C’est ce qui permet d’afficher directement le blog au lieu de la page d’enregistrement sur www.goffi.org.
  • Libervia : gestion des chaînes TLS (Let's Encrypt, si tu nous lis…)
  • Libervia (blog): gestion des étiquettes (tags), y compris la recherche

Voilà pour un aperçu, et c’est loin de couvrir toutes les améliorations de la 0.6.1.

En lisant ceci vous aurez peut-être une petite idée de la quantité de travail nécessaire pour faire avancer un projet comme celui-ci, sachant que nous ne sommes que 2 (et que pour la 0.7 je suis pratiquement tout seul). Aussi si vous voulez participer à un projet éthique et qui refuse de céder aux sirènes des grosses entreprises privatristes, contactez-nous (contact at salut-a-toi point org) ! Rejoignez-nous sur notre salon MUC ! Venez nous aider, on en a grand besoin !

La version 0.6.1 n’est pas parfaite, elle a quelques problèmes (connus ou non), mais nous avons préféré sortir cette version qui malgré tout fonctionne, pour nous concentrer sur la 0.7, qui sera la première version « grand public », annoncée depuis des années.

La version 0.7 passera par une phase de bêta test, et devrait apporter en particulier :

  • un ré-usinage des messages qui permettra d’implémenter de nombreuses extensions bloquées jusqu’ici, comme la correction du dernier message, ou les archives côté serveur (MAM). Cette partie est déjà finie

  • Cagou, l'interface bureau/appareils portatifs que nous avons promis suite au succès de notre campagne de financement participatif. Le développement est bien avancé, bientôt un billet sur le sujet

  • des passerelles de messagerie et de blog. Cela fait longtemps qu'on parle d'en faire, les premières devraient voir le jour dès que Cagou est disponible

En dehors de ça, il est probable que nous implémentions de nouveaux systèmes de chiffrement de bout en bout, en plus d'OTR qui est déjà disponible. OpenPGP est visé en particulier, ainsi qu'OMEMO.

Les grosses fonctionnalités comme l’organisation d’événements ou les calendriers partagés sont plutôt envisagées pour la version suivante.

Ah, et la nouvelle version est disponible comme d’habitude sur le FTP, sur PyPi ou directement depuis le dépôt.

SàT: Comment ça marche ?

goffi 09/11/2015, 12:12 jabber-xmpp SàT tuto technique projet Libre planet-libre SàT seenthis

Salut à vous,

En parallèle de la série d'articles sur XMPP, j'en commence une pour expliquer « Salut à Toi », notre logiciel à tout faire basé sur ce protocole. Il y a beaucoup de choses qui tournent autour de ce logiciel, sur son organisation technique, sa philosophie, et ce qu'on peut faire avec. Aussi je vais faire des articles plus ou moins techniques (plutôt moins), et je vais bientôt expliquer quelques cas concrets d'utilisation.

Ce premier article est un peu technique, puisque je vais expliquer l'organisation générale du logiciel, et ce qu'elle a de particulier.

Donc pour vous donner une idée, SàT c'est dans les grandes lignes ça:

http://ftp.goffi.org/media/pictures/schemas/sat_simplified_overview.png

C'est un client XMPP. Si vous avez lu mes articles, vous savez que XMPP ne signifie pas que « messagerie instantanée », mais beaucoup, beaucoup plus de choses. Le projet SàT essaye non seulement de faire le maximum de ces choses, mais aussi d'expérimenter de nouvelles.

La partie centrale  est la partie « d'arrière-plan » ou « backend » en anglais. C'est elle qui gère le plus gros du logiciel. La partie à droite  sont les « frontaux » (« frontends » en anglais) ou encore les interfaces homme/machine. C'est elles qui gèrent tout l'affichage des informations, ou la réception des commandes et autres messages.

Ce qui fait la force de cette architecture, c'est qu'il est très facile de faire un nouveau frontal, et que le tout représente un seul client. Autrement dit : si vous créez un profil (voir plus bas) sur un frontal, il sera disponible sur tous les autres, si vous envoyez un message d'un côté, il sera visible sur tous les frontaux connectés, l'historique est commun, les fonctionnalités aussi.
En effet, quand on ajoute une fonctionnalité (les messages de groupe par exemple, la copie de fichier, les blogs), c'est dans le « backend » que nous le faisons, et elle se retrouve ainsi disponible partout. Évidemment dans certains cas ça demande du développement particulier pour les interfaces : nous avons un jeu de Tarot par exemple, et on ne dessine pas les cartes de la même manière dans l'interface console (appelée Primitivus) et dans l'interface web (appelée Libervia).

Les interfaces (ou frontaux) disponibles aujourd'hui sont:

  • Libervia : interface web 
  • Primivus : interface de console (avec des fenêtres de type ncurses
  • jp: ligne de commande, permet d'automatiser des tâches facilement, d'envoyer un fichier sans parcourir des menus, d'écrire depuis Vim, etc 

Nous avions une autre interface pour le bureau, appelée « Wix », mais nous l'avons abandonnée, car elle était peu pratique et peu utilisée. Notre campagne de financement en cours permettra de remplacer cette interface et par la même occasion de porter le projet sur Android.

Cette architecture a un autre avantage : il est facile d'intégrer SàT dans des logiciels existants, et avec n'importe quel langage de programmation, mais laissons cela de côté pour le moment.

SàT a également une architecture modulaire via l'utilisation de greffons (ou « plugins » en anglais) au niveau du  sur le schéma : le cœur ne gère que l'essentiel (messages simples, liste de contacts, système de logs, gestion des profils, etc), et toutes les fonctionnalités avancées sont disponibles sous forme de greffons (messages de groupe, blog/microblogs, syntaxes avancées, etc). L'idée est d'une part de pouvoir désactiver les fonctionnalités qu'on ne veut pas, et d'autres part de permettre d'étendre facilement le logiciel : un greffon sera d'autant plus intéressant qu'il sera disponible pour toutes les interfaces. Ainsi un de nos greffons gère les marque-pages (c.-à-d. une liste de salons de discussions) : ils sont utilisables à la fois avec Primitivus (en texte), avec Libervia (graphiquement via le web) ou encore avec jp (en ligne de commande). À terme nous comptons faire un système de téléchargement automatisé de greffons, un peu comme les dépôts de logiciels.

Nous avons besoin de travailler un peu côté serveur, pour notre composant PubSub ou notre annuaire par exemple, nous avons donc aussi quelques travaux de ce côté.

Enfin les profils dont je parlais plus haut sont des comptes locaux associés à un compte XMPP. Ainsi j'ai un profil pour mon compte sur le serveur jabber.fr et un autre pour celui sur libervia.org, je peux utiliser l'un ou l'autre ou les 2 en même temps.

Voilà pour une première introduction, un peu technique parce que je voulais expliquer l'originalité de l'architecture. La prochaine fois je pense parler un plus spécifiquement de Libervia, et du système de blogs/microblogs décentralisé.

N'oubliez pas que nous avons une campagne de financement en cours, et nous avons grand besoin de soutien ! Merci.

Parlons XMPP - épisode 10 - copie de fichiers et Jingle (suite)

goffi 31/03/2016, 11:41 technique planet-libre parlons_xmpp jabber-xmpp Libre seenthis

pour lire les épisodes précédents, suivez l'étiquette correspondante

Maintenant que nous avons vu la copie de fichiers « classique » et ses défauts, abordons une technologie qui a fait beaucoup parler d'elle — et à raison — quand elle est arrivée : Jingle.

Pour la petite histoire, Jingle est une technologie qui résulte d'un effort commun entre des membres de la XSF et une équipe chez Google qui travaillait sur un protocole de voix sur IP (VoIP). La page Wikipédia retrace succinctement l'historique. La technologie Web « WebRTC » hérite et s'inspire de ce travail.

Jingle est souvent considéré à tort comme une technologie dédiée à la visioconférence. En réalité, c'est une technologie qui permet d'établir une session Pair à Pair (P2P) et de la contrôler de manière très souple. Elle a bien été pensée à l'origine pour la visioconférence, et la XEP-0167 s'appuie dessus à cet effet, mais toute application utilisant des connexions directes (et il y en a beaucoup !) peuvent profiter de Jingle : travail collaboratif, tableau blanc, jeux, chiffrement de bout en bout (en évitant ainsi le serveur), partage d'écran, etc. Nous allons nous intéresser plus particulièrement à une de ces applications : le transfert de fichiers.

Jingle fait une séparation claire entre l'application (ici le transfert de fichier), les transports (nous allons retrouver les connexions « in-band » et « SOCKS5 » mentionnées dans le dernier article), et la gestion de session.
Les applications et les transports sont décrits dans des extensions à part : la copie de fichiers est décrite dans la XEP-0234 « Jingle File Transfert ». Vous noterez qu'elle est toujours au statut « d'expérimental » : étant une pièce majeure du futur de XMPP, le travail est long pour obtenir quelque chose de solide et souple. Pour les transports, nous allons donc réutiliser les XEP-0047 et XEP-0065 décrites dans le dernier article, mais en utilisant respectivement les XEP-0261 et XEP-0260 pour les adapter à Jingle. Il faut donc utiliser pas moins de 6 XEPs pour la copie de fichiers avec Jingle (2 d'entre elles servant à la réutilisation d'anciennes), et il est probable que d'autres viennent étendre les possibilités par la suite, en particulier des nouveaux transports (*). Cela peut sembler un peu compliqué, mais c'est ce qui permet la souplesse de Jingle.

Il est possible de modifier ou remplacer à tout moment un transport ou une application, et c'est là la grande force du protocole. Une vidéo passe mal à cause d'une connexion trop faiblarde ? On change l'application pour avoir une vidéo en qualité dégradée. Une connexion SOCKS5 est impossible à établir ? On remplace le transport par un transport « in-band ». Ce dernier cas appelé « plan de secours » (fallback en anglais) était un des problèmes mentionné dans le dernier article, l'ancienne méthode n'indiquant pas comment changer de transport.

Voyons maintenant le fonctionnement. Encore une fois je ne vais pas entrer trop dans les détails, vous pouvez lire la XEP si vous souhaitez les connaître.

Une session Jingle se décide et contrôle à travers le flux XML de XMPP, pour établir une connexion P2P le plus souvent externe (c.-à-d. en dehors du flux XMPP). Une session propose des contenus (« contents »). Un contenu est composé d'une application (transfert de fichier, Vidéo via RTP, etc) et d'un transport (« in-band », « SOCKS5 », « ICE-UDP », etc). L'intérêt principal d'avoir plusieurs contenus est qu'ils sont liés dans la session : par exemple pour une visioconférence, un contenu peut s'occuper de la vidéo, et un autre de l'audio. Si un contenu dans le même logiciel mais non directement lié à la session est utilisé (par exemple un fichier est envoyé au cours de la conversation), on préférera créer une nouvelle session Jingle en parallèle plutôt qu'ajouter un contenu.

Au moment de la création de la session, nous avons 2 entités qui communiquent : l'initiateur (« initiator ») et le destinataire (« responder »). L'initiateur propose des paramètres et/ou une information pour l'application (par exemple des « codecs » pour une vidéo, ou des informations sur le fichier à transférer) ainsi que pour le transport (pour SOCKS5 les candidats par exemple). Si le destinataire accepte la session, il négocie les paramètres en retour pour l'application (par exemple les codecs proposés qu'il connaît) ou le transport (il indique ses propres candidats dans le cas de SOCKS5).

Quand la session est acceptée, elle est considérée « active », mais il n'est pas encore possible d'échanger des données pour autant : il faut d'abord terminer la négociation et accepter un transport (dans le cas de SOCKS5 ça signifie trouver le meilleur candidat, ou changer de transport, probablement pour « in-band »). Une fois tout en place on peut échanger les données, et éventuellement faire des changements en cours d'utilisation comme expliqué plus haut, ou donner des informations (par exemple indiquer qu'un correspondant a coupé le son (« mute »), ou qu'une sonnerie est en cours). Selon les applications, des cas plus compliqués peuvent apparaître, comme changer le sens de transmission de données, rediriger une session (d'un appareil vers un autre par exemple), etc.

Un autre point important avec Jingle, c'est qu'il est possible de demander une pré-condition de sécurité dans une session, par exemple on peut exiger qu'une session soit chiffrée de bout en bout.

Voici une petite liste non exhaustive des améliorations apportées par Jingle rien que pour le transfert de fichiers :

  • une vraie méthode de secours (« fallback »)
  • les XEP-0260 et XEP-261 adaptent les XEP-0065 et XEP-0047 en tirant vraiment profit de Jingle. Ainsi la XEP-0260 permet au destinataire de fournir ses propres candidats, s'inspirant d'une extension jamais standardisée de l'ancienne méthode (appelée « fast-mode »). C'est une grosse avancée, car dans l'ancienne méthode le destinataire doit accepter (et réussir à joindre) les candidats de l'initiateur sinon la connexion échoue. L'échec peut arriver dans de nombreux cas, et si l'initiateur n'a pas de proxy, mais le destinataire en a un, celui du destinataire ne peut pas être utilisé.
    Dans la méthode utilisée avec Jingle, le destinataire peut proposer son proxy, ou la connexion peut s'établir si l'initiateur est injoignable (derrière un NAT par exemple), mais pas le destinataire. L'échec est beaucoup plus rare
  • il est possible de fournir la somme de contrôle (« hash ») quand on le souhaite, et ainsi la calculer au fur et à mesure. Avec l'ancienne méthode c'est tout au début ou rien, ce qui risque de provoquer un ralentissement avant le transfert s'il faut faire le calcul pour un gros fichier
  • avec la XEP-0234, l'initiateur peut demander un fichier au destinataire, au lieu d'uniquement pouvoir lui en proposer un
  • la XEP-0234 permet aussi l'ajout de fichiers en cours de session
  • le chiffrement de bout en bout est possible et prévu, bien que non encore standardisé
  • « ICE-TCP » est en cours de standardisation et devrait arriver cette année (*), permettant de mieux traverser les NATs

Au final, il est quasiment impossible d'échouer un transfert de fichier via Jingle. Le principal cas que je vois est si un des serveurs a une politique interdisant un tel transfert. Cependant, la solution de secours via le flux XMPP « in-band » est gourmande en ressources et très lente, c'est pourquoi il y a du travail sur de nouveaux transports comme ICE-TCP. Ces nouveaux transports serviront à toute application basée sur Jingle : réutiliser l'existant est un des gros points forts de Jingle, et de XMPP en général.

Jingle est une excellente technologie, avec un gros potentiel. Avec PubSub, c'est probablement un des gros piliers du XMPP de demain.

J'en profite pour rappeler que ce blog vient de passer de Dotclear à Salut à Toi, autrement dit il est désormais entièrement basé sur XMPP. J'ai publié une petite série d'articles expliquant la mise en place d'un blog XMPP avec Libervia, son intégration dans une configuration Apache, l'import d'un blog Dotclear et enfin la publication de billets : à lire par ici.

Pour le prochain article, je ne suis pas décidé. Il est possible que je parle de chiffrement de bout en bout vu que c'est un domaine qui bouge en ce moment, ou que je continue sur la lancée Jingle avec les dépôts de fichiers. Cependant j'ai de moins en moins de temps libre, et je préfère consacrer le peu disponible au développement de SàT, le développement de la version bureau/mobiles promise en fin d'année dernière ayant commencé.

(*) cet article ayant été rédigé il y a plusieurs semaines, entre temps la XEP en question est sortie : XEP-0371

Cagou est en chemin

goffi 28/03/2016, 14:53 jabber-xmpp projet GNU-Linux planet-libre SàT seenthis Libre cagou

Un petit billet pour vous dire que suite à notre campagne réussie en fin d'année dernière, le développement sur notre nouvelle interface de bureau et pour appareils mobiles (Android au minimum, peut-être plus) a commencé.

J'ai tenu a faire la migration de mon blog sur SàT avant pour y faire des billets au fil de l'avancement.

Cette interface va s'appeler « Cagou », en référence à la fois à Kivy qui est utilisé, et à la Nouvelle-Calédonie où Souliane (autre développeur principal) et moi nous sommes rencontrés. Le Cagou (ou Kagou) est un superbe oiseau qui aboie et qui ne vole pas, c'est une espèce malheureusement menacée.

L'interface devrait donc fonctionner sur bureau et appareils mobiles, comme promis, mais ne va pas nécessairement suivre les standards auxquels vous êtes peut-être habitués. Par souci de simplification, l'interface sera similaire sur toutes les plate-formes, aussi elle sera pensée pour fonctionner aussi bien avec un écran tactile qu'avec une souris, et il ne faut pas s'attendre à une intégration graphique avec les applications natives de votre bureau. Par contre une intégration avec les fonctionnalités de la plate-forme (notifications, marque-pages, etc) est voulue.

Ce frontal va être pensé pour fonctionner en plein écran (mais aussi en mode fenêtré), éviter tout ce qui est pop-up ou action perturbante (comme les doubles-clics), et elle ne va pas être centrée sur la liste de contacts. Nous en reparlerons bientôt.

Bien entendu, grâce à l'architecture de SàT, vous pouvez vous attendre à voir rapidement toutes les fonctionnalités déjà implémentées (chiffrement de bout en bout, transfert de fichier en Pair à Pair, publication en différentes syntaxes, etc).

Si vous avez des suggestions, des envies ou idées, c'est le moment d'en discuter, soit en commentant ce billet, soit en venant sur le salon sat@chat.jabberfr.org ou en nous écrivant sur contact@salut-a-toi.invalid (remplacez invalid par org). Vous pouvez également écrire sur Diaspora ou SeenThis.

Configuration avancée du conteneur Libervia

goffi 18/03/2016, 18:41 jabber-xmpp projet GNU-Linux planet-libre SàT seenthis Libre Tutorial Libervia_installation

Cet article fait suite à l'article de la semaine dernière indiquant comment installer Libervia en moins de 10 min. Nous allons voir aujourd'hui comment utiliser un certificat TLS existant, intégrer le conteneur dans une configuration Apache, ou lancer automatiquement le service au démarrage de la machine.

Utiliser votre certificat TLS existant

Au premier lancement des conteneurs, un certificat auto-signé est automatiquement créé pour pouvoir utiliser Prosody ou le serveur HTTPS de Libervia. Ce genre de certificat est très bien pour du test, mais d'une part provoquera un avertissement dans les navigateurs, et d'autre part son authenticité n'est assurée par aucun organisme (les certificats TLS sont signés par des organismes que votre navigateur et/ou système connaissent, ce qui permet de les valider – principe qui n'est pas idéal, mais c'est un autre sujet –).

Pour utiliser votre propre certificat plutôt que celui généré par les conteneurs, il faut utiliser la variable d’environnement SAT_CONT_TLS_DIR avec un chemin absolu vers vos certificats.

Il faut qu'à l'intérieur de ce dossier se trouvent les fichiers « libervia.key » pour votre clef privée, et « libervia.crt » pour votre certificat public. Ces noms de fichiers sont fixés car déjà configurés dans Libervia et Prosody, si vous voulez les changer il faudra changer les 2 configurations à l'aide de ./libervia_cont.sh config et ./libervia_cont.sh config prosody, comme indiqué dans le dernier article.

Au niveau des permissions des certificats, vous pouvez les laisser accessibles uniquement au « group ID » 9999 qui correspond au groupe « tls-cert » sur les conteneurs.

Let's Encrypt

Comme Let's Encrypt est (à juste titre) à la mode, voyons voir de plus près ce cas particulier.

Le but ici est de ne pas avoir à changer la configuration à chaque renouvellement, qui ont lieu au plus tard tous les 3 mois. Let's Encrypt met ses certificats (par défaut, adaptez au besoin) dans /etc/letsencrypt/archive/<votre_nom_de_domaine>, mais les noms de fichiers changent à chaque renouvellement, et met un lien symbolique vers les certificats en cours dans /etc/letsencrypt/live/<votre_nom_de_domaine>.
Vous ne pouvez pas utiliser directement /etc/letsencrypt/live/ car vous auriez des liens symboliques pointant dans le vide, il va falloir monter le dossier archive également.

La variable d'environement SAT_CONT_DK_EXTRA permet de spécifier des paramètres pour la commande « docker run » qui seront utilisés pour tous les conteneurs (sauf sat_data). Nous allons l'utiliser pour monter toute l'arborescence letsencrypt, comme suit :

export SAT_CONT_DK_EXTRA="-v /etc/letsencrypt:/etc/letsencrypt"

Il va falloir éditer les configurations de Libervia et Prosody pour pointer vers les bons fichiers.
Pour Libervia, utilisez ./libervia_cont.sh config puis spécifiez dans la section [libervia] :

[libervia]
tls_private_key = /etc/letsencrypt/live/<nom_domaine>/privkey.pem 
tls_certificate = /etc/letsencrypt/live/<nom_domaine>/cert.pem 
tls_chain = /etc/letsencrypt/live/<nom_domaine>/chain.pem

N'oubliez pas l'option tls_chain qui permet de spécifier la chaîne de validation.

Pour prosody, c'est ./libervia_cont.sh config prosody qu'il faut utiliser, vous devez avoir modifié votre option ssl pour qu'elle ressemble à :

ssl = {
        key = "/etc/letsencrypt/live/<nom_domaine>/privkey.pem";
        certificate = "/etc/letsencrypt/live/<nom_domaine>/fullchain.pem";
}

dans les 2 cas il faut bien évidemment remplacer <nom_domaine> par votre nom de domaine tel qu'il apparaît dans /etc/letsencrypt/live. Assurez vous aussi que les permissions sont correctes, vous verrez si Prosody ou Libervia n'arrivent pas à lire les fichiers à l'aide de docker logs -f prosody et docker logs -f libervia respectivement.

Intégration à un serveur Apache

Si vous avez déjà un serveur Apache qui tourne, vous préfèrez sans doute intégrer Libervia à la configuration existante plutôt que sur un port séparé.

Pour cela nous allons utiliser un « proxy inverse » (reverse proxy) qui va rediriger une adresse de votre domaine sur le serveur de Libervia.

Si vous avez une configuration HTTPS, elle sera gérée par Apache lui-même, donc commençons par désactiver le serveur HTTPS de Libervia, et par supprimer le message d'avertissement en cas de connexion HTTP. Éditez sat.conf à l'aide de ./libervia_cont.sh config, et mettez ceci dans la section [libervia] :

[libervia]
connection_type = http
security_warning = 0

Désormais seul le port HTTP sera disponible.

Maintenant, nous allons configurer apache pour qu'il redirige les URL correspondant à votre instance de Libervia vers le serveur. Dans le répertoire /etc/apache2/mods-available/ créez un fichier libervia.conf qui ressemble à peu près à ça :

<VirtualHost *:80>
    ServerName www.<votre-serveur.tld>
    ServerAlias <votre-serveur.tld> libervia.<votre-serveur.tld>
    ServerAdmin webmaster@votre-server.tld
    ErrorLog /var/log/apache2/libervia-error.log
    CustomLog /var/log/apache2/libervia-access.log
    ProxyPass / http://127.0.0.1:8080/ nocanon
    ProxyPassReverse / 127.0.0.1
    AllowEncodedSlashes On
    RequestHeader set X-Forwarded-Proto "http"

    <proxy *>
        Require all granted
    </proxy>
</VirtualHost>

Il faut bien entendu remplacer <votre-serveur.tld> par votre nom de domaine, adapter SeverName et ServerAlias à ce que vous souhaitez utiliser, ainsi que les ports pour qu'ils correspondent à ceux que vous utilisez en pratique (si vous avez tout laissé par défaut, les ports indiqués sont valables).

Quelques explications sur la configuration : Passons sur les premières lignes et VirtualHost qui sont des classiques de configuration Apache, vous trouverez les informations nécessaires facilement sur le web au besoin. Les directives qui nous intéressent ici sont à partir de ProxyPass.

  • ProxyPass indique à Apache de rediriger les connexions sur le serveur local au port 8080, soit l'instance en cours de Libervia. Notez bien le « nocanon » qui est très important, il indique à Apache de ne pas utiliser des adresses canoniques, soit en d'autres terme de ne pas modifier les URLs envoyées à Libervia.
  • ProxyPassReverse concerne les redirections
  • AllowEncodedSlashes est nécessaire pour accepter les URLs contenant des « / » (%2F), qui sont utilisées dans Libervia.
  • RequestHeader permet d'ajouter l'en-tête « X-Forwarded-Proto » indiquant à Libervia le protocol utilisé au niveau du proxy

Quand un proxy est utilisé, l'adresse utilisée « vue » de l'extérieur (http(s)://www.<votre-serveur.tld>/[…]) n'est pas la même que celle utilisée pour accéder par Libervia, qui est ici http://127.0.0.1:8080. Or Libervia a besoin de connaître cette adresse pour construire des chemins absolus vers les documents, par exemple dans le flux Atom.
Normalement, ceci est fait automatiquement et vous n'avez besoin de toucher à rien pour que Libervia utilise les bonnes URL ; mais si jamais les URL produites n'étaient pas correctes, vous pourriez utiliser l'option « base_url_ext » pour forcer l'utilisation de la base indiquée. Ainsi pour forcer l'utilisation de http://www.goffi.org, je peux indiquer ceci dans ma configuration Libervia :

base_url_ext = http://www.goffi.org

Ou même « //www.goffi.org » pour laisser Libervia gérer le schema (c.-à-d. le protocol : http ou https). Encore une fois tout ceci devrait être géré automatiquement (*), et il est très peu probable que vous ayez à utiliser cette option. Venez me contacter sur sat@chat.jabberfr.org pour plus d'explications si nécessaire.

Une fois la configuration faite, il vous suffit pour activer le proxy de demander à Apache de prendre en compte la nouvelle configuration. Nous allons également nous assurer que le mode proxy_http est activé, aussi nous allons utiliser les commandes suivantes (en root) :

# a2enmod headers
# a2enmod proxy_http
# a2ensite libervia.cont
# systemctl reload apache2

(*) si vous avez téléchargé les images la dernière fois, ce comportement a été modifié depuis, c'est l'occasion de tester « ./libervia_cont.sh update ».

Utilisation d'un cache

Apache a des modules permettant la gestion d'un cache, qui permettra à la fois d'économiser les ressources, et de fournir la dernière page connue en cas d'indisponibilité du serveur (lors d'une maintenance par exemple). Dans le cas de Libervia, c'est principalement utile pour le blog statique.

Assurez-vous d'abord que le cache est activé à l'aide de :

 # a2enmod cache_disk

qui activera à la fois les modules cache et cache_disk. Ensuite à l'intérieur de la configuration du VirtualHost que nous avons faites plus haut :

<IfModule mod_cache_disk.c>
    CacheEnable disk /
    CacheRoot "/var/cache/apache2/mod_cache_disk/libervia/"
    CacheDirLevels 3
    CacheDirLength 5
    CacheIgnoreHeaders Set-Cookie
    CacheMaxFileSize 200000000
    CacheIgnoreNoLastMod On
    CacheDefaultExpire 300
</IfModule>

Vous pourrez vous reporter à la documentation pour la plupart des directives utilisées ici, mais il est nécessaire d’en préciser quelques-unes :

  • CacheIgnoreHeaders Set-Cookie évitera de mettre en cache les cookies qui sont utilisés pour la session dynamique de Libervia, cette directive est essentielle pour la sécurité
  • CacheIgnoreNoLastMod On permet de mettre en cache des documents qui ne possèdent pas de date de dernière modification, ce qui est le cas actuellement des pages servies par Libervia
  • CacheDefaultExpire indique un cache qui expire après 10 min. Libervia ne gère pas (encore) les indications nécessaires à une gestion automatique du cache, aussi on indique ici la durée voulue. Le cache étant essentiellement utilisé pour le blog statique, j'ai mis 10 min pour qu'une mise à jour apparaîsse suffisament vite.

À moins d'avoir un site extrêmement populaire, il ne devrait pas y avoir de problème de performance pour le blog statique même sans cache, il est à mon sens surtout utile ici pour continuer à servir les pages pendant les maintenances.

Utilisation de tls

L'utilisation de TLS n'est pas plus compliquée que pour un autre site Apache.
Voici à quoi peut ressembler une configuration si vous activez le proxy, le chiffrement TLS, et un cache :

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName www.<votre_site.tld>
        ServerAlias <votre_site.tld> libervia.<votre_site.tld>
        ServerAdmin webmaster@<votre_site.tld>
        LogFormat "h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %{cache-status}e" with_cache
        ErrorLog /var/log/apache2/libervia-error.log
        CustomLog /var/log/apache2/libervia-access.log with_cache
        ProxyPass / http://127.0.0.1:8080/ nocanon
        ProxyPassReverse / http://127.0.0.1:8080/
        AllowEncodedSlashes On

        <proxy *>
                Require all granted
        </proxy>
        SSLCertificateFile /etc/letsencrypt/live/<votre_site.tld>/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/<votre_site.tld>/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateChainFile /etc/letsencrypt/live/<votre_site.tld>/chain.pem

        <IfModule mod_cache_disk.c>
                CacheEnable disk /
                CacheRoot "/var/cache/apache2/mod_cache_disk/libervia/"
                CacheDirLevels 3
                CacheDirLength 5
                CacheIgnoreHeaders Set-Cookie
                CacheMaxFileSize 200000000
                CacheIgnoreNoLastMod On
                CacheDefaultExpire 300
        </IfModule>

</VirtualHost>
</IfModule>

Notez que le « RequestHeader set X-Forwarded-Proto » a désormais la valeur "https" ainsi que le « with_cache » dans les logs, ajoutant des informations utiles (est-ce que la page est servie par le cache ou Libervia ?).

Pour le reste, reportez-vous à la documentation Apache.

Démarrage automatique

Dernier point de cette partie sur la configuration avancée, nous allons voir comment lancer automatiquement notre instance de Libervia au démarrage de la machine. Nous allons pour cela utiliser SystemD qui est désormais le gestionnaire de démarrage par défaut de la plupart des distributions, donc probablement de la vôtre.
Il vous suffit d'utiliser une configuration similaire à la suivante, dans un fichier libervia.service à placer dans /etc/systemd/system :

[Unit]
Description=Libervia (Salut à Toi) XMPP Docker service
After=docker.service
Requires=docker.service

[Service]
User=libervia

Environment= \
SAT_CONT_DOMAIN=votre_domain.tld \
SAT_CONT_PORT_8080=8000

ExecStartPre=/home/goffi/dev/sat_docs/docker/libervia_cont.sh start -p
ExecStart=/usr/bin/docker wait libervia
ExecStop=/home/goffi/dev/sat_docs/docker/libervia_cont.sh stop

[Install]
WantedBy=multi-user.target

Ce fichier indique que le containeur doit attendre que Docker soit lancé. L'utilisateur ici est libervia, changez-le pour celui que vous avez ajouté au groupe « docker ».
Environment vous permet de configurer les options comme le port ou le nom de domaine utilisé, notez bien le "\" en fin de ligne (dernier caractère avant le retour à la ligne, sans espace) qui indique de considérer la ligne suivante comme la suite de la commande.

Le serveur est en fait lancé avec la directive ExecStartPre, afin de pouvoir connaître sont état avec « docker wait ». C'est une petite astuce qui évite des complications, car les conteneurs sont lancés par le démon Docker et non le script lui-même.

À suivre…

Voilà pour cette seconde partie de la série sur l'installation d'un blog Libervia. Ce n'était pas la partie la plus amusante, mais vous n'avez a priori à faire cette configuration qu'une seule fois, et elle n'est pas si compliquée que cela.

La prochaine fois nous importerons un blog depuis Dotclear.

Libervia (Salut à toi) 0.6.0 : des avancées majeures !

goffi 02/12/2015, 12:48 jabber-xmpp GNU-Linux projet Libre planet-libre SàT seenthis

Salut à vous,

Nous avons le plaisir d'annoncer la sortie de Salut à Toi (SàT) 0.6.0 et donc de son interface web « Libervia ». Pour mémoire, SàT est un « couteau suisse de la communication », un outil libre et décentralisé permettant de partager publiquement ou de façon privée des messages, des fichiers, des articles de blog, de microblog, etc.

Le projet a de nombreuses fonctionnalités allant du chiffrement de bout en bout aux jeux, et peut également servir de base pour créer de nouveaux réseaux.
C'est aussi un projet éthique, géré par une association loi 1901, suivant un « contrat social », utilisant exclusivement des logiciels libres, militant pour la décentralisation, et fermement opposé à la publicité.


Cette version a vu un très gros travail sur le système de blogs : Libervia offre un moteur de blog décentralisé, accessible à des groupes restreints ou de l'extérieur, et entièrement basé sur le protocole standard et ouvert « XMPP ». L'utilisation de ce standard permet de communiquer avec d'autres projets comme Movim ou Jappix, créant ainsi un grand réseau libre.

Le partage de fichiers en pair à pair (P2P) a aussi été grandement amélioré grâce au protocole « Jingle », ouvrant la voie pour de futures applications comme la visioconférence.

L'annonce officielle est disponible sur le blog suivant (basé sur Libervia) : https://libervia.org/blog/salut-a-toi.

Une dépêche Linuxfr plus détaillée est en cours de modération et devrait être publiée sous peu.

Une campagne de financement participatif est en cours pour faire une version de bureau (une étape déjà franchie), et une version Android. Cette campagne étant très proche de la fin, c'est le moment de nous soutenir !


 http://ftp.goffi.org/media/screenshots/0.6/overview.png 

 

site officiel : http://salut-a-toi.org
démo : https://libervia.org
campagne de financement : https://www.arizuka.com/fr/projects/libervia
N'hésitez pas à nous contacter (http://salut-a-toi.org/community.html)

L'équipe « Salut à Toi »

RyDroid 02/12/2015, 19:51

Bonjour.

J'ai un compte XMPP chez movim.eu qui marche sans problème sur pod.movim.eu (et Xabber sur Android, en tout cas au moins il y a quelques mois, n'utilisant plus de firmware Wi-Fi propriétaire je ne sais pas ce qu'il en est). Mais je n'arrive pas à l'utiliser avec libervia.org. Iceweasel 38.4.0 et Chromium 46.0 (fournis par Debian GNU/Linux 8.0) me donnent le même message d'erreur : "Did not receive a reply (the timeout expired or the connection is broken).".
Je me suis donc inscrit sur libervia.org pour tester. J'ai reçu un email me disant que je suis inscrit, et aussi une alert JavaScript pas user-friendly "Submit error: UNMANAGED FAULT STRING (NoReply)". J'obtiens la même erreur qu'avec mon compte sur movim.eu...

Sur Chromium (mais pas Iceweasel), il barre le cadenas HTTPS avec libervia.org parce qu'il n'arrive pas à reconnaître l'identité du site web, pourtant le certificat a bien la même empreinte SHA1.
C'est documenté sur salut-a-toi.org, sur lequel Iceweasel n'aime cette fois pas non plus le certificat. http://salut-a-toi.org/faq.html#cer...
Le SHA-256 que j'ai est "F4:63:59:82:71:5C:4B:C8:5F:2F:E9:DB:AA:28:90:D6:6A:D0:2E:76:3E:91:6E:63:92:66:CE:E3:5F:D7:F3:CD", ce qui n'est pas le bon d'après la documentation. Utiliser le Tor Browser ne change rien. La documentation est elle à jour ou j'ai loupé quelque chose ?


author website

Libervia/Salut à Toi à « fêtons Linux » (Lausanne 28/11/2015)

goffi 20/11/2015, 10:14 jabber-xmpp GNU-Linux projet Libre planet-libre SàT seenthis

Un rapide billet pour vous dire que nous avons été invités à participer à « fêtons Linux », une journée de rencontre autour des logiciels libres et de Gnu/Linux.

J'y ferai 2 conférences, une technique de 45 min pour expliquer le cœur du projet (à 13h), et une plus grand public de 20 min (à 14h30), et bien sûr je serai présent toute la journée pour discuter (je passerai également par Genève s'il y a du monde qui veut s'y retrouver).

Un grand merci à l'organisation.

Nous avons également passé le premier palier pour notre campagne de financement, c'est à dire que nous sommes engagés à faire un prototype de version de bureau. Mais il nous manque encore un peu moins de 2000 € pour la version Android, et nous avons 2 semaines pour y arriver, aussi faite tourner ce lien partout ou vous pouvez, nous avons besoin d'un coup de pouce pour nous faire connaître : www.arizuka.com/fr/projects/libervia (ou en anglais: www.arizuka.com/en/projects/libervia). Merci !

Je n'ai pas eu le temps d'écrire d'article cette semaine car je suis débordé par le développement : nous espérons sortir la nouvelle version très bientôt.

À bientôt

N.B.: j'ai dû temporairement mettre la modération a priori sur les commentaires, j'ai depuis 2 semaines une vague de spam qui passe les filtres en place.

centralisé, décentralisé, P2P, mais c'est quoi tout ça ?

goffi 10/11/2015, 13:22 jabber-xmpp technique projet Libre planet-libre SàT vulgarisation seenthis

Une petite mise au point technique, parce que je vois qu'il y a beaucoup de confusion sur les termes « centralisé » (encore lui ça va), « décentralisé », « distribué », « fédéré », « pair à pair », etc.

Il faut dire que la confusion est assez normale, il n'y a pas vraiment de définition de ces termes, et ce que les gens entendent en les employant dépend de leurs lectures, leur compréhension, et leur sensibilité.

Commençons par le plus simple : centralisé. Un système centralisé c'est un système où tout le monde dépend d'une même autorité, un serveur a priori dans le cas informatique. Bien qu'un système centralisé soit beaucoup plus simple à faire sur le plan technique (facile de trouver des gens ou des informations quand ils sont tous au même endroit), il peut avoir ses propres problèmes : montée en charge en particulier ; il est plus difficile d'absorber des données quand il n'y a qu'un centre de traitement, les tuyaux peuvent rapidement se trouver trop petits, etc.

Un système de communication centralisé pose de nombreux problèmes : il est évident qu'il est plus facile d'espionner, censurer ou modifier des données quand elles sont dépendantes d'un seul point. Même sans intention malicieuse, on a un point unique de défaillance (ce que les anglophones appellent « single point of failure »), c.-à-d. qu'une panne, une attaque, une catastrophe naturelle ou pas provoque l'arrêt du service voire la perte des archives.
Dans les cas les plus gros, on prend un hangar et on le remplit d'ordinateurs, ce sont les fameux centres de données ou « data centers ».

Là où ça se complique un peu, c'est qu'un système centralisé peut être physiquement en plusieurs endroits, ou utiliser des systèmes de répartition/répétition des données. Le principe est d'éviter l'engorgement ou les risques de pannes cités plus haut, mais même si ces machines sont séparées et communiquent entre elles à distance, elles sont a priori toujours sous la même autorité.


http://repos.goffi.org/sat_docs/raw-file/tip/schemas/decentralisation/centralised_simple.png


Passons maintenant aux systèmes décentralisés/distribués/fédérés. Certains vont pousser les haut-cris que je mette tout ça ensemble, parce qu'il n'y pas vraiment de définition et que chacun se fait plus ou moins la sienne.

« dé-centralisé » veut dire qui n'a pas de centre, ni plus ni moins. L'idée pour un système de communication, c'est que toute entité (individu, association, organisation, etc) puisse être une partie d'un réseau qui n'a pas d'autorité principale, et que ces autorités puissent parler entre elles.

On essaye ainsi d'éviter les problèmes de la centralisation, mais on se retrouve avec tout un tas de nouveaux problèmes, techniques pour la plupart : il est beaucoup plus difficile de retrouver des données ou des gens en plusieurs endroits, de se mettre d'accord sur la « langue » à utiliser pour communiquer (surtout quand on a des logiciels ou des versions d'un même logiciel différents), ou encore d'être sûr que la donnée qu'on a est à jour (est-ce que le message a été modifié ou supprimé ?).

« fédéré » est généralement employé pour parler de systèmes différents (noms de domaines différents par exemple, voire logiciels différents) qui peuvent communiquer entre eux. Un système décentralisé est fédéré par nature, sinon on a affaire à plusieurs systèmes centralisés indépendants. Disons que si on veut être pointilleux, on peut dire qu'un système décentralisé peut communiquer avec seulement certaines entités (je communique avec les serveurs de mon entreprise internationale, mais pas avec le reste du monde), et que la fédération implique l'idée que c'est ouvert à tous (ou presque, il y a souvent des gens qu'on ne veut pas, les spammeurs par exemple).

« distribué » ne devrait pas être employé pour les systèmes de communication. Le terme est normalement utilisé pour le calcul : si votre ordinateur a plusieurs processeurs, il distribue la charge de calcul entre eux, ou dans le cas de très grosses demandes (recherche par exemple), on peut demander à plusieurs machines distantes de faire chacun une partie d'une grosse opération mathématique. Dans ce cas, l'organisation de la répartition est souvent contrôlé par une même autorité (par exemple le laboratoire qui veut faire cette opération).
Par extension, le terme est aussi utilisé pour les systèmes de fichiers, et certains l'emploient pour les logiciels de communication, mais cela ne veut pas dire autre chose que décentralisé.


http://repos.goffi.org/sat_docs/raw-file/tip/schemas/decentralisation/decentralised_simple.png


Enfin, il y a le terme P2P ou « pair à pair » (« peer to peer » en anglais). En fait une connexion pair à pair n'est rien d'autre qu'une connexion directe entre 2 ordinateurs, mais on l'associe souvent aux technologies plus ou moins apparentées qui ont commencé à apparaître à la fin des années 90/au début des années 2000 et qui servaient (et servent toujours) principalement à partager des fichiers.

Après Napster (lancé mi 1999) qui était un bête système centralisé qui mettait en relation des machines pour une connexion directe, il y a eu beaucoup d'essais et d'évolutions pour trouver un système qui permet de se passer de serveurs, l'idée étant principalement de permettre au réseau de fonctionner même si on lui coupe l'accès à une partie de lui-même.

Je vous passe toutes les techniques qui sont utilisées : c'est un domaine très pointu, très intéressant, et qui demanderait facilement un livre pour être expliqué. Ça part des systèmes de répartition par propagation de proche en proche à la Usenet, jusqu'aux récentes chaînes de blocs (blockchain), en passant par les tables de hachage distribuée (Distributed Hash Table), etc.

Ce qui fait principalement la différence entre un système « décentralisé » et « entièrement P2P », c'est la place du serveur. Un serveur, dans les grandes lignes, c'est ce qui permet à votre logiciel (le « client ») de contacter d'autres clients via d'autres serveurs. Il est là pour tout un tas de raisons : identifier les gens, donner les bonnes données aux bonnes personnes, garder
les fichiers à donner à un client actuellement hors ligne quand il sera disponible, etc.
Si on supprime le serveur, inévitablement c'est votre client (ou un autre) qui va devoir se charger de ce travail, ce qui aura un impact sur votre bande passante, la charge de travail pour votre processeur (et donc la durée de vie de votre batterie le cas échéant), et compliquera la tâche de votre logiciel (plus difficile de savoir à qui parler et à qui faire confiance quand on n'a pas de serveur comme référence).

http://repos.goffi.org/sat_docs/raw-file/tip/schemas/decentralisation/fully_P2P_simple.png

Pour transformer un système décentralisé avec serveurs en système entièrement P2P (c.-à-d. sans serveur), je vais vous donner une recette : vous mettez un seul client sur votre serveur, et vous mettez le serveur et le client sur la même machine.
Bien sûr si vous voulez être vraiment indépendant, il va falloir supprimer le besoin de points de références, et en particulier le système de noms de domaine ou « Domain Name System ». C'est ce qui associe le nom de votre serveur (par exemple « libervia.org ») à l'adresse « IP » qui permet de vous retrouver sur Internet. Il va falloir aussi être capable de retrouver les données ou les gens un peu partout, et là on se retrouve avec les technologies intéressantes mais complexes évoquées plus haut (« D.H.T. », « Blockchain », « SuperPeer », etc).
 

Et XMPP dans tout ça ?

Je vais quand même parler un peu de XMPP. XMPP est un système dit « hybride », c'est à dire qu'il fonctionne normalement sur un modèle client/serveur, mais il peut faire du P2P à la demande (pour transférer un fichier ou faire de la visioconférence par exemple).
Il est même possible de fonctionner sans serveur sur un réseau local (comme expliqué ici), et il peut parfaitement devenir à terme un système entièrement P2P comme expliqué dans le paragraphe précédent.

Ceci dit, même si l'approche entièrement P2P est séduisante, je pense que l'architecture décentralisée sur un modèle client/serveur est un compromis bien plus efficace : elle limite le travail de votre client, permet une meilleure optimisation du trafic ou du calcul, et facilite l'échange asynchrone (quand deux personnes ne sont pas connectées en même temps). Bref, c'est tout sauf un modèle du passé comme on peut le lire parfois, et bien qu'il y ait plusieurs recherches et options intéressantes pour des systèmes entièrement P2P, il ne faudrait pas jeter le bébé avec l'eau du bain.