> 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/ko/maintenance/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 %}

수평 확장을 설정하려면 상당한 노력이 필요합니다. 수평 확장을 고려할 것을 권장합니다 **오직** 일정 규모에 도달했을 때. 예를 들어, 총 사용자 1,000명을 위한 Server Pro 설치는 4코어 프로세서 2개와 시스템 메모리 32GB가 탑재된 단일 서버를 사용하여 성공적으로 구축되었습니다. 다음을 참조하세요. [하드웨어 요구 사항](/on-premises/ko/getting-started/requirements/hardware-requirements.md) 문서에서 권장 사항을 확인하세요.

수평 확장을 사용하는 Server Pro 배포에는 로드 밸런서와 S3 호환 스토리지 백엔드와 같은 외부 구성 요소 집합이 포함됩니다.

잘못된 구성으로 인해 발생할 수 있는 Server Pro 컨테이너의 오류를 문제 해결하도록 도와드리고, 이 문서를 기반으로 일반적인 조언을 제공할 수 있습니다. 안타깝게도 타사 애플리케이션/시스템 구성에 대한 지원은 제공할 수 없습니다.

외부 구성 요소를 제공하기 위해 필요한 하드웨어/소프트웨어 관련 기술 문제 해결은 지원 범위에 포함되지 않습니다.

### 요구 사항

#### 외부 중앙 데이터 저장소

Server Pro의 데이터 저장소는 네 가지 데이터 저장소로 나눌 수 있습니다:

* **MongoDB**

  * 대부분의 데이터는 MongoDB에 저장됩니다.
  * 로컬 인스턴스 또는 다음과 같은 외부 인스턴스 중 하나를 지원합니다 [MongoDB](https://www.mongodb.com/atlas) Atlas(AWS 인프라 내에서 실행되는 완전 관리형 MongoDB 서비스).<br>

  **참고:** 안타깝게도 현재 CosmoDB/DocumentDB와 같은 MongoDB 호환 데이터베이스에 대한 공식 지원은 없습니다. Server Pro를 이러한 데이터베이스와 함께 테스트하지 않았기 때문입니다. 호환 가능한 데이터베이스로 Server Pro를 배포하는 것은 **가능할 수도 있지만** 공식적으로는 MongoDB를 사용하는 배포만 지원합니다.<br>
* **Redis**

  * Redis는 MongoDB에 반영되기 전의 대기 중인 문서 업데이트와 같은 임시 데이터를 저장합니다.
  * Redis는 서로 다른 서비스 간에 문서 업데이트를 전달하고, 특정 프로젝트에서 상태 변경을 편집기에 알리는 데 사용됩니다.
  * Redis는 사용자 세션을 저장하는 데 사용됩니다.
  * 로컬 인스턴스 또는 외부 인스턴스 중 하나를 지원합니다.<br>

  **참고:** 안타깝게도 현재 KeyDB/Valkey와 같은 Redis 호환 키/값 저장소에 대한 공식 지원은 없습니다. Server Pro를 이러한 저장소와 함께 테스트하지 않았기 때문입니다. 호환 가능한 저장소로 Server Pro를 배포하는 것은 **가능할 수도 있지만** 가능할 수도 있지만, 공식적으로는 Redis를 사용하는 배포만 지원합니다.<br>
* **프로젝트 파일 및 히스토리 파일**

  * 편집할 수 없는 프로젝트 파일은 MongoDB 외부에 저장됩니다.

    새로운 프로젝트 히스토리 시스템(Server Pro 3.5 이후)도 히스토리를 MongoDB 외부에 저장합니다.
  * 소규모 단일 인스턴스의 경우 로컬 파일 시스템(로컬 SSD, NFS 또는 EBS에 백업될 수 있음) 또는 [S3 호환 데이터 저장 시스템](/on-premises/ko/configuration/overleaf-toolkit/s3.md).
  * 수평 확장을 위해서는 **오직** S3 호환 데이터 저장 시스템을 지원합니다.<br>

  **중요:** NFS/Amazon EFS/Amazon EBS는 **하지** 수평 확장에서 지원됩니다. 자세한 내용은 [하드웨어 저장소](/on-premises/ko/getting-started/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 데이터 디스크는 정기적으로 백업해야 합니다.

수평 확장을 위한 데이터 저장에는 다음이 필요합니다:

* 모든 Server Pro 인스턴스에서 액세스 가능한 중앙 MongoDB 인스턴스
* 모든 Server Pro 인스턴스에서 액세스 가능한 중앙 Redis 인스턴스
* 프로젝트 및 히스토리 파일용 중앙 S3 호환 스토리지 백엔드
* 각 인스턴스의 일시적 파일용 로컬 디스크
* git-bridge 데이터용 git-bridge 컨테이너를 호스팅하는 인스턴스의 로컬 디스크

#### 로드 밸런서 요구 사항

* **지속적 라우팅**, 예: 쿠키 사용

  이 요구 사항은 다음 구성 요소에서 비롯됩니다:

  * Server Pro의 실시간 편집 기능은 WebSocket을 사용하며, 대체 수단으로 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 페이로드 크기 50MB**
* **Keep-alive 타임아웃** 는 Server Pro의 keep-alive 타임아웃보다 낮아야 합니다

  Server Pro의 keep-alive 타임아웃은 환경 변수 `NGINX_KEEPALIVE_TIMEOUT`를 사용하여 구성할 수 있습니다. 기본값은 65초입니다.

  기본값에서는 로드 밸런서의 60초 keep-alive 타임아웃이 작동합니다.

  다음과 같이 `NGINX_KEEPALIVE_TIMEOUT=120`이면 로드 밸런서는 115초를 선택할 수 있습니다.
* **클라이언트 IP**

  요청 헤더를 설정하세요 `X-Forwarded-For` 를 클라이언트 IP로.
* 만약 **SSL 종료**

  로드 밸런서는 요청 헤더 `X-Forwarded-Proto: https`.

<details>

<summary>HAProxy 설정 예시</summary>

```
global
  group haproxy
  user haproxy

  # 자세한 로깅
  log stdout format raw local0 debug

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

  # 자세한 로깅
  log                     global
  option                  httplog

  # 고정된 백엔드가 다운되면 다른 백엔드로 다시 라우팅
  option                  redispatch 1
  # 이 재시도는 TCP 연결 오류에 대한 것이며 HTTP 상태 500 응답에 대한 것이 아닙니다
  retries                 3

  # 24시간 비활동 시 고정 세션 -- 컴파일 출력은 24시간 후 삭제됩니다
  cookie                  server-pro-ha insert maxidle 24h

  # 1분 동안 어떤 백엔드든 연결을 시도한 다음 503을 반환
  timeout queue           1m
  # Server Pro 인스턴스에 15초의 시작 시간을 부여
  timeout connect         15s

  # 매우 느린 클라이언트의 요청을 중단(요청을 읽는 동안 1분의 비활동 허용)
  timeout client          1m

  # 느린 컴파일 허용 -- clsi의 하드코딩된 제한은 10분
  timeout server          10m

  # 23시간 후 편집기 연결 해제 -- 어제 마지막 사용 시각보다 1시간 전
  timeout tunnel          23h

  # 참고: haproxy의 keepalive 동작은 Server Pro의 기본 keepalive 설정과 아주 잘 작동합니다.
  #       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` (세션 쿠키용)
* `OT_JWT_AUTH_KEY` (히스토리 인증)

이 모든 비밀 값은 각각 고유한 값으로 구성되어야 하며 인스턴스 간에 공유되어야 합니다.

구성되지 않은 상태에서 사용자 요청이 서로 다른 Server Pro 인스턴스로 라우팅되면 해당 요청은 인증 검사를 통과하지 못하고, 자주 로그인 페이지로 리디렉션되거나 UI에서의 작업이 예상치 못한 방식으로 실패할 수 있습니다.

구성되지 않은 경우 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/ko/configuration/overleaf-toolkit/s3.md) 자세한 내용은.

**일시적 파일**

로컬 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 컨테이너는 들어오는 git 요청을 처리하기 위해 형제 Server Pro 컨테이너가 필요합니다. 이 형제 컨테이너는 일반 사용자 트래픽도 처리할 수 있습니다. 샘플 구성에서는 첫 번째 인스턴스가 git-bridge의 형제 컨테이너 역할을 하지만, 실제로는 어떤 인스턴스든 그 역할을 할 수 있습니다.

왜 git-bridge용으로 하나의 Server Pro 컨테이너를 형제 컨테이너로 지정해야 할까요? Server Pro는 히스토리 서비스용 다운로드 URL을 git-bridge에 제공합니다. 이 히스토리 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` 바인드 마운트된 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입니다
                # lb 및 db에는 198.18.0.0/24를 사용
                # server-pro에는 198.18.1.0/24를 사용
                # 임시 컨테이너에는 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"의 대안: 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
            # /수평 확장

        # 실제 수평 확장 설정: 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/ko/getting-started/requirements/hardware-requirements.md) 이 Server Pro 인스턴스에 적용됩니다.

#### Server Pro 업그레이드

업그레이드 과정의 일부로 Server Pro는 데이터베이스 마이그레이션을 자동으로 실행합니다. 이 마이그레이션은 **하지** 여러 인스턴스에서 병렬로 실행되도록 설계되었습니다.

실제 웹 애플리케이션이 시작되기 전에 마이그레이션이 완료되어야 합니다. 로그에서 `마이그레이션 완료` 항목을 확인하거나 애플리케이션이 트래픽을 받을 때까지 기다리면 됩니다.

업그레이드 절차는 다음과 같습니다:

1. 유지보수 기간을 계획하세요
2. Server Pro의 모든 인스턴스를 중지하세요
3. 다음에 설명된 대로 일관된 백업을 수행하세요 [문서](/on-premises/ko/maintenance/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/ko/maintenance/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.
