mirror of
https://github.com/deunix-educ/Fail2banMqttActionBanishment.git
synced 2026-08-24 03:11:58 +02:00
First commit
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
# Déploiement en production
|
||||
|
||||
Cette page détaille le déploiement d'un ensemble master + noeuds en
|
||||
production, au-delà du premier noeud isolé couvert par
|
||||
[Installation](installation.md).
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Trois façons d'utiliser ce projet, du plus simple au plus complet — la
|
||||
même installation de base (`sudo make install`) sert de socle aux trois :
|
||||
|
||||
- **Solo** : `sudo make install`, seul. Ce serveur détecte et bannit
|
||||
localement, sans rien centraliser ailleurs. Suffisant pour protéger un
|
||||
unique VPS. Le service de relais vers un master
|
||||
(`fail2ban-emitter-master-client`) tourne quand même, mais réessaie
|
||||
silencieusement en boucle tant qu'aucun master n'est configuré (aucune
|
||||
gêne, `Restart=on-failure`).
|
||||
- **Solo + master** : `sudo make install` **puis** `sudo make
|
||||
install-master`, sur le **même** serveur. Ce VPS protège ses propres
|
||||
services (comme en mode solo) et sert en plus de master, prêt à
|
||||
accueillir d'autres noeuds plus tard — utile pour démarrer seul
|
||||
aujourd'hui sans fermer la porte à un second serveur demain.
|
||||
- **Master + noeuds** (plusieurs VPS) : un serveur en mode solo+master,
|
||||
et un ou plusieurs autres serveurs, chacun installé en solo puis
|
||||
rattaché à ce master via l'auto-inscription par jeton (ci-dessous). Le
|
||||
master lui-même reste un noeud comme les autres (il détecte et bannit
|
||||
localement en plus de centraliser la décision) — passer de "solo+master
|
||||
tout seul" à "master + noeuds" ne demande donc aucune réinstallation du
|
||||
master, seulement d'y ajouter des noeuds au fur et à mesure.
|
||||
|
||||
Ordre recommandé pour passer à plusieurs noeuds :
|
||||
|
||||
1. Déployer le master (une seule fois — solo+master si ce même serveur
|
||||
doit aussi se protéger lui-même, ce qui est le cas courant).
|
||||
2. Sur le master, émettre un jeton pour chaque nouveau noeud.
|
||||
3. Sur chaque nouveau noeud, s'auto-inscrire avec ce jeton.
|
||||
|
||||
## Déployer le master
|
||||
|
||||
```sh
|
||||
sudo make install-master
|
||||
```
|
||||
|
||||
Nécessite un premier `sudo make install` déjà effectué sur cette même
|
||||
machine. Provisionne :
|
||||
|
||||
- une **CA privée** dédiée (`scripts/master-ca-init.sh`), distincte du
|
||||
certificat Let's Encrypt qui sert l'identité TLS du broker — elle ne
|
||||
sert qu'à signer les certificats clients des noeuds (authentification
|
||||
mTLS) ;
|
||||
- le listener Mosquitto public (port 8883, TLS, `MQTT_MASTER_DOMAIN` dans
|
||||
`.env`) avec ACL par noeud ;
|
||||
- l'ingestion côté master (`fail2ban-emitter-master-listen`, tourne avec
|
||||
sa propre identité mTLS `master-internal`, générée automatiquement).
|
||||
|
||||
`MQTT_MASTER_DOMAIN` doit pointer vers un domaine public réel (DNS déjà en
|
||||
place) — le broker obtient son certificat Let's Encrypt à ce nom.
|
||||
|
||||
## Auto-inscription d'un noeud (recommandé)
|
||||
|
||||
### Le problème
|
||||
|
||||
Ajouter un noeud à la main demanderait de générer une clé + un certificat
|
||||
sur le master, puis de copier ces fichiers vers le nouveau noeud (`scp`),
|
||||
de les renommer correctement, et d'éditer son `.env` — plusieurs étapes
|
||||
manuelles, cross-machine, et la clé privée transiterait par le réseau
|
||||
(jamais une bonne pratique).
|
||||
|
||||
### Le modèle
|
||||
|
||||
Le master émet un **jeton à usage unique**, à courte durée de vie (1h par
|
||||
défaut). Le nouveau noeud utilise ce jeton pour s'inscrire lui-même :
|
||||
|
||||
- Le noeud génère sa **propre clé privée localement** et ne l'envoie
|
||||
jamais — seule une CSR (demande de signature) part vers le master.
|
||||
- Le jeton n'est jamais stocké en clair côté master : seul son hash
|
||||
SHA-256 est persisté (même logique qu'un hachage de mot de passe).
|
||||
- Le jeton est **marqué utilisé de façon atomique** dès sa validation, et
|
||||
**rendu automatiquement** si une étape suivante échoue (CSR
|
||||
incohérente, échec de signature) — un accroc transitoire ne force pas
|
||||
à réémettre un jeton entièrement nouveau.
|
||||
- Le CN de la CSR reçue doit correspondre au nom de noeud déclaré au
|
||||
moment de l'émission du jeton — un jeton volé ne permet pas de réclamer
|
||||
un autre nom.
|
||||
- Toute erreur renvoyée au client est **volontairement générique**
|
||||
("jeton invalide ou expiré"), quelle que soit la cause réelle — le
|
||||
détail (jeton inconnu, expiré, déjà utilisé, CN incohérent, échec de
|
||||
signature) part uniquement dans les journaux du master, pour ne donner
|
||||
aucun indice à un tiers qui sonderait l'endpoint.
|
||||
- Le transport est le tableau de bord HTTPS du master (déjà exposé
|
||||
publiquement, nginx + Let's Encrypt) : aucun nouveau port ni service à
|
||||
ouvrir, et ça résout le problème d'oeuf-et-poule (un noeud ne peut pas
|
||||
utiliser mTLS MQTT pour obtenir... son premier certificat mTLS).
|
||||
|
||||
### Étape par étape
|
||||
|
||||
Sur le **master** :
|
||||
|
||||
```sh
|
||||
make join-token NODE=nom-du-noeud
|
||||
```
|
||||
|
||||
Affiche le jeton en clair **une seule fois**, avec la commande complète à
|
||||
lancer sur le nouveau noeud (jeton perdu : simplement en émettre un
|
||||
nouveau, celui-ci reste valide indépendamment jusqu'à expiration).
|
||||
|
||||
Sur le **nouveau noeud** (déjà passé par `sudo make install` au
|
||||
préalable) :
|
||||
|
||||
```sh
|
||||
sudo make join MASTER=https://<domaine-du-master> NODE=nom-du-noeud TOKEN=<jeton>
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Le second `make install` applique la configuration reçue
|
||||
(`MQTT_MASTER_NODE_NAME` dans `.env`, certificat en place) et redémarre
|
||||
les services.
|
||||
|
||||
### Ce qui se passe en coulisse
|
||||
|
||||
```
|
||||
[nouveau noeud] [master]
|
||||
génère clé + CSR (locale, jamais transmise)
|
||||
POST /api/join/ {node_name, token, csr} ──►
|
||||
vérifie le jeton (hash, expiration, usage unique)
|
||||
vérifie le CN de la CSR == node_name
|
||||
signe la CSR via la CA privée
|
||||
ajoute l'entitlement ACL pour ce noeud
|
||||
redémarre mosquitto
|
||||
{cert, ca_cert} ◄────
|
||||
écrit cert/ca_cert, met à jour .env
|
||||
```
|
||||
|
||||
### Dépannage
|
||||
|
||||
- **"Jeton invalide ou expiré"** — le message est volontairement
|
||||
générique. Causes possibles : jeton déjà utilisé (relancer
|
||||
`make join-token` pour en émettre un nouveau), jeton expiré (durée par
|
||||
défaut 1h, ajustable via `make join-token NODE=... TTL=<minutes>`), ou
|
||||
faute de frappe dans le nom de noeud (doit être identique entre
|
||||
l'émission du jeton et `make join`).
|
||||
- Le nouveau noeud doit pouvoir joindre le master en HTTPS (443) — un
|
||||
pare-feu qui bloquerait la sortie empêcherait l'auto-inscription.
|
||||
|
||||
## Bases de données
|
||||
|
||||
SQLite est le défaut, sans rien à configurer. Deux alternatives :
|
||||
|
||||
```sh
|
||||
sudo make install-mariadb # provisionne un serveur MariaDB local + base/utilisateur dédiés
|
||||
sudo make install # à relancer ensuite pour appliquer les migrations sur la nouvelle base
|
||||
```
|
||||
|
||||
PostgreSQL est supporté côté configuration (`DB_ENGINE=postgresql` dans
|
||||
`.env`, driver `emitter/requirements-postgresql.txt`) mais sans
|
||||
sous-commande de provisionnement automatique pour l'instant — serveur et
|
||||
base à créer manuellement avant de basculer `DB_ENGINE`.
|
||||
|
||||
Portage d'une base vers une autre (dump indépendant du moteur, via
|
||||
`manage.py dumpdata`/`loaddata`) :
|
||||
|
||||
```sh
|
||||
make dump-db # écrit emitter/db-dump-<date>.json (exclu de git, contient des données réelles)
|
||||
# ... bascule DB_ENGINE, migrate ...
|
||||
emitter/.venv/bin/python emitter/manage.py loaddata <fichier>.json
|
||||
```
|
||||
|
||||
## Reverse proxy nginx + TLS public
|
||||
|
||||
```sh
|
||||
sudo make install-nginx # lit DASHBOARD_DOMAIN dans .env
|
||||
```
|
||||
|
||||
Obtient un certificat Let's Encrypt et déploie un vhost nginx devant le
|
||||
tableau de bord (WebSocket inclus) — nécessaire pour un accès public ;
|
||||
sans ça, le tableau de bord n'est accessible qu'en local/VPN.
|
||||
|
||||
## Alternative à systemd : supervisor
|
||||
|
||||
```sh
|
||||
sudo make install-supervisor # bascule les 4 services de l'émetteur vers supervisor
|
||||
sudo make uninstall-supervisor # retour arrière (réactive systemd)
|
||||
```
|
||||
|
||||
## Mise à jour
|
||||
|
||||
```sh
|
||||
git pull
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Réapplique dépendances/migrations et redémarre les services concernés,
|
||||
sur n'importe quel noeud (y compris le master).
|
||||
Reference in New Issue
Block a user