> 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/vi/bao-tri/horizontal-scaling.md).

# Mở rộng theo chiều ngang

Bắt đầu từ phiên bản 3.5.6, Server Pro hỗ trợ mở rộng theo chiều ngang.

Tài liệu này liệt kê các yêu cầu kỹ thuật và cung cấp hướng dẫn để chạy Server Pro trên nhiều hơn một nút.

{% hint style="danger" %}
Bắt đầu từ Server CE/Server Pro `5.0.3` các biến môi trường đã được đổi tên từ `SHARELATEX_*` đến `OVERLEAF_*`.

Nếu bạn đang dùng `4.x` (hoặc sớm hơn) vui lòng đảm bảo các biến được thêm tiền tố tương ứng (ví dụ `SHARELATEX_SITE_URL` thay vì `OVERLEAF_SITE_URL`)
{% endhint %}

Thiết lập mở rộng theo chiều ngang đòi hỏi rất nhiều công sức. Chúng tôi khuyên bạn nên cân nhắc mở rộng theo chiều ngang **chỉ** khi đạt đến một quy mô nhất định. Ví dụ, một cài đặt Server Pro cho tổng cộng 1.000 người dùng đã được thiết lập thành công bằng một máy chủ duy nhất được cấp phát hai bộ xử lý 4 lõi và 32GB bộ nhớ hệ thống. Xem [yêu cầu phần cứng](/on-premises/vi/bat-dau/requirements/hardware-requirements.md) tài liệu để biết khuyến nghị.

Một triển khai Server Pro với mở rộng theo chiều ngang bao gồm một tập hợp các thành phần bên ngoài, chẳng hạn như bộ cân bằng tải và một backend lưu trữ tương thích S3.

Chúng tôi có thể giúp khắc phục lỗi trong các container Server Pro có thể là kết quả của cấu hình sai và cung cấp lời khuyên chung dựa trên tài liệu này. Rất tiếc, chúng tôi không thể hỗ trợ cấu hình các ứng dụng/hệ thống của bên thứ ba.

Việc xử lý các sự cố kỹ thuật cụ thể đối với phần cứng/phần mềm của bạn để cung cấp các thành phần bên ngoài không nằm trong phạm vi điều khoản hỗ trợ của chúng tôi.

### Yêu cầu

#### Lưu trữ dữ liệu trung tâm bên ngoài

Lưu trữ dữ liệu trong Server Pro có thể được chia thành bốn kho dữ liệu:

* **MongoDB**

  * Phần lớn dữ liệu được lưu bền vững vào MongoDB.
  * Chúng tôi hỗ trợ либо một phiên bản cục bộ hoặc một phiên bản bên ngoài, chẳng hạn như [MongoDB](https://www.mongodb.com/atlas) Atlas (một dịch vụ MongoDB được quản lý toàn phần chạy trong hạ tầng AWS).<br>

  **Lưu ý:** Rất tiếc, hiện tại chưa có hỗ trợ chính thức cho các cơ sở dữ liệu tương thích MongoDB như CosmoDB/DocumentDB, vì chúng tôi chưa thử nghiệm Server Pro với chúng. Mặc dù việc triển khai Server Pro với các cơ sở dữ liệu tương thích **có thể** là khả thi, chúng tôi chỉ hỗ trợ chính thức các triển khai sử dụng MongoDB.<br>
* **Redis**

  * Redis lưu trữ dữ liệu tạm thời, chẳng hạn như các cập nhật tài liệu đang chờ trước khi được ghi vào MongoDB.
  * Redis được dùng để truyền các cập nhật tài liệu giữa các dịch vụ khác nhau và thông báo cho trình soạn thảo về các thay đổi trạng thái trong một dự án nhất định.
  * Redis được dùng để lưu các phiên người dùng.
  * Chúng tôi hỗ trợ либо một phiên bản cục bộ hoặc một phiên bản bên ngoài.<br>

  **Lưu ý:** Rất tiếc, hiện tại chưa có hỗ trợ chính thức cho các kho key/value tương thích với Redis như KeyDB/Valkey, vì chúng tôi chưa thử nghiệm Server Pro với chúng. Mặc dù việc triển khai Server Pro với các kho tương thích **có thể** là khả thi, chúng tôi chỉ hỗ trợ chính thức các triển khai sử dụng Redis.<br>
* **Các tệp dự án và tệp Lịch sử**

  * Các tệp dự án không thể chỉnh sửa được lưu bên ngoài MongoDB.

    Hệ thống lịch sử dự án mới (từ Server Pro 3.5 trở đi) cũng lưu lịch sử bên ngoài MongoDB.
  * Đối với các phiên bản đơn nhỏ, chúng tôi hỗ trợ либо một hệ thống tệp cục bộ (có thể được hỗ trợ bởi SSD cục bộ, NFS hoặc EBS) hoặc một [hệ thống lưu trữ dữ liệu tương thích S3](/on-premises/vi/cau-hinh/overleaf-toolkit/s3.md).
  * Đối với mở rộng theo chiều ngang, chúng tôi **chỉ** hỗ trợ các hệ thống lưu trữ dữ liệu tương thích S3.<br>

  **Quan trọng:** NFS/Amazon EFS/Amazon EBS **không** được hỗ trợ cho mở rộng theo chiều ngang. Vui lòng xem [lưu trữ phần cứng](/on-premises/vi/bat-dau/requirements/hardware-requirements.md#storage) phần yêu cầu về việc mở rộng lưu trữ trong Server Pro để biết thêm chi tiết.
* **Các tệp tạm thời**
  * Các lần biên dịch LaTeX cần chạy trên các đĩa cục bộ nhanh để đạt hiệu suất tối ưu. Kết quả của việc biên dịch không cần được lưu bền vững hay sao lưu.
  * Việc đệm các lượt tải tệp mới lên và tạo các tệp zip dự án cũng được hưởng lợi từ việc sử dụng đĩa cục bộ.

{% hint style="danger" %}
Chúng tôi đặc biệt khuyên dùng đĩa cục bộ. Việc sử dụng bất kỳ loại đĩa mạng nào (như NFS hoặc EBS) có thể dẫn đến lỗi biên dịch không mong muốn và các vấn đề hiệu năng khác.
{% endhint %}

#### **Git-bridge**

{% hint style="info" %}
Git-bridge có sẵn trong Server Pro bắt đầu từ phiên bản 4.0.1.
{% endhint %}

Các kho lưu trữ git được lưu cục bộ trên đĩa. Không có tùy chọn sao chép nào. Git-bridge nên được chạy như một **singleton**. Để đạt hiệu suất tối ưu, chúng tôi khuyên dùng đĩa cục bộ cho dữ liệu git-bridge. Đĩa dữ liệu git-bridge nên được sao lưu thường xuyên.

Đối với lưu trữ dữ liệu khi mở rộng theo chiều ngang, bạn cần:

* một phiên bản MongoDB trung tâm có thể truy cập từ tất cả các phiên bản Server Pro
* một phiên bản Redis trung tâm có thể truy cập từ tất cả các phiên bản Server Pro
* một backend lưu trữ tương thích S3 trung tâm cho các tệp dự án và lịch sử
* một đĩa cục bộ trên mỗi phiên bản cho các tệp tạm thời
* một đĩa cục bộ trên phiên bản lưu trữ container git-bridge cho dữ liệu git-bridge

#### Yêu cầu của bộ cân bằng tải

* **Định tuyến cố định**, ví dụ sử dụng cookie

  Yêu cầu này xuất phát từ các thành phần sau:

  * Khả năng chỉnh sửa thời gian thực trong Server Pro sử dụng WebSockets với phương án dự phòng là XHR polling. Mỗi phiên chỉnh sửa có trạng thái cục bộ ở phía máy chủ và các yêu cầu của một phiên chỉnh sửa nhất định luôn cần được định tuyến đến cùng một phiên bản Server Pro. Tính năng cộng tác sử dụng Redis [Pub/Sub](https://redis.io/docs/latest/develop/interact/pubsub/) để chia sẻ cập nhật giữa nhiều phiên bản Server Pro.
  * Biên dịch LaTeX giữ đầu ra và bộ nhớ đệm biên dịch cục bộ để tối ưu hiệu suất. Khi gửi một yêu cầu biên dịch đến một phiên bản Server Pro, các yêu cầu tải PDF/log sau đó cần được định tuyến đến cùng phiên bản Server Pro đó.
* **Thời gian chờ yêu cầu dài** để hỗ trợ biên dịch các tài liệu LaTeX lớn
* **Hỗ trợ WebSocket** để đạt hiệu suất tối ưu
* **kích thước payload POST là 50MB**
* **Thời gian chờ keep-alive** phải thấp hơn thời gian chờ keep-alive của Server Pro

  Thời gian chờ keep-alive trong Server Pro có thể được cấu hình bằng biến môi trường `NGINX_KEEPALIVE_TIMEOUT`. Giá trị mặc định là 65s.

  Với giá trị mặc định, thời gian chờ keep-alive 60s trong bộ cân bằng tải là hoạt động.

  Với `NGINX_KEEPALIVE_TIMEOUT=120`, bộ cân bằng tải có thể chọn 115s.
* **Địa chỉ IP của máy khách**

  Đặt tiêu đề yêu cầu `X-Forwarded-For` thành IP của máy khách.
* Khi **kết thúc SSL**

  Bộ cân bằng tải cần thêm tiêu đề yêu cầu `X-Forwarded-Proto: https`.

<details>

<summary>Cấu hình HAProxy mẫu</summary>

```
global
  group haproxy
  user haproxy

  # Ghi log chi tiết
  log stdout format raw local0 debug

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

  # Ghi log chi tiết
  log                     global
  option                  httplog

  # Chuyển hướng sang backend khác nếu backend dính hiện tại bị lỗi
  option                  redispatch 1
  # Các lần thử lại này dành cho lỗi kết nối TCP, không phải cho phản hồi HTTP trạng thái 500
  retries                 3

  # Phiên dính trong 24h không hoạt động -- đầu ra biên dịch bị xóa sau 24h
  cookie                  server-pro-ha insert maxidle 24h

  # Thử kết nối tới bất kỳ backend nào trong 1 phút, sau đó trả về 503
  timeout queue           1m
  # Cho các phiên bản Server Pro 15 giây để khởi động
  timeout connect         15s

  # Hủy yêu cầu từ các máy khách quá chậm (cho phép 1 phút không hoạt động khi đọc một yêu cầu)
  timeout client          1m

  # Cho phép biên dịch chậm -- giới hạn mã cứng trong clsi là 10 phút
  timeout server          10m

  # Ngắt kết nối trình soạn thảo sau 23 giờ -- sớm hơn 1 giờ so với lần sử dụng cuối cùng của họ hôm qua
  timeout tunnel          23h

  # Lưu ý: Hành vi keepalive trong haproxy hoạt động rất tốt với thiết lập keepalive mặc định trong Server Pro.
  #       Haproxy đang dọn dẹp các kết nối ở nền và nó sẽ chuyển hướng lại yêu cầu khi cần.

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

  # Báo cho ứng dụng rằng chúng ta đang ở phía sau https
  http-request set-header X-Forwarded-Proto https

  # Báo cho ứng dụng biết địa chỉ ip thực của máy khách
  option forwardfor

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

  # Định tuyến lưu lượng git tới container anh em của git-bridge
  use-server server-pro-ha-1 if { path_beg /git/ }

  # Gỡ lỗi
  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>

#### Cấu hình Server Pro

**Bí mật**

Các phiên bản Server Pro cần thống nhất về các bí mật dùng chung:

* `WEB_API_PASSWORD` (xác thực web api)
* `STAGING_PASSWORD` và `V1_HISTORY_PASSWORD` cùng giá trị (xác thực lịch sử)
* `CRYPTO_RANDOM` (dành cho cookie phiên)
* `OT_JWT_AUTH_KEY` (xác thực lịch sử)

Tất cả các bí mật này cần được cấu hình bằng giá trị riêng duy nhất của chúng và được chia sẻ giữa các phiên bản.

Khi không được cấu hình và các yêu cầu người dùng được định tuyến đến các phiên bản Server Pro khác nhau, yêu cầu của họ sẽ không vượt qua các kiểm tra xác thực và họ либо sẽ thường xuyên bị chuyển hướng đến trang đăng nhập hoặc các thao tác của họ trong giao diện sẽ thất bại theo những cách không mong muốn.

Khi không được cấu hình, Server Pro sử dụng một giá trị ngẫu nhiên mới cho mỗi bí mật dựa trên 32 byte ngẫu nhiên từ `/dev/urandom` (256 bit ngẫu nhiên).

{% 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**

Trỏ `OVERLEAF_MONGO_URL` (`SHARELATEX_MONGO_URL` cho các phiên bản `4.x` và sớm hơn) tới phiên bản MongoDB trung tâm.

**Redis**

Trỏ `OVERLEAF_REDIS_HOST` (`SHARELATEX_REDIS_HOST` cho các phiên bản `4.x` và sớm hơn) và `REDIS_HOST` tới phiên bản Redis trung tâm.

**Lưu trữ S3 tương thích cho các tệp dự án và lịch sử**

Vui lòng xem tài liệu về [lưu trữ tương thích S3](/on-premises/vi/cau-hinh/overleaf-toolkit/s3.md) để biết chi tiết.

**Các tệp tạm thời**

Gắn kết mặc định của một SSD cục bộ tới `/var/lib/overleaf` (`/var/lib/sharelatex` cho các phiên bản `4.x` và sớm hơn) là đủ. Hãy đảm bảo trỏ `SANDBOXED_COMPILES_HOST_DIR` vào điểm gắn kết trên máy chủ.

{% hint style="danger" %}
Chúng tôi đặc biệt khuyên dùng đĩa cục bộ. Việc sử dụng bất kỳ loại đĩa mạng nào (như NFS hoặc EBS) có thể dẫn đến lỗi biên dịch không mong muốn và các vấn đề hiệu năng khác.
{% endhint %}

**Cấu hình proxy**

* Đặt `OVERLEAF_BEHIND_PROXY=true` (`SHARELATEX_BEHIND_PROXY` cho các phiên bản `4.x` và sớm hơn) để có địa chỉ IP máy khách chính xác.
* Đặt `TRUSTED_PROXY_IPS` thành IP của bộ cân bằng tải (Có thể chỉ định nhiều CIDR, phân tách bằng dấu phẩy).

**Tích hợp Git-bridge**

{% hint style="info" %}
Git-bridge có sẵn trong Server Pro bắt đầu từ phiên bản 4.0.1.
{% endhint %}

Container git-bridge cần một container Server Pro anh em để xử lý các yêu cầu git đến. Container anh em này cũng có thể phục vụ lưu lượng người dùng thông thường. Trong cấu hình mẫu, phiên bản đầu tiên đóng vai trò container anh em cho git-bridge, nhưng thực ra bất kỳ phiên bản nào cũng có thể làm vai trò đó.

Tại sao chúng ta cần chỉ định một container Server Pro làm anh em cho git-bridge? Server Pro cấp các URL tải xuống cho dịch vụ lịch sử tới git-bridge. Chúng ta cần cấu hình các URL lịch sử này để có thể truy cập từ container git-bridge.

Cấu hình container Server Pro:

* Đặt `GIT_BRIDGE_ENABLED` đến `'true'`
* Đặt `GIT_BRIDGE_HOST` đến `<tên container git-bridge>` ví dụ `git-bridge`
* Đặt `GIT_BRIDGE_PORT` đến `8000`
* Đặt `V1_HISTORY_URL` đến `http://<tên container anh em server-pro>:3100/api`.

  Lưu ý: Điều này chỉ cần thiết trên container anh em cho container git-bridge. Các phiên bản khác có thể dùng URL localhost, là giá trị mặc định.

Cấu hình container git-bridge:

* Đặt `GIT_BRIDGE_API_BASE_URL` đến `http://<tên container anh em server-pro>/api/v0`, ví dụ `http://server-pro-ha-1/api/v0`
* Đặt `GIT_BRIDGE_OAUTH2_SERVER` đến `http://<tên container anh em server-pro>`, ví dụ `http://server-pro-ha-1`
* Đặt `GIT_BRIDGE_POSTBACK_BASE_URL` đến `http://<tên container git-bridge>:8000`, ví dụ `http://git-bridge:8000`
* Đặt `GIT_BRIDGE_ROOT_DIR` tới đĩa dữ liệu git-bridge được gắn kết, ví dụ `/data/git-bridge`

<details>

<summary>Cấu hình docker-compose.yml mẫu</summary>

Cấu hình sau đây đang hiển thị một thiết lập tự chứa. Để demo hoạt động, bạn cần cung cấp một khóa/chứng chỉ SSL hợp lệ và điều chỉnh `OVERLEAF_SITE_URL` (`SHARELATEX_SITE_URL` cho các phiên bản `4.x` và sớm hơn). Đối với một thiết lập thực tế, bạn phải thay thế các bí mật giả bằng các bí mật thực như đã ghi chú tại chỗ. Đối với một thiết lập thực tế, bạn cần chuyển các container riêng lẻ sang các nút dành riêng và điều chỉnh các địa chỉ IP cho phù hợp với thiết lập mạng cục bộ của bạn.

```yaml
version: '2.2'

# Thiết lập mở rộng theo chiều ngang thực tế: chọn mạng của riêng bạn và thay thế IP trong cấu hình.
networks:
    default:
        ipam:
            config:
                # Subnet này là một phần của subnet dành riêng được dùng để benchmark
                # https://tools.ietf.org/html/rfc2544
                # Toàn bộ subnet là 198.18.0.0/15
                # Dùng 198.18.0.0/24 cho lb và dbs
                # Dùng 198.18.1.0/24 cho server-pro
                # Dùng 198.18.0.128/25 cho container tạm thời
                - gateway: 198.18.0.1
                  ip_range: 198.18.0.128/25
                  subnet: 198.18.0.0/23

services:
    # Thiết lập mở rộng theo chiều ngang thực tế: chạy haproxy bên ngoài docker trên một máy chủ riêng.
    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
        # Phương án thay thế cho "ports": dùng mạng host để tránh chi phí docker-proxy
        network_mode: host

        # Phương án thay thế cho "network_mode: host": dùng docker-proxy để cô lập mạng
        # ports:
        #     - "80:80"
        #     - "443:443"
        # networks:
        #     default:
        #         ipv4_address: 198.18.0.2

        # Thiết lập mở rộng theo chiều ngang thực tế: xóa các mục này vì chúng chạy trên các máy chủ khác.
        depends_on:
            server-pro-ha-1:
                condition: service_started
            server-pro-ha-2:
                condition: service_started
            server-pro-ha-3:
                condition: service_started

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này cạnh server-pro-ha-1.
    # Dành cho Server Pro 4.0 trở đi.
    git-bridge:
        restart: always
        # Tag phải khớp với tag container `server-pro-ha-1`.
        image: quay.io/sharelatex/git-bridge:4.0.1
        volumes:
            # Thiết lập mở rộng theo chiều ngang thực tế: trỏ /data/git-bridge tới một SSD cục bộ chuyên dụng.
            - ~/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"]

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.0.6 và mở cổng
        # ports:
        #     - "8000:8000"
        networks:
            default:
                ipv4_address: 198.18.0.6

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này trên một máy chủ riêng.
    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:
            # Thiết lập mở rộng theo chiều ngang thực tế: giữ mục này.
            git-bridge:
                condition: service_started

            # Thiết lập mở rộng theo chiều ngang thực tế: xóa các mục bên dưới vì chúng chạy trên các máy chủ khác.
            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
            # Thiết lập mở rộng theo chiều ngang thực tế: cung cấp tên miền/tên ứng dụng của riêng bạn.
            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
            # Thiết lập mở rộng theo chiều ngang thực tế: chọn thông tin xác thực an toàn.
            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
            # Chỉ cần trên phiên bản cùng cấp của git-bridge
            V1_HISTORY_URL: "http://server-pro-ha-1:3100/api"
            # /git-bridge

            # Tự động mở rộng theo chiều ngang
            # Thiết lập mở rộng theo chiều ngang thực tế: chọn thông tin xác thực an toàn.
            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'
            # Thiết lập mở rộng theo chiều ngang thực tế: địa chỉ IP của bộ cân bằng tải
            TRUSTED_PROXY_IPS: 198.18.0.1,198.18.0.2
            # /Tự động mở rộng theo chiều ngang

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.1.1 và mở các cổng
        # ports:
        #     - "80:80"
        networks:
            default:
                ipv4_address: 198.18.1.1

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này trên một máy chủ riêng.
    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"

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.1.2 và mở các cổng
        # ports:
        #     - "80:80"
        networks:
            default:
                ipv4_address: 198.18.1.2

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này trên một máy chủ riêng.
    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"

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.1.3 và mở các cổng
        # ports:
        #     - "80:80"
        networks:
            default:
                ipv4_address: 198.18.1.3

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này trên một máy chủ riêng.
    minio:
        image: minio/minio:RELEASE.2023-05-18T00-05-36Z
        container_name: minio
        command: server /data
        volumes:
            # Thiết lập mở rộng theo chiều ngang thực tế: chạy minio với nhiều đĩa, xem tài liệu minio.
            - ~/minio_data:/data
        environment:
            # Thiết lập mở rộng theo chiều ngang thực tế: chọn thông tin xác thực an toàn.
            MINIO_ROOT_USER: MINIO_ROOT_USER
            MINIO_ROOT_PASSWORD: MINIO_ROOT_PASSWORD

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.0.5 và mở cổng
        # ports:
        #     - "9000:9000"
        networks:
            default:
                ipv4_address: 198.18.0.5

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy thiết lập này một lần trên một máy chủ riêng.
    minio_setup:
        depends_on:
            - minio
        image: minio/mc:RELEASE.2023-05-18T16-59-00Z
        entrypoint: sh
        lệnh:
            - '-c'
            # Thiết lập mở rộng theo chiều ngang thực tế: chọn thông tin xác thực an toàn.
            - |
                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

                # Đặt nội dung của chính sách ở phần trước vào policy-filestore.json
                # Nhắc nhở: Hãy thay thế tên bucket tương ứng.
                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

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này trên một máy chủ riêng.
    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

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.0.3 và mở cổng
        # 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
        lệnh:
            - '-c'
            - |
                mongo 198.18.0.3 --eval "rs.initiate({ _id: \"overleaf\", members: [ { _id: 0, host: \"198.18.0.3:27017\" } ] })"

    # Thiết lập mở rộng theo chiều ngang thực tế: chạy container này trên một máy chủ riêng.
    redis:
        restart: always
        image: redis:6.2
        container_name: redis
        expose:
            - 6379
        volumes:
            - ~/redis_data:/data

        # Thiết lập mở rộng theo chiều ngang thực tế: chạy trên máy chủ 198.18.0.4 và mở cổng
        # ports:
        #     - "6379:6379"
        networks:
            default:
                ipv4_address: 198.18.0.4
```

</details>

#### Phần cứng

Chúng tôi khuyến nghị sử dụng cùng thông số phần cứng cho tất cả các phiên bản Server Pro tham gia vào việc mở rộng theo chiều ngang.

Các khuyến nghị chung về [thông số phần cứng](/on-premises/vi/bat-dau/requirements/hardware-requirements.md) cho các phiên bản Server Pro cũng được áp dụng.

#### Nâng cấp Server Pro

Trong quá trình nâng cấp, Server Pro tự động chạy các di chuyển cơ sở dữ liệu. Các quá trình di chuyển này là **không** được thiết kế để chạy song song từ nhiều phiên bản.

Các quá trình di chuyển cần hoàn tất trước khi ứng dụng web thực sự được khởi động. Bạn có thể kiểm tra log để tìm mục `Đã hoàn tất di chuyển` hoặc đợi cho đến khi ứng dụng chấp nhận lưu lượng truy cập.

Quy trình nâng cấp như sau:

1. Lên lịch một khoảng thời gian bảo trì
2. Dừng tất cả các phiên bản Server Pro
3. Tạo một bản sao lưu nhất quán như được mô tả trong [tài liệu của chúng tôi](/on-premises/vi/bao-tri/data-and-backups.md#performing-a-consistent-backup)
4. Khởi động một phiên bản Server Pro duy nhất với phiên bản mới
5. Xác minh rằng phiên bản mới hoạt động như mong đợi
6. Khởi động các phiên bản còn lại với phiên bản mới


---

# 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/vi/bao-tri/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.
