tripoli.cloud/tripoli-edge
Adam Belkacemi 8f70c2aae7 Phase 2 : tripoli-edge, service Rust interne derrière Caddy
- tripoli-edge (hyper/tokio bas niveau, pas de framework type axum) :
  /healthz, /metrics (Prometheus, compteurs à la main), reverse-proxy
  vers tripoli-api avec vrais 502 tant que ce service n'existe pas
  (Phase 3), logs JSON structurés par requête.
- Écoute sur 127.0.0.1 + 172.17.0.1 (passerelle docker0), jamais sur
  l'interface publique - même pattern que le Nginx de VoltVision déjà
  sur ce serveur.
- Déployé en prod : systemd (utilisateur système dédié, sans privilège),
  bloc Caddy ajouté pour tripoli.cloud/www.tripoli.cloud, règle ufw
  ajoutée (Ansible) pour que Caddy puisse joindre le port 9000 - sans
  quoi le chemin INPUT de l'hôte bloque le trafic inter-bridges même
  vers 172.17.0.1.
- Vérifié bout-en-bout via https://tripoli.cloud, sans régression sur
  les 6 autres domaines déjà servis par ce Caddy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 22:31:58 +02:00
..
deploy Phase 2 : tripoli-edge, service Rust interne derrière Caddy 2026-09-16 22:31:58 +02:00
src Phase 2 : tripoli-edge, service Rust interne derrière Caddy 2026-09-16 22:31:58 +02:00
Cargo.toml Phase 2 : tripoli-edge, service Rust interne derrière Caddy 2026-09-16 22:31:58 +02:00
README.md Phase 2 : tripoli-edge, service Rust interne derrière Caddy 2026-09-16 22:31:58 +02:00

tripoli-edge

Service Rust interne placé derrière le Caddy déjà en place sur le serveur (voir README.md à la racine du dépôt pour le pourquoi : ce Caddy tient déjà les ports 80/443 pour six autres domaines).

Ce que fait tripoli-edge, concrètement :

  • GET /healthz : répond directement, sans toucher à tripoli-api.
  • GET /metrics : métriques au format d'exposition Prometheus (compteurs à la main, voir src/metrics.rs).
  • Tout le reste : reverse-proxy vers tripoli-api (méthode, en-têtes et corps conservés). Tant que tripoli-api n'existe pas (Phase 3), ça répond un vrai 502 Bad Gateway, pas une réponse simulée.
  • Logs structurés JSON (tracing + tracing-subscriber) pour chaque requête : méthode, chemin, host, statut, latence.

Configuration (variables d'environnement)

Variable Défaut Rôle
TRIPOLI_EDGE_LISTEN 127.0.0.1:9000,172.17.0.1:9000 Adresses d'écoute (jamais 0.0.0.0 — voir plus bas)
TRIPOLI_API_UPSTREAM 127.0.0.1:8081 Adresse de tripoli-api
RUST_LOG — Niveau de logs (info, debug, ...)

172.17.0.1 est la passerelle docker0 du serveur : c'est ce qui permet au conteneur Caddy (sur un réseau Docker différent) de joindre tripoli-edge, qui tourne nativement sur l'hôte — même pattern que le Nginx de VoltVision sur ce même serveur. tripoli-edge n'écoute jamais sur l'interface publique.

Déploiement (fait manuellement pour cette phase)

L'automatisation complète (build + déploiement via CI) est prévue dans la section CI/CD du brief, pas encore faite. Pour l'instant, sur le serveur :

# build (rustc/cargo installés via apt)
cd /opt/tripoli-edge/src && cargo build --release
install -m 755 target/release/tripoli-edge /usr/local/bin/tripoli-edge
systemctl restart tripoli-edge

Le service tourne sous l'utilisateur système tripoli (sans shell, sans privilège) via deploy/tripoli-edge.service, déjà installé dans /etc/systemd/system/.

Le bloc Caddy est dans deploy/Caddyfile.snippet — ajouté à /opt/edge/Caddyfile sur le serveur (fichier partagé, donc pas commité dans son intégralité ici). Une règle ufw supplémentaire était nécessaire pour que Caddy puisse joindre 172.17.0.1:9000 (voir ansible/roles/base/tasks/main.yml).

Vérifié en production

curl https://tripoli.cloud/healthz   -> 200 "ok"
curl https://tripoli.cloud/metrics   -> métriques Prometheus