# Reverse proxy TLS devant le serveur de signalisation Meshamoto.
#
# Caddy obtient et renouvelle seul le certificat Let's Encrypt, sans intervention.
# Il transmet aussi X-Forwarded-For, dont le serveur a besoin pour identifier la source
# reelle des tentatives d'authentification : sans lui, elles paraitraient toutes venir de
# 127.0.0.1 et la limitation de tentatives bloquerait tout le monde d'un coup (rate_limit.py).
#
# Le serveur, lui, n'ecoute que sur 127.0.0.1:8765 : il n'est joignable QUE par Caddy.

monreseau.duckdns.org {
	# Porteur WebSocket du relais de secours (relay_ws.py) — dernier recours pour un
	# pair dont le reseau bloque TOTALEMENT l'UDP (Wi-Fi d'hotel, reseau d'entreprise).
	#
	# ATTENTION : sans cette route, le porteur est INJOIGNABLE et la panne est muette
	# cote client — il croira que le relais ne repond pas.
	#
	# Il etait ecrit ici qu'elle « doit venir AVANT le fourre-tout ». **C'est faux**,
	# mesure le 2026-08-07 : Caddy trie les blocs `handle` par specificite de chemin,
	# donc leur ordre dans ce fichier est sans effet. Ce qui compte est qu'elle
	# EXISTE — voir la note du fourre-tout, en bas.
	#
	# C'est tout l'interet du montage : le porteur emprunte le MEME port 443 et le MEME
	# certificat que la signalisation, donc il passe exactement la ou l'UDP ne passe
	# pas. Le publier sur un port exotique n'apporterait rien — un reseau qui bloque
	# l'UDP bloque aussi ces ports-la.
	handle /relay-ws {
		reverse_proxy localhost:8787
	}

	# Service de licence (licence_app.py) : inscription et activation des clés.
	#
	# PROCESSUS SÉPARÉ du serveur de signalisation, et publié ici sous le MÊME nom et
	# le même certificat — le client active contre l'adresse du serveur qu'il connaît
	# déjà, il n'a donc qu'une seule adresse à saisir. Un hôte distinct casserait
	# aussi la substitution de résolution locale (hairpin NAT) sur l'une des deux.
	#
	# Sans cette route, la demande tombe dans le fourre-tout ci-dessous et le serveur
	# de signalisation répond 404. Le client sait nommer ce cas — « ce serveur n'a pas
	# de service de licence » — mais il l'attribuera à un serveur auto-hébergé, ce qui
	# serait faux ici et enverrait chercher très loin de la vraie cause.
	handle /licence/* {
		reverse_proxy localhost:8788
	}

	# API de signalisation. Ces chemins doivent être publiés EXPLICITEMENT depuis que
	# le fourre-tout sert le site : sans eux, une jointure atterrirait sur une page
	# HTML et le client échouerait sur une réponse qu'il ne sait pas lire.
	handle /networks/* {
		reverse_proxy localhost:8765 {
			# REMPLACE X-Forwarded-For au lieu de le completer. Par defaut Caddy AJOUTE
			# l'IP reelle a la suite de l'en-tete envoye par le client :
			#     le client envoie   X-Forwarded-For: 9.9.9.9
			#     Caddy transmet     X-Forwarded-For: 9.9.9.9, <ip reelle>
			# Or _client_key (app.py) ne garde que la PREMIERE valeur : elle serait donc
			# choisie par l'attaquant, qui n'aurait qu'a la changer a chaque tentative pour
			# que le compteur d'echecs n'atteigne jamais le seuil. Avec header_up, l'en-tete
			# ne contient plus qu'une seule valeur, celle du pair reel.
			header_up X-Forwarded-For {remote_host}
		}
	}

	# Test de vie, interrogé par `curl` et par le panneau d'hébergement du client.
	handle /health {
		reverse_proxy localhost:8765
	}

	# LE SITE EST LE FOURRE-TOUT.
	#
	# **L'ordre dans ce fichier n'a AUCUNE importance, contrairement à ce qui était
	# écrit ici jusqu'au 2026-08-07.** Vérifié en compilant l'exemple avec le
	# fourre-tout placé en premier : `caddy adapt` produit exactement la même chose,
	# parce que Caddy trie les blocs `handle` par SPÉCIFICITÉ de chemin. Un `handle`
	# sans matcher est le moins spécifique, il passe donc toujours en dernier.
	#
	# Ce qui compte réellement, et qu'un test verrouille : **tout chemin d'API doit
	# avoir son propre `handle`.** Celui qu'on oublie tombe ici, donc renvoie une page
	# HTML là où le client attend du JSON — et l'erreur affichée ne ressemblera en
	# rien à la cause.
	handle {
		root * /var/www/meshamoto

		# `try_files` sert les URL SANS extension : /guide/services doit trouver
		# services.html. Sans cette ligne, `file_server` seul renvoie 404 sur tous
		# les liens du guide — et la page d'accueil, elle, continue de fonctionner,
		# donc la panne ne se voit qu'en cliquant.
		try_files {path} {path}.html {path}/index.html

		file_server
	}
}
