Contenu

SEO Hugo : 404 Googlebot, aliases noindex et normalisation des sitemaps

Contexte

Google Search Console remontait quatre catégories de problèmes sur arleo.eu :

  • 404 Googlebot : /fr/tag/cloudflare, /en/tag/nginx, /fr/tag/javascript… URLs avec préfixe /fr/ ou singulier /tag/ jamais servi par nginx
  • 16 pages “Exclue par la balise noindex” : toutes des pages de redirection générées par aliases: dans le frontmatter Hugo
  • Balise robots : noodp hardcodée dans le thème LoveIt
  • Sitemap FR/EN : 104 vs 105 URLs — un tag doublon FR et deux tags manquants

Acte 1 : aliases Hugo → redirections nginx 301

Pourquoi Hugo génère des pages noindex

Hugo génère les entrées aliases: du frontmatter comme des fichiers HTML statiques :

<meta http-equiv="refresh" content="0; url=https://www.arleo.eu/posts/X/">
<meta name="robots" content="noindex">

Le noindex est intentionnel côté Hugo : il empêche Google d’indexer la page de redirection au lieu de la destination. Mais GSC le remonte comme “Exclue par la balise noindex” — ce qui pollue le rapport et signale à Google que des URLs de votre site lui sont intentionnellement cachées.

Fix : nginx permanent + suppression des aliases

59 règles rewrite ... permanent dans le vhost NUC :

# === Redirections SEO ===
# 1. Anciens slugs Grav et alias Hugo
rewrite ^/crowdsec-cloudflare-waf-autoban/?$ /posts/crowdsec-cloudflare-waf-autoban/ permanent;
rewrite ^/en/crowdsec-cloudflare-waf-autoban/?$ /en/posts/crowdsec-cloudflare-waf-autoban/ permanent;
rewrite ^/fr/crowdsec-cloudflare-waf-autoban/?$ /posts/crowdsec-cloudflare-waf-autoban/ permanent;
# ... (56 autres règles spécifiques)

# 2. Préfixe /fr/ — langue par défaut, pas de sous-répertoire
rewrite ^/fr/tag/([^/]+)/?$  /tags/$1/  permanent;
rewrite ^/fr/(.+)$           /$1        permanent;

# 3. Singulier /tag/ → pluriel /tags/ (taxonomie Hugo)
rewrite ^/tag/([^/]+)/?$     /tags/$1/  permanent;
rewrite ^/en/tag/([^/]+)/?$  /en/tags/$1/  permanent;

# 4. Tags FR dans le contexte EN
rewrite ^/en/tags/reseau/?$   /en/tags/network/   permanent;
rewrite ^/en/tags/securite/?$ /en/tags/security/  permanent;

Suppression des blocs aliases: dans les 35 fichiers Markdown concernés. Hugo reconstruit avec 68 alias (seuls les aliases inter-langues automatiques subsistent) au lieu de 208.

Résultat : les redirections sont des 301 purs nginx, invisibles pour GSC comme pages noindex.


Acte 2 : balise robots noodpindex, follow

Le thème LoveIt injecte dans baseof.html :

<meta name="robots" content="noodp" />

noodp était destiné à interdire l’utilisation du titre Open Directory Project (DMOZ) dans les snippets Google. DMOZ a fermé en 2017, la directive est sans effet depuis des années — mais certains crawlers l’interprètent encore comme une contrainte d’indexation.

Override au niveau site dans layouts/baseof.html :

<meta name="robots" content="index, follow" />

Ce fichier prend priorité sur le template du thème sans modifier le thème lui-même.


Acte 3 : normalisation des tags FR et parité des sitemaps

Diagnostic

# Extraire et comparer les chemins FR vs EN
sed 's|https://www.arleo.eu||' sitemap_fr.txt | sort > fr_paths.txt
sed 's|https://www.arleo.eu/en||' sitemap_en.txt | sort > en_paths.txt

comm -13 fr_paths.txt en_paths.txt   # Dans EN, absent de FR
# → /tags/network/  /tags/security/  /tags/performance/  /tags/purge/  /categories/security/

comm -23 fr_paths.txt en_paths.txt   # Dans FR, absent de EN
# → /tags/reseau/  /tags/securite/  /tags/sécurité/  /categories/sécurité/

FR avait :

  • /tags/securite/ ET /tags/sécurité/ — doublon non accentué vs accentué
  • /tags/reseau/ — non accentué, sans correspondant réseau

EN avait en plus : /tags/performance/ et /tags/purge/ sans équivalent FR.

Corrections

# 5 posts FR : securite → sécurité
for post in audit-securite-modsecurity-crowdsec csp-nonce hardening-systemd-mcp \
            roadmap-sprint-securite-mcp sprint-securite-mcp-livre; do
  sed -i 's/^- securite$/- sécurité/' content/posts/$post/index.fr.md
done

# 2 posts FR : reseau → réseau
for post in crowdsec-cloudflare-waf-autoban post-mortem-522-wan-failover; do
  sed -i 's/^- reseau$/- réseau/' content/posts/$post/index.fr.md
done

Ajout de purge et performance dans hugo-mcp-plugin-cloudflare/index.fr.md.

Nettoyage des répertoires obsolètes dans public/ — Hugo ne supprime pas les anciens fichiers lors d’un rebuild incrémental :

rm -rf public/tags/reseau public/tags/securite

Résultat : FR 105 = EN 105.


Acte 4 : boucle de redirection /fr/sitemap.xml

La règle générale rewrite ^/fr/(.+)$ /$1 permanent interceptait /fr/sitemap.xml — un fichier réel généré par Hugo — et le redirigeait vers /sitemap.xml (l’index de sitemaps). L’index liste… /fr/sitemap.xml. Boucle infinie pour les crawlers.

Détection :

curl -sk https://www.arleo.eu/fr/sitemap.xml -o /dev/null -w '%{http_code} → %{redirect_url}\n'
# 301 → https://www.arleo.eu/sitemap.xml

Fix : exception break avant la règle générale :

rewrite ^/fr/(sitemap\.xml)$  /fr/$1  break;
rewrite ^/fr/tag/([^/]+)/?$   /tags/$1/ permanent;
rewrite ^/fr/(.+)$            /$1       permanent;

break stoppe le traitement des rewrites. La requête passe ensuite au bloc location ~* sitemap\.xml$ qui proxifie vers la VM Hugo.

Piège nginx : les rewrites dans le contexte server s’exécutent avant les blocs location. Un break sans changement d’URI laisse donc la requête continuer vers le bon location.


Bilan

Diagram Diagram
Problème Cause Fix
404 /fr/tag/* Singulier + préfixe non géré rewrite ^/fr/tag/ + ^/tag/
16 pages noindex GSC aliases: Hugo génère HTML noindex nginx 301 + suppression aliases
robots: noodp LoveIt baseof.html hardcodé Override layouts/baseof.html
Sitemap FR 104 vs EN 105 Tags doublon + tags manquants sed batch + ajout tags
/fr/sitemap.xml boucle ^/fr/(.+) trop générique break exception avant la règle