Créer le paquet Pétrolette pour Yunohost

Posté par  . Édité par Xavier Teyssier, Ysabeau, Benoît Sibaud et palm123. Modéré par ymz. Licence CC By‑SA.
Étiquettes :
29
18
avr.
2021
Administration système

J’ai récemment découvert comment créer un paquet YunoHost avec l’application Whitebophir (présenté ici même. Suite à la dépêche sur Pétrolette et voyant dans les commentaires une demande pour un paquet YunoHost, je me dis que c’est l’occasion.

Sommaire

Présentation de Yunohost

yunohost

Le projet YunoHost a déjà été présenté plusieurs fois sur linuxfr mais pour rappel :

YunoHost est un système d’exploitation qui vise à simplifier autant que possible l’administration d’un serveur pour ainsi démocratiser l’auto-hébergement tout en restant fiable, sécurisé, éthique et léger. C’est un projet de logiciel libre maintenu exclusivement par des bénévoles. Techniquement, il peut être vu comme une distribution basée sur Debian GNU/Linux et peut s’installer sur de nombreux types de matériel.

Installation de Pétrolette en local

Dans un premier temps, on vérifie comment s’installe l’application ciblée et quelles sont les possibilités d’installation. Il faut notamment savoir s’il est possible de :

  • configurer le/les ports de l’application ;
  • installer l’application sur un sous chemin du domaine ;
  • installer plusieurs instances de l’application sur la même machine ; 
  • s’installer derrière l’authentification de YunoHost.

Dans notre cas, l’application n’a aucun système d’authentification et peut donc se mettre facilement derrière le portail captif de YunoHost. En revanche, on ne peut pas installer l’application dans un sous-répertoire du domaine ni choisir le port de l’application. Ce dernier point empêche donc aussi l’installation de plusieurs instances. Heureusement, une pull request rapidement acceptée corrige ce dernier point.

Création du paquet YunoHost

YunoHost propose une documentation plutôt bien fournie pour créer un nouveau paquet. Un dépôt d’exemple est aussi disponible comme base de travail.

L’architecture

Un paquet YunoHost est une collection de scripts bash associés à des templates de configuration suivant une architecture bien définie. À la racine, un fichier manifest.json, un dossier scripts et un dossier de configuration. Un dossier sources peut être ajouté contenant d’éventuels correctif mais n’est pas utile dans notre cas.

├── check_process
├── conf
│   ├── app.src
│   ├── nginx.conf
│   └── systemd.service
├── issue_template
├── LICENSE
├── manifest.json
├── README_fr.md
├── README.md
└── scripts
    ├── backup
    ├── _common.sh
    ├── install
    ├── remove
    ├── restore
    └── upgrade

manifest.json

C’est la définition du paquet, il comprend les informations comme le nom, la description et la licence de l’application ainsi que les informations demandées lors de l’installation.

Dans notre cas, l’application ne s’installe qu’à la racine d’un domaine, donc on demande simplement le domaine où installer l’application et si celle-ci doit être accessible publiquement.

{
    "name": "Petrolette",
    "id": "petrolette",
    "packaging_format": 1,
    "description": {
        "en": "The news reader that doesn't know you",
        "fr": "La page d'actu qui ne sait rien de toi"
    },
    "url": "https://framagit.org/yphil/petrolette",
    "version": "1.2.5~ynh1",
    "license": "GPL-3.0-only",
    "maintainer": [{
        "name": "oiseauroch.",
        "email": "xxx@xx.xx"
    }],
    "requirements": {
        "yunohost": ">= 4.1.0"
    },
    "multi_instance": true,
    "services": [
        "nginx"
    ],
    "arguments": {
        "install" : [
            {
                "name": "domain",
                "type": "domain",
                "example": "domain.org"
            },
            {
                "name": "is_public",
                "type": "boolean",
                "default": true,
                "help" : {
                    "fr" : "Cette page sera accessible par n'importe qui. En revanche, la configuration reste personnelle",
                    "en" : "The page will be accessible by anyone."
                }
            }
        ]
    }
}

Le dossier de configuration

Celui-ci contient au moins un fichier app.src contenant l’adresse et le checksum de l’application. Il contient aussi les templates de configuration. YunoHost utilise nginx comme reverse-proxy et DBus pour le lancement des applications. Il faut donc au minimum un template pour nginx et un pour systemd.

Les scripts

Écrits en bash, les scripts permettent d’effectuer les opérations (installation, suppression, sauvegarde…) sur l’application. Afin de simplifier la vie du mainteneur et de normaliser ces opérations, YunoHost mets à disposition de nombreux helper.

Pour notre script install par exemple, on va dans un premier temps sourcer notre helper ainsi que ceux de YunoHost et s’assurer de retourner dans un état stable en cas d’erreur.

source _common.sh
source /usr/share/yunohost/helpers

# Exit if an error occurs during the execution of the script
ynh_abort_if_errors

Ensuite, on récupère les arguments du manifest. Ceux-ci sont nommés par convention $YNH_APP_ARG_NOM-DANS-LE-MANIFEST. On définit aussi le chemin de l’application pour l’instant en dur étant donné qu’il ne peut s'installer qu’à la racine. Les variables domaine, is_public, app et path_url sont aussi des conventions qu’il convient de respecter parce qu’elles sont recherchées par défaut dans certains helpers.

domain=$YNH_APP_ARG_DOMAIN
is_public=$YNH_APP_ARG_IS_PUBLIC
app=$YNH_APP_INSTANCE_NAME

path_url="/"

Vient après la définition du dossier de l’application appelé final_path lui aussi par convention. YunoHost m’indique que pour une application possédant un serveur web, le chemin est par défaut /opt/yunohost/$app. Cette opération étant la première à pouvoir prendre du temps, on indique un message de log qui sera visible pendant d’installation.

ynh_script_progression --message="Validating installation parameters..."

final_path=/opt/yunohost/$app
test ! -e "$final_path" || ynh_die --message="This path already contains a folder"

# Register (book) web path
ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url

Yunohost stocke les informations d’installation des applications dans le dossier /home/yunohost.conf sous forme de yaml. Bien entendu, on n’édite pas nous-mêmes ces fichiers, mais on passe par d’autres helpers.

ynh_script_progression --message="Storing installation settings..."

ynh_app_setting_set --app=$app --key=domain --value=$domain
ynh_app_setting_set --app=$app --key=path_url --value=$path_url

YunoHost utilise un utilisateur différent pour chaque app installée, créons-le.

# Create a system user
ynh_system_user_create --username=$app --home_dir=$final_path

Viennent les parties plus spécifiques à notre application. Notre application utilise son propre serveur web, donc on cherche un port disponible (deux dans notre cas) puis on installe les dépendances. Pétrolette se base sur nodejs qui est une dépendance fréquente. YunoHost propose donc un helper spécifique pour gérer les différentes versions de node et appeler la bonne pour chaque application.

# Find an available port
port=$(ynh_find_port --port=8001)
https_port=$(ynh_find_port --port=8002)
ynh_app_setting_set --app=$app --key=port --value=$port
ynh_app_setting_set --app=$app --key=https_port --value=$https_port

ynh_install_nodejs --nodejs_version=$NODEJS_VERSION

Nous en sommes à l’installation proprement dite. Pétrolette utilise bower qui stocke des informations dans le répertoire de l’utilisateur courant. L’installation étant réalisée en root, il faut changer son répertoire pour stocker ces informations dans le répertoire de l’application.

ynh_app_setting_set --app=$app --key=final_path --value=$final_path
ynh_setup_source --dest_dir="$final_path"

pushd $final_path
# use custom home value to avoid bower storing values in root and have right errors
    TMP_HOME=$HOME
    HOME=$(pwd)
    ynh_use_nodejs
    ynh_npm install 
    HOME=$TMP_HOME
popd

chown -R $app:$app $final_path
chmod -R o-rwx $final_path

Pour finir, on s’occupe de l’intégration à YunoHost. On applique le template de Nginx et D-bus et on l’intègre au portail captif. C’est là qu’on est heureux d’avoir respecté les conventions pour les noms de variables, on a ainsi qu’à lister nos variables spécifiques à remplacer.

ynh_add_nginx_config 

yunohost service add $app --description="The news reader that doesn't know you" --log="/home/yunohost.app/${app}/storage/logs/petrolette.log"

ynh_add_systemd_config  --others_var="port ynh_node_load_PATH"

ynh_systemd_action --service_name=$app --action=start --log_path=systemd 

if [ $is_public -eq 1 ]
then
    # unprotected_uris allows SSO credentials to be passed anyway.
    ynh_permission_update --permission="main" --add="visitors"
fi

ynh_systemd_action --service_name=nginx --action=reload

Notre script est terminé. Les autres scripts suivent le même principe. On remarque que, dans notre cas, une grande partie de notre script est générique. On se dit donc qu’une bonne partie est encore automatisable mais toutes les applications ne sont pas aussi simples à installer et le projet s’améliore continuellement sur ce point.

Ajout au catalogue

Maintenant que notre paquet est fait, il serait bon qu’il apparaisse dans la liste de YunoHost. Pour cela, on lance une pull request sur le dépôt yunohost/apps avec les informations concernant notre application. On peut aussi demander à intégrer notre application à l’organisation YunoHost-Apps.

    "Petrolette": {
        "branch": "master",
        "revision": "HEAD",
        "url": "https://github.com/YunoHost-Apps/petrolette_ynh",
        "state": "working"
    }

L’intégration continue

Afin d’assurer une certaine qualité des applications, YunoHost a mis en place un système d’intégration continue. Celui-ci teste un certain nombre de scénarios : (installation, suppression, sauvegarde, restauration, installation dans un sous-dossier…) pour valider le bon fonctionnement de notre application. Cependant, certaines applications ne supportent pas tous les tests lancés par l’intégration continue. On écrit donc un fichier check_process qui spécifie quels tests doivent être effectués.

Voici notre liste de tests :

;; Test complet
    ; Checks
        pkg_linter=1
        setup_sub_dir=0
        setup_root=1
        setup_nourl=0
        setup_private=1
        setup_public=1
        upgrade=1
        backup_restore=1
        multi_instance=1
        port_already_use=0
        change_url=0

Une intégration continue de test est disponible et peut être lancée via un commentaire !testme dans une pull request. L’intégration continue de production est quant à elle automatiquement lancée et mise à jour le vendredi.

Aller plus loin

  • # C'est la gloire :)

    Posté par  (site Web personnel) . Évalué à 10 (+10/-0). Dernière modification le 18/04/21 à 11:34.

    Yo ; Super initiative, la perspective de voir figurer Pétrolette dans la liste des applis Yunohost me remplit d'une fierté roborative :) toutefois.

    Dans la partie "Installation de Pétrolette en local" trois points sur quatre méritent discussion, et aussi probablement un peu d'huile de coude :

    configurer le/les ports de l’application ;configurer le/les ports de l’application ;

    J'ai intégré ta pull request un peu vite (j'étais un peu fébrile, c'est ma premiere PR (qui passe les tests)) mais en fait il serait plus logique (que de définir des variables d'environnement) de configurer les ports dans le fichier de heu, conf ; c'est prèt/testé, c'est propre, c'est mieux.

    installer l’application sur un sous chemin du domaine ;

    Bon ça bien sur c'est même un minimum y compris en dehors de Yunohost, je m'en suis jamais occupé, merci.

    installer plusieurs instances de l’application sur la même machine ;

    C'est ici que les athéniens s'atteignent : Comme tu l'as vu, Pétrolette, entre autres parce que je ne voulais pas gérer une base utilisateurs, fonctionne sur un principe un peu spécial : chaque client (instance de navigateur) est un utilisateur de fait, et voit un contenu spécifique, sauvegardé (juste la liste des feeds, hein, du calme) dans le cache permanent dudit navigateur.

    Mais pour voir le même contenu sur une autre machine (typiquement son phone) cet utilisateur devra utiliser la fonction de synchro au cloud, nous y voilà.

    Donc déjà là, "installer plusieurs instances de l’application sur la même machine" devient un peu redondant (si on entend par "même machine" même instance de YNH, car bien sur si c'est un serveur avec plusieurs instances c'est HS) puisque tout les utilisateurs d'une instance peuvent se connecter au même Pétrolette et voir leur propre contenu.

    s’installer derrière l’authentification de YunoHost.

    Mêmes remarques ici, mais quelque part dans l'autre sens : Chaque utilisateur identifié a accès à un service multi-utilisateur : redondance, mais attend:

    Moi si je ne connais ni Pétrolette ni Yunohost et que je lis ton journal je vais me dire "OK donc j'installe YNH et j'ai accès à mon PTL à partir de toutes mes machines, mon phone tout ça, du moment que je suis logué dans mon YNH" or ce n'est pas tout à fait exact, dans la mesure où sur chaque machine, il faudra utiliser la synchro externe.

    Ce qui est un peu con, je vx dire Yunohost est un cloud, si j'ai bien compris.

    Donc. Plusieurs trucs sont possibles ; tout est possible bien sur, il faut juste qu'on soit à peu près d'accord sur ce qu'on veut obtenir :

    • Identification sur le Yunohost de la famille, puis http://monserveur.tld/actus/christelle, http://monserveur.tld/actus/papy, http://monserveur.tld/actus/mourad, etc. sans plus d'identification additionnelle (sans synchro donc, stockage des flux sur le serveur, dans /christelle, /mourad, etc.) là tout de suite c'est facile à faire, et ça reste compatible avec les autres usages du moment que c'est juste une option à l'install du serveur ;
    • Visite de n'importe quelle instance publique de Pétrolette dans le monde large toile et synchronisation avec mon serveur Yunohost (ma préférée, intuitivement, pour ça il faut causer aux gars de remoteStorage qui sont très sympa, et là ça profite pas juste à Pétrolette mais à tout le monde qui peut maintenant utiliser son instance YNH pour synchro n'importe quoi, je dis ça je dis rien) ;
    • D'autres implémentations / usages auxquels j'ai pas pensé ;
    • All of the above.

    Cette discussion a vocation à continuer dans les pages de suivi, enfin bref, ce long commentaire sert basiquement juste à dire que je suis très content que mon taf devienne une brique qui sert à construire d'autres choses, c'est grisant, merci.

    • [^] # Re: C'est la gloire :)

      Posté par  . Évalué à 6 (+4/-0).

      Le lien correct vers remoteStorage, sans préfixe linuxfr https://remotestoragejs.readthedocs.io/

      • [^] # Re: C'est la gloire :)

        Posté par  (site Web personnel) . Évalué à 4 (+2/-0). Dernière modification le 18/04/21 à 13:27.

        S'il prend à un modo de corriger (quel magnifique dimanche de printemps ensoleillé) j'ai oublié de neutraliser les URL bidons d'exemple et ça fait du bruit de fond Internet qui réveille les chatons, excuse le dérange merci :p

    • [^] # Re: C'est la gloire :)

      Posté par  . Évalué à 3 (+2/-0).

      Juste quelques précisions

      Donc déjà là, "installer plusieurs instances de l’application sur la même machine" devient un peu redondant

      J'avais effectivement compris que l'intérêt d'installer plusieurs instances de pétrolette sur le même yunohost est redondant. Mais l'idée derrière la dépêche est aussi de présenter comment fonctionne le packaging sous Yunohost et la possibilité d'installer plusieurs instances d'un logiciel à son intérêt dans d'autres cas.

      Ce qui est un peu con, je vx dire Yunohost est un cloud, si j'ai bien compris.

      Yunohost n'est pas à proprement parler un cloud à mon sens. C'est une distribution qui propose de faciliter l'hébergement mais un Yunohost fraichement installé ne propose "que" un serveur mail, un serveur xmpp, une interface d'administration et un portail captif préconfigurés. Ensuite, tu installes les applications que tu veux qui te permettent de proposer les services que tu veux.

      Moi si je ne connais ni Pétrolette ni Yunohost et que je lis ton journal je vais me dire "OK donc j'installe YNH et j'ai accès à mon PTL à partir de toutes mes machines, mon phone tout ça, du moment que je suis logué dans mon YNH" or ce n'est pas tout à fait exact, dans la mesure où sur chaque machine, il faudra utiliser la synchro externe.

      effectivement, ce n'était pas très clair.

      Identification sur le Yunohost de la famille, puis http://monserveur.tld/actus/christelle, http://monserveur.tld/actus/papy, http://monserveur.tld/actus/mourad, etc. sans plus d'identification additionnelle (sans synchro donc, stockage des flux sur le serveur, dans /christelle, /mourad, etc.) là tout de suite c'est facile à faire, et ça reste compatible avec les autres usages du moment que c'est juste une option à l'install du serveur ;

      Le paquet en l'état ne permet n'est pas explicitement liée à un utilisateur de Yunohost. L'idée de s'installer derrière Yunohost n'est pour l'instant que pour empecher l'accès publique de l'application. En revanche, l'idée de proposer un Pétrolette sur mon serveur avec ma propre sélection au grand public me parait intéressante.

      Visite de n'importe quelle instance publique de Pétrolette dans le monde large toile et synchronisation avec mon serveur Yunohost (ma préférée, intuitivement, pour ça il faut causer aux gars de remoteStorage qui sont très sympa, et là ça profite pas juste à Pétrolette mais à tout le monde qui peut maintenant utiliser son instance YNH pour synchro n'importe quoi, je dis ça je dis rien) ;

      L'implémentation du protocole remoteStorage n'est pas vraiment du ressort de Yunohost en lui-même à mon sens mais une application proposant cette fonctionnalité pourrait tout à fait être packagée (et grand utilisateur de lesspass, cette fonctionnalité m'intéresserais aussi).

  • # Quitter Github ?

    Posté par  . Évalué à 1 (+6/-6).

    notre paquet […] apparaisse dans la liste de YunoHost […] on lance une pull request sur le dépôt Github

    Yunohost est un fantastique projet libre de décentralisation et d'auto-hébergement. Mais paradoxalement, son utilisation impose de se soumettre à un GAFAM : Microsoft via Github.

    Est-il prévu un plan de migration vers une forge libre, loyale et éthique ? Quand ?

    Rappel de quelques conséquences de l'actuelle dépendance à Github :

    • traçage :

      • les utilisateurs sont tracés à chaque récupération de la liste des paquets ou à chaque installation d'un paquet,
      • aucune garantie ne peut être apportée par Yunohost quant à ce qu'il est fait des données collectées (exploitation, revente, transmission aux agences gouvernementales américaines, Patriot Act. Cloud Act., Prism…),
    • exclusion :

      • toute personne vivant dans un pays boycotté par le gouvernement américain, est empêchée de proposer ses contributions et ses paquets,
      • participation impossible des libristes ayant une éthique…
    • [^] # Re: Quitter Github ?

      Posté par  . Évalué à 2 (+2/-0).

      Bonjour,

      En fait, son utilisation n'impose pas l'utilisation de GitHub. Aujourd'hui, seule la contribution au core et l'ouverture d'issue nécessite de passer par GitHub.

      Oui un plan de migration a déjà été réfléchi, le projet attend juste qu'il existe des forges fédérées (au sens ActivityPub).

  • # Coquille?

    Posté par  . Évalué à 0 (+0/-0).

    Hello,
    c'est peut être une erreur temporaire chez yunohost mais le lien concernant les helpers (https://yunohost.org/en/packaging_apps_helpers) semble en vrac. Par contre celui là fonctionne: https://yunohost.org/fr/packaging_apps_helpers

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n’en sommes pas responsables.