xpeditis2.0/infra/prod/cloudflare
2026-09-07 21:40:50 +02:00
..
README.md feat(infra): provisionnement Hetzner, k3s et secrets SOPS 2026-09-07 21:40:50 +02:00

Configuration Cloudflare — production

Cloudflare est la première ligne de défense : DNS, anti-DDoS, WAF, cache. Le firewall Hetzner n'accepte 80/443 que depuis les rangs Cloudflare, donc si le proxy est désactivé sur un enregistrement, ce domaine devient inaccessible. C'est voulu : personne ne doit pouvoir taper l'IP d'origine.

Le plan Free suffit en phase 1 (≈ 100 utilisateurs). Le plan Pro (20 €/mois, prévu au budget à partir de 1 000 utilisateurs) ajoute le WAF managé et l'analyse de bots.


1. Enregistrements DNS

Toutes les valeurs <IP_APP_01> viennent de make tf-output.

Type Nom Contenu Proxy TTL
A xpeditis.com <IP_APP_01> Proxifié Auto
A www <IP_APP_01> Proxifié Auto
A app <IP_APP_01> Proxifié Auto
A api <IP_APP_01> Proxifié Auto
A grafana <IP_APP_01> Proxifié Auto
AAAA idem si IPv6 activée <IPv6_APP_01> Proxifié Auto

Aucun enregistrement ne pointe vers db-01. Son IP publique ne sert qu'au SSH d'administration et ne doit apparaître nulle part en DNS.

Messagerie (obligatoire pour que les e-mails arrivent)

Type Nom Contenu
TXT xpeditis.com v=spf1 include:spf.brevo.com -all
TXT mail._domainkey clé DKIM fournie par Brevo
TXT _dmarc v=DMARC1; p=quarantine; rua=mailto:dmarc@xpeditis.com; pct=100

Sans SPF/DKIM/DMARC, les confirmations de réservation et les liens magiques transporteurs partent en spam — un défaut de production silencieux et coûteux. Commencez à p=quarantine, passez à p=reject après deux semaines de rapports propres.


2. Réglages SSL/TLS

Réglage Valeur Pourquoi
Mode de chiffrement Full (strict) Cloudflare vérifie le certificat Let's Encrypt du serveur. En « Flexible », le trafic Cloudflare → origine serait en clair.
Always Use HTTPS Activé
Minimum TLS Version 1.2 TLS 1.0/1.1 sont cassés et refusés par la plupart des référentiels de conformité.
TLS 1.3 Activé
Automatic HTTPS Rewrites Activé
HSTS Activé après vérification Voir l'avertissement ci-dessous.

HSTS est irréversible pendant un an. Ne l'activez qu'une fois certain que tous les sous-domaines servent bien du HTTPS valide. Traefik pose déjà l'en-tête (k8s/base/08-traefik-middlewares.yaml) ; l'activer aussi côté Cloudflare ajoute la protection avant même que la requête n'atteigne le serveur.


3. Règles WAF

3.1 Bloquer l'accès direct aux chemins d'administration

(http.host eq "api.xpeditis.com" and starts_with(http.request.uri.path, "/api/docs"))

→ Action : Block

La documentation Swagger est déjà désactivée en production par main.ts, mais une règle de bordure protège même en cas d'erreur de configuration.

3.2 Limiter les tentatives de connexion

Rate limiting (Security → WAF → Rate limiting rules) :

Champ Valeur
Expression starts_with(http.request.uri.path, "/api/v1/auth/login")
Requêtes 10
Période 1 minute
Par Adresse IP
Action Block, 10 minutes

Cette limite s'ajoute à celle de Traefik (rate-limit-auth) et à celle de NestJS (CustomThrottlerGuard). Trois couches indépendantes : une erreur de configuration sur l'une ne laisse pas la porte ouverte.

3.3 Protéger le webhook Stripe

(http.host eq "api.xpeditis.com" and starts_with(http.request.uri.path, "/api/v1/subscriptions/webhook") and not ip.src in {IP_STRIPE})

→ Action : Block

Les rangs d'IP Stripe sont publiés sur https://stripe.com/files/ips/ips_webhooks.txt. La signature du webhook est déjà vérifiée côté applicatif ; ceci évite simplement que du bruit atteigne l'application.

3.4 Filtrage géographique — à décider consciemment

Xpeditis sert des transitaires européens. Bloquer tout sauf l'Europe réduit massivement le bruit, mais coupe aussi les transitaires asiatiques légitimes (les connecteurs transporteurs partent du serveur, ils ne sont pas concernés).

Recommandation : ne pas bloquer par pays au lancement. Activer plutôt « Bot Fight Mode » (gratuit) et surveiller les journaux un mois avant de décider.


4. Cache

Chemin Règle
api.xpeditis.com/* Bypass cache — une réponse d'API mise en cache servirait les données d'un utilisateur à un autre.
app.xpeditis.com/_next/static/* Cache Everything, Edge TTL 1 an (contenu au nom versionné).
app.xpeditis.com/* Standard (Next.js gère ses propres en-têtes).

La règle de bypass sur l'API est critique. Un cache mal placé sur une route authentifiée est une fuite de données, pas un problème de performance.


5. Jeton API pour cert-manager

My Profile → API Tokens → Create Token → Edit zone DNS

Permission Portée
Zone / DNS / Edit Zone xpeditis.com uniquement
Zone / Zone / Read Zone xpeditis.com uniquement

N'utilisez jamais la clé globale du compte : elle permettrait à cert-manager — ou à quiconque lirait le Secret — de rediriger tout votre trafic.

Le jeton alimente le Secret cert-manager/cloudflare-api-token (k8s/base/03-secrets.template.yaml).


6. Accès à Grafana

Deux options, au choix :

  • Liste d'IP (par défaut) — middleware Traefik admin-ip-allowlist, à renseigner dans k8s/base/08-traefik-middlewares.yaml.
  • Cloudflare Access (Zero Trust, gratuit jusqu'à 50 utilisateurs) — authentification par e-mail à usage unique devant grafana.xpeditis.com. Préférable si votre IP est dynamique.

7. Vérification

# Le proxy est-il bien actif ? (l'IP retournée doit être une IP Cloudflare)
dig +short app.xpeditis.com

# L'origine est-elle injoignable en direct ?
curl -sS --max-time 5 --connect-to app.xpeditis.com:443:<IP_APP_01>:443 \
     https://app.xpeditis.com/    # doit échouer par timeout

# SPF / DKIM / DMARC
dig +short TXT xpeditis.com
dig +short TXT _dmarc.xpeditis.com