237 lines
9.6 KiB
Markdown
237 lines
9.6 KiB
Markdown
---
|
|
title: Traefik KOP
|
|
created: 2026-06-06
|
|
updated: 2026-06-06
|
|
type: app
|
|
tags: [catalogue, reverse-proxy, traefik, multi-host, redis, docker, go]
|
|
confidence: high
|
|
contested: false
|
|
sources: [https://selfh.st/apps/?tag=Reverse+Proxy, https://github.com/jittering/traefik-kop]
|
|
---
|
|
|
|
# 🚦 Traefik KOP
|
|
|
|
> **Agent de découverte multi-host pour Traefik : synchronise les containers Docker distants via Redis**. Résout le problème du cluster Docker **sans Swarm/K8s** : un seul Traefik public fait face à Internet, des agents sur chaque node exposent leurs services.
|
|
|
|
## 📋 Informations Générales
|
|
|
|
| Champ | Valeur |
|
|
| :--- | :--- |
|
|
| **Site web** | (GitHub uniquement) |
|
|
| **GitHub** | [jittering/traefik-kop](https://github.com/jittering/traefik-kop) |
|
|
| **License** | MIT |
|
|
| **Langage** | Go (98.4 %) |
|
|
| **Étoiles GitHub** | 493 ⭐ |
|
|
| **Dernière MAJ** | 2026-05-11 (v0.20.1) |
|
|
| **Catégorie** | [[cat-reverse-proxy|Reverse Proxy]], Multi-host, Docker, Redis |
|
|
|
|
## 📝 Description
|
|
|
|
**Traefik KOP** (par Chetan Sarva, alias jittering) est un **agent de découverte Docker→Redis→Traefik** : il tourne sur **chaque host Docker** d'un cluster et **publie dans Redis** les labels Traefik de ses containers, pour qu'une **instance Traefik centrale** (unique, publique) puisse router le trafic vers le bon host via le **redis provider** de Traefik.
|
|
|
|
Le problème résolu : Traefik fonctionne nativement avec **Docker Swarm** ou **Kubernetes** pour la découverte multi-host. Mais en mode "**plain Docker**" multi-host (plusieurs machines, pas d'orchestrateur), il n'y a pas de mécanisme unifié. KOP apporte cette fonctionnalité avec **un binaire Go léger + Redis**.
|
|
|
|
**Caractéristiques principales** :
|
|
|
|
- ✅ **Léger** : un seul binaire Go (~15 MB) par host Docker distant
|
|
- ✅ **Même syntaxe** que le provider Docker de Traefik : labels standards
|
|
- ✅ **Redis backend** : source unique de vérité partagée
|
|
- ✅ **Compatible Sentinel** Redis (pour la HA)
|
|
- ✅ **Bind IP** configurable par service (`:8088` du container sur le bon host)
|
|
- ✅ **Détection auto** de l'IP de bind (interface réseau ou IP explicite)
|
|
- ✅ **CLI flags + env vars** (12-factor)
|
|
- ✅ **Healthcheck** intégré
|
|
- ✅ **Remplacement d'IP** customisable (utile en NAT / WireGuard)
|
|
- ✅ **Cross-platform** : Linux, ARM, FreeBSD
|
|
|
|
**Public cible** : administrateurs qui ont un **cluster Docker multi-host "artisanal"** (3-10 machines, pas envie de Swarm ni K8s) et qui veulent **un seul reverse proxy public** pour tout exposer avec des certs Let's Encrypt unifiés. KOP est cité comme **la** solution de référence pour ce cas d'usage (avec [[app-frp]] et des solutions type Consul).
|
|
|
|
## 🚀 Installation
|
|
|
|
### Architecture cible
|
|
|
|
```
|
|
Internet
|
|
│
|
|
▼
|
|
┌───────────┐
|
|
│ Traefik │ (host public)
|
|
│ + Redis │
|
|
└─────┬─────┘
|
|
│ (redis pub/sub)
|
|
┌──────────┼──────────┐
|
|
▼ ▼ ▼
|
|
┌────────┐ ┌────────┐ ┌────────┐
|
|
│ Host A │ │ Host B │ │ Host C │
|
|
│ traefik-kop │traefik-kop │traefik-kop
|
|
│ + Docker │+ Docker │+ Docker
|
|
└────────┘ └────────┘ └────────┘
|
|
```
|
|
|
|
### Sur le host Traefik public (host central)
|
|
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: '3.8'
|
|
services:
|
|
traefik:
|
|
image: traefik:v3
|
|
container_name: traefik
|
|
restart: unless-stopped
|
|
command:
|
|
- "--providers.docker=true"
|
|
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
|
|
- "--providers.docker.exposedbydefault=false"
|
|
- "--providers.redis=true"
|
|
- "--providers.redis.endpoints=redis:6379"
|
|
- "--entrypoints.web.address=:80"
|
|
- "--entrypoints.websecure.address=:443"
|
|
- "--certificatesresolvers.letsencrypt.acme.email=you@example.com"
|
|
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
|
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
- ./letsencrypt:/letsencrypt
|
|
networks:
|
|
- proxy
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: redis
|
|
restart: unless-stopped
|
|
command: redis-server --save 60 1 --loglevel warning
|
|
volumes:
|
|
- ./redis-data:/data
|
|
networks:
|
|
- proxy
|
|
|
|
networks:
|
|
proxy:
|
|
external: true
|
|
```
|
|
|
|
### Sur chaque host Docker distant
|
|
|
|
```yaml
|
|
# docker-compose.yml (sur host A, B, C...)
|
|
version: '3.8'
|
|
services:
|
|
traefik-kop:
|
|
image: ghcr.io/jittering/traefik-kop:latest
|
|
container_name: traefik-kop
|
|
restart: unless-stopped
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
environment:
|
|
- REDIS_ADDR=192.168.1.50:6379 # IP du host central
|
|
- BIND_IP=192.168.1.75 # IP de CE host distant
|
|
- KOP_HOSTNAME=host-a
|
|
- VERBOSE=true
|
|
networks:
|
|
- proxy
|
|
```
|
|
|
|
### Exemple de service à exposer (sur host distant)
|
|
|
|
```yaml
|
|
# sur host A : service nginx
|
|
version: '3.8'
|
|
services:
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: nginx
|
|
ports:
|
|
- "8088:80"
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.nginx.rule=Host(`nginx.example.com`)"
|
|
- "traefik.http.routers.nginx.tls=true"
|
|
- "traefik.http.routers.nginx.tls.certresolver=letsencrypt"
|
|
- "traefik.http.services.nginx.loadbalancer.server.scheme=http"
|
|
- "traefik.http.services.nginx.loadbalancer.server.port=8088"
|
|
```
|
|
|
|
> ⚠️ Le `traefik.http.services.X.loadbalancer.server.port` **doit** correspondre au port publié sur l'host distant (8088 ici), pas le port interne du container (80).
|
|
|
|
## ⚙️ Configuration Initiale
|
|
|
|
1. **Déployer Traefik + Redis** sur le host public (cf. bloc ci-dessus).
|
|
2. **Déployer `traefik-kop`** sur chaque host distant avec `REDIS_ADDR` pointant vers le Redis public.
|
|
3. **Ajouter des labels Traefik standards** sur les containers des hosts distants (comme s'ils étaient sur le host central).
|
|
4. **Tester** : `curl -H "Host: nginx.example.com" http://TRAEFIK_PUBLIC_IP/` doit répondre.
|
|
|
|
### Configuration avancée (ordre de précédence pour bind IP)
|
|
|
|
1. Label `kop.<service>.bind.ip` (per-service)
|
|
2. Label `kop.bind.ip` (global)
|
|
3. `traefik.docker.network` (auto-détection via réseau)
|
|
4. `--bind-ip` / `BIND_IP` env (global)
|
|
5. `--bind-interface` / `BIND_INTERFACE` (avec `network_mode: host`)
|
|
6. Auto-détection IP de l'host
|
|
|
|
## 🔄 Alternatives
|
|
|
|
### Open Source
|
|
|
|
- **Docker Swarm mode** — la voie "standard" multi-host Docker
|
|
- **Kubernetes + Traefik Ingress** — pour les gros déploiements
|
|
- **HashiCorp Consul** + Traefik provider — alternative à Redis
|
|
- **etcd** + Traefik provider — alternative à Redis
|
|
- **GloboDNS / PowerDNS** — pas vraiment comparable (DNS)
|
|
- **Traefik Pilot** (abandonné)
|
|
- [[app-frp]] — tunnel L4 multi-host (approche différente)
|
|
|
|
### Propriétaires (ce que Traefik KOP remplace)
|
|
|
|
- **Cloudflare Tunnel** (gratuit, gère multi-host)
|
|
- **Ngrok Enterprise** (multi-region)
|
|
- **Ngrok + Reserved domains**
|
|
- **Cloudflare Spectrum** (TCP/UDP)
|
|
- **Datadog Service Map** orienté observabilité
|
|
- **Pusher / Ably** (si usage realtime)
|
|
|
|
### Comparaison rapide
|
|
|
|
| Critère | Traefik KOP | Docker Swarm | Consul + Traefik |
|
|
| :--- | :--- | :--- | :--- |
|
|
| Orchestrateur requis | ❌ | ✅ Swarm | ❌ |
|
|
| Backend state | Redis | Raft (intégré) | Consul KV |
|
|
| Léger | ✅ (15 MB) | ❌ | ⚠️ |
|
|
| Complexité | ✅ Faible | ⚠️ Moyenne | ⚠️ Moyenne |
|
|
| Tolérance panne Redis | ❌ | n/a | ⚠️ |
|
|
| HA | Redis Sentinel | Natif (Raft) | Natif (Consul) |
|
|
| License | MIT | Apache-2.0 | MPL-2.0 |
|
|
|
|
**Verdict** : **Traefik KOP** pour les clusters **3-10 hosts** "à la main" qui ne veulent pas de Swarm/K8s. **Docker Swarm** si on accepte l'orchestrateur Docker natif. **Consul** pour qui a déjà l'écosystème HashiCorp.
|
|
|
|
## 🔐 Sécurité
|
|
|
|
- **Redis** : doit être sécurisé (mot de passe, ACL, TLS). Sans auth, n'importe qui peut injecter des routes dans Traefik.
|
|
- **Docker socket** : `traefik-kop` lit `/var/run/docker.sock` en RW → un container compromis peut **usurper** des routes. À monter en `ro` si possible (mais limité).
|
|
- **Bind IP** : ne pas mettre `0.0.0.0`, utiliser l'IP LAN explicite pour éviter l'exposition sur le WAN
|
|
- **Réseau Redis** : ne **jamais** exposer Redis sur Internet, VPN ou WireGuard entre les hosts
|
|
- **API Traefik** : désactiver le dashboard en production (`--api.insecure=false`) ou le mettre derrière auth
|
|
- **Rotation des credentials Redis** : possible, KOP recharge à chaud
|
|
- **Sentinel** : recommandé pour la HA (plusieurs instances Redis)
|
|
- ⚠️ **Pas d'auth par défaut** entre KOP et Traefik : tout repose sur la sécurité du réseau Redis
|
|
|
|
## 📚 Ressources
|
|
|
|
- [README officiel](https://github.com/jittering/traefik-kop)
|
|
- [Issue Traefik #7886 (sticky sessions)](https://github.com/traefik/traefik/issues/7886) — contexte du problème KOP résout
|
|
- [Forum Traefik sticky sessions](https://community.traefik.io/t/sticky-sessions-dont-work/1949)
|
|
- [Documentation Traefik providers](https://doc.traefik.io/traefik/providers/redis/)
|
|
- [Sponsor : ko-fi chetan](https://github.com/sponsors/chetan) — le dev principal
|
|
|
|
## Pages Liées
|
|
|
|
- [[cat-reverse-proxy]] — Catégorie Reverse Proxy
|
|
- [[app-traefik]] — Le reverse proxy central
|
|
- [[app-caddy]] — Alternative plus simple
|
|
- [[docker-swarm]] — Orchestration native Docker
|
|
- [[comparatif-reverse-proxy]] — Comparaison détaillée
|
|
- [[redis]] — Backend de découverte
|