Ce blog a-t-il vraiment besoin de WordPress et de Kubernetes ? Une expérience avec Hugo, de vrais chiffres et le coût réel d’une migration

J'ai reconstruit une partie de ce blog avec Hugo et je l'ai comparée à WordPress sur K3s : vitesse, matériel, correctifs, sécurité, Grafana, rôles Ansible et effort de migration. La décision reste ouverte.

Browser showing the Hugo test copy of the blog, with an arrow labelled Test Migration from the WordPress logo to the Hugo logo and a Proof of Concept badge

🌐 Aussi en: English · Deutsch · Español

Mise à jour du 6 novembre 2026 : c’est désormais décidé et fait : ce blog tourne sur Hugo. Ce qui s’est passé est décrit ici.

En bref : ce blog se compose surtout de texte et d’images, mais il tourne sur Kubernetes avec une base de données, un pool PHP, un cache et dix extensions. J’en ai donc reconstruit une partie sous forme de site statique avec Hugo, puis j’ai comparé les deux. Le résultat m’a surpris dans les deux sens : pour les lecteurs, le gain de vitesse est plus faible que prévu ; pour l’exploitation, le gain est bien plus important. Rien n’est décidé. Ce blog tourne toujours sur WordPress.

Par le passé, je trouvais Hugo trop compliqué, trop laborieux et peu convivial, aussi bien à l’usage que pour migrer depuis WordPress. Avec une assistance IA rapide, tout a changé : la conversion, le thème et les scripts de vérification de ce test ont vu le jour en peu de temps. C’est pour cela que je me repose la question aujourd’hui.

Cet article rassemble tout ce que je veux savoir avant de trancher : des mesures, des estimations clairement signalées, les conséquences sur chaque rôle Ansible, Grafana, SELinux, la question d’un nouveau dépôt, l’effort réel et une liste de contrôle au cas où je me lancerais.

Table des matières

🧒 Pour les non-informaticiens : quelle est la différence ?

WordPress construit une page quand quelqu’un la demande : un programme lit le texte dans une base de données et assemble la page, et un cache conserve le résultat un moment. Hugo construit toutes les pages une seule fois, à l’avance, sur ma propre machine. Le serveur ne fait ensuite que distribuer des fichiers terminés. Aucun programme ne s’exécute pour le visiteur, il n’y a pas de base de données ni de page de connexion à attaquer.

Le prix à payer : il n’y a plus d’éditeur confortable dans le navigateur. Un article devient un fichier texte, et publier signifie construire puis envoyer.

À retenir : WordPress est un programme en marche qui sert des pages. Hugo est un outil qui produit des fichiers. Presque toutes les différences décrites ici en découlent.

🧪 L’expérience : trois articles, toutes les pages, quatre langues

J’ai converti en Markdown les trois derniers articles et toutes les pages statiques en anglais, allemand, français et espagnol, puis j’ai écrit un petit thème avec les mêmes couleurs, les mêmes polices et la même structure. Un article ressemble désormais à ceci sur le disque :

---
title: 'HTTP/3 pour mon blog et Nextcloud'
slug: http-3-pour-mon-blog-et-nextcloud
date: '2026-11-03T19:59:27+01:00'
translationKey: wp3277
categories: [DevSecOps]
image: img/2026_11_no_http3.webp
---

**Mise à jour du 4 novembre 2026 :** HTTP/3 est de nouveau désactivé sur tous mes serveurs.

Pour un lecteur, le site se comporte de la même façon : même menu, drapeaux de langue, bandeau, carrousel, liste d’articles, barre latérale, table des matières et recherche. Les petites différences ne se voient qu’en comparant côte à côte. Le thème est ma propre reconstruction et non une copie du thème WordPress, si bien que quelques pixels diffèrent.

Une ressemblance ne prouve pas grand-chose. Un script a donc comparé chaque page à l’original :

VérifiéRésultat
Pages comparées à l’original WordPress28 sur 28, texte identique
Blocs de code, caractère par caractère24, aucune différence
Tableaux, titres, éléments de liste20, 251 et 300, nombres identiques
Liens dans le texte des articles84, tous corrects
Adresses, canonical, hreflang, noindexIdentiques sur les 28 pages
Références internes de tout le site généré7 740 dans 225 fichiers HTML, 0 cassée
Temps de construction1,9 s la première fois, puis 0,14 s
Taille du thème et des outils561 lignes de thème, 217 lignes de Python

Le test a aussi trouvé les erreurs qui justifient son existence. Hugo remplaçait silencieusement les liens tel: de mes mentions légales par #ZgotmplZ. Les archives mensuelles des autres langues atterrissaient dans le chemin anglais. Ma première version affichait la méta-description au lieu du véritable extrait. Et le logo était inversé. Seul le script de comparaison a repéré la première erreur ; je n’aurais jamais cliqué sur un lien téléphonique.

À retenir : une migration ne vaut que par sa comparaison automatique. Un site qui a l’air correct peut quand même contenir des contenus cassés.

⚡ Vitesse : ce que j’ai mesuré et ce que j’estime seulement

D’abord les mesures. Elles ont été réalisées depuis mon serveur domestique vers le vrai blog, avec 14 requêtes par ligne, en mesurant le temps jusqu’au premier octet. Un fichier statique sur le serveur réel représente ce que livrerait un site Hugo.

RequêteMédianePlage
Fichier statique57 ms50–59 ms
Page d’accueil depuis le cache de pages WordPress58 ms55–62 ms
Article depuis le cache de pages WordPress60 ms56–63 ms
Même article, généré par PHP (cache contourné)146 ms134–163 ms

Voilà la surprise : une page WordPress en cache est aussi rapide qu’un fichier statique. Le cache fait déjà son travail. La différence n’apparaît que lorsqu’il n’est pas utilisé.

Le gain est plus net sur le volume que le navigateur doit télécharger, sans compter les images et les polices :

Page d’accueil, compresséeWordPressHugoVariation
HTML19,4 Ko4,9 Ko−75 %
CSS8 fichiers, 67,7 Ko1 fichier, 3,6 Ko−95 %
JavaScript16 fichiers, 111,1 Ko1 fichier, 1,0 Ko−99 %
Total25 fichiers, 198 Ko3 fichiers, 9,5 Ko−95 %

Passons aux estimations. Ce sont mes attentes, pas des mesures. Je n’ai pas encore réalisé de véritable test dans un navigateur et en conditions réalistes.

SituationGain attenduBase
Page déjà dans le cache WordPressEnviron 0 %Mesuré : 57 contre 58 ms
Page absente du cacheEnviron 60 % d’attente en moins, soit 2,5 fois plus rapideMesuré : 146 contre 57 ms
Première visite sur téléphone avec une connexion moyenneEnviron 20–40 % plus rapide jusqu’à ce que la page soit utilisableEstimation à partir de 95 % de CSS et JavaScript en moins
Pages suivantes de la même visiteFaibleLes fichiers sont déjà dans le cache du navigateur
Pic de traficNettement plus robusteNi limite de workers ni base de données sur le chemin

À retenir : la vitesse seule ne justifierait pas une migration. Un WordPress bien mis en cache est déjà rapide. Le lecteur gagne surtout parce qu’il télécharge moins de code, en particulier sur téléphone.

🖥️ Matériel : ce dont le serveur aurait vraiment besoin

Voici les valeurs actuelles du serveur du blog et mon estimation pour un site statique. Grafana et toute la supervision restent dans les deux cas, car je veux les conserver.

ValeurWordPress sur K3s (mesuré)Hugo (estimation)
Processeur4 cœurs, charge d’environ 0,21–2 cœurs
Mémoire utilisée2,7 Go sur 7,5 GoEnviron 1,0–1,2 Go
Taille de serveur raisonnable4 Go ou plus2 Go
Données Kubernetes sur le disque7,1 Go0
Site sur le disque375 Mo d’application et de médiasMoins de 500 Mo pour tous les articles
Pods actifs / images de conteneurs17 / 140 / 0
Tâche de fond toutes les quelques minuteswp-cronAucune
Règles de pare-feu (sortie de nftables)7 760 lignes, surtout de K3sQuelques centaines de lignes

Voici où va la mémoire aujourd’hui, par processus. Ces valeurs se recoupent, leur somme dépasse donc la consommation réelle :

ComposantMémoireAvec Hugo
k3s-server847 MoDisparaît
containerd et ses shims383 MoDisparaît
php-fpm349 MoDisparaît
MariaDB249 MoDisparaît
Ingress (nginx et contrôleur)316 MoRemplacé par un petit nginx
Grafana357 MoReste
Alloy273 MoReste
Loki179 MoReste
Prometheus175 MoReste

À retenir : le site lui-même ne demanderait presque rien. Avec environ 1 Go, la supervision deviendrait le plus gros poste du serveur et en fixerait la taille minimale.

📅 Travail quotidien et correctifs

Depuis le 1er septembre, ce dépôt a reçu 256 commits, dont 76 touchaient les trois grands rôles du blog. Tout n’est pas de la maintenance, car une bonne partie relevait de la construction. Cela montre néanmoins où va l’attention. La journée de mise à jour et les deux failles PHP en un jour illustrent bien ce que cela signifie en pratique.

TâcheWordPress sur K3sHugo
Mises à jour du systèmeOuiOui
K3s, Helm, ingress, cert-managerOuiDisparaît
WordPress, 10 extensions, thèmeOui, automatique avec contrôlesDisparaît
PHP, y compris correctifs d’urgenceOuiDisparaît du serveur
MariaDB et RedisOuiDisparaît
Versions figées pour le blog9 entrées sur 30, plus la pile K3s communenginx du système, Hugo sur ma machine
Analyse nocturne des images et ses résultatsOui, voir TrivyDisparaît ; les paquets système restent
Alertes sur workers, pods, base de donnéesOuiDisparaît
Vider les caches après un changementCache de pages, d’objets et d’optimisationDisparaît
Lire les courriels de supervision et de sécuritéOuiOui, pour bien moins de raisons
Écrire un articleÉditeur dans le navigateurFichier texte, Git, construction, envoi
Si une mise à jour casse quelque choseLe site réel peut tomberLa construction échoue, le site reste tel quel
Retour arrièreDump de base et restauration de fichiersRenvoyer la construction précédente

Les Nextcloud restent sur K3s, ma journée de mise à jour ne disparaît donc pas. Elle raccourcit seulement.

À retenir : c’est là le vrai gain. Des catégories entières de mises à jour, d’urgences et d’alertes disparaissent, car le logiciel n’existe plus sur le serveur.

🔐 Sécurité : une évaluation honnête

Cette évaluation est mon jugement, pas une mesure. « Élevé » signifie ici un risque élevé.

MenaceWordPress sur K3sHugoPourquoi
Faille d’une extension ou du cœurMoyen à élevéAucunAucun code ne s’exécute sur le serveur
Exécution de code à distance en PHPMoyenAucunPas de PHP
Injection SQLFaible à moyenAucunPas de base de données
Connexion admin voléeFaible, grâce à la 2FA et au filtre géographiqueAucunIl n’y a pas de connexion web
Perte de données après une intrusionMoyenFaiblePas de données d’utilisateurs ; une reconstruction propre suffit
Faille de nginxMoyenMoyenDemeure
Noyau ou système d’exploitationMoyenMoyenDemeure
SSH ou clé de déploiementFaibleFaible à moyenLa clé de déploiement devient le secret précieux
Chaîne de construction (Hugo, thème, ma machine)Non concernéFaible à moyenNouveau : une construction empoisonnée serait publiée
Connexion à GrafanaFaible à moyenFaible à moyenDemeure et devient la principale cible web
Kubernetes comme surface d’attaqueFaible à moyenAucunPas de serveur d’API

Deux points inconfortables. D’abord, « statique » ne veut pas dire « sûr » : le serveur, SSH, nginx et le DNS demandent le même soin, et mes neuf couches de défense ne deviennent pas inutiles. Ensuite, avec Grafana, l’hôte n’est justement pas purement statique. Une connexion y subsiste, et c’est elle qui mérite le plus d’attention.

À retenir : la surface d’attaque diminue fortement, car plusieurs catégories d’attaques n’ont plus rien à viser. Les risques restants se déplacent vers la clé de déploiement et Grafana.

🧱 Ai-je encore besoin de K3s sur le serveur du blog ?

Techniquement, non. L’article approfondi sur K3s et l’article sur WordPress sur Kubernetes expliquent pourquoi je l’avais choisi. Un simple nginx avec un dossier de fichiers n’a pas besoin d’orchestrateur. Mais K3s a des avantages que je perdrais réellement :

AspectAvec K3sSans K3s
Mémoire et disque➖ Environ 1,2 Go de RAM et 7,1 Go de disque➕ Rien
Pièces mobiles➖ Serveur d’API, kubelet, containerd, CNI, ingress, cert-manager➕ Un service
Pare-feu➖ K3s ajoute des milliers de lignes ; prudence à chaque changement➕ Seulement mes règles
Mises à jour➖ K3s, charts et images➕ Paquets système
Haute disponibilité➖ Aucune de toute façon sur un seul nœud➖ Aucune non plus
Isolation entre les composants➕ Pods, NetworkPolicies➖ Guère nécessaire avec un service
Mises à jour sans interruption➕ Mises à jour progressives intégrées➕ Remplacées par une bascule atomique de dossier
Mêmes outils que sur les Nextcloud➕ Une seule façon de travailler➖ Deux façons de travailler
Banc d’essai pour les Nextcloud➕ Petit hôte qui reçoit K3s en premier➖ Perdu ; une VM de test devrait le remplacer
Valeur d’apprentissage et matière pour le blog➕ Élevée➖ Plus faible sur cet hôte

Les Nextcloud sont un autre cas : PHP, Collabora, push et tâches cron y forment vraiment plusieurs services qui coopèrent.

À retenir : pour le blog, K3s ne se justifie plus par une nécessité technique, mais par l’uniformité, les tests et l’apprentissage. Ce sont des raisons légitimes, à condition de les nommer honnêtement.

📝 Ce qui justifie encore WordPress

Il serait facile d’enterrer WordPress ici. Ce serait une erreur, car il résout de vrais problèmes que Hugo ne résout pas :

Atout de WordPressAvec Hugo
Éditeur dans le navigateur, utilisable par tousÉditeur de texte et Git, ou un outil CMS supplémentaire
Écrire et publier depuis un téléphonePeu pratique sans outils supplémentaires
Médiathèque avec envoi et rechercheDes fichiers dans un dossier
Plusieurs auteurs avec des rôlesSeulement via Git ou un outil supplémentaire
Commentaires et formulairesService externe nécessaire
Publication programméeSeulement avec une construction planifiée
Des extensions pour presque toutÀ construire soi-même
Analyse SEO pendant l’écriture (Yoast)Balises méta oui, analyse en direct non
Transmission à une personne non techniquePresque impossible
Boutique, membres, contenu dynamiquePas le bon outil

Voici ce que deviendraient les extensions actuelles :

ExtensionAvec Hugo
PolylangIntégré à Hugo
Yoast SEOMes propres modèles : titres, méta, Open Graph, schema, sitemap. Schema plus simple, pas d’analyse dans l’éditeur
Easy Table of ContentsIntégré à Hugo
AutoptimizeIntégré à Hugo (minify)
CompressXTraitement d’image de Hugo à la construction
WP Super Cache, Redis CacheInutiles
Two Factor, Limit Login AttemptsInutiles sans connexion
Classic EditorSans objet

Il y a aussi un aspect personnel. La plupart de mes derniers articles sont rédigés avec l’aide de l’IA, et l’éditeur confortable compte donc moins pour moi que pour la plupart des blogueurs. Avec un fichier Markdown et un commit Git, le travail avec un assistant IA serait même plus simple qu’aujourd’hui. Je n’en deviendrais pas dépendant pour autant : le Markdown se modifie avec n’importe quel éditeur de texte.

À retenir : WordPress reste le bon choix quand d’autres personnes écrivent, quand on publie en déplacement ou quand le site fait plus qu’afficher du contenu. Il n’est le mauvais outil que si rien de tout cela ne s’applique.

📈 Combien de sites WordPress, combien de sites Hugo ?

Sur le marché, Hugo est une petite niche. Selon W3Techs, au 5 novembre 2026 :

IndicateurWordPressHugo
Part de tous les sites web39,5 %0,1 %
Part des sites au CMS connu58,2 %0,2 %
Rapport sur l’ensemble des sitesEnviron 400 : 11
Étoiles sur GitHub21 519 (un miroir ; le développement se fait ailleurs)90 379
LicenceGPLApache 2.0

Ces chiffres sont à lire avec prudence. W3Techs donne des parts et non des nombres absolus, et ne reconnaît pas toujours les sites statiques : Hugo est donc probablement sous-estimé. Les étoiles mesurent l’intérêt des développeurs et non les sites en service, et le dépôt WordPress n’est qu’un miroir. Il ne faut pas comparer directement ces deux valeurs.

Les chiffres montrent tout de même quelque chose : des millions de personnes utilisent WordPress sans avoir jamais vu un dépôt Git, alors que Hugo a une communauté étonnamment grande au regard de sa part de marché. Mon impression, sans données solides : ce sont surtout les passionnés qui prennent ce chemin, et pour des raisons qui correspondent à cet article : pas de PHP, pas de base de données, pas de connexion, peu de surface d’attaque, Markdown et Git plutôt qu’une interface web. Un site rapide est un bonus appréciable. Pour beaucoup, je suppose que c’est aussi le plaisir d’une installation que l’on comprend entièrement.

À retenir : WordPress est la valeur sûre avec le plus grand écosystème, Hugo une niche choisie délibérément. Être minoritaire n’est un argument dans aucun sens.

🛡️ SELinux deviendrait-il plus simple ?

Oui, nettement pour la partie web, mais il ne disparaît pas. L’article approfondi sur SELinux montre tout le travail que cela représente.

SujetWordPress sur K3sHugo sur AlmaLinux
Paquet de règles pour conteneursk3s-selinux, pas encore stable pour AlmaLinux 10Inutile
Domaines de la partie webConteneurs avec leurs catégoriesnginx dans le domaine éprouvé httpd_t
FichiersVolumes et étiquettes de conteneursUn dossier en httpd_sys_content_t
Réétiquetage après un téléchargement de K3sObligatoireSans objet
Proxy vers GrafanaVia l’ingress dans un podUn booléen ou un port étiqueté
Mes domaines de supervision (homelab_*)RestentRestent
Refus masqués par dontauditÀ vérifierÀ vérifier
Effort de migration—Nouvelle phase d’apprentissage pour nginx sur l’hôte

Sur FreeBSD, la question change totalement, car SELinux n’y existe pas. Les jails et le framework MAC prennent sa place.

À retenir : la partie la plus difficile de SELinux, les conteneurs et leur paquet, disparaît. Le mode enforcing reste, tout comme le devoir de vérifier le domaine réel de chaque service.

📊 Grafana reste. Qu’est-ce que cela implique ?

Grafana fonctionne aujourd’hui comme un service système normal, mais il est accessible via l’ingress de K3s. C’est la dépendance la plus importante :

ComposantAujourd’huiAvec HugoEffort
Service GrafanaService systèmeInchangéAucun
Accès via /grafana/Ingress K3sProxy inverse dans le nginx de l’hôte, avec WebSocketFaible
Filtre géographique de la connexionDans l’ingressÀ déplacer dans le nginx de l’hôteFaible
fail2ban pour la connexion GrafanaLit les journaux des podsLit le journal nginx, nouveau chemin et filtreFaible
PrometheusNode, kubelet, kube-state, MariaDB, PHP-FPMNode et un exportateur nginxFaible
Alloy et LokiLisent /var/log/podsLisent /var/log/nginx et le journalMoyen
Tableau de bord des conteneursPrésentPlus sur cet hôteRetirer
Tableaux de bord PHP-FPM, MariaDB, RedisPrésentsPlus sur cet hôteRetirer
Alertes sur workers, pods, base de donnéesActivesÀ retirer, sinon elles signalent NoDataMoyen
Nouveau : requêtes et erreurs nginxVia l’ingressVia l’exportateur nginx et les journauxMoyen
Nouveau : dernier déploiement réussi—Métrique d’horodatage avec alerteFaible
Expiration des certificats TLSContrôle Monit sur l’ingressContrôle Monit sur l’hôteFaible
MémoireEnviron 1 GoEnviron 1 GoDétermine la taille du serveur

Une ancienne leçon s’applique ici directement : si je retire des métriques et oublie une règle, elle peut ne plus rien signaler et rester verte à jamais. Après une migration, je vérifierais donc l’état de chaque règle, et non l’absence de courriels.

Une autre solution serait un Grafana central à la maison, qui collecterait les données de tous les serveurs. Cela retirerait la dernière connexion de l’hôte du blog, mais c’est une décision à part, avec ses propres risques.

À retenir : garder Grafana n’est pas un obstacle. Cela signifie toutefois qu’un proxy inverse, le filtre géographique et une connexion restent sur l’hôte, et que la supervision doit être réorientée des pods vers nginx.

🎭 Les rôles Ansible, un par un

Ma première hypothèse était qu’il ne resterait presque aucun rôle. Elle était fausse. La plupart des rôles protègent l’hôte et non WordPress, ils restent donc en majorité. Voici les 29 rôles de blog.yml, avec le nombre de lignes qui concernent Kubernetes :

RôleLignesLignes K8sAvec Hugo
blog_k3s_deploy2 96269❌ Supprimé
blog_wordpress1 47345❌ Supprimé
common_k3s1 139186❌ Pas sur cet hôte (Nextcloud le garde)
common_kube_metrics2145❌ Pas sur cet hôte
common_trivy40614❌ Pas sur cet hôte (pas d’images)
blog_packages2220🔄 À réécrire : nginx, client ACME, rsync
blog_verify47813🔄 À réécrire : site, certificats, liens, déploiement
blog_visitor_stats2373🔄 Nouveau chemin de journal, même idée
common_version_check34049🔄 Nouvelle branche pour le blog
common_version_active22317🔄 Nouvelle branche pour le blog
common_fail2ban48742🔧 Nouveaux chemins, jail WordPress supprimée
common_firewall1 17918🔧 Plus simple : ni tables K3s ni NodePorts
common_monit70212🔧 Pas de contrôle des pods ; contrôles nginx et déploiement
common_grafana1 5520🔧 Moins de tableaux de bord et d’alertes
common_loki8437🔧 Fichiers journaux au lieu des journaux de pods
common_prometheus4511🔧 Autres cibles
common_selinux2206🔧 Pas de k3s-selinux ; règles nginx
common_selinux_monitoring3990🔧 Moins de domaines
common_clamav2610🔧 Sans doute désactivé : pas d’envois sur le serveur
common_cis_hardening5718🔧 Retirer les exceptions K3s
common_auditd2524🔧 Retirer les chemins K3s
common_sysctl3132🔧 Retirer les réglages K3s
common_aide_refresh1011🔧 Dossier web exclu volontairement
common_dnf_automatic2251🔧 Petit ajustement
common_ssh6500✅ Inchangé
common_msmtp1380✅ Inchangé
common_rkhunter1870✅ Inchangé
common_logrotate1150✅ Inchangé, nginx en plus
common_node_exporter2731✅ Inchangé
RésultatRôles
❌ Retiré de cet hôte5
🔄 À réécrire5
🔧 À ajuster14
✅ Inchangé5

En lignes, environ 6 200 des quelque 16 600 lignes que le blog parcourt aujourd’hui n’y serviraient plus, soit 37 %. Seules 4 400 environ quitteraient vraiment le dépôt, car les Nextcloud ont besoin du reste. La visite Ansible consacrée au blog deviendrait un document historique.

Bien sûr, certaines choses seraient à créer :

NouveauRôleAmpleur
Rôle pour le site statiquenginx sur l’hôte, en-têtes de sécurité, redirections, proxy GrafanaMoyenne
CertificatsClient ACME avec renouvellement et rechargement de nginx, à la place de cert-managerFaible
DéploiementUtilisateur restreint, rsync, nouveau dossier par version, bascule atomique, dernières versions conservéesFaible à moyenne
Exportateur nginxRequêtes et erreurs pour PrometheusFaible
Chaîne de constructionVersion de Hugo figée, construction, comparaison, index de recherche, envoiMoyenne
VérificationContrôle des liens et comparaison du contenu à chaque constructionExiste depuis l’expérience
Table de redirectionsAnciennes adresses comme le flux et les chemins de médiasFaible
SauvegardeSimplifiée : contenu dans Git, plus configuration du serveur et journauxFaible

À retenir : les rôles coûteux disparaissent, le socle de sécurité reste. C’est une bonne nouvelle : le durcissement construit pendant des mois est conservé.

📦 Un nouveau dépôt ?

Mon dépôt contient actuellement les deux piles. Les rôles communs décident d’après la variable stack, et ma règle est que chaque changement doit fonctionner pour les deux. Passer à Hugo pose la question du découpage :

OptionAvantageInconvénient
A : tout dans le dépôt actuelUn seul endroit, un seul historiqueChaque article et image arrive dans l’historique Ansible et passe par son lint ; le dépôt grossit avec les médias
B : nouveau dépôt pour contenu, thème et construction. Ansible resteSéparation nette ; aucun changement aux rôles communs ; CI propre et simpleDeux dépôts ; le déploiement doit les relier
C : séparation complète, rôles communs en collectionPropre pour plusieurs utilisateursVersions et publications pour deux utilisateurs seulement ; effort élevé
D : dépôt Ansible séparé pour le blog avec rôles copiésTotalement indépendantChaque correctif de sécurité en double ; les copies divergent

Je choisirais l’option B. Articles, images, thème et scripts de construction iraient dans un nouveau dépôt. Le serveur reste dans le dépôt Ansible avec une troisième valeur, stack: static. Les rôles restent au même endroit et le durcissement n’a pas à être maintenu deux fois. Pour publier, une clé de déploiement restreinte suffit, sans accès au code Ansible ni à son coffre-fort.

Le prix est réel cependant : la règle « fonctionne pour les deux piles » deviendrait « fonctionne pour les trois ». En contrepartie, les branches WordPress disparaissent de nombreux rôles.

À retenir : le contenu et l’infrastructure n’évoluent pas au même rythme et ne portent pas les mêmes secrets : ils doivent être dans des dépôts séparés. Le durcissement commun, lui, ne doit pas être copié.

🐡 Et sur FreeBSD ?

Je suis enthousiasmé par FreeBSD depuis des années, même s’il mène une existence de niche à côté de Linux. C’est un système complet et cohérent, très bien documenté, avec les jails, ZFS et pf. Il n’a pourtant jamais eu sa chance pour ce blog, car K3s dépend de fonctions du noyau Linux et n’y tourne pas de façon adaptée à la production.

C’est exactement ce que Hugo change. Sans K3s, conteneurs, PHP ni base de données, les besoins se réduisent à nginx, un client ACME, rsync et la supervision, qui sont tous des logiciels ordinaires sur FreeBSD. La complexité qui me liait à Linux a disparu. Voici les trois variantes comparées :

SujetWordPress sur K3sHugo sur AlmaLinuxHugo sur FreeBSD
RAM avec supervision complète (estimation)2,7 GoEnviron 1,0–1,2 GoEnviron 1,0–1,2 Go
Correctifs➖ Nombreuses couches➕ Système et nginx➕ freebsd-update et pkg
Mises à jour automatiques➕ Existent➕ Existent➖ À construire
Isolation des services➕ SELinux et pods➕ SELinux et bac à sable systemd➖ Jails, plus grossières mais simples
Pare-feu et bannissements➕ Existent➕ Existent, plus simples➖ pf et fail2ban à refaire
Rôles réutilisablesTous24 sur 29, en partie ajustésPeu ; l’essentiel serait nouveau
Grafana, Prometheus, Loki➕ Existent➕ Existent, ajustés➖ Paquets disponibles ; chemins et règles à refaire
Instantanés avant mise à jour➖ Aucun➖ Aucun par défaut➕ ZFS
Exploitation à côté des Nextcloud➕ Identique➕ Même système➖ Deuxième plateforme
Connaissances existantes➕ Grandes➕ Grandes➖ À acquérir
Intérêt comme sujet de blogDéjà écritMoyen➕ Élevé

La question décisive est de savoir si cette installation pourrait être aussi bien sécurisée que l’actuelle. Je l’ai évaluée couche par couche. C’est une évaluation théorique : je ne l’ai ni construite ni testée sur FreeBSD.

CoucheAujourd’hui sur AlmaLinuxHugo sur FreeBSDÉvaluation
Filtre de paquetsnftablespf avec des tables🟢 Équivalent
Durcissement SSH, filtre géographiquesshd et ensembles nftablessshd et tables pf🟢 Équivalent
Bannir les attaquantsfail2banfail2ban avec pf🟢 Équivalent, nouvelles règles nécessaires
Isoler nginxSELinux et bac à sable systemdJail, contenu monté en lecture seule🟢 Bon ; simple et facile à vérifier
Isoler la supervisionMes domaines SELinuxUne jail par service🟡 Plus grossier, mais frontières claires
Règles fines par processusType enforcement SELinuxPas d’équivalent direct ; framework MAC, Capsicum seulement si le logiciel le prend en charge🔴 Plus faible
Surface d’attaque du serveur webAvec WordPress : grandeFichiers statiques🟢 Bien plus petite qu’aujourd’hui
Informations sur les faillesdnf, Trivypkg audit et freebsd-update🟢 Bon
Journal d’auditauditdOpenBSM🟡 Équivalent en principe ; exploitation à refaire
Intégrité des fichiers, rootkitsAIDE, rkhunterAIDE, rkhunter, freebsd-update IDS🟢 Équivalent
Retour arrière après mise à jourPaquets, restaurationInstantanés ZFS et boot environments🟢 Meilleur
Base de durcissementRéférentiel CIS appliqué dans mon rôleÀ refaire à la main🟡 Effort ; moins de matériel prêt à l’emploi
GrafanaDerrière filtre géographique et fail2banPareil, dans sa propre jail🟡 Reste la principale cible
Expérience d’incidents réelsDes mois de constats réelsPart de zéro🔴 Plus faible au début

Mon évaluation : oui, pour un site statique, FreeBSD pourrait être globalement sécurisé à un niveau comparable, mais par d’autres moyens. Ce que je perdrais vraiment, c’est le contrôle fin de SELinux par processus. Pour un WordPress avec PHP et des extensions, ce serait pénalisant. Pour un nginx qui livre des fichiers en lecture seule depuis une jail, cela pèse bien moins, puisqu’un attaquant peut tout simplement y faire beaucoup moins. En échange, les jails sont assez simples pour être vérifiées à l’œil. Les deux vrais points faibles sont Grafana, qui exige toujours une connexion, et mon manque de pratique : mon installation AlmaLinux a traversé des mois de vraies erreurs, pas une installation FreeBSD.

Un point reste ouvert : à ma connaissance, les paquets de Grafana, Prometheus, Loki et node_exporter existent dans les ports FreeBSD, mais je devrais d’abord vérifier Alloy et les versions actuelles. Sinon, il faudrait un autre collecteur de journaux.

À retenir : le grand gain vient de Hugo, pas du système d’exploitation. Mais c’est Hugo qui rend FreeBSD possible : une fois K3s parti, le choix n’est plus technique. Ce serait un choix de conviction, et pour un site statique, un choix défendable.

💶 Coûts et bénéfices

PointCoûtBénéfice
MigrationPonctuel, voir plus bas—
Serveur—Serveur plus petit et moins cher possible
MaintenanceNouvelle chaîne de construction à entretenirBeaucoup moins de correctifs et d’alertes
SécuritéProtéger la clé de déploiement et la constructionPlusieurs catégories d’attaques éliminées
Vitesse—Moins à télécharger ; mieux lors des pics et hors cache
ÉcriturePas d’éditeur, pas de travail depuis le téléphoneHistorique Git, fichiers simples, facile avec l’IA
Sauvegardes—Bien plus simples
Portabilité—Le Markdown fonctionne partout ; pas de dépendance à une base
Savoir-faireBanc d’essai K3s perduMoins de cas particuliers en tête
SEORisque pendant le déménagement ; plus d’analyse YoastPages rapides et contrôle total
Matière pour le blogMoins d’histoires d’exploitation sur cet hôteUne belle histoire de migration

Je ne peux pas donner ici de prix de serveur utile, car cela dépend de l’hébergeur. L’économie reste de toute façon modeste. La vraie monnaie ici, c’est l’attention.

À retenir : cette migration ne se paie pas en argent et ne rapporte pas d’argent non plus. C’est un échange : le confort d’écriture contre beaucoup moins de travail d’exploitation.

⏱️ Quelle quantité de travail ?

Le blog compte 143 articles dans chacune des quatre langues, soit 572 au total, plus 16 pages statiques et environ 1 400 fichiers médias. Les valeurs suivantes sont des estimations. L’expérience a pris environ une soirée avec l’aide de l’IA, ce qui laisse penser que la conversion est la plus petite partie.

PhaseAvec l’aide de l’IARemarque
Inventaire : extensions, blocs spéciaux, téléchargements2–3 hL’outil d’export existe
Convertir tous les articles et médias3–6 hLe script existe ; les anciens articles réservent des surprises
Finir le thème : pagination, étiquettes, archives, téléphone3–5 hLa base existe
SEO : adresses, redirections, flux, schema, sitemap2–3 hComparaison automatique avec le sitemap actuel
Ansible : nouveau rôle, 14 ajustés, 5 réécrits, VM de test8–15 hLa plus grande partie
Supervision et Grafana3–5 hVérifier chaque règle
Sauvegarde, test de restauration, documentation en trois langues, politique de confidentialité3–5 hÀ faire avec soin
Bascule et surveillance active2–3 hPuis deux semaines d’observation
Total, Hugo sur AlmaLinuxEnviron 26–45 hEn pratique sur 2–3 semaines
En plus pour FreeBSDEnviron 15–30 hPeu de rôles réutilisables
Sans l’aide de l’IA (estimation grossière)3–5 semaines de travailSurtout le thème, la conversion et les trois langues

Les exécutions réelles en production, la relecture de chaque diff et les décisions restent de mon ressort. L’IA accélère la saisie, mais elle ne dispense pas de vérifier.

À retenir : l’essentiel du travail n’est pas dans la conversion, mais dans Ansible, la supervision et la vérification. C’est là qu’il faut prévoir du temps.

✅ Ce que je devrais faire si je choisis Hugo

  1. Clarifier le besoin : puis-je me passer de l’éditeur dans le navigateur et du travail sur téléphone ? Sans cette réponse, le reste n’a pas d’importance.
  2. Choisir la plateforme : AlmaLinux par défaut, FreeBSD seulement par choix délibéré.
  3. Tout sauvegarder : base de données, fichiers et médias. Garder WordPress disponible plusieurs semaines.
  4. Créer le dépôt de contenu avec articles, médias, thème et version de Hugo figée. Rechercher les secrets avant le premier push.
  5. Tout convertir et comparer chaque page automatiquement : texte, blocs de code avec leurs barres obliques inverses, tableaux, liens, textes alternatifs, titres et descriptions.
  6. Conserver chaque adresse : articles, langues, catégories, étiquettes et aussi /wp-content/uploads/, car des images sont liées depuis l’extérieur. Comparer avec le sitemap actuel.
  7. Mettre en place les redirections : sans configuration, le flux RSS passe de /feed/ à /index.xml. Vérifier aussi les liens ?p= et l’ancienne adresse de recherche.
  8. Réécrire la politique de confidentialité et vérifier les mentions légales. Le texte actuel décrit WordPress et ses extensions. Vérifier aussi la notice sur l’IA et les licences de tous les téléchargements.
  9. Finir le thème et le SEO, y compris des images Open Graph sous la limite de WhatsApp et noindex pour les pages légales.
  10. Construire la partie Ansible sur une VM de test : stack: static, le nouveau rôle, les rôles ajustés. Lancer deux fois ; la seconde exécution doit afficher changed=0.
  11. Vraiment vérifier SELinux : domaines avec ps -eZ, refus masqués avec semodule -DB et journal propre à chaque service.
  12. Refaire la supervision : Grafana derrière nginx avec filtre géographique et fail2ban, nouvel exportateur, anciennes règles retirées, puis contrôle de l’état de chaque règle.
  13. Protéger le chemin de déploiement : clé restreinte, bascule atomique, dernières versions conservées et alerte en cas d’échec.
  14. Tester une restauration : construire un serveur propre à partir des seuls dépôts, avant de toucher à la production.
  15. Adapter tout ce qui gravite autour : scripts de sauvegarde, surveillance externe, contrôle des mises à jour et de la dérive, guides d’exploitation en trois langues, note sur les anciens articles approfondis.
  16. Planifier la bascule : baisser le TTL DNS, choisir un moment calme, garder le retour arrière prêt, puis contrôler les moteurs de recherche et les 404 dans les journaux.
  17. Observer pendant deux semaines, et seulement ensuite retirer WordPress et K3s de l’hôte.

À retenir : la plupart de ces points ne concernent pas du tout Hugo. Ils visent à ne perdre aucune adresse, à rester correct juridiquement, à conserver la supervision et à garder un chemin de retour.

🌐 HTTP/3 serait-il plus simple ?

En partie. Comme je l’ai décrit dans l’article sur HTTP/3, je l’ai désactivé parce que des connexions restaient bloquées après un rechargement. Avec nginx directement sur l’hôte, la mise en place serait plus simple, car le détour par l’ingress disparaît. La cause demeure pourtant : les anciens workers gardent les sockets UDP. C’est une question de nginx et non de K3s, et c’est pourquoi j’ai ouvert l’issue #1937. Moins de connexions longues et des rechargements rares atténueraient le problème. Je ne l’ai pas testé. Sur un site statique, le bénéfice serait de toute façon faible, je le laisserais donc désactivé pour l’instant.

À retenir : une mise en place plus simple ne corrige pas un défaut dans la couche inférieure.

🎯 Les leçons

  1. Mesurer avant de croire. J’attendais un grand gain de vitesse. Un WordPress en cache répondait en 58 ms, un fichier statique en 57 ms.
  2. L’essentiel du bénéfice est dans l’exploitation. Un logiciel qui n’existe plus n’a besoin ni de correctif, ni d’alerte, ni d’urgence.
  3. Le durcissement survit. Mon idée qu’il resterait peu de rôles était fausse : 24 sur 29 restent au moins en partie, car ils protègent l’hôte.
  4. « Statique » ne veut pas dire « simple ». Grafana, le déploiement et la chaîne de construction restent, et le risque se déplace vers la clé de déploiement.
  5. Une migration exige un outil de comparaison. Sans lui, je n’aurais pas vu les liens téléphoniques cassés de mes mentions légales.

🤔 Où j’en suis

Je n’ai pas tranché. Pour ce blog, K3s et WordPress ne sont plus techniquement nécessaires, c’est clair. Tout aussi clair : ils me coûtent de l’attention, pas de l’expérience aux lecteurs. De l’autre côté, il y a l’éditeur, le banc d’essai K3s pour les Nextcloud et une installation qui fonctionne et que je connais très bien.

Si je me lance, ce sera avec Hugo et un dépôt de contenu séparé, et la supervision reste. AlmaLinux est le choix raisonnable, car presque tout est conservé. FreeBSD est le choix qui m’enthousiasme, et pour la première fois, il serait réaliste sur ce blog. Et si je le fais, il y aura une deuxième partie avec les vrais chiffres, y compris tout ce que ces estimations ont mal prévu.

Certains textes et images de ce site sont assistés ou générés par IA. Détails