Skip to main content
Des déploiements séparés sur un seul hôte — un par client, ou un par environnement. Ce n’est pas un cluster : ce sont des passerelles indépendantes avec leurs propres bases de données et leur propre trafic. Pour comprendre pourquoi plusieurs instances contre une seule base de données ne fonctionnent pas, voir Clustering.

Un nom, deux produits

--tenant est toute l’idée : le même mot nomme la même instance aux deux installateurs. Un nom par client, deux produits.

À la mise à jour, c’est une recherche, pas une disposition

C’est la partie qui évite l’erreur coûteuse.
Sur update, service et rollback, --tenant trouve l’installation portant ce nom et utilise ses propres chemins, unité, compte et ports.
Sans cela, une mise à niveau visée en oubliant un drapeau arrêterait une unité qui pourrait ne pas exister, remplacerait un répertoire appartenant à une autre instance, et activerait un second service contre la même base de données.Une unité dont le WorkingDirectory= nomme une installation différente est refusée, avant que quoi que ce soit ne soit arrêté.

Ports

Donnez une plage et l’installateur prend le prochain port d’écoute libre, de sorte que l’instance deux ne rentre pas en collision avec l’instance un. --http-port et --ops-port sont également définis par instance. Les deux installateurs relisent les ports depuis le fichier d’environnement sur update, de sorte qu’une instance sur des ports non par défaut cesse d’échouer sa propre vérification à la fin de chaque mise à niveau.

Un hôte virtuel

Place l’instance sous un dossier personnel par client : /home/websmsc/gateway, avec le panneau à /home/websmsc/panel. Ce que cela apporte : les deux unités générées montent un tmpfs sur /home et ne réintroduisent que ce seul hôte virtuel, de sorte qu’une passerelle ne peut voir aucun autre répertoire personnel client.
--user est requis ici, et c’est l’étape la plus facile à oublier. Un répertoire personnel est en 0750 et appartient à son propre compte, et l’installateur ne fera pas de chown sur un répertoire qui existe déjà — cette protection est délibérée, afin qu’une installation ne puisse jamais réécrire la propriété de tout ce qui se trouve déjà dans le dossier personnel de quelqu’un.Ainsi, un service tournant sous n’importe quel autre compte ne peut tout simplement pas traverser l’hôte virtuel. ProtectHome=tmpfs et BindPaths= rendent le répertoire visible à l’intérieur de l’espace de noms de l’unité ; aucun des deux ne modifie un bit de permission.Le symptôme ne nomme pas la cause : le panneau meurt à npm ci avec can't cd to /home/<nom>/panel/app, et la passerelle enregistre une unité qui ne peut ensuite pas lire sa propre configuration. Passez le compte propriétaire aux deux installateurs.
Sous --vhost, CDR_EXPORT_DIR du panneau doit également se trouver à l’intérieur d’une racine BindPaths=. Cet échec est silencieux — les exports sont préparés puis ne peuvent pas être lus.
--vhost seul, sans --tenant, signifie quelque chose de différent — ne l’utilisez pas pour un nouveau tenant. Cela conserve une ancienne disposition à plat, CHEMIN/{app,conf,data}, au lieu de CHEMIN/panel.Cette compatibilité existe pour que les panneaux installés sous /home/<nom> avant --tenant soient atteints exactement comme avant, et qu’une mise à niveau ne relocalise jamais une installation en cours d’exécution. Sur un nouveau tenant, cela place silencieusement la passerelle et le panneau dans des dispositions différentes — la passerelle sous /srv/fireflo/<nom>/gateway et le panneau libre dans /home/<nom> — après quoi update --tenant <nom> ne trouve plus le panneau. Passez les deux drapeaux ensemble.
Les trois drapeaux de répertoire — --app-dir, --conf-dir, --data-dir — l’emportent toujours sur l’un ou l’autre schéma partout où ils sont donnés.

Ce dont chaque instance a besoin en propre

Suppression d’un tenant

Il n’existe pas de verbe uninstall. Les deux installateurs offrent check, install, update, service et rollback — la suppression est manuelle, ce qui explique pourquoi il vaut mieux énumérer les unités que de les deviner.
Un tenant, c’est quatre unités systemd, pas deux. La passerelle en écrit trois : Le timer logclean est celui qui reste oublié derrière. Supprimez uniquement l’unité principale et il reste activé, se déclenchant chaque jour sur un répertoire de journaux qui n’existe plus. Regardez avant de supprimer — ceci ne change rien :
Ensuite les unités, toutes les quatre :
Ensuite les répertoires — selon la disposition qu’a utilisée ce tenant :
Loaded: not-found aux côtés de Active: failed est normal ici, ce n’est pas une anomalie. C’est la mémoire d’exécution de systemd d’une unité dont le fichier a disparu ; reset-failed la nettoie. De même, un code de sortie status=143 dans le journal, c’est 128 + SIGTERM — un arrêt propre, pas un plantage.

Ce que cela laisse délibérément intact

La base de données. Le routage d’un tenant, ses fournisseurs, ses ports d’écoute, ses identifiants, ses enregistrements d’appels et ses soldes y résident, pas dans le répertoire d’installation — c’est ce qui rend une réinstallation sûre, et ce qui fait de la suppression de la base de données une décision distincte :
Le compte de service, qui peut être partagé avec d’autres services ou être un véritable identifiant client. Supprimez-le à la main seulement une fois certain que rien d’autre ne l’utilise. Les règles de pare-feu, si l’installation a utilisé --firewall. Vérifiez sudo ufw status numbered pour la plage SMPP et le port HTTP de ce tenant.

Réinstaller plutôt que supprimer

Relocaliser une instance n’est pas un mv. fireflo.env enregistre ses propres chemins absolus, et seuls certains sont réécrits par des verbes ultérieurs — FIREFLO_CONF_DIR, FIREFLO_DATA_DIR et QUARKUS_LOG_FILE_PATH sont écrits par install uniquement. Une installation déplacée continue d’écrire ses enregistrements d’appels et ses journaux à l’ancien emplacement, tandis que le ReadWritePaths= de la nouvelle unité ne couvre que le nouveau. Supprimez et réinstallez à la place. La base de données survit, donc la nouvelle installation omet --bootstrap — celle-ci refuse de s’exécuter sur une base de données qui possède déjà une table de routage, un worker ou un identifiant.