Sélectionner une page
Comparer 4 modèles LLM en local : le crash test en français

Comparer 4 modèles LLM en local : le crash test en français

Ollama et Open web UI installés, modèles téléchargés – reste à savoir lequel utiliser au quotidien. Un prompt unique soumis aux 4 modèles permet de les départager rapidement sur ce qui compte : logique, maîtrise du français, et comportement de la machine.


La configuration de test

  • Mini PC sous Ubuntu, processeur Intel i5, 16 Go de RAM
  • Inférence CPU uniquement – pas de GPU dédié
  • 4 modèles testés via Open WebUI connecté à Ollama. Voir le processus d’installation dans l’article Installer Ollama et Open WebUI sur Ubuntu avec Docker.

Les 4 modèles et leurs caractéristiques :

ModèleTailleProfil
qwen2.5:3b~2,2 Go RAMPetit modèle, développé par Alibaba
gemma2:2b~1,6 Go RAMTrès compact, développé par Google
llama3.1 (8B)~4,7 Go RAMModèle de référence de Meta
mistral (7B)~4,1 Go RAMDéveloppé en France par Mistral AI

Le protocole : un seul prompt, quatre critères

Le même prompt a été soumis à chacun des 4 modèles, sans modification :

« Résous ce problème de logique étape par étape : Trois personnes (Alice, Bob et Charlie) ont chacune une couleur de pull différente (Bleu, Rouge, Vert). Alice dit qu’elle ne porte pas de bleu. Charlie porte un pull vert. Quelle est la couleur du pull de Bob ? Ensuite, traduis cette expression anglaise de manière naturelle en français : ‘It is raining cats and dogs’. Enfin, écris une seule phrase poétique sur la pluie. »

Ce prompt évalue quatre critères en une seule passe :

  • Logique : résoudre l’énigme par déduction (solution attendue : Bob = Bleu)
  • Traduction idiomatique : éviter la traduction littérale, trouver l’équivalent naturel en français
  • Créativité : qualité et fluidité de la phrase poétique
  • Comportement machine : vitesse d’affichage, charge CPU et RAM observées via htop

Conditions du test : avant chaque modèle, vérification qu’aucun autre modèle n’est chargé en RAM (sudo docker exec ollama ollama ps), et arrêt forcé si nécessaire (sudo docker exec ollama ollama stop <nom_du_modele>). Le chronométrage est fait à la main, du moment où le prompt est envoyé jusqu’à la fin de l’affichage de la réponse. Les modèles sont testés du plus léger au plus lourd.


Résultats modèle par modèle

qwen2.5:3b – L’outsider agile

Durée : 44 secondes

Logique : correct. Raisonnement concis, conclusion juste (Bob = Bleu).

Traduction : correct mais en retrait. Il propose « Il pleut très fort » – ce qui est juste, mais banal. Lors d’une session précédente avec ce même modèle, il avait spontanément proposé quatre variantes idiomatiques (« Il pleut à torrents », « Il pleut à verse », « Il pleut comme jamais ») – une performance nettement meilleure. C’est un rappel utile : les LLM ne sont pas déterministes, la même question peut produire des réponses différentes d’une session à l’autre.

Poésie : correct, avec une image intéressante. « L’onde silencieuse des gouttes, qui chuchotent à travers le ciel. »

Machine : très bon comportement. Affichage quasi instantané, charge CPU modérée, RAM peu sollicitée. La machine reste disponible pendant et après le test.


gemma2:2b – Le petit modèle décevant

Durée : 30 secondes

Logique : faux. Il identifie correctement que Charlie porte le vert et qu’Alice ne porte pas le bleu, mais ne parvient pas à conclure correctement – il introduit même une couleur inexistante dans l’énoncé. C’est la limite des modèles à 2 milliards de paramètres : la surface cognitive est insuffisante pour enchaîner plusieurs étapes de déduction avec une négation.

Traduction : échec. Il traduit « It is raining cats and dogs » par « Il pleut des chats et des chiens » – traduction littérale, qui perd tout le sens de l’expression.

Poésie : il répond en anglais (« The sky weeps a soft, silver song »), ignorant la consigne en français.

Machine : comportement moyen. Plus lent que qwen2.5:3b malgré sa taille inférieure – l’architecture de Gemma est plus gourmande en ressources CPU relativement à sa taille.


llama3.1 (8B) – Le raisonneur qui déraille

Durée : 2 minutes 17 secondes

Logique : faux. Le modèle développe un raisonnement structuré en plusieurs étapes, mais arrive à une conclusion erronée : il annonce Bob = Rouge, alors que la bonne réponse est Bob = Bleu. C’est d’autant plus surprenant que le raisonnement intermédiaire est correct – il identifie bien que Charlie = Vert et qu’Alice ne porte pas de bleu – mais la conclusion finale ne suit pas.

Traduction : parfait. « Il pleut des cordes » – sans hésitation, avec en complément « il pleut à verse ».

Poésie : correct. « La pluie tombant avec insistance et régularité est comme une promesse de renouveau. »

Machine : lourd. Affichage lent, charge CPU élevée sur les 8 coeurs, RAM fortement sollicitée. La machine reste saturée après le test et nécessite un arrêt forcé du modèle via sudo docker restart ollama pour revenir à la normale.


mistral (7B) – Les pieds dans le tapis

Durée : 1 minute 39 secondes

Logique : raisonnement contradictoire. Mistral part d’une bonne intuition mais son développement est incohérent : il affirme qu’Alice ne peut pas porter le vert alors que l’énoncé ne dit rien de tel, et conclut finalement Bob = Bleu – la bonne réponse – mais pour de mauvaises raisons. Un résultat juste obtenu par un chemin faux.

Traduction : mauvais, à deux titres. D’abord il donne la traduction littérale « Il pleut des chats et des chiens », puis tente de se rattraper en expliquant que « cela pleut beaucoup ». Cette formulation « cela pleut » est un calque direct de l’anglais « it’s raining » – un francophone écrit « il pleut », jamais « cela pleut ». Pour un modèle développé en France et réputé pour son français, c’est une déception.

Poésie : faute de grammaire. Mistral écrit « Les gouttes de pluie sont les diamants que tombent du ciel » – il aurait fallu écrire « qui tombent ». C’est la surprise du test : un modèle développé en France commet une erreur de syntaxe élémentaire sur sa langue maternelle. Cela illustre l’effet de la quantification – la compression du modèle pour réduire sa taille peut dégrader certaines compétences linguistiques, même sur la langue d’origine.

Machine : critique. Avec Home Assistant et les autres containers actifs en parallèle, la machine a atteint la limite de sa RAM physique et a commencé à utiliser le swap (espace disque utilisé comme mémoire de secours). Un arrêt forcé du container Ollama est nécessaire pour revenir à la normale.


Tableau récapitulatif

Critèreqwen2.5:3bgemma2:2bllama3.1 (8B)mistral (7B)
LogiqueCorrectFauxFauxRésultat juste, raisonnement faux
TraductionCorrectÉchecParfaitMauvais
PoésieCorrectHors consigneCorrectFaute de syntaxe
Durée45 sec31 sec2 min 171 min 39
Impact machineLégerMoyenLourdCritique

Ce que ce test apprend sur les LLM locaux

La taille ne fait pas tout. qwen2.5:3b (3 milliards de paramètres) surpasse gemma2:2b (2 milliards) sur tous les critères linguistiques, y compris la traduction en français, alors qu’il est plus grand. L’architecture et les données d’entraînement comptent autant que le nombre de paramètres.

Les LLM ne sont pas déterministes. Le même modèle, le même prompt, des résultats différents d’une session à l’autre. qwen a produit quatre variantes idiomatiques lors d’un premier passage, et une réponse banale lors du second. C’est une caractéristique fondamentale des LLM, pas un bug.

Les grands modèles ont un coût réel sur CPU. Llama 3.1 et Mistral sont utilisables, mais pas sur une machine déjà chargée par d’autres services. Sur un PC dédié uniquement à Ollama, le résultat serait différent.


Recommandation pour ma configuration

Au quotidien : qwen2.5:3b. Rapide, léger, correct en français, il ne sollicite pas la machine. C’est le modèle à utiliser en priorité sur une machine qui fait tourner d’autres services en parallèle.

Pour les tâches complexes : llama3.1 si la machine est disponible et si tu peux attendre – mais en gardant à l’esprit que ses performances en logique se sont révélées décevantes dans ce test.

À désinstaller : gemma2:2b. Ses performances en logique et en français sont insuffisantes, et il n’offre aucun avantage sur qwen2.5:3b.

À utiliser avec précaution : mistral. Son impact sur la RAM est trop important pour une machine partagée, et ses performances en français sont inférieures à ce qu’on pourrait attendre d’un modèle développé en France.

Nota

Ces modèles ne lisent pas les fichiers. Les 4 modèles testés sont des modèles texte uniquement. Envoyer un PDF ou une image depuis Open WebUI produit une erreur – le modèle ne sait pas traiter ce type d’entrée. Deux pistes pour y remédier : le RAG (Retrieval-Augmented Generation), qui permet d’interroger des documents en extrayant leur texte en amont, et les modèles multimodaux, capables de traiter des images directement. Ces deux sujets feront l’objet d’articles séparés.

Installer Ollama et Open WebUI sur Ubuntu avec Docker

Installer Ollama et Open WebUI sur Ubuntu avec Docker

Tu veux faire tourner un modèle d’IA en local, sans envoyer tes données sur un serveur externe ? Ollama gère les modèles, Open WebUI fournit l’interface – les deux s’installent en quelques minutes via Portainer.


Prérequis

Vérifie les ports occupés avant de commencer :

sudo docker ps --format "table {{.Names}}\t{{.Ports}}"

Cette méthode fonctionne sur n’importe quel Ubuntu avec Docker et Portainer, que tu aies ou non d’autres containers en place. C’est pour faire fonctionner des modèles de langage qu’il peut être essentiel de réaliser cette installation sur un ordinateur un peu rapide, et pas trop occupé par d’autres activités. Les LLM consomment de l’espace disque pour leur stockage local (quelques giga octets par modèle) et de la mémoire vive lorsqu’ils sont utilisés (un ordinateur avec 8 Go de RAM minimum est recommandé, 16 Go si tu veux tester des modèles plus puissants).


Ce qu’on installe

Ollama est le moteur qui télécharge et fait tourner les modèles de langage (LLM). Il expose une API locale sur le port 11434. Il fonctionne en ligne de commande. Il ne stocke aucun historique de tes conversations.

Open WebUI est l’interface web qui se connecte à Ollama. Tu y accèdes depuis n’importe quel navigateur sur le même réseau local – PC Windows, tablette, Android. Open WebUI permet de disposer d’une interface de type « chat », pour « discuter » avec le LLM. Et Open WebUI assure le stockage de l’historique des conversations.

Les deux tournent en containers Docker séparés, avec leurs données dans /home/USER/docker/ pour être couverts par la sauvegarde automatique rclone (voir l’article sur la sauvegarde des containers).


Étape 1 – Installer Ollama

Créer le répertoire de config

bash

mkdir -p /home/USER/docker/ollama/config

Ce répertoire accueille tes fichiers de configuration personnalisés (Modelfiles). Les modèles eux-mêmes, qui peuvent peser plusieurs gigaoctets, sont stockés dans un volume Docker interne – ils ne sont pas sauvegardés, et se retéléchargent facilement si besoin.

Déployer la stack dans Portainer

Dans Portainer : Stacks > Add stack, donne le nom ollama, puis colle ce contenu dans le Web editor :

version: '3.8'
services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    restart: unless-stopped
    ports:
      - "11434:11434"
    volumes:
      - ollama_models:/root/.ollama/models
      - /home/USER/docker/ollama/config:/root/.ollama/config
    environment:
      - TZ=Europe/Paris

volumes:
  ollama_models:

Remplace USER par ton nom d’utilisateur Linux, puis clique sur Deploy the stack.

Vérifier

sudo docker ps --format "table {{.Names}}\t{{.Ports}}"

Le container ollama doit apparaître avec le port 11434 comme ici :


Étape 2 – Installer Open WebUI

Créer le répertoire de données

mkdir -p /home/USER/docker/open-webui/data

Déployer la stack dans Portainer

Dans Portainer : Stacks > Add stack, donne le nom open-webui, puis colle ce contenu :

version: '3.8'
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui
    restart: unless-stopped
    ports:
      - "3000:8080"
    volumes:
      - /home/USER/docker/open-webui/data:/app/backend/data
    environment:
      - TZ=Europe/Paris
      - OLLAMA_BASE_URL=http://ollama:11434
    extra_hosts:
      - "host.docker.internal:host-gateway"
    networks:
      - ollama_default

networks:
  ollama_default:
    external: true

Remplace USER par ton nom d’utilisateur Linux, puis clique sur Deploy the stack.

Le réseau ollama_default est créé automatiquement par la première stack. Open WebUI s’y connecte pour joindre Ollama directement, sans passer par l’IP de la machine. C’est pour cette raison que les deux stacks doivent être déployées dans cet ordre.

Vérifier l’accès

Depuis n’importe quel navigateur sur ton réseau local :

http://IP_DU_PC_LINUX:3000

Tu dois voir l’interface Open WebUI. Le premier compte créé devient automatiquement administrateur – choisis un mot de passe solide.


Étape 3 – Télécharger un premier modèle

Dans Open WebUI, va dans Panneau d’administration > Réglages > Modèles, puis utilise l’option de téléchargement depuis Ollama pour récupérer un modèle.

Pour commencer, qwen2.5:3b est un bon choix : léger (environ 2,2 Go), rapide sur CPU, et d’excellente qualité en français.

Une fois téléchargé, ouvre une nouvelle conversation, sélectionne le modèle dans le menu déroulant en haut, et teste.


Ce qui est sauvegardé

ÉlémentEmplacementSauvegardé
Config et Modelfiles Ollama/home/USER/docker/ollama/config/Oui (rclone)
Données Open WebUI (historique, comptes)/home/USER/docker/open-webui/data/Oui (rclone)
Modèles LLMVolume Docker interneNon – à retélécharger

Les sauvegardes sont faites par rclone si vous avez fait la configuration indiquée plus haut (« ce qu’on installe »)


Pour aller plus loin

L’article suivant, Comparer 4 modèles LLM en local : le crash test en français, compare quatre modèles sur cette configuration via un protocole de test en français : logique, traduction idiomatique, créativité et charge CPU.

Mettre à jour Ubuntu vers la dernière version stable en ligne de commande

Mettre à jour Ubuntu vers la dernière version stable en ligne de commande

Ubuntu propose un outil officiel pour passer d’une version à la suivante sans tout effacer. Ce guide te montre comment faire, étape par étape, depuis le terminal.


Étape 1 : Sauvegarder tes données (recommandé)

Avant toute mise à niveau majeure du système, sauvegarde tes fichiers importants – documents, photos, fichiers de configuration – sur un disque externe ou dans le cloud.


Étape 2 : Mettre à jour le système actuel

Ta version actuelle d’Ubuntu doit être totalement à jour avant de lancer la mise à niveau.

Ouvre ton terminal (Ctrl + Alt + T) et lance cette commande :

sudo apt update && sudo apt dist-upgrade -y && sudo apt autoremove -y

Voici ce que fait chacune des trois parties :

  • apt update : actualise la liste des paquets disponibles (un « paquet », c’est l’équivalent d’une application ou d’un composant système sous Linux).
  • dist-upgrade : installe les mises à jour en gérant intelligemment les changements de dépendances (les dépendances, ce sont les composants dont un logiciel a besoin pour fonctionner).
  • autoremove : supprime les anciens paquets devenus inutiles.

Une fois terminé, redémarre ton ordinateur pour appliquer les changements – notamment si le noyau Linux (le coeur du système) a été mis à jour :

sudo reboot

Étape 3 : Configurer le type de mise à niveau souhaité

Ubuntu doit savoir quel type de version tu recherches. Ouvre le fichier de configuration avec cette commande :

sudo nano /etc/update-manager/release-upgrades

Repère la ligne qui commence par Prompt=. Tu as deux options :

Prompt=lts – recommandé

Te met à jour uniquement vers la prochaine version LTS (Long Term Support, support à long terme). Par exemple, de la 22.04 LTS à la 24.04 LTS, soit un changement tous les 2 ans environ.

  • Sécurité : maximale, tu reçois toutes les mises à jour de sécurité pour ta version actuelle.
  • Stabilité : maximale, tu changes de version du système rarement, ce qui réduit le risque de casser tes logiciels ou ta configuration.

Prompt=normal

Te propose toutes les versions stables, y compris les versions intermédiaires sorties tous les 6 mois.

  • Tu seras obligé de faire une mise à niveau majeure tous les 6 mois, car ces versions intermédiaires ne sont maintenues que pendant 9 mois. Passé ce délai, tu te retrouves avec un système obsolète et non sécurisé.
  • Changer de version deux fois par an augmente le risque de rencontrer des bugs ou des incompatibilités matérielles.

Modifie si nécessaire, puis sauvegarde avec Ctrl + O (puis Entrée) et quitte avec Ctrl + X.


Étape 4 : Lancer la mise à niveau

Maintenant que tout est prêt, lance l’outil officiel de mise à niveau d’Ubuntu :

sudo do-release-upgrade

Si aucune mise à niveau n’est détectée

Les versions LTS ne proposent parfois la mise à jour automatique qu’après la sortie de leur première version corrective (par exemple, la 24.04.1 plutôt que la 24.04). Dans ce cas, tu peux forcer la recherche avec l’option -d :

sudo do-release-upgrade -d

⚠️ Attention : l’option -d donne accès aux versions en accès anticipé, pas encore totalement stabilisées. À n’utiliser que si tu sais ce que tu fais et que tu as bien sauvegardé tes données au préalable.


Étape 5 : Suivre le processus et patienter

Le terminal t’affiche un résumé des changements prévus – paquets à installer, paquets à supprimer, taille du téléchargement – et te demande de confirmer avec o (pour Oui).

Pendant tout le processus :

  • Ne ferme pas le terminal.
  • Ne coupe pas ta connexion internet.
  • Si le système te demande si tu veux conserver tes fichiers de configuration modifiés ou installer les versions des nouveaux paquets, appuie sur Entrée pour garder le choix par défaut – c’est généralement la bonne option.

Cas particulier : connexion à distance via SSH

Si tu gères l’ordinateur à distance via SSH, do-release-upgrade ouvre automatiquement un port de secours (généralement le port 1022) en cas de coupure de connexion. Suis simplement les instructions affichées à l’écran.

Une fois le processus terminé, le terminal t’invite à redémarrer. Tu peux ensuite vérifier ta nouvelle version avec :

bash

lsb_release -a

Félicitations, tu es sur la nouvelle version stable d’Ubuntu !

Fail2ban pour Nginx Proxy Manager (NPM)

Fail2ban pour Nginx Proxy Manager (NPM)

Article de la série « Mon ordinateur Ubuntu » 

Contexte

Environnement cible : un ordinateur Ubuntu sur lequel sont installés Nginx Reverse Proxy (NPM), Portainer, Home Assistant et Stirling PDF. Tout est déployé sous forme de containers Docker avec des chemins absolus (Bind Mounts), sans volumes nommés. Stirling PDF et Home Assistant sont accessibles via des URL externes, ce qui impose une sécurisation rigoureuse.

L’objectif est d’ajouter Fail2Ban pour passer d’une sécurité passive (certificats Let’s Encrypt) à une sécurité active.

Qu’est-ce que Fail2Ban ?

Les certificats Let’s Encrypt garantissent que la connexion est chiffrée (personne ne peut lire ce qui transite). Fail2Ban agit comme un videur à l’entrée.

Contre les attaques par brute force – sa mission principale. Si quelqu’un tente de deviner un mot de passe sur une page d’authentification, Fail2Ban détecte les échecs répétés dans les logs et bannit l’IP au niveau du pare-feu (iptables).

Contre les bots de scan (DoS léger) – il bloque les robots qui scannent le serveur trop rapidement à la recherche de vulnérabilités.

Contre la recherche de fichiers sensibles – il bannit les IPs qui tentent d’accéder à des dossiers inexistants mais critiques (.env, wp-config.php, /admin).

Résumé : HTTPS garantit que le tuyau est sécurisé, mais pas que la personne au bout du tuyau est autorisée à entrer. Le HTTPS empêche l’espionnage sur le Wi-Fi public. Fail2Ban empêche l’attaquant de frapper 10 000 fois à la porte.

Vérifier le format des logs NPM (étape préalable)

Avant toute configuration, il faut s’assurer que NPM enregistre les vraies IPs publiques des visiteurs dans ses logs, et non l’IP interne du réseau Docker.

Commande de vérification – ouvre un terminal sur Ubuntu et inspecte un fichier de log :

cat /home/USER/docker/nginx-proxy-manager/data/logs/proxy-host-1_access.log | head -20

Cherche le champ [Client X.X.X.X] dans chaque ligne de log.

✓  Si tu vois des IPs publiques (ex: 205.210.x.x, 45.84.x.x) dans [Client …] : NPM transmet déjà les bonnes IPs, aucune configuration supplémentaire n’est nécessaire.

⚠  Si tu vois des IPs internes Docker (ex: 172.18.x.x) dans [Client …] : Fail2Ban sera inefficace et risque de bannir ta passerelle Docker. Ajoute les proxy_set_header dans l’onglet Advanced de chaque Proxy Host dans NPM (voir ci-dessous).

Note importante sur les IPs dans les logs NPM – le champ [Sent-to X.X.X.X] contient l’IP interne de ta machine Linux (destination du trafic) : c’est normal. Le champ [Client X.X.X.X] est la seule IP qui compte pour Fail2Ban (source du trafic entrant).

Si les IPs internes sont présentes – configuration dans NPM – dans l’interface NPM, pour chaque Proxy Host (Stirling PDF, Home Assistant…), onglet Advanced, zone Custom Nginx Configuration, ajoute :

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Dans mon cas, les logs affichent déjà des IPs publiques. Cette configuration n’est pas nécessaire.

Installer Fail2Ban

Créer le dossier et le fichier docker-compose

mkdir ~/docker/fail2ban

cd ~/docker/fail2ban

nano docker-compose.yml

⚠  Pour que Fail2Ban puisse surveiller NPM, il doit avoir accès aux fichiers de logs générés dans le dossier /data/logs de NPM.

Contenu du docker-compose.yml :

services:

  fail2ban:

    image: crazymax/fail2ban:latest

    container_name: fail2ban

    network_mode: host

    cap_add:

      - NET_ADMIN

      - NET_RAW

    environment:

      - TZ=Europe/Paris

      - F2B_LOG_TARGET=/data/fail2ban.log

      - F2B_LOG_LEVEL=INFO

      - F2B_DB_PURGE_AGE=28d

    volumes:

      # Logs de Nginx a surveiller (lecture seule)

      - /home/USER/docker/nginx-proxy-manager/data/logs:/data/nginx/logs:ro

      # Dossier central Fail2Ban (config, db et log)

      - /home/USER/docker/fail2ban:/data

      # Logs systeme (lecture seule)

      - /var/log:/var/log:ro

    restart: always

    Pourquoi network_mode: host ? En mode host, Fail2Ban partage la pile réseau de la machine Ubuntu. C’est indispensable pour qu’il voie les vraies IPs sources et puisse agir sur iptables.

    Pourquoi monter les logs dans /data/nginx/logs ? L’image crazymax/fail2ban a un système de fichiers en lecture seule dans certains répertoires comme /var/log/nginx. Monter les logs dans /data/nginx/logs (qui est le volume /data accessible en écriture) évite cette erreur au démarrage.

    Structure des dossiers de configuration

    L’image crazymax/fail2ban attend ses fichiers de configuration dans /data/ (dans le conteneur), ce qui correspond à /home/USER/docker/fail2ban/ sur Ubuntu.

    Avant de déployer, crée la structure manuellement :

    mkdir -p /home/USER/docker/fail2ban/action.d
    
    mkdir -p /home/USER/docker/fail2ban/filter.d
    
    mkdir -p /home/USER/docker/fail2ban/jail.d
    

    Structure finale sur Ubuntu :

    /home/USER/docker/fail2ban/
    ├── action.d/
    │   └── docker-action.conf
    ├── filter.d/
    │   └── nginx-404.conf
    ├── jail.d/
    │   └── jail.local
    └── fail2ban.log    (cree automatiquement au demarrage)
    

    ⚠  Ne crée pas de sous-dossier ‘config/’ ou ‘data/’ supplémentaire. Les dossiers action.d, filter.d et jail.d doivent être directement dans /home/USER/docker/fail2ban/.

    Note sur les permissions – si les dossiers ont été créés par Docker (au premier démarrage du conteneur), ils appartiennent à root. Utilise sudo pour créer les fichiers, ou reprends la propriété du dossier :

    sudo chown -R USER:USER/home/USER/docker/fail2ban/
    

    Configuration de Fail2Ban

    Fichier action.d/docker-action.conf

    Ce fichier définit les règles iptables appliquées lors d’un bannissement. Il crée une chaîne dédiée f2b-npm-docker dans la table FORWARD.

    Crée le fichier /home/USER/docker/fail2ban/action.d/docker-action.conf :

    sudo nano /home/USER/docker/fail2ban/action.d/docker-action.conf
    

    Contenu :

    [Definition]
    
    actionstart = iptables -N f2b-npm-docker
    
                  iptables -A f2b-npm-docker -j RETURN
                  iptables -I FORWARD -p tcp -m multiport --dports 0:65535 -j f2b-npm-docker
    
    actionstop  = iptables -D FORWARD -p tcp -m multiport --dports 0:65535 -j f2b-npm-docker
    
                  iptables -F f2b-npm-docker
                  iptables -X f2b-npm-docker
    
    actioncheck = iptables -n -L FORWARD | grep -q 'f2b-npm-docker[ \t]'
    actionban   = iptables -I f2b-npm-docker -s &lt;ip> -j DROP
    actionunban = iptables -D f2b-npm-docker -s &lt;ip> -j DROP
    

    Fichier jail.d/jail.local

    Ce fichier définit les règles de bannissement et lie les filtres aux logs.

    Crée le fichier /home/USER/docker/fail2ban/jail.d/jail.local :

    sudo nano /home/USER/docker/fail2ban/jail.d/jail.local
    

    Contenu :

    [DEFAULT]
    
    # Temps de bannissement (1h)
    bantime  = 1h
    
    # Fenetre d'observation (10 min)
    findtime = 10m
    
    # Nombre d'erreurs avant bannissement
    maxretry = 5
    
    # Action : utilise le fichier docker-action.conf
    action = docker-action
    
    # --- JAIL POUR AUTHENTIFICATION NGINX ---
    
    [nginx-http-auth]
    enabled  = true
    filter   = nginx-http-auth
    
    # Surveille les logs d'erreur de NPM
    logpath  = /data/nginx/logs/proxy-host-*_error.log
    
    # --- JAIL ANTI-BOTS (erreurs 404/401/403) ---
    [nginx-404]
    enabled  = true
    port     = http,https
    filter   = nginx-404
    logpath  = /data/nginx/logs/proxy-host-*_access.log
    # Plus severe : 30 erreurs en 1 minute = banni 24h
    maxretry = 30
    findtime = 1m
    bantime  = 24h
    

    Fichier filter.d/nginx-404.conf

    Ce filtre indique à Fail2Ban quoi chercher dans les logs d’accès. Le format des logs NPM est différent du format Nginx standard – le regex doit en tenir compte.

    Format réel d’une ligne de log NPM :

    [11/May/2026:08:30:08 +0000] – 401 401 – GET https pdf.domaine.com « / » [Client 205.210.31.135] …

    Crée le fichier /home/USER/docker/fail2ban/filter.d/nginx-404.conf :

    sudo nano /home/USER/docker/fail2ban/filter.d/nginx-404.conf
    

    Contenu :

    [Definition]
    
    # Regex adapte au format de log NPM (champ [Client X.X.X.X])
    failregex = ^\[.*\] - \d+ \d+ - \w+ https? \S+ "\S+" \[Client &lt;HOST>\] .*(404|401|403)
    ignoreregex =
    

    Le marqueur <HOST> est la variable Fail2Ban qui capture l’adresse IP – elle correspond au contenu du champ [Client …] dans les logs NPM.

    ignoreregex = avec rien après le signe égal signifie « aucune ligne à ignorer ». Cette ligne doit être présente même vide, sinon Fail2Ban peut générer une erreur au démarrage.

    Déploiement dans Portainer

    1. Dans Portainer, clique sur ton environnement « local », puis va dans l’onglet « Stacks » à gauche.
    2. Clique sur le bouton « + Add stack ».
    3. Donne-lui un nom : fail2ban.
    4. Dans la zone « Web editor », copie et colle le contenu du docker-compose.yml.
    5. Clique sur « Deploy the stack ». Docker télécharge l’image (1 à 2 minutes selon la connexion).

    Une fois la stack déployée, vérifie que le fichier fail2ban.log a bien été créé dans /home/USER/docker/fail2ban/. S’il n’apparaît pas, c’est souvent une question de permissions (le conteneur doit avoir le droit d’écrire dans ce dossier).

    Vérification

    Étape 1 – Vérifier que les logs sont accessibles

    Ouvre un terminal sur Ubuntu et tape :

    docker exec -it fail2ban ls /data/nginx/logs
    

    ✓  Si tu vois la liste de tes fichiers .log (en particulier proxy-host-*_access.log et proxy-host-*_error.log), le pont entre Fail2Ban et les logs NPM fonctionne.

    Étape 2 – Vérifier les jails actives

    Dans Portainer, ouvre la console (Exec) du conteneur fail2ban et tape :

    fail2ban-client status
    

    ✓  Tu dois voir apparaître deux jails : nginx-http-auth et nginx-404. C’est bien le cas pour moi :

    Résumé des sources de logs

    Type de logChemin dans logpathCe qu’il contient
    Erreurs d’authentification/data/nginx/logs/proxy-host-*_error.logTentatives de mots de passe ratés
    Visites (404/401/403)/data/nginx/logs/proxy-host-*_access.logBots cherchant des fichiers inexistants
    Log Fail2Ban/data/fail2ban.logCorrespond au volume /home/USER/docker/fail2ban:/data

    Commandes utiles

    Supervision

    Status général des jails :

    docker exec -t fail2ban fail2ban-client status

    Status détaillé d’une jail (ex: nginx-404) :

    docker exec -t fail2ban fail2ban-client status nginx-404

    Liste de toutes les IPs bannies :

    docker exec -t fail2ban fail2ban-client banned

    Recherche des requêtes d’une IP dans les logs :

    grep <IP-ADRESSE> /home/USER/docker/nginx-proxy-manager/data/logs/proxy-host-*_access.log

    Actions manuelles

    Bannir manuellement une IP :

    docker exec -t fail2ban fail2ban-client set nginx-404 banip <IP>

    Lever manuellement un bannissement :

    docker exec -t fail2ban fail2ban-client set nginx-404 unbanip <IP>

    Informations

    Version de Fail2Ban :

    docker exec -t fail2ban fail2ban-client version

    Aide complète :

    docker exec -t fail2ban fail2ban-client –help

    Rendons à César

    Pour concevoir ce processus d’installation et rédiger cet article, je me suis aidée de :

    • https://wiki.blablalinux.be/fr/docker-compose-fail2ban
    • l’IA Gemini (gemini.google.com)
    • l’IA Claude (claude.ai)

    100% testé et ajusté par moi.

    Installer Home Assistant sur Ubuntu avec Docker et Portainer

    Installer Home Assistant sur Ubuntu avec Docker et Portainer

    Article de la série « Mon ordinateur Ubuntu » 
    Actions et articles créés avec l’aide de Claude.ai et 100% testé et ajusté par moi.

    Home Assistant est une plateforme domotique open source puissante. Il en existe plusieurs variantes d’installation. Cet article explique comment installer la variante « Container » sur un ordinateur Ubuntu qui fait déjà tourner d’autres services Docker, avec un accès sécurisé depuis l’extérieur via Nginx Proxy Manager.

    Quelle variante de Home Assistant choisir ?

    Il existe trois grandes variantes :

    • HA OS – remplace complètement l’OS de la machine. À réserver à un appareil dédié (Raspberry Pi par exemple).
    • HA Supervised – donne accès au magasin d’add-ons officiel, mais officiellement supporté sur Debian uniquement. Risques de friction sur Ubuntu.
    • HA Container – s’installe comme n’importe quel container Docker. Pas d’accès au magasin d’add-ons natif, mais les add-ons les plus courants ont un équivalent en container Docker séparé. C’est la solution la plus cohérente si tu as déjà un PC Ubuntu avec Docker et Portainer.

    Ce dont tu as besoin avant de commencer

    Étape 1 – Créer les répertoires

    Sur le PC Linux, ouvre un terminal et crée les répertoires qui accueilleront les données de Home Assistant :

    sudo mkdir /home/USER/docker/home-assistant/
    sudo mkdir /home/USER/docker/home-assistant/config/
    

    C’est cohérent avec l’organisation décrite dans Docker et Portainer : regrouper les données. Toutes les données de HA seront dans ce dossier, et donc automatiquement couvertes par ta sauvegarde rclone.

    Étape 2 – Déployer la stack dans Portainer

    Connecte-toi à Portainer (https://TON-IP:9443), clique sur ton environnement « local », puis « Stacks » dans le menu gauche. Clique sur « + Add stack » et donne-lui le nom home-assistant.

    Dans la zone « Web editor », colle ce YAML :

    services:
      home-assistant:
        container_name: home-assistant
        image: "ghcr.io/home-assistant/home-assistant:stable"
        volumes:
          - /home/USER/docker/home-assistant/config:/config
          - /etc/localtime:/etc/localtime:ro
          - /run/dbus:/run/dbus:ro
        restart: unless-stopped
        privileged: true
        network_mode: host
        environment:
          TZ: Europe/Paris
    

    Quelques points importants sur ce YAML :

    • network_mode: host – HA utilise directement le réseau du PC, sans isolation. C’est recommandé par le projet HA pour la découverte automatique des appareils sur le réseau local.
    • privileged: true – nécessaire pour accéder au matériel (Bluetooth, USB, etc.).
    • /run/dbus:/run/dbus:ro – permet à HA de communiquer avec les services système, utile pour Bluetooth notamment.
    • Le volume letsencrypt n’est pas nécessaire ici – c’est Nginx Proxy Manager qui gère les certificats SSL.

    Clique sur « Deploy the stack ». Au bout de quelques secondes, HA est accessible sur ton réseau local via http://TON-IP:8123.

    Étape 3 – Accès externe via Nginx Proxy Manager

    Ouvrir le port 8123

    Dans l’interface de gestion de ton routeur, ajoute une règle de redirection de port :

    • Port externe : 8123
    • IP locale de destination : l’IP fixe de ton PC Linux
    • Port interne : 8123
    • Protocole : TCP
    Créer le proxy host dans NPM

    Connecte-toi à NPM (http://TON-IP:81), va dans « Proxy Hosts » et clique sur « Add Proxy Host ».

    Onglet « Details » :

    • Domain Names : ha.TON-DOMAINE.com
    • Scheme : http
    • Forward Name/IP : 127.0.0.1
    • Forward Port : 8123
    • Coche « Block Common Exploits » et « Websockets Support »

    Onglet « SSL » :

    • SSL Certificate : « Request a new SSL Certificate »
    • Coche « Force SSL », « HTTP/2 Support » et « HSTS Enabled »

    Clique sur « Save ».

    Le point spécifique à Home Assistant – configuration.yaml

    Contrairement aux autres containers, HA intègre une protection contre les accès via proxy non déclarés. Sans configuration supplémentaire, tu obtiendras une erreur 400 (Bad Request) en accédant via https://ha.TON-DOMAINE.com.

    Il faut déclarer NPM comme proxy de confiance. Ouvre le fichier de configuration :

    sudo nano /home/USER/docker/home-assistant/config/configuration.yaml
    

    Et ajoute ces lignes à la fin :

    http:
      use_x_forwarded_for: true
      trusted_proxies:
        - 127.0.0.1
        - 172.16.0.0/12
    

    Attention à l’indentation : 2 espaces par niveau, pas de tabulations. YAML est strict là-dessus.

    Redémarre le container HA dans Portainer. HA est maintenant accessible depuis l’extérieur via https://ha.TON-DOMAINE.com.

    Étape 4 – Premier démarrage et assistant de configuration

    Au premier accès, HA t’ouvre automatiquement l’assistant de démarrage. Tu y crées ton compte administrateur, choisis la langue, le fuseau horaire et la localisation.

    Bonne surprise : HA scanne ton réseau local et détecte automatiquement les appareils compatibles. Sur mon réseau il a trouvé Bluetooth, Google Cast, Frontier Silicon, Matter, Tado, Thread et UPnP – sans aucune configuration de ma part. La connexion effective de ces appareils est une étape ultérieure, mais la détection automatique donne un bon aperçu du potentiel.

    Étape 5 – Sauvegardes

    Si tu as déjà mis en place la sauvegarde automatique avec rclone décrite dans Sauvegarder ses containers Docker automatiquement avec Rclone, il n’y a rien à faire de plus. Le dossier /home/USER/docker/home-assistant/ est automatiquement inclus dans la sauvegarde quotidienne.

    Pour tester la restauration, la procédure est identique à celle décrite dans Restauration de containers Docker avec Rclone.

    Et ensuite ?

    Home Assistant est installé et opérationnel. Les prochaines étapes possibles :

    Ajouter des containers Docker complémentaires (MQTT, Zigbee2MQTT, etc.) selon les besoins

    Connecter les appareils détectés (Tado, Google Cast, etc.)

    Migrer des appareils depuis une box domotique existante

    ajouter un dongle Zigbee et ajouter des nouveaux appareils (j’ai trois ampoules et quelques capteurs d’ouverture de porte).