> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/on-premises/ru/obsluzhivanie/horizontal-scaling.md).

# Горизонтальное масштабирование

Начиная с версии 3.5.6 Server Pro поддерживает горизонтальное масштабирование.

В этом документе перечислены технические требования и приведены рекомендации по запуску Server Pro более чем на одном узле.

{% hint style="danger" %}
Начиная с Server CE/Server Pro `5.0.3` переменные окружения были переименованы с `SHARELATEX_*` с `OVERLEAF_*`.

Если вы используете `4.x` версию (или более раннюю), убедитесь, что у переменных соответствующий префикс (например, `SHARELATEX_SITE_URL` вместо `OVERLEAF_SITE_URL`)
{% endhint %}

Настройка горизонтального масштабирования требует значительных усилий. Мы рекомендуем рассматривать горизонтальное масштабирование **только** при достижении определённого масштаба. Например, установка Server Pro для 1000 пользователей была успешно развернута на одном сервере с двумя 4-ядерными процессорами и 32 ГБ оперативной памяти. См. [требования к оборудованию](/on-premises/ru/nachalo-raboty/requirements/hardware-requirements.md) документацию с рекомендациями.

Развёртывание Server Pro с горизонтальным масштабированием включает набор внешних компонентов, таких как балансировщик нагрузки и S3-совместимый бэкенд хранилища.

Мы можем помочь с устранением ошибок в контейнерах Server Pro, которые могут быть вызваны неправильной настройкой, и дать общие рекомендации на основе этого документа. К сожалению, мы не можем помочь с настройкой сторонних приложений/систем.

Решение технических проблем, связанных с вашим оборудованием/ПО, необходимым для предоставления внешних компонентов, не входит в условия нашей поддержки.

### Требования

#### Внешнее, централизованное хранилище данных

Хранилище данных в Server Pro можно разделить на четыре хранилища данных:

* **MongoDB**

  * Большая часть данных сохраняется в MongoDB.
  * Мы поддерживаем как локальный экземпляр, так и внешний экземпляр, например [MongoDB](https://www.mongodb.com/atlas) Atlas (полностью управляемый сервис MongoDB, работающий в инфраструктуре AWS).<br>

  **Примечание:** К сожалению, на данный момент официальной поддержки совместимых с MongoDB баз данных, таких как CosmoDB/DocumentDB, нет, поскольку мы не тестировали Server Pro с ними. Хотя развёртывание Server Pro с совместимыми базами данных **может** быть возможным, официально мы поддерживаем только развёртывания с использованием MongoDB.<br>
* **Redis**

  * Redis хранит временные данные, например ожидающие обновления документа до их записи в MongoDB.
  * Redis используется для передачи обновлений документов между разными сервисами и уведомления редактора об изменениях состояния в данном проекте.
  * Redis используется для хранения пользовательских сессий.
  * Мы поддерживаем как локальный экземпляр, так и внешний экземпляр.<br>

  **Примечание:** К сожалению, на данный момент официальной поддержки совместимых с Redis хранилищ ключ/значение, таких как KeyDB/Valkey, нет, поскольку мы не тестировали Server Pro с ними. Хотя развёртывание Server Pro с совместимыми хранилищами **может** быть возможным, официально мы поддерживаем только развёртывания с использованием Redis.<br>
* **Файлы проекта и файлы истории**

  * Нередактируемые файлы проекта хранятся вне MongoDB.

    Новая система истории проекта (начиная с Server Pro 3.5) также хранит историю вне MongoDB.
  * Для небольших одиночных экземпляров мы поддерживаем либо локальную файловую систему (которая может быть основана на локальном SSD, NFS или EBS), либо [S3-совместимую систему хранения данных](/on-premises/ru/konfiguraciya/overleaf-toolkit/s3.md).
  * Для горизонтального масштабирования мы **только** поддерживаем S3-совместимые системы хранения данных.<br>

  **Важно:** NFS/Amazon EFS/Amazon EBS **не** поддерживаются для горизонтального масштабирования. См. [требования к аппаратному хранилищу](/on-premises/ru/nachalo-raboty/requirements/hardware-requirements.md#storage) раздел с требованиями к хранилищу при масштабировании в Server Pro для подробностей.
* **Временные файлы**
  * Сборки LaTeX должны выполняться на быстрых локальных дисках для оптимальной производительности. Результаты компиляции не нужно сохранять или резервировать.
  * Буферизация загрузки новых файлов и создание zip-архивов проектов также выигрывают от использования локального диска.

{% hint style="danger" %}
Мы настоятельно рекомендуем использовать локальный диск. Использование любого сетевого диска (например, NFS или EBS) может привести к неожиданным ошибкам компиляции и другим проблемам с производительностью.
{% endhint %}

#### **Git-bridge**

{% hint style="info" %}
Git-bridge доступен в Server Pro начиная с версии 4.0.1.
{% endhint %}

Git-репозитории хранятся локально на диске. Параметры репликации недоступны. Git-bridge следует запускать как **синглтон**. Для оптимальной производительности мы рекомендуем использовать локальный диск для данных git-bridge. Диск с данными git-bridge следует регулярно резервировать.

Для хранения данных при горизонтальном масштабировании вам понадобится:

* центральный экземпляр MongoDB, доступный из всех экземпляров Server Pro
* центральный экземпляр Redis, доступный из всех экземпляров Server Pro
* центральный S3-совместимый бэкенд хранилища для файлов проекта и истории
* локальный диск на каждом экземпляре для временных файлов
* локальный диск на экземпляре, на котором размещён контейнер git-bridge, для данных git-bridge

#### Требования к балансировщику нагрузки

* **Постоянная маршрутизация**, например с помощью cookie

  Это требование обусловлено следующими компонентами:

  * Функция редактирования в реальном времени в Server Pro использует WebSocket с резервным вариантом в виде XHR-polling. Каждая сессия редактирования имеет локальное состояние на стороне сервера, и запросы одной и той же сессии всегда должны направляться в один и тот же экземпляр Server Pro. Функция совместной работы использует Redis [Pub/Sub](https://redis.io/docs/latest/develop/interact/pubsub/) для обмена обновлениями между несколькими экземплярами Server Pro.
  * Компиляция LaTeX хранит вывод и кэш компиляции локально для повышения производительности. После отправки запроса на компиляцию одному экземпляру Server Pro следующие запросы на скачивание PDF/логов должны быть направлены тому же экземпляру Server Pro.
* **Долгие таймауты запросов** для поддержки компиляции больших документов LaTeX
* **Поддержка WebSocket** для оптимальной производительности
* **Размер POST-полезной нагрузки 50 МБ**
* **Таймаут keep-alive** должен быть меньше таймаута keep-alive Server Pro

  Таймаут keep-alive в Server Pro можно настроить с помощью переменной окружения `NGINX_KEEPALIVE_TIMEOUT`. Значение по умолчанию — 65 с.

  При значении по умолчанию таймаут keep-alive 60 с на балансировщике нагрузки работает.

  При `NGINX_KEEPALIVE_TIMEOUT=120`, балансировщик нагрузки может выбрать 115 с.
* **IP-адреса клиентов**

  Установите заголовок запроса `X-Forwarded-For` на IP клиента.
* Когда **завершение SSL**

  Балансировщику нагрузки нужно добавить заголовок запроса `X-Forwarded-Proto: https`.

<details>

<summary>Пример конфигурации HAProxy</summary>

```
global
  group haproxy
  user haproxy

  # Подробное логирование
  log stdout format raw local0 debug

defaults
  mode                    http
  option                  httpchk HEAD /status
  http-check              expect status 200
  default-server          check

  # Подробное логирование
  log                     global
  option                  httplog

  # Перенаправлять на другой бэкенд, если закреплённый недоступен
  option                  redispatch 1
  # Эти повторные попытки предназначены для ошибок TCP-соединения, а не для ответов HTTP со статусом 500
  retries                 3

  # Закреплённая сессия на 24 часа бездействия — вывод компиляции удаляется через 24 часа
  cookie                  server-pro-ha insert maxidle 24h

  # Попробовать подключиться к любому бэкенду в течение 1 мин, затем вернуть 503
  timeout queue           1m
  # Дать экземплярам Server Pro 15 с на запуск
  timeout connect         15s

  # Прерывать запросы от очень медленных клиентов (разрешить 1 мин бездействия при чтении запроса)
  timeout client          1m

  # Разрешить медленные компиляции — жёстко заданный лимит в clsi составляет 10 мин
  timeout server          10m

  # Отключать редактор через 23 ч — на 1 час раньше, чем через сутки после последнего использования вчера
  timeout tunnel          23h

  # Примечание: поведение keepalive в haproxy отлично работает со стандартной настройкой keepalive в Server Pro.
  #       Haproxy очищает соединения в фоновом режиме и при необходимости будет перенаправлять запросы повторно.

listen server-pro-ha-http
  bind :80
  http-request redirect scheme https unless { ssl_fc }

listen server-pro-ha-https
  bind :443 ssl crt /etc/ssl/certs/ssl-key-and-certificate-bundle.pem

  # Сообщить приложению, что мы за https
  http-request set-header X-Forwarded-Proto https

  # Сообщить приложению фактический IP клиента
  option forwardfor

  # См. https://hstspreload.org/#deployment-recommendations
  http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload;"

  # Направлять git-трафик во вспомогательный контейнер git-bridge
  use-server server-pro-ha-1 if { path_beg /git/ }

  # Отладка
  http-response add-header X-Served-By %s
  stats enable
  stats uri /haproxy

  server server-pro-ha-1 198.18.1.1:80 cookie server-pro-ha-1
  server server-pro-ha-2 198.18.1.2:80 cookie server-pro-ha-2
  server server-pro-ha-3 198.18.1.3:80 cookie server-pro-ha-3
```

</details>

#### Конфигурация Server Pro

**Секреты**

Экземпляры Server Pro должны использовать общие секреты:

* `WEB_API_PASSWORD` (аутентификация web API)
* `STAGING_PASSWORD` и `V1_HISTORY_PASSWORD` то же значение (аутентификация истории)
* `CRYPTO_RANDOM` (для cookie сессии)
* `OT_JWT_AUTH_KEY` (аутентификация истории)

Все эти секреты должны быть настроены со своими уникальными значениями и общими для всех экземпляров.

Если они не настроены и запросы пользователя попадают на разные экземпляры Server Pro, их запросы не пройдут проверку подлинности, и пользователя либо будет часто перенаправлять на страницу входа, либо его действия в интерфейсе будут неожиданно сбоить.

Если не настроено, Server Pro использует новое случайное значение для каждого секрета на основе 32 случайных байт из `/dev/urandom` (256 случайных бит).

{% code overflow="wrap" %}

```bash
# https://github.com/overleaf/overleaf/blob/45ca0f796c679103efd305ddbef28073c4a5de32/server-ce/init_scripts/00_regen_sharelatex_secrets.sh#L14
dd if=/dev/urandom bs=1 count=32 2>/dev/null | base64 -w 0 | rev | cut -b 2- | rev | tr -d '\n+/'
```

{% endcode %}

**MongoDB**

Укажите `OVERLEAF_MONGO_URL` (`SHARELATEX_MONGO_URL` для версий `4.x` и более ранних) на центральном экземпляре MongoDB.

**Redis**

Укажите `OVERLEAF_REDIS_HOST` (`SHARELATEX_REDIS_HOST` для версий `4.x` и более ранних) и `REDIS_HOST` на центральном экземпляре Redis.

**S3-совместимое хранилище для файлов проекта и истории**

См. документацию по [хранилище, совместимое с S3](/on-premises/ru/konfiguraciya/overleaf-toolkit/s3.md) для подробностей.

**Временные файлы**

Стандартное bind-mount подключение локального SSD к `/var/lib/overleaf` (`/var/lib/sharelatex` для версий `4.x` и более ранних) будет достаточно. Обязательно укажите `SANDBOXED_COMPILES_HOST_DIR` на точку монтирования на хосте.

{% hint style="danger" %}
Мы настоятельно рекомендуем использовать локальный диск. Использование любого сетевого диска (например, NFS или EBS) может привести к неожиданным ошибкам компиляции и другим проблемам с производительностью.
{% endhint %}

**Конфигурация прокси**

* Установите `OVERLEAF_BEHIND_PROXY=true` (`SHARELATEX_BEHIND_PROXY` для версий `4.x` и более ранних) для корректного определения IP клиентов.
* Установите `TRUSTED_PROXY_IPS` на IP балансировщика нагрузки (можно указать несколько CIDR, разделённых запятой).

**Интеграция Git-bridge**

{% hint style="info" %}
Git-bridge доступен в Server Pro начиная с версии 4.0.1.
{% endhint %}

Контейнеру git-bridge нужен соседний контейнер Server Pro для обработки входящих git-запросов. Этот соседний контейнер может также обслуживать обычный пользовательский трафик. В примере конфигурации первый экземпляр выступает как соседний контейнер для git-bridge, но на самом деле им может быть любой экземпляр.

Зачем нужно назначать один контейнер Server Pro соседним для git-bridge? Server Pro выдаёт git-bridge URL-адреса загрузки для сервиса истории. Нам нужно настроить эти URL истории так, чтобы они были доступны из контейнера git-bridge.

Конфигурация контейнера Server Pro:

* Установите `GIT_BRIDGE_ENABLED` с `'true'`
* Установите `GIT_BRIDGE_HOST` с `<имя контейнера git-bridge>` например `git-bridge`
* Установите `GIT_BRIDGE_PORT` с `8000`
* Установите `V1_HISTORY_URL` с `http://<имя соседнего контейнера server-pro>:3100/api`.

  Примечание: это нужно только на соседнем контейнере для контейнера git-bridge. Остальные экземпляры могут использовать URL localhost, что и является значением по умолчанию.

Конфигурация контейнера git-bridge:

* Установите `GIT_BRIDGE_API_BASE_URL` с `http://<имя соседнего контейнера server-pro>/api/v0`, например `http://server-pro-ha-1/api/v0`
* Установите `GIT_BRIDGE_OAUTH2_SERVER` с `http://<имя соседнего контейнера server-pro>`, например `http://server-pro-ha-1`
* Установите `GIT_BRIDGE_POSTBACK_BASE_URL` с `http://<имя контейнера git-bridge>:8000`, например `http://git-bridge:8000`
* Установите `GIT_BRIDGE_ROOT_DIR` на диск данных git-bridge, подключённый через bind-mount, например `/data/git-bridge`

<details>

<summary>Пример конфигурации docker-compose.yml</summary>

Следующая конфигурация показывает автономную установку. Чтобы демо работало, вам нужно предоставить действительный SSL-ключ/сертификат и скорректировать `OVERLEAF_SITE_URL` (`SHARELATEX_SITE_URL` для версий `4.x` и более ранних). Для реальной установки вы должны заменить фиктивные секреты на реальные, как указано в комментариях. Для реальной установки вам нужно перенести отдельные контейнеры на выделенные узлы и скорректировать IP-адреса под вашу локальную сетевую конфигурацию.

```yaml
version: '2.2'

# Реальная настройка горизонтального масштабирования: выберите свою сеть и замените IP в конфигурации.
networks:
    default:
        ipam:
            config:
                # Эта подсеть является частью зарезервированной подсети, используемой для бенчмаркинга
                # https://tools.ietf.org/html/rfc2544
                # Вся подсеть — 198.18.0.0/15
                # Используйте 198.18.0.0/24 для lb и dbs
                # Используйте 198.18.1.0/24 для server-pro
                # Используйте 198.18.0.128/25 для временного контейнера
                - gateway: 198.18.0.1
                  ip_range: 198.18.0.128/25
                  subnet: 198.18.0.0/23

services:
    # Реальная настройка горизонтального масштабирования: запустите haproxy вне docker на отдельном хосте.
    lb:
        image: haproxy:2.6
        container_name: lb
        user: root
        logging:
            driver: local
            options:
                max-size: 10g
                max-file: '100'
        volumes:
            - ./haproxy.conf:/usr/local/etc/haproxy/haproxy.cfg
            # $ cat certificate.pem key.pem > ssl-key-and-certificate-bundle.pem
            - /path/to/ssl-key-and-certificate-bundle.pem:/etc/ssl/certs/ssl-key-and-certificate-bundle.pem
        # Альтернатива параметру ports: используйте host network, чтобы избежать накладных расходов docker-proxy
        network_mode: host

        # Альтернатива параметру network_mode: host: используйте docker-proxy для изоляции сети
        # ports:
        #     - "80:80"
        #     - "443:443"
        # networks:
        #     default:
        #         ipv4_address: 198.18.0.2

        # Реальная настройка горизонтального масштабирования: удалите это, поскольку они работают на других хостах.
        depends_on:
            server-pro-ha-1:
                condition: service_started
            server-pro-ha-2:
                condition: service_started
            server-pro-ha-3:
                condition: service_started

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер рядом с server-pro-ha-1.
    # Для Server Pro 4.0 и новее.
    git-bridge:
        restart: always
        # Тег должен совпадать с тегом контейнера `server-pro-ha-1`.
        image: quay.io/sharelatex/git-bridge:4.0.1
        volumes:
            # Реальная настройка горизонтального масштабирования: укажите /data/git-bridge на выделенный локальный SSD.
            - ~/git_bridge_data:/data/git-bridge
        container_name: git-bridge
        environment:
            GIT_BRIDGE_API_BASE_URL: "http://server-pro-ha-1/api/v0"
            GIT_BRIDGE_OAUTH2_SERVER: "http://server-pro-ha-1"
            GIT_BRIDGE_POSTBACK_BASE_URL: "http://198.18.0.6:8000"
            GIT_BRIDGE_ROOT_DIR: "/data/git-bridge"
        user: root
        command: ["/server-pro-start.sh"]

        # Реальная настройка горизонтального масштабирования: запускать на хосте 198.18.0.6 и открыть порт
        # ports:
        #     - "8000:8000"
        networks:
            default:
                ipv4_address: 198.18.0.6

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер на отдельном хосте.
    server-pro-ha-1: &server-pro-ha-config
        restart: always
        image: quay.io/sharelatex/sharelatex-pro:4.0.1
        container_name: server-pro-ha-1
        hostname: server-pro-ha-1
        depends_on:
            # Реальная настройка горизонтального масштабирования: оставьте эту запись.
            git-bridge:
                condition: service_started

            # Реальная настройка горизонтального масштабирования: удалите нижеприведённые, поскольку они работают на других хостах.
            mongo:
                condition: service_healthy
            redis:
                condition: service_started
            minio:
                condition: service_started
            mongo_replica_set_setup:
                condition: service_completed_successfully
            minio_setup:
                condition: service_completed_successfully
        stop_grace_period: 60s
        volumes:
            - /tmp/scratch-disk1:/var/lib/sharelatex
            - /var/run/docker.sock:/var/run/docker.sock
        environment: &server-pro-ha-environment
            # Реальная настройка горизонтального масштабирования: укажите свой домен/имя приложения.
            OVERLEAF_SITE_URL: 'https://overleaf.example.com'
            OVERLEAF_APP_NAME: Server Pro Horizontal Scaling Demo

            OVERLEAF_MONGO_URL: mongodb://198.18.0.3/sharelatex
            OVERLEAF_REDIS_HOST: 198.18.0.4
            REDIS_HOST: 198.18.0.4

            ENABLED_LINKED_FILE_TYPES: 'project_file,project_output_file'
            EMAIL_CONFIRMATION_DISABLED: 'true'

            SANDBOXED_COMPILES: 'true'
            SANDBOXED_COMPILES_SIBLING_CONTAINERS: 'true'
            SANDBOXED_COMPILES_HOST_DIR: '/tmp/scratch-disk1/data/compiles'

            # S3
            # Реальная настройка горизонтального масштабирования: выберите безопасные учётные данные.
            OVERLEAF_FILESTORE_BACKEND: s3
            OVERLEAF_FILESTORE_USER_FILES_BUCKET_NAME: overleaf-user-files
            OVERLEAF_FILESTORE_TEMPLATE_FILES_BUCKET_NAME: overleaf-template-files
            OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID: OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID
            OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY: OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY
            OVERLEAF_FILESTORE_S3_ENDPOINT: http://198.18.0.5:9000
            OVERLEAF_FILESTORE_S3_PATH_STYLE: 'true'
            OVERLEAF_FILESTORE_S3_REGION: ''

            OVERLEAF_HISTORY_BACKEND: "s3"
            OVERLEAF_HISTORY_PROJECT_BLOBS_BUCKET: "overleaf-project-blobs"
            OVERLEAF_HISTORY_CHUNKS_BUCKET: "overleaf-chunks"
            OVERLEAF_HISTORY_S3_ACCESS_KEY_ID: "OVERLEAF_HISTORY_S3_ACCESS_KEY_ID"
            OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY: "OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY"
            OVERLEAF_HISTORY_S3_ENDPOINT: http://198.18.0.5:9000
            OVERLEAF_HISTORY_S3_PATH_STYLE: 'true'
            OVERLEAF_HISTORY_S3_REGION: ''
            # /S3

            # git-bridge
            GIT_BRIDGE_ENABLED: 'true'
            GIT_BRIDGE_HOST: 198.18.0.6
            GIT_BRIDGE_PORT: 8000
            # Нужно только на соседнем экземпляре git-bridge
            V1_HISTORY_URL: "http://server-pro-ha-1:3100/api"
            # /git-bridge

            # Горизонтальное масштабирование
            # Реальная настройка горизонтального масштабирования: выберите безопасные учётные данные.
            WEB_API_PASSWORD: WEB_API_PASSWORD
            STAGING_PASSWORD: V1_HISTORY_PASSWORD
            V1_HISTORY_PASSWORD: V1_HISTORY_PASSWORD
            CRYPTO_RANDOM: CRYPTO_RANDOM
            OT_JWT_AUTH_KEY: OT_JWT_AUTH_KEY
            OVERLEAF_BEHIND_PROXY: 'true'
            # Реальная настройка горизонтального масштабирования: IP-адреса балансировщиков нагрузки
            TRUSTED_PROXY_IPS: 198.18.0.1,198.18.0.2
            # /Horizontal scaling

        # Реальная настройка горизонтального масштабирования: запустите на хосте 198.18.1.1 и откройте порты
        # ports:
        #     - "80:80"
        networks:
            default:
                ipv4_address: 198.18.1.1

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер на отдельном хосте.
    server-pro-ha-2:
        <<: *server-pro-ha-config
        hostname: server-pro-ha-2
        container_name: server-pro-ha-2
        volumes:
            - /tmp/scratch-disk2:/var/lib/sharelatex
            - /var/run/docker.sock:/var/run/docker.sock
        environment:
            <<: *server-pro-ha-environment
            SANDBOXED_COMPILES_HOST_DIR: '/tmp/scratch-disk2/data/compiles'
            V1_HISTORY_URL: "http://localhost:3100/api"

        # Реальная настройка горизонтального масштабирования: запустите на хосте 198.18.1.2 и откройте порты
        # ports:
        #     - "80:80"
        networks:
            default:
                ipv4_address: 198.18.1.2

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер на отдельном хосте.
    server-pro-ha-3:
        <<: *server-pro-ha-config
        hostname: server-pro-ha-3
        container_name: server-pro-ha-3
        volumes:
            - /tmp/scratch-disk3:/var/lib/sharelatex
            - /var/run/docker.sock:/var/run/docker.sock
        environment:
            <<: *server-pro-ha-environment
            SANDBOXED_COMPILES_HOST_DIR: '/tmp/scratch-disk3/data/compiles'
            V1_HISTORY_URL: "http://localhost:3100/api"

        # Реальная настройка горизонтального масштабирования: запустите на хосте 198.18.1.3 и откройте порты
        # ports:
        #     - "80:80"
        networks:
            default:
                ipv4_address: 198.18.1.3

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер на отдельном хосте.
    minio:
        image: minio/minio:RELEASE.2023-05-18T00-05-36Z
        container_name: minio
        command: server /data
        volumes:
            # Реальная настройка горизонтального масштабирования: запустите minio с несколькими дисками, см. документацию minio.
            - ~/minio_data:/data
        environment:
            # Реальная настройка горизонтального масштабирования: выберите безопасные учётные данные.
            MINIO_ROOT_USER: MINIO_ROOT_USER
            MINIO_ROOT_PASSWORD: MINIO_ROOT_PASSWORD

        # Реальная настройка горизонтального масштабирования: запустите на хосте 198.18.0.5 и откройте порт
        # ports:
        #     - "9000:9000"
        networks:
            default:
                ipv4_address: 198.18.0.5

    # Реальная настройка горизонтального масштабирования: выполните эту настройку один раз на отдельном хосте.
    minio_setup:
        depends_on:
            - minio
        image: minio/mc:RELEASE.2023-05-18T16-59-00Z
        entrypoint: sh
        команды:
            - '-c'
            # Реальная настройка горизонтального масштабирования: выберите безопасные учётные данные.
            - |
                mc alias set s3 http://198.18.0.5:9000 MINIO_ROOT_USER MINIO_ROOT_PASSWORD \
                || sleep 10 && \
                mc alias set s3 http://198.18.0.5:9000 MINIO_ROOT_USER MINIO_ROOT_PASSWORD \
                || sleep 10 && \
                mc alias set s3 http://198.18.0.5:9000 MINIO_ROOT_USER MINIO_ROOT_PASSWORD \
                || sleep 10 && \
                mc alias set s3 http://198.18.0.5:9000 MINIO_ROOT_USER MINIO_ROOT_PASSWORD

                mc mb --ignore-existing s3/overleaf-user-files
                mc mb --ignore-existing s3/overleaf-template-files
                mc admin user add s3 \\
                  OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID \\
                  OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY

                mc mb --ignore-existing s3/overleaf-project-blobs
                mc mb --ignore-existing s3/overleaf-chunks
                mc admin user add s3 \\
                  OVERLEAF_HISTORY_S3_ACCESS_KEY_ID \\
                  OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY

                echo '
                  {
                    "Version": "2012-10-17",
                    "Statement": [
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:ListBucket"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-user-files"
                      },
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:PutObject",
                          "s3:GetObject",
                          "s3:DeleteObject"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-user-files/*"
                      },
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:ListBucket"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-template-files"
                      },
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:PutObject",
                          "s3:GetObject",
                          "s3:DeleteObject"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-template-files/*"
                      }
                    ]
                  }' > policy-filestore.json

                echo '
                  {
                    "Version": "2012-10-17",
                    "Statement": [
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:ListBucket"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-project-blobs"
                      },
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:PutObject",
                          "s3:GetObject",
                          "s3:DeleteObject"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-project-blobs/*"
                      },
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:ListBucket"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-chunks"
                      },
                      {
                        "Effect": "Allow",
                        "Action": [
                          "s3:PutObject",
                          "s3:GetObject",
                          "s3:DeleteObject"
                        ],
                        "Resource": "arn:aws:s3:::overleaf-chunks/*"
                      }
                    ]
                  }' > policy-history.json

                # Поместите содержимое политики из предыдущего раздела в policy-filestore.json
                # Напоминание: замените имена бакетов соответствующим образом.
                mc admin policy create s3 overleaf-filestore policy-filestore.json
                mc admin policy attach s3 overleaf-filestore \\
                  --user=OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID || true

                mc admin policy create s3 overleaf-history policy-history.json
                mc admin policy attach s3 overleaf-history \\
                  --user=OVERLEAF_HISTORY_S3_ACCESS_KEY_ID || true

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер на отдельном хосте.
    mongo:
        restart: always
        image: mongo:4.4
        container_name: mongo
        command: "--replSet overleaf"
        expose:
            - 27017
        volumes:
            - ~/mongo_data:/data/db
        healthcheck:
            test: echo 'db.stats().ok' | mongo localhost:27017/test --quiet
            interval: 10s
            timeout: 10s
            retries: 5

        # Реальная настройка горизонтального масштабирования: запустите на хосте 198.18.0.3 и откройте порт
        # ports:
        #     - "27017:27017"
        networks:
            default:
                ipv4_address: 198.18.0.3

    mongo_replica_set_setup:
        image: mongo:4.4
        entrypoint: sh
        depends_on:
            mongo:
                condition: service_healthy
        команды:
            - '-c'
            - |
                mongo 198.18.0.3 --eval "rs.initiate({ _id: \"overleaf\", members: [ { _id: 0, host: \"198.18.0.3:27017\" } ] })"

    # Реальная настройка горизонтального масштабирования: запустите этот контейнер на отдельном хосте.
    redis:
        restart: always
        image: redis:6.2
        container_name: redis
        expose:
            - 6379
        volumes:
            - ~/redis_data:/data

        # Реальная настройка горизонтального масштабирования: запустите на хосте 198.18.0.4 и откройте порт
        # ports:
        #     - "6379:6379"
        networks:
            default:
                ipv4_address: 198.18.0.4
```

</details>

#### Оборудование

Мы рекомендуем использовать одинаковые аппаратные характеристики для всех экземпляров Server Pro, участвующих в горизонтальном масштабировании.

Общие рекомендации по [аппаратным характеристикам](/on-premises/ru/nachalo-raboty/requirements/hardware-requirements.md) для экземпляров Server Pro применимы.

#### Обновление Server Pro

В рамках процесса обновления Server Pro автоматически выполняет миграции базы данных. Эти миграции **не** предназначены для запуска с нескольких экземпляров параллельно.

Миграции должны завершиться до запуска фактического веб-приложения. Вы можете либо проверить журналы на наличие записи `Миграции завершены` либо подождать, пока приложение начнёт принимать трафик.

Процедура обновления выглядит так:

1. Запланируйте окно обслуживания
2. Остановите все экземпляры Server Pro
3. Сделайте согласованную резервную копию, как описано в [документации](/on-premises/ru/obsluzhivanie/data-and-backups.md#performing-a-consistent-backup)
4. Запустите один экземпляр Server Pro с новой версией
5. Проверьте, что новый экземпляр работает как ожидается
6. Запустите остальные экземпляры с новой версией


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/on-premises/ru/obsluzhivanie/horizontal-scaling.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
