> For the complete documentation index, see [llms.txt](https://ayakaleaf-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://ayakaleaf-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 использует WebSockets с резервным переходом на XHR-поллинг. Каждая сессия редактирования имеет локальное состояние на стороне сервера, и запросы данной сессии редактирования всегда должны направляться к одному и тому же экземпляру 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

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

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

  # Пытаться подключиться к любому backend в течение 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. Остальные экземпляры могут использовать localhost URL, что является значением по умолчанию.

Конфигурация контейнера 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` к bind-mounted диску данных git-bridge, например, `/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

            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://ayakaleaf-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.
