Presearch : Faire fonctionner plusieurs nodes sur un VPS avec podman

Comme je le disais dans la présentation des nodes, chaque node "rapporte" pour environ 3€ / mois. Avec une telle somme il n'est absolument pas intéressant de faire fonctionner des nodes. Ou alors uniquement sur des VPS premiers prix voir "gratuit".

Maj au 14/03/23
Présentation
Solution technique
Installation de Debian
Installation de podman
Ajout d'une IP
Création d'un utilisateur
Lancer une node
Lancement / Maj auto
Options :
Configuration SSH
Mises à jour automatiques du système


Mise à jour au 14/03/23

Depuis l'écriture de ce tuto OVH a changé la tarification de ses IPFO.
Désormais il faut compter 1,5€ HT / mois et / IP.
Cela remet sérieusement en cause l'intérêt financier d'une telle solution pour ce projet.
Je laisse néanmoins le tuto en ligne pour ceux qui souhaiteraient malgré tout utiliser cette méthode.

De + au moment de l'écriture, pour activer une node il fallait stacker 1000 PRE. Aujourd'hui c'est 4000.


Présentation

Mais quand c'est gratuit c'est que vous êtes le produit. Et en tant qu'infogérant je ne soutiens absolument pas cette idée de faire fonctionner des serveurs gratuitement. Aussi mauvais soient ils. Pour ceux qui seraient intéressé il y a Ionos qui fait des VPS à 1€ / mois qui peuvent héberger sans problème une node. J'en ai un en test, ça fait le job.

Mais pour ma part je préfère travailler avec OVH. Oui beaucoup critiquent le SAV, qu'ils sont mauvais, etc... Perso je ne trouve pas. Leur gamme de VPS est particulièrement intéressante, le ratio puissance / prix / stabilité est très intéressant. Pour faire fonctionner nos nodes Presearch un VPS **value** est amplement suffisant. De plus ils sont l'un des rares hébergeur à proposer des IP supplémentaires sans coût mensuel. Et ça dans notre situation avec les nodes ça devient intéressant.

En effet, comme je le dis dans la page node, chaque node "rapporte" l'équivalent en PRE de 3€ / mois (attention ça peut varier). Par conséquent louer un VPS à 5€ HT / mois n'est vraiment pas intéressant. Toutefois là où ça devient intéressant c'est de faire fonctionner une dizaine de nodes sur un VPS. Et là en "gain" vous êtes autour d'une trentaine d'€ pour un coût de 5€ HT. Attention toutefois, lancer 10 nodes implique de "stacker" 10 000 PRE, ce qui équivaut selon les cours autour de 250€.

Attention, toutes les commandes données en exemple dans cet article sont à exécuter en tant que root. De base vous allez vous connecter avec l'utilisateur debian, pour passer root il faut simplement faire : sudo su


Solution technique

Pour mettre en place cette solution j'utilise Debian 11, toujours en testing mais freeze depuis quelques temps, et elle devrait passer stable dans peu de temps.

Côté container c'est podman que j'utilise, il sait rester à sa place, ne va pas s'amuser à jouer avec iptables quand je ne lui demande rien, ne s'amuse pas non plus à vouloir créer des réseaux virtuelles dont je n'ai pas besoin ! De plus podman permet d'exécuter des containers sans les droits root, et ça c'est vraiment le top. Ceci va permettre d'exécuter chaque node avec un utilisateur différent pour mieux les isoler.

Pour chaque node il va falloir commander et configurer une IP FailOver, c'est 2€ HT à la commande, puis 0 frais mensuel. C'est important dans notre scénario au vu de la faible "rentabilité" des nodes.

Côté parefeu j'utilise Firewalld avec NFTables en backend. Ce n'est pas indispensable, je ferai peut être un petit topo dessus si j'en ai le temps, mais ce n'est pas le coeur du sujet ici.


Installation Debian

Je ne vais pas faire de tuto sur comment passer sur une debian testing. Car de base OVH vous proposera d'installer une image Debian 10, il faudra ensuite, une fois connecté, faire un dist-upgrade vers une Debian 11.

Pour faire très court il faut modifier le fichier /etc/apt/sources.list pour remplacer buster par bullseye Après modification votre fichier devrait ressembler à ceci :

deb http://deb.debian.org/debian/ bullseye main contrib non-free
deb-src http://deb.debian.org/debian/ bullseye main contrib non-free
deb http://deb.debian.org/debian/ bullseye-updates main contrib non-free
deb-src http://deb.debian.org/debian/ bullseye-updates main contrib non-free
deb http://security.debian.org/debian-security bullseye-security main contrib non-free
deb-src http://security.debian.org/debian-security bullseye-security main contrib non-free

Une fois cela fait il faut mettre à jour les caches avec la commande :
apt-get update
Puis mettre à jour tout le système vers Debian 11 avec la commande :
apt-get dist-upgrade

Quand l'opération sera terminé il faudra redémarrer votre VPS pour démarrer sur le nouveau noyau :
shutdown -r now


Installation podman

Rien de bien complexe ici, si ce n'est 2/3 subtilités qu'il faut prendre en compte.
Tout d'abord la commande pour installer podman :
apt-get -y install podman

Une fois cela fait il nous faut une version plus récente de slirp4netns. Celle fournie par Debian n'est pas assez récente pour répondre à nos besoins.
Par conséquent première étape, désinstaller la version présente sur le système :
apt-get remove --purge slirp4netns

Puis il faut récupérer la dernière version dispo sur Github ici.

Pour la version actuelle (v1.1.11) la commande pour l'installation est la suivante :
cd /user/local/bin
curl -o slirp4netns --fail -L https://github.com/rootless-containers/slirp4netns/releases/download/v1.1.11/slirp4netns-$(uname -m)
chmod +x slirp4netns

Si tout s'est bien déroulé vous devriez désormais avoir la version 1.1.11 sur votre serveur, vous pouvez vérifier cela en faisant :
slirp4netns -v

Dernière étape, il faut ajouter les "repos" docker à podman pour pouvoir télécharger les images presearch.
Pour cela il faut éditer le fichier /etc/containers/registries.conf et ajouter à la fin du fichier :
[registries.search]
registries = ['docker.io']


Ajout d'une IP

Pour faire fonctionner une node il faut une adresse IPV4 publique par node. Par conséquent il va être nécessaire d'ajouter des "IP FailOver".
Vous pouvez commander ces IPs dans le menu "bare-metal cloud" > "commander" > "IP Supplémentaire".

Vous choisissez le service concerné :

Puis vous validez l'offre, le nombre d'IP, le pays (restez sur la même zone géographique que le VPS).

Vous allez au bout du process de commande, puis quelques minutes plus tard vous allez recevoir un mail avec les infos concernant votre nouvelle adresse IP. A partir de là il faut l'ajouter au VPS. Il existe différentes façon de faire cela.
Perso j'ai ma méthode que j'aime bien, libre à chacun de faire autrement.
On va créer un fichier : /etc/network/if-up.d/ipfo
Dedans on va y écrire :
#!/bin/sh
ip a add votreIP/32 dev eth0

Puis on rend ce fichier exécutable :
chmod +x /etc/network/if-up.d/ipfo

Ce fichier va être exécuté à chaque fois que le réseau sera "monté" (if up).
A ce moment, la commande ip a add votreIP/32 dev eth0 sera lancé.
Elle veut dire que l'on va ajouter l'adresse IP votreIP/32 à l'interface eth0

Quand vous allez ajouter d'autres adresse IP à votre serveur il suffira de rajouter une ligne à ce fichier avec votre nouvelle IP en respectant la syntaxe.

Mais en ajoutant l'IP dans ce fichier celle-ci ne sera réellement ajouté que lorsque l'interface réseau va être montée.
Pour que l'IP soit ajouté immédiatement on va simplement lancer la commande :
/etc/network/if-up.d/ipfo
A noter que si vous avez déjà IP additionnelles active vous aurez un message d'erreur, mais sans conséquence.
Vous pouvez également lancer uniquement la commande :
ip a add votreIP/32 dev eth0

On peut également créer le fichier jumeau, dans /etc/network/if-down.d/ipfo
Ici c'est le script qui sera exécuté lorsque l'interface réseau sera "désactivée". Dans la pratique cela ne sert pas à grand chose, mais si vous voulez faire les choses "proprement" voici le script :
#!/bin/sh
ip a del votreIP/32 dev eth0

Puis on rend ce fichier exécutable :
chmod +x /etc/network/if-down.d/ipfo

C'est exactement l'inverse du premier script, celui-ci va supprimer l'IP additionnelle sur le serveur. Il sera exécuté à l'arrêt du serveur ou à l'arrêt du réseau par exemple.


Création d'un utilisateur

Comme je l'ai dit plus haut, nous allons faire fonctionner chaque node avec un utilisateur différent. Cela permet de mieux isoler les containers.
Pour ma part je nomme mes comptes utilisateurs "nodea","nodeb","nodec", etc.
Par conséquent pour créer le premier utilisateur il faut faire la commande suivante :
adduser nodea

Etant donné que nous faisons tourner nos containers avec des utilisateurs aux droits restreints il est nécessaire de faire la commande suivante également :
loginctl enable-linger nodea

Cette commande est nécessaire car de base systemctl va "tuer" les process des utilisateurs quand ils se déconnectent, et on n'a pas vraiment envie de ça :)


Démarrer une node

Bon, après avoir fait tout ça, il serait temps de lancer une node !
Pour cela il faut se connecter en SSH avec votre utilisateur crée plus tôt. Dans notre exemple il se nomme nodea a adapter en fonction de ce que vous avez fait.
Pour démarrer "manuellement" une node j'utilise le script suivant que je lance dans un "screen".

Pour passer dans un "screen" je lance simplement la commande screen
Note, vous pouvez faire autrement, perso j'aime bien avoir mon service qui fonctionne ainsi...
Donc, vous voici dans un "screen", c'est une session "détachable", on en sort en faisant ctrl + a + d

Vous pouvez créer un fichier node-start.sh dans votre home par exemple. Ce script permet non seulement de lancer une node mais également de mettre à jour une node si nécessaire. Et voici ce que l'on va y mettre :
#!/bin/sh
podman stop presearch-$USER
podman rm presearch-$USER
podman image prune --all --force
podman pull presearch/node
podman run --name presearch-$USER --network=slirp4netns:outbound_addr="VotreIP" --restart=unless-stopped -v presearch-node-storage:/app/node -e REGISTRATION_CODE="votre registration code" presearch/node

Pour ceux qui ne voudraient pas utiliser screen, vous pouvez utiliser le script suivant pour que la node fonctionne en arrière plan :
#!/bin/sh
podman stop presearch-$USER
podman rm presearch-$USER
podman image prune --all --force
podman pull presearch/node
podman run -dt --name presearch-$USER --network=slirp4netns:outbound_addr="VotreIP" --restart=unless-stopped -v presearch-node-storage:/app/node -e REGISTRATION_CODE="votre registration code" presearch/node

La différence se situe au niveau du flag -dt

Petite explication pour chaque ligne :
podman stop : on arrête une éventuelle node en cours de fonctionnement.
podman rm : on supprime le container.
podman image prune --all --force : on supprime les images non utilisées pour libérer de l'espace disque. Attention, n'utilisez pas cela si vous êtes facturé à la bande passante utilisée !
podman pull : on récupère la dernière image à jour du container de la node sur le repos docker.
podman run : cette commande va lancer réellement la node.
--name : pour avoir le nom à donner localement. presearch-$USER donnera le nom presearch-nodea.
--network=slirp4netns:outbound_addr="VotreIP" : on "bind" le container sur l'IP "VotreIP". Pensez à remplacer "VotreIP" par l'adresse IP que vous aurez déclaré comme IP additionnelle.
-e REGISTRATION_CODE="votre registration code" : ici il faut préciser votre "registration code" que vous trouverez dans le dashboard presearch.

Je ne rentre pas dans le détail des autres flags, rien de bien passionnant.

On pense à rendre le script exécutable avec la commande :
chmod +x node-start.sh
Pour lancer le script il suffit de faire ./node-start.sh

Si vous avez lancé le premier script dans un screen il faudra sortir du screen avec ctrl + a + d.
Si vous avez lancé le deuxième script la node passera automatiquement en arrière plan.
Pour voir ce qui se passe vous pouvez faire podman logs -f presearch-nodea

A partir de là vous pouvez vous déconnecter de votre session, la node va continuer à fonctionner.
Vous pouvez répéter l'opération plusieurs fois pour lancer plusieurs nodes en même temps sur le même VPS.


Démarrage et mise à jour automatique

Maintenant que l'on a vu comment lancer une node ce serait tout de même pas mal que ça démarre en automatique en cas de restart du serveur ou tout simplement que les nodes se mettent à jour automatiquement quand c'est nécessaire.
Il est à noter qu'il est probablement possible de faire ça plus proprement que moi via systemd ou les commandes propre à Podman.
Vous pouvez voir pour systemd ici : podman-generate-systemd
Ou pour les maj auto des containers ici : podman-auto-update

De mon côté je vais utiliser un simple cron qui va lancer un script maison en PHP qui va vérifier si le container est bien lancé.
C'est tout simple, ça fonctionne bien, et ça fait le job. Libre à vous de faire autrement.

Vous pouvez trouver ce script ici : lien
A noter qu'il est très important d'installer php-cli pour que le script fonctionne. Pour cela il faut faire :
apt-get install php-cli

Je ne vais pas rentrer dans le détail du script, vous le mettez n'importe où sur votre système, tant que tous les utilisateurs peuvent le lire (et uniquement le lire, ça ne sert à rien qu'ils puissent écrire).
Perso il est dans /usr/share/presearch/, libre à vous de le mettre ailleurs.
Il faut le décompresser (forcément compressé en .tar.gz ça marche moins bien), et le modifier.
Seul le début doit être modifié.

$srvname = "srv01";
Cela va servir à nommer la node, si vous avez plusieurs serveurs donnez un nom simple, court, pour nommer le serveur. La node se nommera srvname-user.
$registration_code = "";
Là vous devez mettre votre "registration code" que vous pouvez trouver sur le dashboard Presearch.

if ($user == "nodea") { $ip = ""; }
Vous remplacez nodea par le nom d'utilisateur que vous avez crée.
Et à l'endroit $ip = "" vous mettez l'adresse IP que vous utilisez pour cette node.
Par exemple $ip = "1.1.1.1"

Une fois cela fait, avec pour chaque user le nom qui va bien et l'IP qui lui est associée vous pouvez créer la task cron.
Pour cela on va créer le fichier /etc/cron.d/check_nodes et y mettre ce qui suit :
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0,10,20,30,40,50 \* \* \* \* nodea /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
1,11,21,31,41,51 \* \* \* \* nodeb /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
2,12,22,32,42,52 \* \* \* \* nodec /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
4,14,24,34,44,54 \* \* \* \* nodee /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
3,13,23,33,43,53 \* \* \* \* noded /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
5,15,25,35,45,55 \* \* \* \* nodef /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
6,16,26,36,46,56 \* \* \* \* nodeg /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
7,17,27,37,47,57 \* \* \* \* nodeh /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
8,18,28,38,48,58 \* \* \* \* nodei /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1
9,19,29,39,49,59 \* \* \* \* nodej /usr/bin/php /usr/share/presearch/check_node.php > /dev/null 2>&1

Cela dit que chaque user (ici de nodea à nodej) va lancer la commande /usr/bin/php /usr/share/presearch/check_node.php

Cette commande c'est le fameux script, pensez à adapter le chemin si vous ne l'avez pas mis dans /usr/share/presearch/
Chaque user va vérifier si le container est bien démarré, si oui il ne fait rien, si non il supprime le container (pas le volume rassurez vous) et va télécharger la dernière version.
Ainsi au reboot du serveur les nodes vont être démarrées une à une, progressivement.
Si la gateway envoie une commande d'arrêt (car node trop ancienne par exemple) cela déclenchera une mise à jour de la node à la dernière version.

Et voilà, avec ça vous devriez avoir un bon uptime et une mise à jour auto de vos nodes.
Même si le serveur reboot pour une raison ou une autre (maj, plantage, ...) vos nodes seront bien redémarrées au reboot.


Configuration SSH

Il est vivement (mais vraiment vivement) recommandé de changer le n° de port de votre serveur SSH.
Pour cela il faut éditer le fichier /etc/ssh/sshd_config et trouver la ligne Port 22.
Vous mettez ce que vous voulez au dessus de 1024. Cela n'a pas d'importance. De toute façon le VPS n'hébergera pas d'autre service que les nodes.

Une fois la modification faite, vous pouvez redémarrer le service ssh avec la commande /etc/init.d/ssh restart. Oui je suis un vieux monsieur, on peut aussi utiliser systemctl restart ssh qui devrait faire le même job.

Quand vous en êtes là, la première chose à faire c'est d'essayer de vous reconnecter sur votre serveur en SSH sur le nouveau port à la place du 22. Ce serait c.n de se retrouver à la porte du VPS...


Mise à jour automatique système

Une autre chose extrêmement recommandée est la mise en place des mises à jour automatique du système.
Pour cela on va configurer UnattendedUpgrades

Je vais vous donner ici les 2/3 étapes minimales à faire, pour plus de détails n'hésitez pas à lire la doc citée juste au dessus.

On install le programme :
apt-get install unattended-upgrades apt-listchanges

Ensuite on édite le fichier /etc/apt/apt.conf.d/50unattended-upgrades

Ici pour ma part j'active les 2 lignes suivantes (supprimer les // en début de ligne) :
"origin=Debian,codename=${distro_codename}-updates";
"origin=Debian,codename=${distro_codename}-proposed-updates";

On va également rechercher la ligne mail :
Unattended-Upgrade::Mail "vote mail";
La aussi on supprime les **//** en début de ligne pour activer la fonction.

Attention, il est fort probable que vous ne receviez pas bcp de mails pour le moment, il faudra probablement configurer convenablement un serveur mail. A voir si je propose une explication rapide.

Dernier point on active les mises à jour auto avec la commande suivante :
dpkg-reconfigure -plow unattended-upgrades

Avec ceci votre système devrait être mis à jour automatiquement.