Limpida Apps · architecture réseau

Du nom de domaine au conteneur

Comment une requête vers *.apps.limpida.com ou mcp.limpida.com traverse le DNS, la Dedibox, la VM pfSense, puis la VM Ubuntu et ses conteneurs Docker, reverse proxy Nginx en tête.

1IP publique · 212.129.32.80
2VM · pfSense + Ubuntu 22.04
5réseaux Docker bridge
27apps derrière un seul proxy

Le parcours, pas à pas

Choisissez un scénario puis avancez avec les flèches : le schéma met en lumière les éléments traversés à chaque étape.

Client sur Internet Navigateur · Claude.ai Claude Code · Codex (ou Let's Encrypt) DNS public limpida.com · GoDaddy serveurs ns25 / ns26.domaincontrol.com *.apps.limpida.com A 212.129.32.80 mcp.limpida.com A 212.129.32.80 limpida.com A 198.202.211.1 (hors Dedibox) Let's Encrypt émet les certificats TLS après un défi HTTP-01 sur le port 80 Serveur dédié Dedibox IP publique 212.129.32.80 VM pfSense pare-feu · NAT · DNS WAN 212.129.32.80 NAT · redirection de ports TCP 80 → 192.168.189.3 TCP 443 → 192.168.189.3 seuls 80 et 443 sont nécessaires aux apps Résolveur DNS (Unbound) Host Override : mcp.limpida.com → 192.168.189.3 *.apps → NXDOMAIN ⚠ DHCP · NAT sortant bail de la VM Ubuntu, sortie vers GitHub, apt… LAN 192.168.189.1/25 LAN virtuel 192.168.189.0/25 VM Ubuntu 22.04.5 LTS · limpida-apps Docker Engine ens160 · 192.168.189.3/25 :80 :443 → proxy :9000 :9443 → portainer :55432-33 réseau Docker proxy-net · 172.18.0.0/16 proxy · Nginx nginx:1.27-alpine 172.18.0.3 1 vhost par app (conf.d) TLS · HSTS · 80 → 443 ACME → /var/www/certbot sandbox-mcp 172.18.0.4 : 8080 serveur MCP « sandbox-ops » create_app, write_file… monte docker.sock, /opt/sandbox et une clé de déploiement GitHub paul (11)172.18.0.38 :80 billard (20)conteneur :3000 gaspard (1)conteneur :3000 alice (10)conteneur :3000 support (22)conteneur :3000 sebreno (23)172.18.0.37 soustraitantv4conteneur :3000 compterenduconteneur :3000 finance (14)conteneur :3000 portainer172.18.0.2 Postgresgaspard-db… + 18 appsmême modèle Les conteneurs d'apps n'exposent aucun port sur l'hôte : seul le proxy les joint, par leur nom Docker. sandbox-core_default · 172.19.0.0/16 docker.sock certbot 172.19.0.2 certificats partagés avec le proxy (volumes) volumes communs : /etc/letsencrypt /var/www/certbot réseaux internes sebreno_internal 172.21.0.0/16 · sebreno-db aumonerie_internal 172.20.0.0/16 · aumonerie-db base isolée du proxy
DNS public pfSense VM Ubuntu réseaux Docker reverse proxy serveur MCP / pilotage

Vue d'ensemble

Astuce : flèches ← → du clavier. Sur mobile, le schéma défile horizontalement.

1Le DNS limpida.com

La zone limpida.com est hébergée chez GoDaddy (serveurs de noms ns25 et ns26.domaincontrol.com). C'est le premier maillon : il transforme un nom en l'unique IP publique de la Dedibox.

Ce que voit Internet

Un enregistrement générique *.apps.limpida.com → 212.129.32.80 couvre toutes les apps : paul, 11, billard… et même un nom qui n'existe pas encore. C'est pour cela que create_app n'a jamais besoin de toucher au DNS : il suffit qu'un vhost Nginx reconnaisse le nom.

mcp.limpida.com pointe lui aussi vers 212.129.32.80. Le domaine nu limpida.com pointe ailleurs (198.202.211.1) : il n'est pas servi par la Dedibox.

Ce que voit le LAN : le « split-horizon »

Depuis Internet mcp.limpida.com → 212.129.32.80 Depuis le LAN mcp.limpida.com → 192.168.189.3 GoDaddy répond l'IP publique ; pfSense la redirige vers la VM Unbound (pfSense) répond l'IP privée : pas d'aller- retour par le WAN

Une machine du LAN qui viserait l'IP publique devrait sortir par le WAN puis revenir par la NAT (« NAT reflection »), ce que les pare-feu gèrent mal. Le Host Override de pfSense court-circuite ce détour pour mcp.limpida.com.

2La Dedibox et la VM pfSense

Le serveur dédié héberge deux machines virtuelles reliées par un commutateur virtuel privé. pfSense est la seule à porter l'IP publique : c'est le portier de toute la plateforme.

Côté WAN : 212.129.32.80

Tout le trafic entrant arrive sur l'interface WAN de pfSense. Deux règles de redirection de ports le transmettent à la VM Ubuntu :

  • TCP 443 → 192.168.189.3:443 — le trafic HTTPS des apps et du serveur MCP ;
  • TCP 80 → 192.168.189.3:80 — indispensable aux défis Let's Encrypt et à la redirection vers HTTPS.

La VM Ubuntu n'a aucune IP publique : sans ces règles, elle serait invisible d'Internet.

Côté LAN : 192.168.189.0/25

pfSense est la passerelle (192.168.189.1), le serveur DHCP et le résolveur DNS du réseau privé. Le masque /25 offre 126 adresses (.1 à .126).

Dans l'autre sens, le NAT sortant de pfSense permet à la VM Ubuntu de joindre Internet : GitHub pour pousser le code des apps, les registres Docker, les mises à jour, et Let's Encrypt pour demander les certificats.

3La VM Ubuntu « limpida-apps »

Ubuntu 22.04.5 LTS, une seule interface réseau, et Docker qui fait tout le reste.

ParamètreValeurRôle
Interfaceens160 · 192.168.189.3/25Adresse attribuée par le DHCP de pfSense
Route par défautvia 192.168.189.1Toute sortie passe par pfSense
Résolution DNS127.0.0.53systemd-resolved, qui interroge pfSense
Ports publiés80, 443→ conteneur proxy (sur toutes les interfaces)
9000, 9443→ portainer, console web Docker
192.168.189.3:55432 / 55433→ bases Postgres de soustraitant v3 / v4, joignables depuis le LAN uniquement

4Les conteneurs Docker et leurs réseaux

Docker crée des réseaux virtuels internes à la VM (172.16.0.0/12, jamais visibles du LAN). Chaque réseau est un pont Linux avec son propre DNS interne (127.0.0.11) qui résout les noms de conteneurs.

proxy-net le réseau commun

Réseau externe partagé par le proxy, le serveur MCP et chaque conteneur d'app. Chaque docker-compose.yml d'app s'y rattache :

networks:
  proxy-net:
    external: true
services:
  app:
    container_name: paul-app
    image: nginx:alpine
    networks: [proxy-net]   # pas de "ports:" !

Aucune app ne publie de port : le proxy les joint par leur nom (paul-app, billard-app…).

Les autres réseaux

  • sandbox-core_default 172.19.0.0/16 : héberge certbot, qui partage avec le proxy les volumes des certificats et du webroot ACME.
  • sebreno_internal 172.21.0.0/16 et aumonerie_internal 172.20.0.0/16 : l'app est sur deux réseaux (proxy-net + son réseau interne), sa base Postgres uniquement sur l'interne. Le proxy et les autres apps ne peuvent pas l'atteindre.
  • bridge 172.17.0.0/16 : réseau par défaut de Docker, inutilisé par la plateforme.

sandbox-mcp pilote tout ce petit monde via le socket /var/run/docker.sock monté dans son conteneur, ainsi que le dossier /opt/sandbox (apps, vhosts, certificats, registre apps.json).

5Le reverse proxy en tête

Un seul conteneur Nginx (proxy, nginx:1.27-alpine) reçoit 100 % du trafic web et le répartit selon le nom demandé. Voici le vhost réel de cette app, /opt/sandbox/proxy/conf.d/paul.conf :

server {
    listen 80;
    server_name paul.apps.limpida.com 11.apps.limpida.com;   ①
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;                           ②
    }
    location / { return 301 https://$host$request_uri; }
}

server {
    listen 443 ssl;  http2 on;
    server_name paul.apps.limpida.com 11.apps.limpida.com;
    ssl_certificate /etc/letsencrypt/live/paul/fullchain.pem; ③
    ssl_certificate_key /etc/letsencrypt/live/paul/privkey.pem;
    add_header Strict-Transport-Security "max-age=31536000…";

    location / {
        proxy_pass http://paul-app:80;                     ④
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;     # WebSocket
    }
}
  • 1Routage par nom. Toutes les apps partagent la même IP et le même port 443 ; Nginx choisit le bon bloc grâce au nom envoyé par le navigateur (SNI en TLS, en-tête Host ensuite). Le nom canonique et l'alias numérique figurent ensemble.
  • 2Défi Let's Encrypt. Sur le port 80, seul le chemin ACME est servi, depuis le dossier partagé avec certbot ; tout le reste est redirigé en HTTPS.
  • 3Terminaison TLS. Le chiffrement s'arrête au proxy. Un certificat par app (ici valable jusqu'au 25 janvier 2027), renouvelé par certbot.
  • 4Relais interne. La requête continue en HTTP clair sur proxy-net vers le conteneur, avec les en-têtes X-Forwarded-* pour que l'app connaisse l'IP et le protocole d'origine.

Le cas particulier du serveur MCP

Le vhost mcp.limpida.com relaie vers http://sandbox-mcp:8080 avec proxy_buffering off et des délais de 3600 s : le protocole MCP renvoie ses réponses en flux et une opération (build, certificat) peut durer.

Plan d'adressage

Relevé effectué le 27 octobre 2026.

ÉlémentAdresseRôle
Dedibox · WAN pfSense212.129.32.80IP publique, cible de *.apps et mcp
pfSense · LAN192.168.189.1/25Passerelle, DNS (Unbound), DHCP
VM Ubuntu limpida-apps192.168.189.3/25Hôte Docker
Réseau proxy-net172.18.0.0/16Proxy ↔ apps ↔ serveur MCP
Réseau sandbox-core_default172.19.0.0/16certbot
Réseau aumonerie_internal172.20.0.0/16App ↔ base, isolé
Réseau sebreno_internal172.21.0.0/16App ↔ base, isolé
proxy172.18.0.3Nginx, ports hôte 80 / 443
sandbox-mcp172.18.0.4:8080Serveur MCP sandbox-ops
portainer172.18.0.2Console Docker, ports hôte 9000 / 9443
certbot172.19.0.2Certificats Let's Encrypt
paul-app (cette page)172.18.0.38:80paul.apps.limpida.com · 11.apps.limpida.com

Points d'attention relevés

Constats faits en explorant la plateforme pour construire cette page.

*.apps.limpida.com ne résout pas depuis le LAN

Interrogé via pfSense, paul.apps.limpida.com renvoie NXDOMAIN alors qu'il résout publiquement : le résolveur ne relaie visiblement pas les noms de limpida.com qu'il ne connaît pas. Piste : dans Unbound (options avancées), une zone local-zone: "apps.limpida.com." redirect + local-data: "apps.limpida.com. A 192.168.189.3" couvrirait toutes les apps d'un coup.

Portainer publié sur toutes les interfaces

Les ports 9000 / 9443 sont ouverts sur la VM pour tout le LAN. À vérifier côté pfSense qu'aucune redirection ne les expose sur Internet, ou les restreindre à 127.0.0.1.

Bases Postgres partagées sur proxy-net

Les apps plus anciennes (gaspard, finance, compterendu, ficheespace…) ont leur base sur proxy-net, donc joignable par le proxy et les autres apps. Le modèle « réseau interne par app » de sebreno et aumonerie est plus sûr ; les bases soustraitant v3/v4 sont en outre publiées sur le LAN (55432 / 55433).

Un peu de ménage possible

Deux conteneurs arrêtés sans nom explicite (cool_pare, inspiring_northcutt) et l'ancien vhost sbcmi1.limpida.com subsistent.