Si tu as ouvert cette page, c'est probablement parce que tu as un serveur à la maison, des applis à montrer au monde, et qu'à chaque passage dans le dashboard Cloudflare tu cliques un peu au hasard en espérant que ça marche. Cette page explique ce que sont réellement un tunnel, un hostname publié, un enregistrement DNS et une policy Access — en s'appuyant sur une vraie panne de 3 semaines (la fameuse erreur 1033) et sa résolution sur le homelab qui héberge AetherWX. Lecture ~15 min. Complément naturel de la bible /argocd-k8s-pour-les-nuls côté cluster.
0. Le problème de départ
Tu as une appli qui tourne chez toi — sur un NAS, un vieux PC,
un cluster K8s de salon. Elle marche très bien sur
http://192.168.1.38.
Maintenant tu veux que monapp.mondomaine.dev
marche depuis n'importe où. Instinctivement, tu penses :
« j'ouvre le port 443 sur ma box et je redirige vers le serveur ».
C'est la méthode historique, et elle a trois problèmes :
Ton IP publique change. Les box résidentielles
ont une IP dynamique. Ton DNS pointe dans le vide au premier
renouvellement de bail.
Tu exposes ta maison. Un port ouvert, c'est
une porte que les scanners automatiques du monde entier
testent en continu. La moindre CVE sur ton reverse proxy et
c'est ton réseau domestique qui est en jeu.
Le TLS, c'est toi qui le gères. Certificats,
renouvellements, la totale.
Le tunnel Cloudflare renverse le problème :
au lieu de laisser Internet entrer chez toi, c'est chez
toi qui sort vers Internet.
1. Le tunnel : une connexion à l'envers
Un petit programme, cloudflared,
tourne dans ton réseau (chez nous : un pod K8s de 64 Mo).
Au démarrage, il ouvre 4 connexions sortantes
vers les serveurs Cloudflare les plus proches (à Paris :
les datacenters cdg) et
les garde ouvertes en permanence.
Quand un visiteur demande aetherwx.sladoire.dev,
sa requête arrive chez Cloudflare — jamais chez toi directement.
Cloudflare la pousse dans le tuyau déjà ouvert, cloudflared la
reçoit et la transmet au service interne. La réponse fait le
chemin inverse.
Architecture
Loading diagram…
Aucune flèche n'entre dans la maison : cloudflared a appelé Cloudflare en premier, et la connexion reste ouverte pour faire passer les requêtes à contresens.
Conséquences immédiates, toutes agréables :
Zéro port ouvert sur la box. Un scanner ne voit rien.
L'IP dynamique n'est plus un sujet : c'est cloudflared qui appelle, peu importe d'où.
TLS géré par Cloudflare : ton service interne peut parler HTTP tout nu, le visiteur voit un cadenas.
Le tunnel est identifié par un token (le long
eyJhbGci... que le
dashboard te fait copier à la création). Ce token est la seule
chose dont cloudflared a besoin pour se présenter : « je suis
le connecteur du tunnel dark-blue ». Chez nous il vit dans un
Secret K8s, jamais dans Git.
2. Les 4 objets du dashboard
Tout ce qu'on fait dans Cloudflare pour un homelab tient en
4 objets. Si tu sais lesquels tu touches, tu ne cliques plus
au hasard :
Le tunnel (Zero Trust → Networks → Tunnels) —
le tuyau lui-même. Un par site physique suffit : le nôtre
s'appelle dark-blue,
comme le serveur. Son statut (HEALTHY / DOWN) reflète l'état
des connecteurs cloudflared.
Les applications publiées (« Published
applications », onglet du tunnel) — la table de routage :
tel sous-domaine public → tel service interne.
C'est ici qu'on décide ce qui est visible d'Internet.
Les enregistrements DNS (dashboard classique
→ ta zone → DNS) — pour chaque application publiée, Cloudflare
crée automatiquement un CNAME
monapp → <id-du-tunnel>.cfargotunnel.com.
Tu n'y touches quasiment jamais… sauf pour faire le ménage
(on y revient, c'est du vécu).
Les applications Access (Zero Trust →
Access → Applications) — des portiers optionnels devant un
hostname : « avant de servir cette app, vérifie l'identité
du visiteur ». Chez nous : un code par email, réservé à une
seule adresse, devant l'interface d'administration ArgoCD.
La table de routage réelle du tunnel dark-blue text
Sous-domaine public → Service interne (DNS du cluster K8s)
aetherwx.sladoire.dev → http://maritime-frontend.maritime.svc.cluster.local:80
geoserver.sladoire.dev → http://geoserver.maritime.svc.cluster.local:8080
argocd.sladoire.dev → http://argocd-server.argocd.svc.cluster.local:80 (+ Access)
ol.sladoire.dev → http://ol-frontend.preprod.svc.cluster.local:80
warhammer.sladoire.dev → http://warhammer-frontend.preprod.svc.cluster.local:80
finance.sladoire.dev → (RIEN. Volontairement.)
La dernière ligne est la plus importante de cette page.
L'appli finance manipule de vraies données bancaires : elle
n'a ni route dans le tunnel, ni enregistrement DNS.
Résultat : finance.sladoire.dev
ne se résout même pas. Ce n'est pas « protégé par un
mot de passe », c'est inexistant vu d'Internet —
la meilleure sécurité est celle qui n'a rien à défendre.
L'appli reste accessible en LAN, et son PIN devient un simple
deuxième rideau.
3. Le chemin complet d'une requête
Architecture
Loading diagram…
Ce qui se passe entre « je tape l'URL » et « la carte s'affiche ». Les étapes 2 et 3 sont chez Cloudflare, tout le reste chez toi.
Note bien où le TLS s'arrête : au bord de Cloudflare. Entre
cloudflared et ton service, on est dans le réseau privé du
cluster, en HTTP simple. C'est pour ça que la colonne
« Service » d'une application publiée commence par
http:// sans que
personne ne hurle.
4. Erreur 1033 : autopsie d'une panne de 3 semaines
Maintenant qu'on a le modèle en tête, décodons la panne qui a
motivé cette page. Pendant 3 semaines,
ol.sladoire.dev affichait :
Ce que voyaient les visiteurs text
Error 1033 — Cloudflare Tunnel error
The host (ol.sladoire.dev) is configured as a Cloudflare Tunnel,
and Cloudflare is currently unable to resolve it.
Traduction avec notre vocabulaire : le DNS est bon
(l'objet 3 pointe vers le tunnel), la route existe (objet 2),
mais aucun connecteur cloudflared n'est branché au tuyau
(objet 1 : tunnel DOWN). Cloudflare reçoit la requête,
se tourne vers le tunnel… et il n'y a personne au bout.
Chez nous, le cloudflared tournait dans un cluster K8s sous
WSL qui gelait régulièrement — puis dont la machine a fini
débranchée. L'appli elle-même était en pleine forme sur une
autre machine : 1033 ne dit rien de ton appli, il
parle uniquement du connecteur. C'est le piège
classique : on debug le service alors que c'est le tuyau.
Le tableau de diagnostic à garder sous le coude :
Symptôme → coupable → réflexe text
Erreur 1033 / 530 → connecteur mort → kubectl -n infra get pods
(tunnel DOWN) kubectl -n infra logs deploy/cloudflared
Erreur 502 → tunnel OK, service interne → l'URL "Service" de la route est-elle
injoignable bonne ? le pod visé tourne-t-il ?
NXDOMAIN → pas d'enregistrement DNS → la route/le CNAME existe-t-il ?
Page de login exposée → il manque le portier → Zero Trust → Access → Applications
(200 au lieu de 302) Access
"DNS record already → un CNAME fantôme d'un → zone DNS : supprimer les records
exists" à la création ancien tunnel traîne pointant sur l'ancien tunnel
Vécu, épisode 2 : à la création du nouveau
tunnel, impossible de publier
aetherwx — « A DNS
record with this name already exists ». Les CNAME de
l'ancien tunnel mort étaient encore là. Un tunnel
supprimé ou remplacé ne nettoie pas ses enregistrements DNS :
c'est à toi de passer dans la zone et de supprimer les records
*.cfargotunnel.com
orphelins. En le faisant, on a même retrouvé un fantôme
d'avant un renommage de projet, mort depuis des mois.
Attention en revanche à ne pas emporter les CNAME légitimes —
chez nous, deux sites statiques sur Cloudflare Pages
(*.pages.dev) vivent
dans la même zone.
5. Access : le portier devant l'admin
Dernier objet, le plus « Zero Trust » de tous. Certaines URLs
méritent d'exister publiquement (pratique pour administrer
depuis n'importe où) sans être ouvertes à n'importe
qui. L'interface ArgoCD, par exemple : elle a son propre
login, mais on préfère que même sa page de login ne soit pas
servie au premier scanner venu.
Une application Access intercepte tout le
trafic d'un hostname avant qu'il n'entre dans le
tunnel. Le visiteur tombe sur une page Cloudflare qui exige
une preuve d'identité — chez nous, la plus simple : un code à
usage unique envoyé par email, avec une policy « Allow » qui
ne liste qu'une seule adresse. Pas de VPN, pas de client à
installer, et la charge de gérer l'authentification est chez
Cloudflare.
Vérifier qu'un portier est bien en place text
$ curl -sI https://argocd.sladoire.dev/ | head -2
HTTP/2 302
location: https://sladoire.cloudflareaccess.com/cdn-cgi/access/login/...
# 302 vers cloudflareaccess.com = le portier fait son travail.
# Un 200 direct ici = la page d'admin est servie à tout Internet.
Anecdote honnête : en refaisant l'infra, on a découvert que ce
portier ne protégeait… que le mauvais service (un outil interne
décommissionné depuis). ArgoCD, lui, était exposé nu depuis le
début. On a recyclé l'application Access existante — renommée,
re-pointée — en 2 minutes. Morale : teste avec curl,
pas de mémoire. Un portier, ça se vérifie.
6. Côté cluster : 40 lignes de YAML, et Git commande
Tout ce qui précède se passe côté Cloudflare. Côté cluster, la
partie est minuscule — un Deployment d'un container, et un
Secret pour le token :
charts/cloudflared/ — l'essentiel du chart yaml
# Le secret (créé à la main, JAMAIS commité — le repo est public) :
# kubectl -n infra create secret generic cloudflared-token \
# --from-literal=token='eyJhbGci...'
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflared
namespace: infra
spec:
replicas: 1 # Cloudflare gère la HA côté edge
template:
spec:
containers:
- name: cloudflared
image: cloudflare/cloudflared:latest
args: ["tunnel", "run", "--token", "$(TUNNEL_TOKEN)"]
env:
- name: TUNNEL_TOKEN
valueFrom:
secretKeyRef: { name: cloudflared-token, key: token }
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { cpu: 200m, memory: 256Mi }
Le chart est déployé par ArgoCD comme tout le reste
(cf. la bible ArgoCD).
Le jour où on a migré de l'ancien serveur au nouveau, la
procédure complète côté Cloudflare a tenu en : créer un tunnel
neuf, coller le token dans un Secret, nettoyer les CNAME
fantômes, re-saisir 5 routes, re-poser 1 portier Access.
Trente minutes, en comprenant chaque clic — c'est tout l'enjeu
de cette page.
Piège d'interface (2026) : dans le nouveau
dashboard « Cloudflare One », les Public Hostnames s'appellent
désormais Published applications. L'onglet
voisin « Hostname routes » ressemble beaucoup mais fait tout
autre chose : du routage réseau privé, qui exige
d'installer le client Cloudflare One sur chaque appareil
visiteur. Si ta page parle de « Gateway » et de « on-ramp »,
tu es au mauvais endroit. Le plus court chemin vers n'importe
quel écran : la loupe 🔍 en haut de la barre latérale.
7. Ce qu'on n'a pas couvert (et qui existe)
Cloudflare Pages — l'hébergement statique :
les deux CNAME *.pages.dev
épargnés pendant le ménage sont des sites Astro déployés à
chaque push Git, sans serveur du tout.
Les Cache Rules — le CDN devant les tuiles
cartographiques : une règle qui force la mise en cache des
GetMap GeoServer a
divisé la charge du serveur maison sans dépenser un euro.
WAF, rate limiting, analytics — tout le
trafic passant par Cloudflare, on peut filtrer et observer
au même endroit.
Mais l'essentiel tient dans le modèle mental : un tuyau
sortant (tunnel), une table de routage (published applications),
des CNAME automatiques (DNS), des portiers optionnels
(Access). Une fois ces quatre objets identifiés, le
dashboard cesse d'être un labyrinthe — et l'erreur 1033 cesse
d'être un mystère : c'est juste un tuyau dont personne ne tient
l'autre bout.