Publication auto des conteneurs #41
Labels
No labels
Optimization
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Dockerfiles/nginx-reverse-proxy-dashboard#41
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Autopublication des conteneurs à la demande à la mode Traefik
"Cette partie va être très dense"
Comme le Nginx Control acceder au socket Docker on devrait pouvoir le faire.
comme toujours on garde le mecanisme de test avant recharge de nginx
Partie 1 : depuis le meme hote que Nginx Control
A la manière de Traefik on se base sur les labels Docker pour générer de façon dynamique les fichiers de virtualhost.
Snippet au niveau server si qui donne en config : include snippets/<filename.conf>
Declaration des locations XX est un increment 01 / 02 / 03 ...
Auto HTTP vers HTTPS devrait créer un bloc server automatique de redirection 301 de HTTP vers HTTPS
Pour les $backendXX certainement generer ce block avec la liste des localtions car on est docker donc proxpass peut poser des problèmes :
resolver 127.0.0.11 valid=30s;
set $backendXX http(s)://$backendXX:port;
...
Prévoir des labels aussi pour activer le monitoring global, la désactivation si niveau location si on le souhaite des desactiver le monitoring à ce niveau
Prévoir des labels pour désactiver le diagnostic au niveau vhost
Voir d apres toi ce qui manque
Prendre en compte le deploiement Git, comme les vhosts sont généré à la voler pas Nginx Control sur les … peut etre créer un modele du type docker_<server_name>.conf
Partie 2 : gestion des hôtes docker distant
Pour cette partie l'idée va être de faire la même chose pour les hôtes distants, ce qui va nécessite un agent qui doit etre déployer sur les hôtes Docker et va communiquer avec Nginx Control.
Reprendre la partie avec l'agent
Dans le Dashboard une gestion des agents et aussi des métriques (cpu, ram, traffic …)
Depuis les hôtes distants devrait pouvoir être de 3 types les deux premiers ne devrait pas posser de probleme :
L agent doit etre leger (Go ?)
Securité, chaque doit etre approuver dans le Dashboard , trafic chiffré (TLS, SSL ?) et commnication Nginx Control proterger (cle api, hash …)
En fonction du mode 1,2,3 le proxy_pass Backend doit etre adapter et je suppose que le resolver …, ici n'est pas necessaire. dans le fichier vhost en entete avoir en commentaire
Generer auto
Agent XX
…
idéalement dans le top, serait qu'un agent puisse communiquer avec plusieurs Nginx Control, car j'ai régulièrement plusieurs reverse proxy (DMZ pour exterieure et LAN pour interne) mais certain sites/application sont publié sur les deux reverse
Autopublication des conteneurs par labels Docker (façon Traefik) — Design
Statut : proposition à valider avant implémentation. Ce document couvre
les deux parties demandées, complète le schéma de labels proposé, et liste
explicitement ce qu'il manque à mon avis. Rien n'est codé — c'est la base de
discussion avant de démarrer.
Principe général
Nginx Control a déjà un accès (lecture) au socket Docker (health-checks,
listing de conteneurs pour
/api/backends). L'extension proposée est demême nature : un watcher qui scanne les conteneurs, en extrait un état
désiré, génère un/des fichiers vhost, et applique le même pipeline de
sécurité que tout le reste du projet : écrire →
nginx -tsur le résultat→ rollback si échec → reload seulement si un changement réel → jamais
committer ces fichiers dans Git → skip proprement au premier boot.
C'est exactement le mécanisme déjà construit pour
features/blocklists.js(cache-on-failure, test-before-reload, unchanged-detection, protection
contre le déploiement Git). Il sera généralisé plutôt que dupliqué.
Partie 1 — Auto-config locale (même hôte que Nginx Control)
Schéma de labels (révisé)
Je garde votre proposition, avec quelques ajustements pour la cohérence et
la sécurité :
nginx-control.enable=trueauto_config=enablepour un booléen cohérent avec le reste du projetnginx-control.network=<network>nginx-control.vhost.server_name=example.comserver_namenginx-control.vhost.listen=443nginx-control.vhost.ssl_certificate=auto|certbot_dns|certbot_http|snippet|nonenginx-control.vhost.ssl_certificate.snippet=<file>snippetnginx-control.vhost.server.snippet01,02, ...server{}include /nginx/snippets/<file>;nginx-control.vhost.location01=/,location02=/api, ...nginx-control.vhost.location01.proxy_pass=http://backend:8080nginx-control.vhost.location01.snippet01,02, ...server.snippetXX)nginx-control.vhost.http_to_https_auto=true|falsefalsesi absentnginx-control.monitor.enable=true|falsenginx-control.vhost.location01.monitor.enable=falsenginx-control.diagnostic.enable=false# nginx-control-diagnostic: offen tête — réutilise le mécanisme déjà existant, pas un nouveaunginx-control.vhost.analyze.enable=false# nginx-control-analyze: off— idem, mécanisme existant réutilisénginx-control.vhost.analyze.ignore_rules=1,2,4# nginx-control-analyze-ignore-rules: 1, 2, 4Point important : les deux derniers ne sont pas de nouveaux mécanismes —
ce sont les commentaires magiques déjà supportés par le parseur de vhost
existant (
parseVhostFile(), testé dans votre suite actuelle). Legénérateur auto n'a qu'à les écrire lui-même en tête de fichier/bloc.
Résolution du backend (le point technique le plus sensible)
Votre intuition est correcte et c'est la bonne pratique nginx+Docker : sans
variable, nginx résout le nom une seule fois au chargement de la config et
ne revoit jamais un conteneur backend qui redémarre avec une autre IP.
Pour chaque location, le générateur produira :
127.0.0.11est le résolveur DNS embarqué de Docker — pas une valeur àlaisser configurable, elle est fixe par construction Docker.
Mode
ssl_certificate=autoLe projet a déjà une logique de résolution SSL (
GET /api/vhost/ssl-sources,utilisée par la génération manuelle de vhost). Le mode
autola réutilisetelle quelle plutôt que d'être réinventée : chercher un certificat
existant qui matche
server_name, sinon un snippet SSL existant, sinonéchec explicite (pas de vhost HTTPS cassé silencieusement — on retombe sur
HTTP le temps qu'un certificat soit obtenu).
Modes
certbot_dns/certbot_httpCe sont les seuls modes asynchrones : obtenir un certificat prend du
temps (délai DNS-01 en particulier). Proposition :
certificat déclenchée en tâche de fond via les features Certbot
existantes.
redirection, si
http_to_https_autoest actif.certificat" est un état normal, pas une erreur.
Nommage et protection Git
Fichier généré :
sites/docker_<server_name>.conf, comme vous le proposez.Le préfixe
docker_sert à trois choses :reflètent un état runtime Docker, pas une intention versionnée) ;
exactement comme les fichiers générés par
blocklists.js.Changement nécessaire au mécanisme existant : aujourd'hui,
features/deploy.js'sGENERATED_FILESest une liste statique dechemins fixes (deux ou trois fichiers connus au boot). Avec l'auto-config
Docker, le nombre de fichiers est dynamique (un par conteneur labellisé,
apparaît/disparaît à la volée). Je généraliserai
setDeps({ generatedFiles })pour accepter soit un tableau (rétrocompatible avec blocklists.js), soit une
fonction rappelée à chaque vérification (
() => [...fichiers courants]) —et j'ajouterai un second critère : tout fichier de
sites/dont le nomcommence par
docker_est protégé par préfixe, pas seulement par listeexhaustive. Ceinture et bretelles.
Détection : événements Docker + filet de sécurité
Deux mécanismes combinés, comme partout ailleurs dans ce projet (précédent :
blocklists.jsa un scheduler + un bouton de rafraîchissement manuel) :/eventsen streaming sur le socket) pour réagirimmédiatement à un
start/stop/die/updated'un conteneur labellisé— la réactivité "à la Traefik".
événement serait manqué (redémarrage du dashboard pendant qu'un conteneur
démarre).
docker compose upd'une stack de 10 services) ne doivent jamais déclencher 10reloads nginx à la suite. Un court délai de regroupement (quelques
secondes) avant d'appliquer un lot de changements en un seul test+reload.
Sécurité — le point le plus important de toute cette fonctionnalité
Un label Docker peut être posé par quiconque a le droit de lancer un
conteneur sur l'hôte. C'est une source de données à traiter avec la même
méfiance qu'une liste IP externe (cf.
lib/blocklist-parse.js) :nginx :
server_namevalidé par regex, ports numériques bornés, noms desnippet validés contre la liste réelle des fichiers existants sur le
disque (jamais un chemin arbitraire, jamais de traversée de répertoire).
server_nameentre deux conteneurs : jamais un écrasementsilencieux — détection explicite, log clair, notification, aucun des deux
n'est appliqué tant que le conflit n'est pas résolu (sauf usage voulu du
upstream_group, voir "ce qui manque" ci-dessous).légitimement déclarer un vhost pour lui-même, mais rien n'empêche un
conteneur compromis de déclarer
server_name=admin.example.compourdétourner un vhost existant. Je propose un réglage
(
docker-autoconfig.yml) avec deux options combinables :allowed_server_name_patterns— domaines/wildcards pré-autorisés,appliqués automatiquement sans intervention ;
require_approval: true— toutserver_namehors de cette listeapparaît "en attente" dans l'UI jusqu'à validation manuelle.
Traefik lui-même n'a pas cette granularité (confiance totale à quiconque
peut lancer un conteneur) ; je pense que ce filet est cohérent avec les
instructions du projet ("bonnes pratiques de sécurité").
Ce qu'il manque à mon avis (au-delà de votre liste)
upstream_group— plusieurs conteneurs (répliques) contribuant aumême service :
nginx-control.vhost.location01.upstream_group=apigénèreun bloc
upstream api { server ...; server ...; }agrégeant toutes lesinstances portant ce même nom de groupe, plutôt qu'un conflit de
server_name.supprimé, son vhost doit être retiré (avec test avant reload, comme
toujours) — sinon accumulation de vhosts fantômes pointant vers des
backends morts.
changé, comme l'unchanged-detection de blocklists.js — jamais un reload
sur un no-op.
dans le log d'événements existant, avec sa source (Docker local vs quel
agent en Partie 2).
labellisés, leur statut (actif / en attente d'approbation / en attente de
certificat / erreur), un aperçu en lecture seule du vhost généré, et un
bouton "Forcer un rescan".
Partie 2 — Hôtes Docker distants (agent)
Principe
Un agent léger (Go — accord avec votre proposition : binaire statique,
faible empreinte, cross-compilation facile) tourne sur chaque hôte distant.
Il lit les mêmes labels sur son Docker local, construit un manifest de
vhosts désirés, et le pousse à un ou plusieurs Nginx Control. Nginx Control
génère alors le vhost exactement comme en Partie 1, avec un
proxy_passadapté au mode de connectivité.
Workflow d'approbation (jamais de confiance implicite)
attente, bouton Approuver → génère un jeton scoped dédié (même
famille que les jetons de déploiement CI/CD déjà livrés : rôle propre,
permissions limitées aux seules routes agent, révocable à tout moment
sans fenêtre de cache).
Sécurité des communications
cohérent avec le mécanisme des jetons de déploiement déjà en place, rapide
à livrer, révocable instantanément.
déploiements à plus haute exigence — plus robuste (résiste à un vol du
seul jeton) mais nécessite une PKI et une révocation de certificat, plus
lourd. Je recommande de démarrer par V1.
Les 3 modes — analyse
Modes 1 et 2 (bind port hôte, ou frontal Traefik/reverse-proxy déjà en
place) sont en réalité le même mode côté Nginx Control : un simple
proxy_passdirect vers une IP:port joignable, sans blocresolver(quin'a de sens que pour la résolution DNS interne Docker sur le même hôte que
nginx). Je les fusionne en un seul "mode direct" dans l'implémentation ;
la distinction 1 vs 2 n'existe que côté hôte distant (bind natif vs délégué
à un autre reverse proxy), pas dans le code de Nginx Control.
Mode 3 (l'agent fait lui-même reverse proxy, aucun port bindé) :
proxy_passvers l'agent (pas vers le conteneurbackend directement).
communiqué dans le manifest) plutôt qu'un routing par
Host/SNI partagé —plus simple, plus robuste, pas de dépendance à la préservation du
Hostheader bout en bout.
autres vhosts, gestion de certificat centralisée) — la liaison Nginx
Control ↔ agent est un canal interne déjà chiffré (voir tunnel ci-dessous).
l'agent (à la Cloudflare Tunnel/ngrok) plutôt qu'une connexion entrante
Nginx Control → agent. Ça résout un vrai problème réseau que Traefik ne
résout pas nativement : un hôte distant derrière NAT, sans IP publique
ni port entrant ouvert, peut quand même publier ses services — l'agent
ouvre la connexion vers Nginx Control, jamais l'inverse. Gros avantage
pratique.
En-tête des vhosts générés pour un agent distant
Multi-master (un agent, plusieurs Nginx Control — DMZ + LAN)
Le fichier de config de l'agent contient une liste de cibles Nginx
Control, chacune avec sa propre approbation/jeton (deux Nginx Control
indépendants ne se connaissent pas entre eux, donc deux identités
distinctes). Nouveau label pour contrôler la diffusion :
dmz/lansont des noms logiques définis dans la config locale de l'agent,qui les fait correspondre à ses cibles réelles. Un conteneur publié
uniquement en LAN n'apparaît jamais dans le manifest envoyé au Nginx Control
DMZ.
Métriques
Nouvelle page Agents : statut (en ligne/hors ligne, dernière
communication), CPU/RAM de l'hôte, trafic réseau, liste des conteneurs
exposés par agent. Récupération en push (heartbeat périodique initié
par l'agent) plutôt qu'en pull — cohérent avec le modèle de connexion
sortante du mode 3/tunnel, et plus simple côté authentification (toujours
l'agent qui initie).
Ce qu'il manque à mon avis
que le cache blocklists — garder la dernière configuration connue,
afficher "agent hors ligne depuis Xmin" dans l'UI, jamais de suppression
automatique sur un simple flap réseau. Une suppression ne doit intervenir
que sur une action explicite (agent désapprouvé/supprimé) ou un délai de
grâce long et configurable.
protocol_versiondans le manifest) pourfaire évoluer le format sans casser des agents plus anciens déployés sur
des hôtes qu'on ne met pas à jour au même rythme que le dashboard.
de service (spam de vhosts, reload en boucle) — même limitation de
fréquence/debounce qu'en Partie 1, plus un plafond du nombre de vhosts
acceptés par agent.
docker-compose.ymlannoté avec leslabels, à livrer comme les pipelines CI de la dernière fonctionnalité.
Plan de mise en œuvre proposé (phasage)
Vu la densité assumée du sujet, je propose quatre livraisons distinctes
plutôt qu'un unique gros chantier :
(server_name + listen + une location + proxy_pass + resolver), test +
reload, fichier
docker_<name>.conf, généralisation de la protectionGit (liste dynamique + protection par préfixe).
location), monitoring/diagnostic par label,
http_to_https_auto,upstream_group, Docker Events + debounce, UI dédiée.manifest), page Agents (liste/approbation/jetons scoped), mode direct
uniquement (fusion 1+2).
multi-master (
publish=), agent Go complet.Je recommande de démarrer par l'étape 1, livrée et testée, avant de figer le
protocole de la Partie 2 (qui a plus d'inconnues réseau/sécurité à valider).
fonctionnalité totalement implémenter, test à faire les tests