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

# Mở rộng 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 một `4.x` phiên bản (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 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 trang bị 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 các khuyến nghị.

Việc triển khai Server Pro với mở rộng theo chiều ngang bao gồm một bộ 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 giải quyết các sự cố kỹ thuật cụ thể cho 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 tập trung 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 trong 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 không 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ể** thực hiện được, chúng tôi chỉ chính thức hỗ trợ 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 bản cập nhật tài liệu đang chờ trước khi được ghi vào MongoDB.
  * Redis được dùng để trao đổi các bản 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 trữ 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 không có hỗ trợ chính thức cho các kho lưu trữ key/value tương thích 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 lưu trữ tương thích **có thể** có thể thực hiện được, chúng tôi chỉ chính thức hỗ trợ các triển khai sử dụng Redis.<br>
* **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 lẻ 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 được **không** hỗ trợ cho mở rộng theo chiều ngang. Vui lòng xem [mục yêu cầu lưu trữ phần cứng](/on-premises/vi/bat-dau/requirements/hardware-requirements.md#storage) trong phần mở rộng lưu trữ của Server Pro để biết thêm chi tiết.
* **Tệp tạm thời**
  * Các lượt biên dịch LaTeX cần chạy trên đĩa cục bộ nhanh để đạt hiệu năng tối ưu. Kết quả biên dịch không cần được lưu bền vững hoặc sao lưu.
  * Việc đệm các lượt tải lên tệp mới và tạo các tệp zip của dự án cũng được hưởng lợi từ việc 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 khả dụng trong Server Pro kể 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 **thực thể đơn lẻ**. Để đạt hiệu năng 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 được 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 được từ tất cả các phiên bản Server Pro
* một backend lưu trữ tương thích S3 tập trung 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 đối với 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 WebSocket với phương án dự phòng là thăm dò XHR. 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 tới 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ác bản cập nhật giữa nhiều phiên bản Server Pro.
  * Biên dịch LaTeX giữ output và bộ nhớ đệm biên dịch cục bộ để đạt hiệu năng tối ưu. Khi gửi một yêu cầu biên dịch tới một phiên bản Server Pro, các yêu cầu tải xuống PDF/log sau đó cần được định tuyến tới 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 năng tối ưu
* **kích thước payload POST 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à 65 giây.

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

  Với `NGINX_KEEPALIVE_TIMEOUT=120`, bộ cân bằng tải có thể chọn 115 giây.
* **IP của client**

  Đặt tiêu đề yêu cầu `X-Forwarded-For` thành IP của client.
* Khi **chấm dứt 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

  # Định tuyến lại sang backend khác nếu backend sticky 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 các phản hồi trạng thái HTTP 500
  retries                 3

  # Phiên sticky trong 24 giờ không hoạt động -- output biên dịch sẽ bị xóa sau 24 giờ
  cookie                  server-pro-ha insert maxidle 24h

  # Thử kết nối tới bất kỳ backend nào trong 1 phút, rồi 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 các yêu cầu từ những client 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 cố định 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ủ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à sẽ định tuyến lại các 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 biết rằng chúng ta đang ở sau https
  http-request set-header X-Forwarded-Proto https

  # Báo cho ứng dụng biết IP thực của client
  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

**Thông tin 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` (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 với 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 của người dùng được định tuyến tới 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ẽ bị chuyển hướng tới trang đăng nhập thường xuyên hoặc các thao tác của họ trong giao diện người dùng 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à cũ 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à cũ hơn) và `REDIS_HOST` tại phiên bản Redis trung tâm.

**Lưu trữ tương thích S3 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.

**Tệp tạm thời**

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

{% 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à cũ hơn) để có IP client 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 khả dụng trong Server Pro kể 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ể đảm nhiệm vai trò đó.

Tại sao chúng ta cần chỉ định một container Server Pro làm container anh em cho git-bridge? Server Pro cung 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 sao cho 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 ý: Chỉ cần thiết trên container anh em cho container git-bridge. Các phiên bản khác có thể sử dụng URL localhost, là 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 bind-mount, ví dụ: `/data/git-bridge`

<details>

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

Cấu hình sau đây đang minh họa một thiết lập độc lập. Để bản 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à cũ hơn). Đối với một thiết lập thực tế, bạn phải thay các bí mật giả bằng các bí mật thực như đã lưu ý ngay tại chỗ. Đối với một thiết lập thực tế, bạn cần chuyển từng container lên các nút chuyên dụng và điều chỉnh địa chỉ IP theo 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ế các IP trong cấu hình.
networks:
    default:
        ipam:
            config:
                # Mạng con này là một phần của mạng con được dành riêng dùng để benchmark
                # https://tools.ietf.org/html/rfc2544
                # Toàn bộ mạng con 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 host 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
        # Thay thế cho "ports": dùng mạng host để tránh overhead của docker-proxy
        network_mode: host

        # Thay thế cho "network_mode: host": dùng docker-proxy để cách ly 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 host 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 bên cạnh server-pro-ha-1.
    # Dành cho Server Pro 4.0 trở lên.
    git-bridge:
        restart: always
        # Tag nên 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 host 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 host 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 host 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 domain/tên ứng dụng của riêng bạn.
            OVERLEAF_SITE_URL: 'https://overleaf.example.com'
            OVERLEAF_APP_NAME: Bản demo mở rộng theo chiều ngang của 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
            # 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

            # 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ế: IP của các bộ cân bằng tải
            TRUSTED_PROXY_IPS: 198.18.0.1,198.18.0.2
            # /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 host 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 host 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 host 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 cấu hình này một lần trên một máy chủ riêng biệt.
    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 từ phần trước vào policy-filestore.json
                # Nhắc nhở: Hãy thay thế các 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 host 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 host 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) áp dụng cho các phiên bản Server Pro.

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

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

Các di chuyển cần hoàn tất trước khi ứng dụng web thực tế được khởi động. Bạn có thể kiểm tra nhật ký để 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 trông 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 của 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](/on-premises/vi/bao-tri/data-and-backups.md#performing-a-consistent-backup)
4. Khởi động một phiên bản duy nhất của Server Pro với phiên bản mới
5. Xác nhận 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://overleaf-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.
