Четверг, 14 Май 2026 18:49

Настройка реверс-прокси для Nextcloud + ONLYOFFICE Docs

Автор
Оцените материал
(1 Голосовать)

Ранее, я уже описывал установку, обновление и настройку связки Nextcloud + ONLYOFFICE Docs. Почитать можно тут:

https://typical-admin.ru/item/99-nextcloud-update-18-to-30

Но что если эта связка будет настроена во внутреннем контуре, не имеющим выхода наружу, и, при этом, внешним пользователям тоже требуется пользоваться Nextcloud + ONLYOFFICE Docs?
Для этой цели подойдёт реверс прокси.

Постановка задачи.

Итак, пусть у меня есть две полностью изолированные друг от друга сети:

  • 192.168.10.0/24 — изолированная сеть без DNS и DHCP. В ней работают два сервера:
    • nextcloud.company.local (192.168.10.107) — Nextcloud 30 на Apache + PHP 8.3 + MySQL 8.4.
    • docsrv.company.local (192.168.10.109) — ONLYOFFICE Docs Community Edition 9.1 на nginx.
  • 10.10.102.0/24 — полноценная корпоративная сеть с Active Directory, DNS и DHCP.

Nextcloud и ONLYOFFICE настроены на взаимодействие строго по доменным именам (из файла hosts) и используют валидный wildcard-сертификат *.company.local. При обращении по IP‑адресам связка не работает.

Передо мной стояла цель: дать пользователям из сети 10.10.102.0/24 доступ к этим серверам, но не под теми же именами, а под новыми публичными доменами с сертификатом *.mydomain.ru:

  • nextcloud.mydomain.runextcloud.company.local
  • docsrv.mydomain.rudocsrv.company.local

При этом, требовалось сохранить работоспособность больших файлов (загрузка до 10 ГБ в Nextcloud) и совместное редактирование в реальном времени (WebSocket в ONLYOFFICE).

Выбор решения.

Я решил использовать промежуточный компьютер с двумя сетевыми интерфейсами, который будет выполнять роль шлюза и обратного прокси.

  • Интерфейс в изолированную сеть: 192.168.10.17/24
  • Интерфейс в корпоративную сеть: 10.10.102.234/24
  • ПО: Debian 13, nginx 1.26.3 (реверс-прокси)

Nginx возьмёт на себя приём HTTPS-запросов с публичных доменов, проверку сертификатов и проксирование трафика на внутренние серверы по их оригинальным именам. Такая схема позволяет прозрачно работать с оригинальными сертификатами на бэкендах и не менять конфигурацию самих приложений (кроме нескольких финальных штрихов).

Подготовка шлюза.

1. Установка nginx.

На Debian 13 nginx ставится стандартно:

sudo apt update && sudo apt install nginx -y

2. Сертификаты.

У меня уже есть валидный wildcard-сертификат для *.mydomain.ru. Я разместил его в /etc/nginx/cert/:

/etc/nginx/cert/mydomain.ru.fullchain   # полная цепочка (fullchain.pem)
/etc/nginx/cert/mydomain.ru.key         # приватный ключ

Этот сертификат будет использоваться для обоих публичных доменов.

3. Сеть и hosts.

На шлюзе прописал оба интерфейса с указанными IP. Маршрутизация уже была настроена: пакеты между сетями не ходят напрямую, только через прокси.

Чтобы nginx на шлюзе мог резолвить внутренние имена из изолированной сети, я добавил в /etc/hosts:

192.168.10.107 nextcloud.company.local
192.168.10.109 docsrv.company.local

4. Доработка глобального nginx.conf

Я немного подкорректировал /etc/nginx/nginx.conf. Основные изменения:

  • Увеличил worker_connections до 2048 (по умолчанию 1024), чтобы держать больше одновременных сессий WebSocket.
  • Добавил keepalive_timeout 65 и keepalive_requests 100 для клиентских соединений.
events {
    worker_connections 2048;
}

http {
    keepalive_timeout 65;
    keepalive_requests 100;
    # ... остальные настройки ...
}

Остальные параметры я оставил по умолчанию. Теперь переходим к главному — конфигам сайтов.

Конфигурация nginx на шлюзе.

Я решил сделать два независимых файла в /etc/nginx/sites-available/, чтобы можно было включать и выключать прокси для каждого сервиса отдельно через символические ссылки в sites-enabled.

Конфиг для Nextcloud: /etc/nginx/sites-available/nextcloud.mydomain.ru

# ======================================================================
# Nextcloud gateway
# Публичное имя:   nextcloud.mydomain.ru
# Внутренний хост: nextcloud.company.local
# ======================================================================

upstream nextcloud_backend {
    # Внутренний сервер Nextcloud в изолированной сети.
    # Если на gateway нет DNS для этого имени, добавьте запись в /etc/hosts.
    server nextcloud.company.local:443;
    keepalive 64;
}

# ----------------------------------------------------------------------
# HTTP -> HTTPS
# ----------------------------------------------------------------------
server {
    listen 80;
    server_name nextcloud.mydomain.ru;

    # Всегда отправляем пользователей на HTTPS.
    return 301 https://$host$request_uri;
}

# ----------------------------------------------------------------------
# HTTPS reverse proxy for Nextcloud
# ----------------------------------------------------------------------
server {
    listen 443 ssl;
    http2 on;  # Включаем HTTP/2 (актуально для nginx 1.25+)
    server_name nextcloud.mydomain.ru;

    ssl_certificate     /etc/nginx/cert/vsmpo-avisma.ru.fullchain;
    ssl_certificate_key /etc/nginx/cert/vsmpo-avisma.ru.key;

    # Большие файлы: загрузки/скачивания до 10 ГБ.
    client_max_body_size 10g;
    client_body_timeout 7200s;

    # Долгие операции с файлами и большие ответы от upstream.
    proxy_connect_timeout 60s;
    proxy_send_timeout    7200s;
    proxy_read_timeout    7200s;

    # Для Nextcloud лучше не буферизовать ответы и тело запроса на диск.
    proxy_buffering off;
    proxy_request_buffering off;

    # Nextcloud использует эти URL для автоконфигурации CalDAV/CardDAV.
    location = /.well-known/carddav {
        return 301 https://$host/remote.php/dav/;
    }

    location = /.well-known/caldav {
        return 301 https://$host/remote.php/dav/;
    }

    location ^~ /.well-known {
        return 301 https://$host/index.php$request_uri;
    }

    location / {
        proxy_pass https://nextcloud_backend;

        proxy_http_version 1.1;

        # Заголовки, которые нужны Nextcloud за reverse proxy.
        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  https;
        proxy_set_header X-Forwarded-Host   $host;
        proxy_set_header X-Forwarded-Port   443;

	# Важно для переиспользования upstream keepalive
	proxy_set_header Connection "";

        # Важно для HTTPS-upstream: nginx должен отправлять SNI и
        # проверять сертификат именно под внутренним именем хоста.
        proxy_ssl_server_name on;
        proxy_ssl_name nextcloud.company.local;

        # Не задаём proxy_redirect off; оставляем стандартную обработку nginx.
        # Это безопаснее для редиректов, которые может отдавать Nextcloud.
    }
}

Конфиг для ONLYOFFICE: /etc/nginx/sites-available/docsrv.mydomain.ru

Здесь основной нюанс — правильная маршрутизация WebSocket. Реальный URL для веб-сокетов содержит версионный префикс, например /9.1.0-.../doc/.../c/?transport=websocket. Поэтому я использовал регулярное выражение, которое ищет doc/ или websocket/ в любом месте пути.

# ======================================================================
# ONLYOFFICE Docs gateway
# Публичное имя:   docsrv.mydomain.ru
# Внутренний хост: docsrv.company.local
# ======================================================================

upstream onlyoffice_backend {
    # Внутренний сервер ONLYOFFICE Docs в изолированной сети.
    # Если на gateway нет DNS для этого имени, добавьте запись в /etc/hosts.
    server docsrv.company.local:443;
    keepalive 64;
}

# ----------------------------------------------------------------------
# HTTP -> HTTPS
# ----------------------------------------------------------------------
server {
    listen 80;
    server_name docsrv.mydomain.ru;

    # Всегда отправляем пользователей на HTTPS.
    return 301 https://$host$request_uri;
}

# ----------------------------------------------------------------------
# HTTPS reverse proxy for ONLYOFFICE Docs
# ----------------------------------------------------------------------
server {
    listen 443 ssl;
    http2 on;  # Включаем HTTP/2 (актуально для nginx 1.25+)
    server_name docsrv.mydomain.ru;

    ssl_certificate     /etc/nginx/cert/vsmpo-avisma.ru.fullchain;
    ssl_certificate_key /etc/nginx/cert/vsmpo-avisma.ru.key;

    # Для редактора достаточно обычных размеров, но загрузки документов
    # и длительные сессии редактирования всё равно требуют нормальных таймаутов.
    client_max_body_size 100m;

    proxy_connect_timeout 60s;
    proxy_send_timeout    7200s;
    proxy_read_timeout    7200s;

    proxy_buffering off;
    proxy_request_buffering off;

    # Обычный HTTP-трафик к ONLYOFFICE.
    location / {
        proxy_pass https://onlyoffice_backend;

        proxy_http_version 1.1;

        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  https;
        proxy_set_header X-Forwarded-Host   $host;

        proxy_set_header Connection "";

        # Для HTTPS-upstream обязательно указываем SNI.
        proxy_ssl_server_name on;
        proxy_ssl_name docsrv.company.local;

        # Стандартное поведение nginx по переписыванию редиректов оставляем.
    }

    # WebSocket / realtime editing.
    # location ~ ^/(doc/|websocket/) {
    location ~ /(doc|websocket)/ {
        proxy_pass https://onlyoffice_backend;

        proxy_http_version 1.1;

        # Для WebSocket обязательно передаём Upgrade/Connection именно здесь.
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";

        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  https;
        proxy_set_header X-Forwarded-Host   $host;

        proxy_ssl_server_name on;
        proxy_ssl_name docsrv.company.local;

        proxy_read_timeout 7200s;
        proxy_send_timeout 7200s;
    }
}

Активировал оба конфига:

sudo ln -s /etc/nginx/sites-available/nextcloud.mydomain.ru /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/docsrv.mydomain.ru /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Настройка серверов в изолированной сети.

Теперь нужно сделать так, чтобы сами серверы Nextcloud и ONLYOFFICE «видели» друг друга под правильными именами и корректно обрабатывали запросы, приходящие через прокси.

1. Файл /etc/hosts на обоих серверах.

На сервере Nextcloud (192.168.10.107) и на сервере ONLYOFFICE (192.168.10.109) я добавил следующие строки:

192.168.10.17  nextcloud.mydomain.ru
192.168.10.17  docsrv.mydomain.ru

Это заставляет внутренние запросы, обращённые к публичным именам, идти на шлюз. Шлюз терминирует SSL с сертификатом *.mydomain.ru и проксирует их дальше. Таким образом, проверка сертификата всегда успешна, а маршрут остаётся корректным.

2. Nextcloud: правка config.php

На сервере Nextcloud я открыл /var/www/html/nextcloud/config/config.php и добавил/изменил следующие параметры:

'trusted_domains' => [
    'nextcloud.company.local',
    'nextcloud.mydomain.ru',
],
'trusted_proxies' => [
    '192.168.10.17',   // IP шлюза в изолированной сети
],
'overwritehost' => 'nextcloud.mydomain.ru',
'overwriteprotocol' => 'https',
'overwrite.cli.url' => 'https://nextcloud.mydomain.ru',
'overwritecondaddr' => '^192\.168\.10\.17$',

3. Настройка ONLYOFFICE в Nextcloud.

Этот момент важный! В веб-интерфейсе Nextcloud зашёл в «Настройки» → «ONLYOFFICE» и указал:

  • Адрес ONLYOFFICE Docs: https://docsrv.mydomain.ru/
  • Адрес ONLYOFFICE Docs для внутренних запросов сервера: https://docsrv.company.local/
  • Адрес сервера Nextcloud для внутренних запросов от ONLYOFFICE Docs: https://nextcloud.company.local/

Healthcheck успешно прошёл (зелёная галочка).

Проблемы и их решение.

Первая попытка — ошибка SSL и healthcheck.

Сначала я попытался прописать в настройках ONLYOFFICE публичный адрес docsrv.mydomain.ru как для внешних, так и для внутренних запросов. Healthcheck валился с ошибкой:

cURL error 60: SSL: no alternative certificate subject name matches target host name 'docsrv.mydomain.ru'

Дело в том, что Nextcloud пытается проверить сертификат на самом сервере ONLYOFFICE, а там установлен сертификат *.company.local. Помогла описанная выше схема с /etc/hosts и разделением адресов на внешние и внутренние. Внутренние запросы от Nextcloud к ONLYOFFICE и обратно теперь идут по короткому пути через шлюз (или напрямую внутри сети), но с правильными именами и сертификатами.

Вторая проблема — тормоза при открытии документов.

После того как healthcheck загорелся зелёным, я открыл несколько файлов. Первые 5–6 открывались нормально, но дальше начинались заметные тормоза, а новые документы просто переставали загружаться. При этом напрямую из изолированной сети открывалось до 20 документов без проблем.

Я заглянул в логи nginx на шлюзе (/var/log/nginx/access.log) и увидел странную картину: на запросы с transport=websocket возвращался статус 400 Bad Request, а не ожидаемый 101 Switching Protocols.

GET /9.1.0-.../doc/.../c/?...&transport=websocket HTTP/1.1" 400 ...

Проанализировав конфиг ONLYOFFICE, я понял причину. Мой первый вариант WebSocket-блока использовал привязку к началу строки:

location ~ ^/(doc/|websocket/) {

Но фактический URL содержит версионный префикс (/9.1.0-555e.../doc/...), поэтому регулярка не срабатывала. Запрос попадал в общий location /, где не было заголовков Upgrade и Connection: upgrade, и nginx не мог установить WebSocket-соединение. ONLYOFFICE Docs в ответ использовал long polling, который потребляет больше ресурсов и не справлялся с нагрузкой.

Исправление: я заменил регулярное выражение на такое, которое ищет doc/ или websocket/ в любом месте пути:

location ~ /(doc|websocket)/ {

После перезагрузки nginx WebSocket‑запросы начали получать статус 101, а тормоза полностью исчезли. Я спокойно открыл 20 файлов одновременно, и все они работали так же быстро, как при прямом доступе.

Результат

Теперь пользователи из локальной сети 10.10.102.0/24 заходят на:

  • https://nextcloud.mydomain.ru — полноценный доступ к Nextcloud
  • https://docsrv.mydomain.ru — редактор ONLYOFFICE (прозрачно, через Nextcloud)

Работает совместное редактирование, загрузка больших файлов, автоконфигурация CalDAV/CardDAV. Схема надёжна, потому что все TLS-соединения терминируются с правильными сертификатами как на шлюзе, так и на бэкендах. При необходимости любой из сервисов можно быстро отключить, просто удалив символьную ссылку из sites-enabled.

Этот опыт ещё раз подтвердил: казалось бы, мелочь вроде регулярного выражения может полностью сломать производительность. Но когда всё собрано правильно, nginx отлично справляется с ролью шлюза для сложных веб-приложений.

Донаты принимаются на кошельки:

Yoomoney:
4100118091867315

Карта Т-Банк (бывший Тиньков):
2200 7017 2612 2077

Карта Альфа-Банк:
2200 1539 1357 2013

Прочитано 19 раз Последнее изменение Четверг, 14 Май 2026 20:31
Другие материалы в этой категории: « Обновление Nextcloud с 18.0.3 до 30.0.6

You have no rights to post comments

Вы здесь: Home Мои статьи Linux Debian/Ubuntu Настройка реверс-прокси для Nextcloud + ONLYOFFICE Docs