← Документация

Обратный прокси

Настройте OpenChamber корректно за Nginx, Nginx Proxy Manager или другим обратным прокси.

Раздел: remote · Статус: draft · Релиз-проверка: v1.18.2

Обратный прокси

Используйте эту страницу, если вы запускаете OpenChamber за Nginx, Nginx Proxy Manager, Caddy, Cloudflare или другим обратным прокси.

Прежде чем проксировать

  1. Сначала убедитесь, что OpenChamber работает напрямую.
  2. Откройте http://<server-ip>:3000 или ваш кастомный порт из той же сети.
  3. Добавляйте обратный прокси только после того, как прямое подключение заработало.

Что должен поддерживать прокси

  • WebSockets для живой передачи сообщений:
    • /api/event/ws
    • /api/global/event/ws
    • /api/terminal/ws
  • SSE без буферизации:
    • /api/event
    • /api/global/event
    • /api/notifications/stream
    • /api/openchamber/events
    • /api/terminal/:sessionId/stream
  • Большие тела запросов для вложений и файловых операций
  • Долгие read-таймауты для живых потоков и терминальных сессий

Важные правила

  • Включите проксирование WebSocket.
  • Отключите буферизацию на SSE-маршрутах.
  • Отключите gzip на прокси, если OpenChamber уже сжимает ответы.
  • Держите сжатие включённым только на одном уровне.
  • Прокидывайте стандартные прокси-заголовки: Host, X-Forwarded-For, X-Forwarded-Proto.
  • Увеличьте лимиты размера тела, если пользователи загружают файлы.

Быстрый чеклист

  • OpenChamber доступен напрямую в LAN
  • WebSockets включены в прокси
  • На SSE-маршрутах буферизация выключена
  • gzip off на хосте прокси или сжатие прокси отключено иным способом
  • client_max_body_size достаточно велик для вложений
  • proxy_read_timeout достаточно долог для потоков

Пример: 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;
}

Пример: Nginx Proxy Manager

Показать пример для вкладки Advanced
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;
}

Также включите Websockets Support в Nginx Proxy Manager для этого хоста.

Частые признаки проблем

Страница грузится, но отправка сообщений падает

  • WebSockets не включены в прокси
  • /api/event/ws или /api/global/event/ws не прокидывается корректно

Уведомления или живой статус не обновляются

  • один из SSE-маршрутов буферизуется или кэшируется
  • отсутствует X-Accel-Buffering "no"

Загрузка файлов падает

  • client_max_body_size слишком мал

Всё работает локально, но ломается только за прокси

  • прокси сжимает и буферизует живой трафик
  • в прокси нет поддержки WebSocket

Пример: 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
    }
}

Caddy обрабатывает WebSocket-апгрейды автоматически — дополнительная настройка не нужна. Директива flush_interval -1 гарантирует, что SSE-чанки пересылаются немедленно, без буферизации.

CDN и предупреждение о двойном сжатии

Если вы ставите CDN (например, Cloudflare) перед обратным прокси, учтите двойное сжатие:

  • OpenChamber сжимает HTTP-ответы gzip’ом (порог 1 КБ).
  • Cloudflare и другие CDN тоже сжимают ответы по умолчанию.
  • Это может вызвать дважды сжатые ответы или неверные заголовки Content-Encoding.

Чтобы этого избежать, отключите сжатие на одном уровне:

  • Cloudflare: Rules → Compression → отключить (или режим «Passthrough»).
  • Nginx: gzip off (уже показано в примерах выше).
  • Caddy: Caddy по умолчанию не пересжимает, если апстрим уже отдаёт сжатый контент.

SSE-маршруты исключены из сжатия самим OpenChamber, но CDN может их буферизовать. Проверьте документацию вашего CDN, как отключить буферизацию на SSE-путях.

Связанное