ubus est le microbus système développé par OpenWRT. u étant la version ASCII de µ.
Pourquoi yet another bus?
OpenWRT
OpenWRT est une distribution Linux ciblant l’embarqué : des appareils avec peu de mémoire, un stockage lent et maigrichon, et un processeur minimaliste. L’appareil fera peu de chose, mais bien, sans bouffer des gigawatts.
OpenWRT est conçu sur la notion de contrainte, faisant passer Alpine pour une distrib de débauché.
OpenWRT est surtout connu pour son utilisation dans les routeurs wifi, il est même possible d’en acheter avec directement un openWRT dessus, sans avoir besoin de le flasher.
Composabilité
OpenWRT s’appuie sur la philosophie UNIX : un ensemble de services qui ne font qu’une seul chose, mais correctement. Cette approche théorique est élégante dans un shell, où, avec quelques commandes et autant de pipes, on obtient à peu prés ce que l’on veut. Cette composabilité favorise l’émergence de logiciels largement utilisé pour mériter des audits et des CVEs, et suffisamment de contributions pour avoir des corrections et des évolutions (en théorie).
Les services en ligne perdent les atouts du shell et de sa composabilité. Le shell ne prévoit rien pour la notion d’événement de plus, dans ce glorieux passé, à part des cliques sur un clavier, un reboot de la machine, il ne se passait pas grand chose. Non, le cron n’est pas une réponse acceptable, et encore moins l’immonde polling.
Pour que des services puissent discuter entre eux, il faut passer par un bus. UNIX fournit gentiment des sockets UNIX et même des files d’attentes (le très peu connu /dev/mqueue
), mais ces outils ont été conçu à l’ère des processeurs mono-coeurs, et fournissent que des IPC (communications inter processus) pas de la gestion d’événements.
UI centralisé
OpenWRT est entièrement configurable en ligne de commande via un accés SSH, mais sa vraie force est de proposer une interface web, maintenant écrite en lua : LuCI. LuCI a permis de tirer une (petite) dépendance dans cet univers de minimalisme : Lua, la pépite du “code as config”.
D-bus
Le besoin de coordination et d’évenement a très vite était ressenti pour les desktops (le fameux “est-ce que Linux est raidi pour le dekstop?”). Mais KDE, le premier bureau pas tout moche, avait un soucis de licence (avec la licence de Qt, soyons précis), ce qui a conduit l’apparition de Gnome (basé sur gtk, concurrent de Qt, crée pour Gimp), les deux se sont tirés la bourre, et ont fait le maximum de choix différents, pour, euh pourquoi? pour se différencier. Chacun a bien sur choisi un bus différent.
Freedesktop a été crée pour arrêter le massacre, et établir consensus puis des normes. Freedesktop a fournit D-bus, débuté en 2002, avec une API stable en 2006. Fortement inspiré de DCOP, d-bus a rapidement été intégré dans KDE, Gnome a un peu plus trainé la patte. Mais c’esst de l’histoire ancienne, d-bus va maintenant au delà du desktop et gère maintenant le réseau avec NetworkManager le bluetooth avec bluez, mais surtout le boot avec systemd.
Systemd qui tire d-bus a fait hurler sur le coup, mais la concurrence était tellement inférieur et une norme contestable (mais utilisé) pour une couche basse a tellement plus de valeur que de vaines divergences.
D-bus a gagné la guerre du bus desktop, mais n’a jamais trop pris sur les serveurs, même si il reste un prérequis système.
Les applications métiers se concentrent sur les couches au dessus, avec des services maintenant distribués, utilisant soit de la découverte/configuration (zookeeper, etcd, consul) soit du gros bus avec maintenant de la persistance/reprises d’événement (Kafka, nats, Redis STREAM…).
Trop gros, trop complexe, D-bus n’a aucun intérêt pour des applications cotés serveurs.
Les bus prévus pour les applications distribués sont tout aussi sur-dimensionnés pour de l’embarqué.
Ubus
OpenWRT fonctionne sur des petits Linux, bien incapable de gérer D-bus.
Ubus (µbus ?) est un logiciel embarqué, cousu main en C, premier commit en 2010, avec une chaine de dépendance minimaliste, utilisant les libs maison pour mutualiser des fonctions pour grapiller de la place. On parle de libs qui se pèsent en kilo.
Pas de README (la doc, c’est pour les faibles), une arborescence plate, cmake
et un compilateur C sont les seul prérequis pour compiler.
Ubus s’appuie sur ubox, la bibliothèque fourre-tout de openwrt, et json-c via un wrapper maison.
Pour ne pas se laisser distraire par des fonctionnalités exotiques, qui mettrait en péril le minimalisme du projet, mais sans pour autant bloquer les évolutions, lua est bindé à l’application.
Une architecture classique et de bon gout : core en C minimaliste, modules en lua.
Le principal usage de lua est un module http, qui expose ubus en REST avec l’incontournable JSON, qui permet de lui causer avec curl
et même d’exposer ubus au reste du monde (dans le LAN, hein, foufou, mais pas trop), avec de l’authentification et des ACLs.
Le module http pour ubus est bien sur prévu pour s’intégrer à LuCI, l’UI web d’OpenWRT.
Pour parler le ubus (à ubusd
, donc), il n’y a que 3 possibilités :
- l’outil en ligne de commande :
ubus
- la lib officielle, le protocole n’est pas spécifié, il existe juste une implémentation
- l’API REST, avec le classique
curl
ou whatever qui cause HTTP/1.1 et JSON
Ubus est très lié à l’écosystème d’OpenWRT, les sources ne compilent pas sur une simple Debian (et encore moins sur un Mac). OpenWRT cible une multitude d’architectures exotiques, et pour ça utilise une chaine de compilation (cross compilation, en l’occurence), disponible via Docker, par ce qu’on est quand même en 2023 : openwrt/docker.
Une image “bac à sable” est fourni, pour avoir un shell dans un environnement OpenWRT, mais sans les services lancés (pas de ubusd
, donc), l’idée est de pouvoir simplement tester un paquet.
Le plus simple pour jeter un oeil reste de passer par un Vagrant avec vagran-openwrt-box.
Le bus roi
Pour pouvoir composer une application à base de services, le plus simple est de passer par un bus métier.
Un peu fatigué par les zélotes de Kafka (ou pire, des services spécifiques des gros du Cloud), ubus apporte une touche de fraicheur, avec une approche petit boutiste, bien loin des orgies grand boutiennes.
OpenWRT, Linux comme avant
Utiliser OpenWRT donne l’impression de voyager dans le passé, d’effleurer l’age d’or d’UNIX, avec son C omniprésent et des contraintes matériels énormes.
OpenWRT est minimaliste et traditionaliste, sans pour autant être complaisant et réactionnaire (chose assez facile à trouver dans le monde des firewalls) : il utilise un kernel récent (un 5.10), ne démarre pas les services depuis un dossier rempli de shell (il utilise son procd), utilise les possibilités d’isolations qui font la joie de Docker (namespace, capabilities, cgroup2, seccomp, bpf…).
Minimaliste, mais contemporain.
Aller plus loin
Il existe des boitiers avec OpenWRT installé dessus, coutant quelques dizaines d’euros, pour pouvoir jouer et profiter tout de suite de l’écosystème d’OpenWRT.
Si vous aimez l’absurde et les jeux de mots bancals sur père Ubu allez jeter un oeil l’étonnante adaptation filmé par Jean Christophe Averty.