
reproxy v1.7.1
Serveur HTTP(S) de périphérie léger et proxy inverse avec SSL automatique, découverte Docker/Consul, authentification par route, limitation de débit, et basculement basé sur les vérifications de santé.
Reproxy est un serveur edge HTTP(s) / proxy inverse simple supportant divers fournisseurs (docker, static, file, consul catalog). Un ou plusieurs fournisseurs fournissent des informations sur le serveur demandé, l'URL demandée, l'URL de destination et l'URL de vérification de santé. Il est distribué sous forme de binaire unique ou de conteneur docker.
- Terminaison SSL automatique avec Let's Encrypt
- Prise en charge des certificats SSL fournis par l'utilisateur
- Règles de proxy simples mais flexibles
- Fournisseur de règles de proxy statique en ligne de commande
- Fournisseur de règles de proxy dynamique basé sur fichier
- Fournisseur Docker avec découverte automatique
- Fournisseur Consul Catalog avec découverte par tags de service
- Prise en charge de multiples hôtes (virtuels)
- Compression du trafic optionnelle
- Contrôle d'accès basé sur IP optionnel
- Authentification de base par route
- Limites de taille et délais d'attente définis par l'utilisateur
- Distribution en binaire unique
- Distribution en conteneur Docker
- Serveur d'actifs statiques intégré avec mode « SPA friendly » optionnel
- Prise en charge des règles de redirection
- Limiteur optionnel pour l'activité globale ainsi que pour l'activité de l'utilisateur
- Vérification de santé en direct et basculement/équilibrage de charge
- Serveur de gestion avec informations sur les routes et métriques Prometheus
- Prise en charge des plugins via RPC pour implémenter des fonctionnalités personnalisées
- Journalisation optionnelle avec à la fois le format Apache Log Format et des rapports stdout simplifiés.
Le serveur (hôte) peut être défini comme un FQDN, c'est-à-dire s.example.com, * (tous) ou une expression régulière. La correspondance exacte a priorité, donc s'il y a deux règles avec les serveurs example.com et example\.(com|org), la requête vers example.com/some/url correspondra à la première. L'URL demandée peut être une regex, par exemple ^/api/(.*) et l'URL de destination peut contenir des groupes correspondant à la regex, c'est-à-dire http://d.example.com:8080/$1. Pour l'exemple ci-dessus, http://s.example.com/api/something?foo=bar sera proxyfié vers http://d.example.com:8080/something?foo=bar.
Par commodité, les requêtes avec un / final et sans groupes regex sont étendues à /(.*), et les destinations dans ces cas sont étendues à /$1. C'est-à-dire /api/ -> http://127.0.0.1/service sera traduit en ^/api/(.*) -> http://127.0.0.1/service/$1.
La substitution d'hôte est prise en charge dans l'URL de destination. Par exemple, /files/${host} sera remplacé par le nom d'hôte correspondant. $host (sans accolades) peut également être utilisé.
HTTP et HTTPS sont tous deux pris en charge. Pour HTTPS, un certificat statique peut être utilisé ainsi que des certificats ACME automatisés (Let's Encrypt). Un serveur d'actifs optionnel peut être utilisé pour servir des fichiers statiques. Démarrer reproxy nécessite au moins un fournisseur défini. Le reste des paramètres est strictement optionnel et a des valeurs par défaut raisonnables.
Exemples :
- avec un fournisseur statique :
reproxy --static.enabled --static.rule="*,example.com/api/(.*),https://api.example.com/$1" - avec une découverte automatique docker :
reproxy --docker.enabled --docker.auto - en tant que conteneur docker :
docker up -p 80:8080 umputun/reproxy --docker.enabled --docker.auto - avec SSL automatique :
docker up -p 80:8080 -p 443:8443 umputun/reproxy --docker.enabled --docker.auto --ssl.type=auto --ssl.fqdn=example.com
Installation
Reproxy est distribué sous forme d'un petit binaire autonome ainsi que d'une image docker. Le binaire et l'image supportent de multiples architectures et systèmes d'exploitation, notamment linux_x86_64, linux_arm64, linux_arm, macos_x86_64, macos_arm64, windows_x86_64 et windows_arm. Nous fournissons également des paquets deb et rpm pour arm64 et x86.
- pour une distribution binaire, téléchargez le fichier approprié dans la section des versions
- pour les utilisateurs de Homebrew :
brew install umputun/apps/reproxy - le conteneur docker est disponible sur Docker Hub ainsi que sur Github Container Registry. C'est-à-dire
docker pull umputun/reproxyoudocker pull ghcr.io/umputun/reproxy.
La dernière version stable a le tag docker :vX.Y.Z (avec l'alias :latest) et le master actuel a le tag :master.
Fournisseurs
Les règles de proxy sont fournies par divers fournisseurs. Actuellement inclus - file, docker, static et consul-catalog. Chaque fournisseur peut définir plusieurs règles de routage pour les requêtes proxyfiées et les actifs statiques. L'utilisateur peut définir plusieurs fournisseurs en même temps.
Voir des exemples de divers fournisseurs dans examples
Fournisseur statique
C'est le fournisseur le plus simple, définissant toutes les règles de correspondance directement en ligne de commande (ou environnement). Plusieurs règles supportées. Chaque règle est composée de 3 à 7 éléments séparés par des virgules server,sourceurl,destination[,ping-url[,forward-health-checks[,timeout[,throttle]]]]. Par exemple :
*,^/api/(.*),https://api.example.com/$1- proxyfie toute requête vers tout hôte/serveur avec le préfixe/apivershttps://api.example.comexample.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping- proxyfie toutes les requêtes versexample.comet avec l'URL/foo/barvershttps://api.example.com/zzzet utilisehttps://api.example.com/pingpour la vérification de santé.example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping,true- identique à ci-dessus mais transmet également les requêtes/pinget/healthau backend.example.com,^/upload/(.*),https://api.example.com/$1,,,5m- délai d'attente de requête par route de 5 minutes (4e et 5e champs laissés vides pour ignorer ping-url et forward-health-checks).example.com,^/login,https://api.example.com/login,,,,2- limitation par route de 2 req/s par utilisateur (les champs positionnels précédents sont laissés vides).
Le 4e élément définit une URL ping facultative utilisée pour le rapport de santé. Le 5e élément active éventuellement la transmission des requêtes de vérification de santé au backend (true, yes, 1). Voir la section Vérification de santé pour plus de détails. Le 6e élément est un délai d'attente de requête facultatif par route (durée Go, par exemple 5m, 30s); 0 ou vide hérite du paramètre global --timeout.write. Le 7e élément est une limite facultative de req/s par utilisateur par route ; 0 ou vide hérite de --throttle.user. Les champs positionnels vides sont autorisés (par exemple ,, pour les champs intermédiaires inutilisés).
Fournisseur fichier
Ce fournisseur utilise un fichier yaml avec des règles de routage.
reproxy --file.enabled --file.name=config.yml
Exemple de config.yml:```yaml
default: # the same as * (catch-all) server
- { route: "^/api/svc1/(.*)", dest: "http://127.0.0.1:8080/blah1/$1" }
- { route: "/api/svc3/xyz", dest: "http://127.0.0.3:8080/blah3/xyz", ping: "http://127.0.0.3:8080/ping", remote: "192.168.1.0/24, 127.0.0.1", # optional, restrict access to the route forward-health-checks: true # optional, forward /ping and /health to backend }
- { route: "^/admin/(.*)", dest: "http://127.0.0.4:8080/$1", auth: "admin:$2y$05$..." # optional, per-route basic auth (htpasswd bcrypt format) }
- { route: "^/upload/(.*)", dest: "http://127.0.0.5:8080/$1", timeout: 5m # optional, per-route request timeout (Go duration). 0 or omitted inherits --timeout.write }
- { route: "^/login", dest: "http://127.0.0.6:8080/login", throttle: 2 # optional, per-route req/sec per user. 0 or omitted inherits --throttle.user } srv.example.com:
- { route: "^/api/svc2/(.*)", dest: "http://127.0.0.2:8080/blah2/$1/abc" }
- { route: "/web/", dest: "/var/www", "assets": true } "*.files.example.com":
- { route: "^/files/(.*)", dest: "http://123.123.200.200:8080/$host/$1" }
Ceci est un fournisseur dynamique et les modifications de fichiers seront appliquées automatiquement.
**Plusieurs sites statiques sur différents domaines** peuvent être servis en utilisant des noms de serveur comme clés avec `assets: true`:```yaml
site-en.example.com:
- { route: "/", dest: "/var/www/en", "assets": true }
site-ru.example.com:
- { route: "/", dest: "/var/www/ru", "assets": true }
Important : le champ route pour les règles d'actifs doit être un préfixe de chemin (par exemple / /web/), pas une expression régulière. Les motifs regex comme ^/(.*) ne fonctionneront pas avec assets: true car la correspondance des actifs statiques utilise une comparaison de préfixe de chemin, pas de regex.
Docker provider
Le fournisseur Docker prend en charge une découverte entièrement automatique (avec --docker.auto) sans configuration supplémentaire nécessaire. Par défaut, il redirige toutes les requêtes comme http://<url>/<nom du conteneur>/(.*) vers l'IP interne du conteneur donné et le port exposé. Seuls les conteneurs actifs (en cours d'exécution) seront détectés.
Cette valeur par défaut peut être modifiée avec des labels :
reproxy.server- serveur (nom d'hôte) à faire correspondre. Peut également être une liste de serveurs séparés par des virgules.reproxy.route- route source (emplacement)reproxy.dest- chemin de destination. Note : ce n'est pas une URL complète, mais simplement le chemin qui sera ajouté à l'ip:port du conteneur.reproxy.port- port de destination pour le conteneur découvert.reproxy.ping- chemin de ping pour le conteneur de destination.reproxy.remote- restreindre l'accès à la route avec une liste de sous-réseaux ou d'IP séparés par des virgules.reproxy.auth- exiger une authentification de base pour la route avec des pairesuser:bcrypt_hashséparées par des virgules (générées parhtpasswd -nbB).reproxy.assets- définir le mappage des actifs commeweb-root:location, par exemplereproxy.assets=/web:/var/wwwreproxy.keep-host- conserver l'en-tête Host tel quel (yes,true,1) ou le remplacer par l'hôte de destination (no,false,0)reproxy.forward-health-checks- transmettre les requêtes/pinget/healthau backend plutôt que de les gérer par reproxy (yes,true,1). Utile lorsque le backend a ses propres points de terminaison de vérification de santé avec des réponses spécifiques à l'application.reproxy.timeout- délai d'attente de requête par route en tant que durée Go (par exemple5m,30s).0ou non défini hérite du--timeout.writeglobal. Les valeurs invalides sont ignorées avec un avertissement.reproxy.throttle- limite req/sec par route par utilisateur.0ou non défini hérite de--throttle.user. Les valeurs invalides ou négatives sont ignorées avec un avertissement.reproxy.enabled- activer (yes,true,1) ou désactiver (no,false,0) le conteneur des destinations reproxy.
Veuillez noter : sans --docker.auto, le conteneur de destination doit avoir au moins un des labels reproxy.* pour être considéré comme une destination potentielle.
Avec --docker.auto, tous les conteneurs avec un port exposé seront considérés comme des destinations de routage. Il y a 3 façons de le restreindre :
- Exclure explicitement certains conteneurs avec
--docker.exclude, c'est-à-dire--docker.exclude=c1 --docker.exclude=c2 ... - Autoriser uniquement un réseau docker particulier avec
--docker.network - Définir le label
reproxy.enabled=falseoureproxy.enabled=nooureproxy.enabled=0
Si aucun reproxy.route n'est défini, la route par défaut est ^/<nom_conteneur>/(.*). Dans le cas où toutes les sources proxy doivent avoir le même motif de préfixe, par exemple /api/(.*), l'utilisateur peut définir le préfixe commun (dans ce cas /api) pour toutes les routes basées sur des conteneurs. Cela peut être fait avec le paramètre --docker.prefix.
Le fournisseur Docker permet également de définir plusieurs ensembles de labels reproxy.N.something pour faire correspondre plusieurs routes distinctes sur le même conteneur. Cela est utile car dans certains cas, un seul conteneur peut exposer plusieurs points de terminaison, par exemple une API publique et une API d'administration. Tous les labels ci-dessus peuvent être utilisés avec un "index N", c'est-à-dire reproxy.1.server, reproxy.1.port, etc. N doit être dans la plage 0 à 9.
Il s'agit d'un fournisseur dynamique et tout changement d'état du conteneur sera appliqué automatiquement.
Consul Catalog provider
Utilisation : reproxy --consul-catalog.enabled
Le fournisseur Consul Catalog appelle l'API Consul périodiquement (toutes les secondes par défaut) pour obtenir les services qui ont un tag avec le préfixe reproxy.. L'utilisateur peut redéfinir l'intervalle de vérification avec l'option de ligne de commande --consul-catalog.interval ainsi que l'adresse consul avec l'option de ligne de commande --consul-catalog.address. L'adresse par défaut est http://127.0.0.1:8500.
Par exemple :``` reproxy --consul-catalog.enabled --consul-catalog.address=http://192.168.1.100:8500 --consul-catalog.interval=10s
Par défaut, le fournisseur définit les valeurs pour chaque service :
- enabled `false`
- server `*`
- route `^/(.*)`
- dest `http://<SERVICE_ADDRESS_FROM_CONSUL>/$1`
- ping `http://<SERVICE_ADDRESS_FROM_CONSUL>/ping`
Cette valeur par défaut peut être modifiée avec des balises :
- `reproxy.server` - serveur (nom d'hôte) à faire correspondre. Peut également être une liste de serveurs séparés par des virgules.
- `reproxy.route` - route source (emplacement)
- `reproxy.dest` - chemin de destination. Remarque : ce n'est pas une URL complète, mais seulement le chemin qui sera ajouté à l'ip:port du service.
- `reproxy.port` - port de destination pour le service découvert
- `reproxy.remote` - restreindre l'accès à la route avec une liste de sous-réseaux ou d'IP séparés par des virgules
- `reproxy.auth` - exiger une authentification de base pour la route avec des paires `user:bcrypt_hash` séparées par des virgules (générées par `htpasswd -nbB`)
- `reproxy.ping` - chemin ping pour le service de destination.
- `reproxy.forward-health-checks` - transférer les requêtes `/ping` et `/health` au backend (`true`, `yes`, `1`).
- `reproxy.timeout` - délai d'attente par route pour les requêtes sous forme de durée Go (ex. `5m`, `30s`). `0` ou non défini hérite du `--timeout.write` global. Les valeurs invalides sont ignorées avec un avertissement.
- `reproxy.throttle` - limite de requêtes par seconde par route et par utilisateur. `0` ou non défini hérite de `--throttle.user`. Les valeurs invalides ou négatives sont ignorées avec un avertissement.
- `reproxy.enabled` - activer (`yes`, `true`, `1`) ou désactiver (`toute autre valeur`) le service des destinations reproxy.
### Détails spécifiques à Compose
Dans le cas où les règles sont définies dans un environnement docker compose, la destination avec le groupe regex entrera en conflit avec la syntaxe de compose. Par exemple, tenter d'utiliser `https://api.example.com/$1` dans un environnement compose échouera en raison d'une erreur de syntaxe. La solution standard ici est d'« échapper » le signe `$` en le remplaçant par `$$`, soit `https://api.example.com/$$1`. Cette substitution est prise en charge par docker compose et n'a rien à voir avec reproxy lui-même. Une autre méthode consiste à utiliser `@` au lieu de `$`, ce qui est pris en charge au niveau de reproxy, par exemple `https://api.example.com/@1`_
## Support SSL
Le mode SSL (par défaut aucun) peut être défini sur `auto` (certificats ACME/LE), `static` (certificat existant) ou `none`. Si `auto` est activé, le certificat SSL sera délivré automatiquement pour tous les noms de serveur découverts. L'utilisateur peut le remplacer en définissant la ou les valeurs `--ssl.fqdn`. En mode SSL `auto` et `static`, Reproxy ajoutera automatiquement les en-têtes `X-Forwarded-Proto` et `X-Forwarded-Port`. Ces en-têtes sont utiles pour les services derrière le proxy afin de connaître le protocole d'origine (http ou https) et le numéro de port utilisés par le client.
Lors de l'utilisation d'ACME avec les fournisseurs de découverte (docker, file, consul), les certificats SSL sont automatiquement obtenus pour les serveurs nouvellement découverts sans nécessiter de redémarrage de reproxy.
### Défis ACME
Reproxy prend en charge deux types de défis ACME pour la validation des certificats SSL :
1. **Défi HTTP-01** (par défaut) : Valide la propriété du domaine en servant un jeton à une URL HTTP spécifique. Nécessite que le port 80 soit accessible publiquement.
2. **Défi DNS-01** : Valide la propriété du domaine en créant des enregistrements TXT DNS. Cette méthode :
- Ne nécessite pas que le port 80 soit accessible
- Fonctionne avec les certificats wildcard
- Nécessite une configuration de fournisseur DNS prise en charge
#### Sélection du défi
Reproxy détermine automatiquement quelle méthode de défi utiliser en fonction de votre configuration :
- **HTTP-01** (par défaut) : Utilisé lorsqu'aucun fournisseur DNS n'est configuré
- **DNS-01** : Utilisé lorsqu'un fournisseur DNS est configuré
Vous n'avez pas besoin de sélectionner explicitement un type de défi - configurez simplement un fournisseur DNS si vous souhaitez utiliser les défis DNS-01.
#### Fournisseurs DNS actuellement pris en charge
Reproxy inclut actuellement la prise en charge des fournisseurs DNS suivants :
- **Cloudflare** : `--ssl.dns.type=cloudflare --ssl.dns.cloudflare.api-token=TOKEN`
- **Route53 (AWS)** : `--ssl.dns.type=route53 --ssl.dns.route53.region=REGION --ssl.dns.route53.hosted-zone-id=ID`
- **Gandi** : `--ssl.dns.type=gandi --ssl.dns.gandi.bearer-token=TOKEN`
- **DigitalOcean** : `--ssl.dns.type=digitalocean --ssl.dns.digitalocean.api-token=TOKEN`
- **Hetzner** : `--ssl.dns.type=hetzner --ssl.dns.hetzner.api-token=TOKEN`
- **Linode** : `--ssl.dns.type=linode --ssl.dns.linode.api-token=TOKEN`
- **GoDaddy** : `--ssl.dns.type=godaddy --ssl.dns.godaddy.api-token=TOKEN`
- **Namecheap** : `--ssl.dns.type=namecheap --ssl.dns.namecheap.api-key=KEY --ssl.dns.namecheap.user=USER`
- **Scaleway** : `--ssl.dns.type=scaleway --ssl.dns.scaleway.secret-key=KEY --ssl.dns.scaleway.organization-id=ID`
- **Porkbun** : `--ssl.dns.type=porkbun --ssl.dns.porkbun.api-key=KEY --ssl.dns.porkbun.api-secret-key=SECRET`
- **DNSimple** : `--ssl.dns.type=dnsimple --ssl.dns.dnsimple.api-access-token=TOKEN --ssl.dns.dnsimple.account-id=ID`
- **DuckDNS** : `--ssl.dns.type=duckdns --ssl.dns.duckdns.api-token=TOKEN`
Exemple avec Cloudflare comme fournisseur DNS :```
export CLOUDFLARE_API_TOKEN=your_api_token
reproxy --ssl.type=auto [email protected] --ssl.fqdn=example.com
Le défi DNS-01 est particulièrement utile quand :
- Votre serveur n'a pas le port 80 exposé publiquement
- Vous avez besoin de certificats wildcard (par ex., *.example.com)
- Vous êtes derrière des pare-feu restrictifs
En-têtes
Reproxy permet de nettoyer (supprimer) les en-têtes entrants en passant le paramètre --drop-header (peut être répété). Ce paramètre peut être utile pour s'assurer que certains en-têtes, définis en interne par les services, ne peuvent pas être définis/contrefaits par l'utilisateur final. Par exemple, si certains services responsables de l'authentification définissent X-Auth-User et X-Auth-Token, il est probablement judicieux de supprimer ces en-têtes des requêtes entrantes en passant le paramètre --drop-header=X-Auth-User --drop-header=X-Auth-Token ou via l'environnement DROP_HEADERS=X-Auth-User,X-Auth-Token
La fonction inverse, définir des en-têtes sortants, est également prise en charge. Cela peut être utile dans de nombreux cas, par exemple pour appliquer des règles CORS personnalisées, des en-têtes liés à la sécurité, etc. Cela peut être fait avec le paramètre --header (peut être répété) ou l'environnement HEADER. Par exemple, voici comment cela peut être fait avec docker compose :```yaml
environment:
- HEADER=
X-Frame-Options:SAMEORIGIN,
X-XSS-Protection:1; mode=block;,
Content-Security-Policy:default-src 'self'; style-src 'self' 'unsafe-inline';
## Journalisation
Par défaut, aucun journal de requête n'est généré. Cela peut être activé en définissant `--logger.enabled`. Le journal (auto-rotatif) a [le format de journal combiné Apache](http://httpd.apache.org/docs/2.2/logs.html#combined)
L'utilisateur peut également activer le journal sur stdout avec `--logger.stdout`. Cela n'affectera pas la journalisation des fichiers ci-dessus mais affichera quelques informations minimales sur les requêtes traitées, quelque chose comme ceci :```
2021/04/16 01:17:25.601 [INFO] GET - /echo/image.png - xxx.xxx.xxx.xxx - 200 (155400) - 371.661251ms
2021/04/16 01:18:18.959 [INFO] GET - /api/v1/params - xxx.xxx.xxx.xxx - 200 (74) - 1.217669m
Serveur d’actifs
Les utilisateurs peuvent activer le serveur d’actifs (désactivé par défaut) pour servir des fichiers statiques. Tant que --assets.location est défini, toute requête non proxyfiée sous assets.root est traitée comme une requête pour des fichiers statiques. Le serveur d’actifs peut être utilisé sans aucun fournisseur de proxy ; dans ce mode, reproxy agit comme un simple serveur web pour le contenu statique. Le serveur d’actifs prend également en charge le « mode SPA » avec --assets.spa où toute requête non trouvée est redirigée vers index.html.
En plus du serveur d’actifs commun, plusieurs serveurs d’actifs personnalisés sont pris en charge. Chaque fournisseur a une manière différente de définir une telle règle statique, et certains fournisseurs peuvent ne pas la prendre du tout en charge. Par exemple, plusieurs serveurs d’actifs ont du sens avec un fournisseur statique (ligne de commande), un fournisseur de fichier, et même utile avec les fournisseurs Docker, mais cela a très peu de sens avec un fournisseur de catalogue Consul.
- fournisseur statique – si l’élément source est préfixé par
assets:ouspa:, il sera traité comme un serveur de fichiers. Par exemple,*,assets:/web,/var/www,servira toutes les requêtes/web/*avec un serveur de fichiers basé sur le répertoire/var/www. - fournisseur de fichier – définir les champs optionnels
assets: trueouspa: true. Note : le champroutedoit être un préfixe de chemin (par exemple/,/web/), pas un motif regex. - fournisseur Docker –
reproxy.assets=web-root:location, par exemplereproxy.assets=/web:/var/www. Le passage en mode SPA se fait en définissantreproxy.spaàyesoutrue.
Mise en cache
Le serveur d’actifs prend en charge le contrôle du cache avec le paramètre --assets.cache=<durée>. Une durée de 0s (valeur par défaut) désactive le contrôle du cache. Une durée est une séquence de nombres décimaux, chacun avec une fraction optionnelle et un suffixe d’unité, comme « 300ms », « 1.5h » ou « 2h45m ». Les unités de temps valides sont « ns », « us » (ou « µs »), « ms », « s », « m », « h » et « d ».
Il existe deux façons de définir la durée du cache :
- Une valeur unique pour tous les actifs statiques. C’est aussi simple que
--assets.cache=48h. - Durée personnalisée pour différents types MIME. Cela doit inclure deux parties – la valeur par défaut et les paires mime:durée. En ligne de commande, cela ressemble à plusieurs options
--assets.cache, par exemple--assets.cache=48h --assets.cache=text/html:24h --assets.cache=image/png:2h. Les valeurs d’environnement doivent être séparées par des virgules, par exempleASSETS_CACHE=48h,text/html:24h,image/png:2h.
Une page 404 personnalisée (non trouvée) peut être définie avec le paramètre --assets.not-found=<chemin>. Le chemin doit être relatif à la racine des actifs.
Utiliser reproxy comme image de base
Servir du contenu purement statique est l’un des cas d’utilisation populaires. Généralement, cela est utilisé pour un conteneur frontend distinct fournissant uniquement l’interface utilisateur. Avec le serveur d’actifs, un tel conteneur est presque trivial à réaliser. Voici un exemple provenant du conteneur servant reproxy.io```docker FROM node:22-alpine as build
WORKDIR /build COPY site/ /build COPY README.md /build/src/index.md
RUN yarn --frozen-lockfile RUN yarn build RUN ls -la /build/public
FROM ghcr.io/umputun/reproxy COPY --from=build /build/public /srv/site EXPOSE 8080 USER app ENTRYPOINT ["/srv/reproxy", "--assets.location=/srv/site"]
Tout ce qu'il faut, c'est copier les actifs statiques vers un emplacement et passer cet emplacement comme `"--assets.location` au point d'entrée de reproxy.
## Mode SPA-friendly
Certaines applications SPA comptent sur le proxy pour gérer les 404 sur les actifs statiques d'une manière spéciale, en redirigeant vers "/index.html". Cela est similaire à la directive `try_files $uri $uri/ …` de nginx et, apparemment, cette fonctionnalité est quelque peu importante pour les applications web modernes.
Ce mode est désactivé par défaut et peut être activé en définissant `--assets.spa` ou la variable d'environnement `ASSETS_SPA=true`.
## Redirections
Par défaut, reproxy traite la destination comme un emplacement de proxy, c'est-à-dire qu'il effectue un appel http interne et renvoie la réponse au client. Cependant, en préfixant l'URL de destination avec `@code`, ce comportement peut être modifié en redirection permanente (code 301) ou temporaire (code 302). Par exemple, une destination définie à `@301 https://example.com/something` provoquera une redirection http permanente vers `Location: https://example.com/something`
codes pris en charge :
- `@301`, `@perm` - redirection permanente
- `@302`, `@temp`, `@tmp` - redirection temporaire
## Plus d'options
- `--gzip` active la compression gzip pour les réponses.
- `--max=N` permet de définir la taille maximale de la requête (64k par défaut). Mettre à `0` désactive la vérification de taille.
- `--timeout.*` divers délais d'attente pour le serveur et le transport proxy. Voir la section `timeout` dans [Toutes les options d'application](#all-application-options). Une valeur nulle ou négative signifie qu'il n'y aura pas de délai d'attente.
- `--insecure` désactive la vérification SSL sur l'hôte de destination. Utile pour les certificats auto-signés.
## Ports par défaut
Afin d'éliminer le besoin de passer des paramètres/env personnalisés, le `--listen` par défaut est dynamique et essaie d'être raisonnable et utile pour les cas typiques :
- Si l'utilisateur a défini quoi que ce soit pour `--listen`, toute la logique ci-dessous est ignorée et le host:port passé est utilisé directement.
- Si l'utilisateur n'a rien défini pour `--listen` et que reproxy s'exécute en dehors d'un conteneur Docker, la valeur par défaut est `127.0.0.1:80` pour le mode http (`ssl.type=none`) et `127.0.0.1:443` pour le mode ssl (`ssl.type=auto` ou `ssl.type=static`).
- Si l'utilisateur n'a rien défini pour `--listen` et que reproxy s'exécute à l'intérieur de Docker, la valeur par défaut est `0.0.0.0:8080` pour le mode http, et `0.0.0.0:8443` pour le mode ssl.
Un autre paramètre par défaut défini de manière dynamique similaire est `--ssl.http-port`. Pour une exécution à l'intérieur d'un conteneur Docker, il est défini à `8080` et à l'extérieur à `80`.
## Ping, vérifications de santé et basculement
reproxy fournit deux points de terminaison à cet effet :
- `/ping` répond par `pong` et indique que reproxy est en marche
- `/health` renvoie le statut `200 OK` si tous les serveurs de destination ont répondu à leur requête ping avec `200`, ou `417 Expectation Failed` si l'un des serveurs a répondu avec un code non-200. Il renvoie également un corps json avec les détails des services réussis/échoués.
En plus des points de terminaison ci-dessus, reproxy prend en charge les vérifications de santé en direct optionnelles. Dans ce cas (si activé), chaque destination est vérifiée périodiquement pour la réponse ping et les routes de destination ayant échoué sont exclues. Il est possible de renvoyer plusieurs destinations identiques provenant d'un même fournisseur ou de fournisseurs différents, et seule la destination réussie est sélectionnée. Si de nombreuses correspondances sont découvertes et réussies - la dernière est sélectionnée selon la stratégie `lb-type` (par défaut sélection aléatoire).
Pour activer la vérification de santé en direct, l'utilisateur doit définir `--health-check.enabled` (ou la variable d'environnement `HEALTH_CHECK_ENABLED=true`). Pour personnaliser l'intervalle de vérification, `--health-check.interval=` peut être utilisé.
## API de gestion
Optionnelle, peut être activée avec `--mgmt.enabled`. Expose 2 points de terminaison sur `mgmt.listen` (adresse:port) :
- `GET /routes` - liste de toutes les routes découvertes
- `GET /metrics` - renvoie les métriques Prometheus (`http_requests_total`, `response_status` et `http_response_time_seconds`)
Par défaut, `http_response_time_seconds` utilise les chemins de requête bruts comme étiquettes, ce qui peut entraîner une cardinalité élevée avec des URL dynamiques (par exemple, `/api/users/123`, `/api/users/456`). Utilisez `--mgmt.low-cardinality` pour passer aux motifs de route (par exemple, `^/api/users/(.*)`) à la place, réduisant ainsi considérablement la cardinalité des métriques.
_voir aussi [examples/metrics](https://github.com/umputun/reproxy/tree/master/examples/metrics)_
## Rapport d'erreurs
Reproxy renvoie une erreur 502 (Bad Gateway) si la requête ne correspond à aucune route ou actif fourni. Si une erreur interne inattendue se produit, il renvoie 500. Par défaut, reproxy affiche la version textuelle la plus simple de l'erreur - « erreur serveur ». Définir `--error.enabled` active le message d'erreur html par défaut et avec `--error.template`, l'utilisateur peut définir n'importe quel fichier de modèle html personnalisé pour le rendu des erreurs. Le modèle comporte deux variables : `{{.ErrCode}}` et `{{.ErrMessage}}`. Par exemple, ce modèle `oh là là ! {{.ErrCode}} - {{.ErrMessage}}` sera rendu en `oh là là ! 502 - Bad Gateway`
## Limitation de débit
Reproxy permet de définir une valeur maximale de requêtes par seconde au niveau du système pour l'activité globale, ainsi que par utilisateur. Les valeurs 0 (par défaut) sont considérées comme illimitées.
L'activité utilisateur est limitée à la fois pour les routes correspondantes et non correspondantes. Toutes les routes non correspondantes sont considérées comme un « groupe de destination unique » et obtiennent un limiteur commun qui est `rate*3`. Cela signifie que si 10 (req/s) sont définis avec `--throttle.user=10`, l'utilisateur final pourra effectuer jusqu'à 30 requêtes par seconde pour les actifs statiques ou les routes non correspondantes. Pour les routes correspondantes, ce limiteur est maintenu par destination (route), c'est-à-dire que la requête transmise à s1.example.com/api autorisera 10 req/s et la requête transmise à s2.example.com en autorisera 10 autres req/s.
### Délai d'attente et limitation par route
Les routes individuelles peuvent remplacer les paramètres globaux `--timeout.write` et `--throttle.user` via les champs `timeout` et `throttle` spécifiques au fournisseur. Ceci est utile pour les points de terminaison de longue durée (par exemple, téléchargements, génération de rapports) qui ont besoin d'un délai plus élevé que le délai d'écriture global, et pour resserrer les limites de débit sur les routes sensibles (par exemple, connexion) sans augmenter le plafond global pour tout le reste.
La priorité est « zéro hérite du global, positif remplace » : une route avec `timeout: 0` (ou sans champ `timeout`) conserve le `--timeout.write` global ; une route avec `timeout: 5m` le remplace uniquement pour les requêtes correspondantes. La même règle s'applique à `throttle`.
Le délai d'attente par route remplace les délais de lecture et d'écriture de la connexion pour les requêtes correspondantes, il peut donc dépasser le `--timeout.write` global (30s par défaut). Les routes sans délai par route respectent toujours le réglage global.
**Limitation — délai d'attente de l'en-tête de réponse au niveau transport :** le `timeout` par route ne remplace PAS `--timeout.resp-header` (5s par défaut). Ce délai est défini sur le `http.Transport` partagé et s'applique avant que le serveur amont ne commence à envoyer les en-têtes de réponse. Si un serveur amont prend plus de temps que `--timeout.resp-header` pour commencer sa réponse (par exemple, un point de terminaison de rapport lent), la requête échoue à cette étape, quel que soit le `timeout` par route. Pour prendre en charge ces routes, augmentez `--timeout.resp-header` globalement au maximum nécessaire pour toute route à réponse lente. Le remplacement par route des délais au niveau transport est intentionnellement hors de portée.
Syntaxe des fournisseurs :
- **Fournisseur de fichier** (YAML) : `timeout: 5m`, `throttle: 2`
- **Fournisseur statique** (CSV) : 6ème et 7ème champs positionnels, par exemple `*,^/upload/(.*),http://up:8080/$1,,,5m,2`
- **Fournisseur Docker** : `reproxy.timeout=5m`, `reproxy.throttle=2` (ou `reproxy.<n>.timeout` / `reproxy.<n>.throttle` pour les conteneurs multi-routes)
- **Fournisseur Consul Catalog** : `reproxy.timeout=5m`, `reproxy.throttle=2`
## Limites de connexion amont
Reproxy permet de configurer les paramètres du pool de connexions amont pour contrôler le nombre de connexions maintenues vers les serveurs backend :
- `--upstream.max-idle-conns` - Nombre maximum de connexions inactives sur tous les hôtes amont. Par défaut : 100.
- `--upstream.max-conns` - Nombre maximum de connexions par hôte amont (0 = illimité). Par défaut : 0.
Définir `--upstream.max-conns` limite les connexions simultanées à chaque backend, ce qui est utile lorsque les serveurs amont ont une capacité limitée ou pour éviter l'épuisement des connexions.
## Authentification de base
### Authentification de base globale
L'authentification de base globale protège toutes les routes. Utile pour protéger les points de terminaison pendant le développement et les tests. Pour l'activer, définissez le fichier htpasswd avec `--basic-htpasswd=<emplacement du fichier>` ou la variable d'environnement `BASIC_HTPASSWD=<emplacement du fichier>`.
Reproxy s'attend à ce que le fichier htpasswd soit au format suivant :```
username1:bcrypt(password1)
username2:bcrypt(password2)
...
cela peut être généré avec la commande htpasswd -nbB, c'est-à-dire htpasswd -nbB test passwd
Authentification de base par route
L'authentification par route permet d'utiliser des identifiants différents pour différentes routes. Lorsqu'une route est configurée avec une authentification par route, l'authentification globale est contournée pour cette route. L'authentification par route est configurée via des paramètres spécifiques au fournisseur :
- Fournisseur de fichiers : champ
authdans YAML, par ex.,auth: "user1:$2y$..., user2:$2y$..." - Fournisseur Docker : étiquette
reproxy.auth - Fournisseur Consul Catalog : tag
reproxy.auth - Fournisseur statique : non pris en charge (utiliser le fournisseur de fichiers pour l'authentification par route)
Le format est une liste séparée par des virgules de paires user:bcrypt_hash (même format htpasswd). Plusieurs utilisateurs peuvent être spécifiés pour la même route.
Exemple avec docker-compose :```yaml services: admin-api: labels: - "reproxy.route=^/admin/(.*)" - "reproxy.dest=/$1" - "reproxy.auth=admin:$$2y$$05$$hashedpassword"
Remarque : dans docker-compose, `$` doit être échappé en `$$`.
## Contrôle d'accès basé sur IP
Reproxy permet de restreindre l'accès aux routes avec une liste de sous-réseaux ou adresses IP séparées par des virgules. Ceci est utile pour le développement et les tests, avant d'autoriser un accès sans restriction. Cela peut également être utilisé pour restreindre l'accès aux services internes. Par défaut, toutes les routes sont ouvertes à tous les clients.
Pour restreindre l'accès aux routes, l'utilisateur doit définir les clés appropriées pour les routes, c'est-à-dire `reproxy.remote` pour docker et consul, et `remote` pour le fournisseur de fichiers. La valeur doit être une liste de sous-réseaux ou adresses IP ou sous-réseaux séparées par des virgules. Par exemple `127.0.0.1, 192.168.1.0/24`. Pour plus de détails, voir les sections [docker provider](#docker-provider) et [consul catalog provider](#consul-catalog-provider).
Par défaut, reproxy vérifie l'adresse distante à partir de la requête du client. Cependant, dans certains cas, cela ne fonctionnera pas comme prévu, par exemple derrière un autre proxy, ou avec un réseau bridge Docker. Cela peut être modifié avec le paramètre `--remote-lookup-headers` qui permet de vérifier la valeur de l'en-tête `X-Real-IP` ou `X-Forwarded-For` (dans cet ordre) et de l'utiliser pour la vérification. Si l'en-tête n'est pas défini, la vérification sera effectuée par rapport à l'adresse distante du client. Ces en-têtes sont fournis par le client et peuvent être trivialement falsifiés, donc ce paramètre ne doit être activé que lorsque reproxy s'exécute derrière un proxy frontal de confiance qui définit et écrase toujours ces en-têtes.
La vérification des en-têtes doit être utilisée avec prudence, car il est possible de les falsifier. Lorsque `--remote-lookup-headers` est activé, la liste blanche d'IP repose entièrement sur cette hypothèse de confiance : un client envoyant `X-Real-IP` ou `X-Forwarded-For` avec une adresse autorisée peut autrement contourner la restriction. N'activez cette option que si reproxy se trouve derrière un proxy de confiance qui contrôle ces en-têtes et que vous pouvez garantir qu'ils ne sont pas falsifiés.
## Prise en charge des plugins
Les fonctionnalités de base de reproxy peuvent être étendues avec des plugins externes. Chaque plugin est un processus/conteneur indépendant implémentant un [serveur rpc](https://golang.org/pkg/net/rpc/). Les plugins sont enregistrés avec le conducteur reproxy et ajoutés à la chaîne des middlewares. Chaque plugin reçoit une requête avec l'url d'origine, les en-têtes et toutes les informations de route correspondantes et répond avec les en-têtes et le code de statut. Tout code de statut >= 400 est traité comme une réponse d'erreur et termine le flux immédiatement avec l'erreur du proxy. Il y a deux types d'en-têtes que les plugins peuvent définir :
- `HeadersIn` - en-têtes entrants. Ceux-ci seront envoyés à l'url proxifiée
- `HeadersOut` - en-têtes sortants. Seront renvoyés au client
Par défaut, les en-têtes définis par un plugin seront mélangés avec les en-têtes d'origine. Dans le cas où un plugin doit contrôler tous les en-têtes, par exemple en supprimer certains, le champ `OverrideHeaders*` peut être défini par un plugin pour indiquer au processus central de reproxy la nécessité d'écraser tous les en-têtes au lieu de les mélanger.
- `OverrideHeadersIn` - indique que le plugin est responsable de tous les en-têtes entrants.
- `OverrideHeadersOut` - indique que le plugin est responsable de tous les en-têtes sortants
Pour simplifier le processus de développement, tous les blocs de construction sont fournis. Cela inclut `lib.Plugin` gérant l'enregistrement, l'écoute et la distribution des appels ainsi que `lib.Request` et `lib.Response` définissant l'entrée et la sortie. Les auteurs de plugins doivent implémenter des gestionnaires concrets satisfaisant la signature `func(req lib.Request, res *lib.HandlerResponse) (err error)`. Chaque plugin peut contenir plusieurs gestionnaires de ce type.
_Voir [examples/plugin](https://github.com/umputun/reproxy/tree/master/examples/plugin) pour plus d'informations_
## Sécurité du conteneur
Par défaut, le conteneur reproxy s'exécute sous l'utilisateur root pour simplifier la configuration initiale et accéder au socket Docker. Ceci est nécessaire pour permettre au fournisseur Docker de découvrir les conteneurs en cours d'exécution. Cependant, si une telle découverte n'est pas requise ou si le fournisseur Docker n'est pas utilisé, il est recommandé de changer l'utilisateur pour un utilisateur moins privilégié. Cela peut être fait au niveau de docker-compose et au niveau de Docker avec l'option `user`, voir la section ci-dessous pour plus de détails.
Parfois, même avec le routage à l'intérieur de Docker, il est logique de désactiver le fournisseur Docker et de configurer les règles avec un fournisseur statique ou fichier. Tous les conteneurs s'exécutant dans un même compose partagent le même réseau et sont accessibles via le DNS local. L'utilisateur peut avoir une règle comme celle-ci pour éviter la découverte Docker : `- STATIC_RULES=*,/api/email/(.*),http://email-sender:8080/$$1`. Cette règle s'attend à ce que le conteneur `email-sender` soit défini dans le même compose. Veuillez noter : les utilisateurs peuvent obtenir le même résultat en utilisant le réseau Docker même si le service de destination était défini dans un fichier compose différent. De cette façon, la configuration de reproxy peut rester séparée des services réels.
Il n'y a rien d'autre que le binaire reproxy à l'intérieur du conteneur reproxy, car il est construit sur une image vide (scratch).
### Exécution avec un utilisateur non root
Un utilisateur avec UID `1001` (appartenant aux groupes `1001` et `999`) est pré-créé dans le conteneur et peut être utilisé pour exécuter reproxy en tant qu'utilisateur non root :```yaml
services:
reproxy:
user: 1001
image: umputun/reproxy:latest
# <...>
# see examples/ssl/docker-compose.yml for the full file example
Si vous souhaitez utiliser le fournisseur Docker, vous devrez vous assurer que cet utilisateur a la permission d'accéder au socket Docker sur le système hôte. La manière de configurer ces permissions dépend de la configuration de votre système hôte. Pour plus d'informations sur la configuration des permissions du socket Docker, consultez la documentation Docker sur la sécurisation du socket du démon Docker.
Options
Chaque option peut être fournie sous deux formes : ligne de commande ou paire clé:valeur d'environnement. Certaines options de ligne de commande ont une forme courte, comme -l localhost:8080 et toutes ont une forme longue, par exemple --listen=localhost:8080. La clé d'environnement (nom) listée pour chaque option comme suffixe, par exemple [$LISTEN].
Toutes les options de taille prennent en charge les suffixes d'unité, par exemple 10K (ou 10k) pour les kilo-octets, 16M (ou 16m) pour les méga-octets, 10G (ou 10g) pour les giga-octets. L'absence de suffixe (par exemple 1024) signifie des octets.
Certaines options sont répétables, dans ce cas l'utilisateur peut les passer plusieurs fois en ligne de commande, ou séparées par des virgules dans l'environnement. Par exemple --ssl.fqdn est une telle option et peut être passée comme --ssl.fqdn=a1.example.com --ssl.fqdn=a2.example.com ou en variable d'environnement SSL_ACME_FQDN=a1.example.com,a2.example.com
Voici la liste de toutes les options prenant en charge plusieurs éléments :
ssl.fqdn(SSL_ACME_FQDN)assets.cache(ASSETS_CACHE)docker.exclude(DOCKER_EXCLUDE)static.rule($STATIC_RULES)header($HEADER)drop-header($DROP_HEADERS)
Toutes les options de l'application```
-l, --listen= listen on host:port (default: 0.0.0.0:8080/8443 under docker, 127.0.0.1:80/443 without) [$LISTEN]
-m, --max= max request size (default: 64K) [$MAX_SIZE]
-g, --gzip enable gz compression [$GZIP]
-x, --header= outgoing proxy headers to add [$HEADER]
--drop-header= incoming headers to drop [$DROP_HEADERS]
--basic-htpasswd= htpasswd file for basic auth [$BASIC_HTPASSWD]
--lb-type=[random|failover|roundrobin] load balancer type (default: random) [$LB_TYPE]
--signature enable reproxy signature headers [$SIGNATURE]
--remote-lookup-headers enable remote lookup headers, trust only behind a trusted proxy [$REMOTE_LOOKUP_HEADERS]
--keep-host keep original Host header as default when proxying [$KEEP_HOST]
--insecure skip SSL verification on destination host [$INSECURE]
--dbg debug mode [$DEBUG]
ssl: --ssl.type=[none|static|auto] ssl (auto) support (default: none) [$SSL_TYPE] --ssl.cert= path to cert.pem file [$SSL_CERT] --ssl.key= path to key.pem file [$SSL_KEY] --ssl.acme-location= dir where certificates will be stored by autocert manager (default: ./var/acme) [$SSL_ACME_LOCATION] --ssl.acme-email= admin email for certificate notifications [$SSL_ACME_EMAIL] --ssl.http-port= http port for redirect to https and acme challenge test (default: 8080 under docker, 80 without) [$SSL_HTTP_PORT] --ssl.fqdn= FQDN(s) for ACME certificates [$SSL_ACME_FQDN]
assets: -a, --assets.location= assets location [$ASSETS_LOCATION] --assets.root= assets web root (default: /) [$ASSETS_ROOT] --assets.spa spa treatment for assets [$ASSETS_SPA] --assets.cache= cache duration for assets [$ASSETS_CACHE] --assets.not-found= path to file to serve on 404, relative to location [$ASSETS_NOT_FOUND]
logger: --logger.stdout enable stdout logging [$LOGGER_STDOUT] --logger.enabled enable access and error rotated logs [$LOGGER_ENABLED] --logger.file= location of access log (default: access.log) [$LOGGER_FILE] --logger.max-size= maximum size before it gets rotated (default: 100M) [$LOGGER_MAX_SIZE] --logger.max-backups= maximum number of old log files to retain (default: 10) [$LOGGER_MAX_BACKUPS]
docker: --docker.enabled enable docker provider [$DOCKER_ENABLED] --docker.host= docker host (default: unix:///var/run/docker.sock) [$DOCKER_HOST] --docker.network= docker network [$DOCKER_NETWORK] --docker.exclude= excluded containers [$DOCKER_EXCLUDE] --docker.auto enable automatic routing (without labels) [$DOCKER_AUTO] --docker.prefix= prefix for docker source routes [$DOCKER_PREFIX] --docker.api-version= docker API version (default: 1.24) [$DOCKER_API_VERSION]
consul-catalog: --consul-catalog.enabled enable consul catalog provider [$CONSUL_CATALOG_ENABLED] --consul-catalog.address= consul address (default: http://127.0.0.1:8500) [$CONSUL_CATALOG_ADDRESS] --consul-catalog.interval= consul catalog check interval (default: 1s) [$CONSUL_CATALOG_INTERVAL]
file: --file.enabled enable file provider [$FILE_ENABLED] --file.name= file name (default: reproxy.yml) [$FILE_NAME] --file.interval= file check interval (default: 3s) [$FILE_INTERVAL] --file.delay= reload only after the file has been unchanged for this long (default: 500ms) [$FILE_DELAY]
static: --static.enabled enable static provider [$STATIC_ENABLED] --static.rule= routing rules [$STATIC_RULES]
timeout: --timeout.read-header= read header server timeout (default: 5s) [$TIMEOUT_READ_HEADER] --timeout.write= write server timeout (default: 30s) [$TIMEOUT_WRITE] --timeout.idle= idle server timeout (default: 30s) [$TIMEOUT_IDLE] --timeout.dial= dial transport timeout (default: 30s) [$TIMEOUT_DIAL] --timeout.keep-alive= keep-alive transport timeout (default: 30s) [$TIMEOUT_KEEP_ALIVE] --timeout.resp-header= response header transport timeout (default: 5s) [$TIMEOUT_RESP_HEADER] --timeout.idle-conn= idle connection transport timeout (default: 90s) [$TIMEOUT_IDLE_CONN] --timeout.tls= TLS hanshake transport timeout (default: 10s) [$TIMEOUT_TLS] --timeout.continue= expect continue transport timeout (default: 1s) [$TIMEOUT_CONTINUE]
mgmt: --mgmt.enabled enable management API [$MGMT_ENABLED] --mgmt.listen= listen on host:port (default: 0.0.0.0:8081) [$MGMT_LISTEN] --mgmt.low-cardinality use route patterns instead of raw paths for metrics labels [$MGMT_LOW_CARDINALITY]
error: --error.enabled enable html errors reporting [$ERROR_ENABLED] --error.template= error message template file [$ERROR_TEMPLATE]
health-check: --health-check.enabled enable automatic health-check [$HEALTH_CHECK_ENABLED] --health-check.interval= automatic health-check interval (default: 300s) [$HEALTH_CHECK_INTERVAL]
throttle: --throttle.system= throttle overall activity' (default: 0) [$THROTTLE_SYSTEM] --throttle.user= limit req/sec per user and per proxy destination (default: 0) [$THROTTLE_USER]
upstream: --upstream.max-idle-conns= max idle connections total (default: 100) [$UPSTREAM_MAX_IDLE_CONNS] --upstream.max-conns= max connections per upstream host (0=unlimited) (default: 0) [$UPSTREAM_MAX_CONNS]
plugin: --plugin.enabled enable plugin support [$PLUGIN_ENABLED] --plugin.listen= registration listen on host:port (default: 127.0.0.1:8081) [$PLUGIN_LISTEN]
Help Options: -h, --help Show this help message
## Statut
Le projet est en cours de développement actif et peut comporter des modifications cassantes jusqu'à la sortie de la version `v1`. Cependant, nous faisons de notre mieux pour ne pas casser les choses sauf s'il y a une bonne raison. Depuis la version 0.4.x, reproxy est considéré comme suffisamment mature pour une utilisation réelle, et de nombreuses configurations l'utilisent en production.