* feat: add French locale runtime Add French to OpenChamber's shared i18n runtime, dictionaries, and parity tests so the existing language picker can load a complete fr locale across shared UI surfaces. * fix: localize shared UI formatting Remove remaining shared UI locale hardcodings so dates, numbers, and first-party helper copy follow the active app locale instead of leaking English on French surfaces. * feat: localize VS Code French surfaces Localize VS Code bootstrap, native runtime messages, panel titles, and manifest contribution strings so French users get consistent first-party copy across the extension experience. * fix: TASK-2026-05-30-008 correct French review findings Fix broken French relative-time and weekday strings reported on PR #1482 and restore proper import order in quota utils without broadening scope. * fix: TASK-2026-05-30-008 address final PR review comments Capture the localized More Info label once in the VS Code CLI-missing flow and replace the remaining inline French-only utility strings with dictionary-driven copy plus required locale keys. * fix: TASK-2026-05-30-008 normalize French glossary Correct glossary-level French terminology on the live PR branch, keeping canonical technical terms like PR, worktree, stash, HEAD, Mermaid, Markdown, remote, and session while replacing misleading literal translations. * fix: TASK-2026-05-30-008 refine French terminology pass Clean up remaining glossary mistakes on the French PR branch, especially around Mermaid, Markdown, PR, worktree, stash, branch, remote, and commit terminology, while keeping behavior unchanged. * fix: TASK-2026-05-30-008 clean remaining French false friends Correct the SOCKS5 mistranslation and a final small set of obvious false-friend technical nouns on the French branch without changing behavior. * fix: TASK-2026-05-30-008 correct French glossary terms Replace remaining false-friend translations in the French UI dictionaries and normalize technical labels for the French PR branch. * fix: TASK-2026-05-30-008 remove remaining French Mermaid false friend Replace the last confirmed Sirène translation with Mermaid and re-run the requested blacklist and build verification on the PR branch. * fix: TASK-2026-05-30-008 enforce French glossary policy Keep skill/PR/worktree/remote terminology developer-credible in French and remove remaining machine-translated Git and settings copy. * fix: TASK-2026-05-30-008 keep prompt terminology in French Replace remaining technical invite translations with prompt wording across scheduled tasks, multi-run, prompt templates, and Magic Prompts. * fix: TASK-2026-05-30-008 finalize French terminology cleanup Polish remaining worktree/remote wording, remove visible metadata leakage, and correct final Git and settings labels on the French PR branch. * fix: TASK-2026-05-30-008 polish final French strings Correct the last aria-like artifacts and awkward worktree/remote/GitHub URL phrasing in the French dictionaries. * fix: TASK-2026-05-30-008 normalize final French glossary framing Tighten the last worktree/remote/checkout wording and fix remaining French grammar around canonical technical terms. * fix: TASK-2026-05-30-008 align final developer glossary wording Normalize the last French framing around canonical developer terms like worktree, remote, prompt, and checkout. * fix: TASK-2026-05-30-008 harmonize final French sentence framing Replace the last raw franglais around checkout, remote, worktree, and prompt-facing labels with more natural French framing while keeping the chosen technical terms. * fix: TASK-2026-05-30-008 add compact relative date keys Replace French-specific prefix stripping in compact session date labels with dedicated i18n keys across locale dictionaries, preserving existing compact label output while making French wording robust. * docs: add French documentation * docs: mention French locale folder --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
348 lines
10 KiB
Plaintext
348 lines
10 KiB
Plaintext
---
|
||
title: Reverse proxy
|
||
description: Configurez correctement OpenChamber derrière Nginx, Nginx Proxy Manager ou un autre reverse proxy.
|
||
---
|
||
|
||
# Reverse proxy
|
||
|
||
Utilisez cette page si vous exécutez OpenChamber derrière Nginx, Nginx Proxy Manager, Caddy, Cloudflare ou un autre reverse proxy.
|
||
|
||
## Avant de le proxifier
|
||
|
||
1. Confirmez d’abord qu’OpenChamber fonctionne en accès direct.
|
||
2. Ouvrez `http://<server-ip>:3000` ou votre port personnalisé depuis le même réseau.
|
||
3. N’ajoutez le reverse proxy qu’une fois la connexion directe fonctionnelle.
|
||
|
||
## Ce que le proxy doit prendre en charge
|
||
|
||
- WebSockets pour le transport des messages en direct :
|
||
- `/api/event/ws`
|
||
- `/api/global/event/ws`
|
||
- `/api/terminal/ws`
|
||
- SSE sans buffering :
|
||
- `/api/event`
|
||
- `/api/global/event`
|
||
- `/api/notifications/stream`
|
||
- `/api/openchamber/events`
|
||
- `/api/terminal/:sessionId/stream`
|
||
- corps de requête volumineux pour les pièces jointes et les opérations de fichiers
|
||
- timeouts de lecture longs pour les flux en direct et les sessions de terminal
|
||
|
||
## Règles importantes
|
||
|
||
- Activez le proxy WebSocket.
|
||
- Désactivez le buffering sur les routes SSE.
|
||
- Désactivez gzip sur le proxy si OpenChamber compresse déjà les réponses.
|
||
- Gardez la compression active dans une seule couche.
|
||
- Transmettez les headers proxy normaux comme `Host`, `X-Forwarded-For` et `X-Forwarded-Proto`.
|
||
- Augmentez les limites de taille de corps si les utilisateurs uploadent des fichiers.
|
||
|
||
## Checklist rapide
|
||
|
||
- OpenChamber joignable directement sur le LAN
|
||
- WebSockets activés dans le proxy
|
||
- buffering désactivé sur les routes SSE
|
||
- `gzip off` sur le proxy host, ou compression proxy désactivée autrement
|
||
- `client_max_body_size` assez grand pour les pièces jointes
|
||
- `proxy_read_timeout` assez long pour les streams
|
||
|
||
## Exemple : Nginx
|
||
|
||
<details>
|
||
<summary>Afficher l’exemple de configuration</summary>
|
||
|
||
```nginx
|
||
client_max_body_size 50M;
|
||
client_body_buffer_size 50M;
|
||
proxy_request_buffering off;
|
||
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Connection "";
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_set_header X-Forwarded-Host $host;
|
||
|
||
gzip off;
|
||
|
||
location = /api/terminal/ws {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
}
|
||
|
||
location = /api/global/event/ws {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
}
|
||
|
||
location = /api/event/ws {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
}
|
||
|
||
location ~ ^/api/(event|global/event|notifications/stream|openchamber/events)$ {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
}
|
||
|
||
location ~ ^/api/terminal/.+/stream$ {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
}
|
||
|
||
location /api {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
}
|
||
|
||
location / {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
}
|
||
```
|
||
|
||
</details>
|
||
|
||
## Exemple : Nginx Proxy Manager
|
||
|
||
<details>
|
||
<summary>Afficher l’exemple pour l’onglet Advanced</summary>
|
||
|
||
```nginx
|
||
client_max_body_size 50M;
|
||
client_body_buffer_size 50M;
|
||
proxy_request_buffering off;
|
||
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Connection "";
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_set_header X-Forwarded-Host $host;
|
||
|
||
gzip off;
|
||
|
||
location = /api/terminal/ws {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location = /api/global/event/ws {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location = /api/event/ws {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location = /api/event {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location = /api/global/event {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location = /api/notifications/stream {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location = /api/openchamber/events {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location ~ ^/api/terminal/.+/stream$ {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_set_header Accept "text/event-stream";
|
||
proxy_set_header Cache-Control "no-cache";
|
||
proxy_buffering off;
|
||
proxy_cache off;
|
||
gzip off;
|
||
add_header X-Accel-Buffering "no" always;
|
||
add_header Cache-Control "no-cache, no-transform" always;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location /api {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
proxy_connect_timeout 30s;
|
||
}
|
||
|
||
location / {
|
||
proxy_pass http://127.0.0.1:3000;
|
||
}
|
||
```
|
||
|
||
</details>
|
||
|
||
Activez aussi `Websockets Support` dans Nginx Proxy Manager pour ce host.
|
||
|
||
## Signes courants de panne
|
||
|
||
### La page se charge, mais l’envoi de messages échoue
|
||
|
||
- les WebSockets ne sont pas activés dans le proxy
|
||
- `/api/event/ws` ou `/api/global/event/ws` ne passe pas correctement
|
||
|
||
### Les notifications ou le statut en direct ne se mettent pas à jour
|
||
|
||
- l’une des routes SSE est bufferisée ou mise en cache
|
||
- `X-Accel-Buffering "no"` manque
|
||
|
||
### Les uploads de fichiers échouent
|
||
|
||
- `client_max_body_size` est trop petit
|
||
|
||
### Tout fonctionne en local, mais casse seulement derrière le proxy
|
||
|
||
- le proxy compresse et bufferise le trafic en direct
|
||
- le proxy n’a pas le support WebSocket
|
||
|
||
## Exemple : Caddy
|
||
|
||
<details>
|
||
<summary>Afficher l’exemple de configuration</summary>
|
||
|
||
```caddy
|
||
reverse_proxy 127.0.0.1:3000 {
|
||
# WebSocket support is automatic in Caddy
|
||
|
||
# Flush SSE responses immediately
|
||
flush_interval -1
|
||
|
||
# Pass through Host and proxy headers
|
||
header_up Host {host}
|
||
header_up X-Real-IP {remote_host}
|
||
header_up X-Forwarded-For {remote_host}
|
||
header_up X-Forwarded-Proto {scheme}
|
||
|
||
# Increase timeouts for long-lived streams
|
||
transport http {
|
||
read_timeout 3600s
|
||
write_timeout 3600s
|
||
}
|
||
}
|
||
```
|
||
|
||
</details>
|
||
|
||
Caddy gère automatiquement les upgrades WebSocket — aucune configuration supplémentaire n’est nécessaire. La directive `flush_interval -1` garantit que les morceaux SSE sont transmis immédiatement, sans buffering.
|
||
|
||
## Avertissement CDN et double compression
|
||
|
||
Si vous placez un CDN (comme Cloudflare) devant votre reverse proxy, faites attention à la double compression :
|
||
|
||
- OpenChamber compresse les réponses HTTP avec gzip (seuil de 1 Ko).
|
||
- Cloudflare et d’autres CDN compressent aussi les réponses par défaut.
|
||
- Cela peut produire des réponses compressées deux fois ou des headers `Content-Encoding` incorrects.
|
||
|
||
Pour éviter cela, désactivez la compression à **une** couche :
|
||
|
||
- **Cloudflare :** Rules → Compression → désactiver (ou utiliser le mode « Passthrough »).
|
||
- **Nginx :** `gzip off` (déjà montré dans les exemples ci-dessus).
|
||
- **Caddy :** Caddy ne re-compresse pas par défaut si l’upstream envoie déjà du contenu compressé.
|
||
|
||
Les routes de streaming SSE sont exclues de la compression par OpenChamber, mais le CDN peut encore les bufferiser. Consultez la documentation de votre CDN pour désactiver le buffering sur les chemins SSE.
|
||
|
||
## Pages liées
|
||
|
||
- [Tunnels](/tunnels/)
|
||
- [Dépannage](/troubleshooting/)
|