> 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/cau-hinh/overleaf-toolkit/sandboxed-compiles.md).

# Các bản biên dịch trong hộp cát

Overleaf Pro đi kèm tùy chọn chạy biên dịch trong môi trường hộp cát an toàn để bảo mật cho doanh nghiệp. Nó thực hiện điều này bằng cách chạy mỗi dự án trong môi trường docker an toàn riêng của nó.

### Bảo mật được cải thiện

Sandboxed Compiles là phương pháp được khuyến nghị cho Server Pro vì nhiều tài liệu LaTeX yêu cầu/có khả năng thực thi các lệnh shell tùy ý như một phần của quá trình biên dịch PDF. Nếu bạn dùng Sandboxed Compiles, mỗi lần biên dịch sẽ chạy trong một container Docker riêng biệt với các khả năng bị giới hạn, không được chia sẻ với bất kỳ người dùng hay dự án nào khác và không có quyền truy cập vào các tài nguyên bên ngoài như mạng của máy chủ.

{% hint style="warning" %}
Nếu bạn cố chạy Overleaf Pro **không có** Sandboxed Compiles, quá trình biên dịch sẽ chạy song song với các lần biên dịch đồng thời khác bên trong container Docker chính và người dùng có quyền đọc và ghi đầy đủ vào `sharelatex` các tài nguyên của container (hệ thống tệp, mạng và biến môi trường) khi chạy biên dịch LaTeX.
{% endhint %}

### Quản lý gói dễ dàng hơn

Để tránh phải cài đặt gói thủ công, chúng tôi khuyến nghị bật Sandboxed Compiles. Đây là một thiết lập có thể cấu hình trong Server Pro, cung cấp cho người dùng của bạn quyền truy cập vào cùng một môi trường TeX Live như trên overleaf.com nhưng trong bản cài đặt tại chỗ của riêng bạn. Các ảnh TeX Live được dùng bởi Sandboxed Compiles chứa các gói và phông chữ phổ biến nhất đã được kiểm thử với các mẫu thư viện của chúng tôi, đảm bảo khả năng tương thích tối đa với các dự án tại chỗ.

Việc bật Sandboxed Compiles cho phép bạn cấu hình những phiên bản TeX Live nào mà người dùng có thể chọn trong dự án của họ, đồng thời đặt một phiên bản ảnh TeX Live mặc định cho các dự án mới.

{% hint style="info" %}
Nếu bạn cố chạy Overleaf Pro mà không có Sandboxed Compiles, phiên bản của bạn sẽ mặc định dùng một phiên bản lược đồ cơ bản của TeX Live cho các lần biên dịch. Phiên bản cơ bản này nhẹ và chỉ chứa một tập hợp con rất hạn chế của các gói LaTeX, vì vậy rất có thể người dùng của bạn sẽ gặp lỗi thiếu gói, đặc biệt nếu họ cố dùng các mẫu dựng sẵn.
{% endhint %}

Vì Overleaf Pro được thiết kế để hoạt động ngoại tuyến, không có cách tự động nào để tích hợp các mẫu từ thư viện overleaf.com vào bản cài đặt tại chỗ của bạn; tuy nhiên, bạn có thể làm việc này thủ công theo từng mẫu. Để biết thêm thông tin về cách thức hoạt động, vui lòng xem hướng dẫn chuyển mẫu từ overleaf.com của chúng tôi: [/pages/8b9ba7d0925f6bd687383d61bc8206e570931bb0#transferring-templates-from-overleaf.com](https://ayakaleaf-pro.ayaka.space/on-premises/vi/cau-hinh/overleaf-toolkit/pages/8b9ba7d0925f6bd687383d61bc8206e570931bb0#transferring-templates-from-overleaf.com "mention").

{% hint style="info" %}
Sandboxed Compiles yêu cầu rằng `sharelatex` container phải có quyền truy cập vào Docker socket trên máy chủ (thông qua một bind mount) để nó có thể quản lý các container biên dịch anh em này.
{% endhint %}

## Cách hoạt động

Khi Sandboxed Compiles được bật, Docker socket sẽ được mount từ máy chủ vào `sharelatex` container, để dịch vụ biên dịch trong container có thể tạo các container Docker mới trên máy chủ. Sau đó, với mỗi lần chạy trình biên dịch trong từng dự án, dịch vụ biên dịch LaTeX (CLSI) sẽ làm như sau:

* Ghi các tệp của dự án ra một vị trí bên trong `OVERLEAF_DATA_PATH`.
* Sử dụng Docker socket đã mount để tạo một `texlive` container mới cho lần chạy biên dịch.
* Cho `texlive` container đọc dữ liệu dự án từ vị trí dưới `OVERLEAF_DATA_PATH`.
* Biên dịch dự án bên trong `texlive` container.

### Bật Sandboxed Compiles

#### Dành cho người dùng Toolkit

Để bật biên dịch trong hộp cát (còn gọi là Sibling containers), hãy đặt các tùy chọn cấu hình sau trong `overleaf-toolkit/config/overleaf.rc`:

{% code title="config/overleaf.rc" %}

```dotenv
SERVER_PRO=true
SIBLING_CONTAINERS_ENABLED=true
```

{% endcode %}

#### Dành cho người dùng Docker Compose <a href="#docker-compose-example" id="docker-compose-example"></a>

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

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

<pre class="language-yml"><code class="lang-yml">version: '2'
services:
    sharelatex:
        #...
        volumes:
            - /data/overleaf_data:/var/lib/overleaf
<strong>            - /var/run/docker.sock:/var/run/docker.sock
</strong>        environment:
            #...
<strong>            DOCKER_RUNNER: "true"
</strong><strong>            SANDBOXED_COMPILES: "true"
</strong><strong>            SANDBOXED_COMPILES_HOST_DIR: "/data/overleaf_data/data/compiles"
</strong>            #...
        #...
</code></pre>

### Thay đổi ảnh TexLive

{% hint style="info" %}
Đối với người dùng ở Trung Quốc đại lục, bạn có thể dùng `ghcr.nju.edu.cn` để tăng tốc tải xuống của bạn.
{% endhint %}

Overleaf Pro sử dụng ba biến môi trường để xác định ảnh TeX Live nào sẽ dùng cho Sandboxed Compiles:

* `TEX_LIVE_DOCKER_IMAGE` **(bắt buộc),** Ảnh TeX Live mặc định dùng để biên dịch các dự án mới. Ảnh này phải được bao gồm trong `ALL_TEX_LIVE_DOCKER_IMAGES`.
* `ALL_TEX_LIVE_DOCKER_IMAGE_NAMES` **(bắt buộc),** Danh sách các tên thân thiện của các ảnh, phân tách bằng dấu phẩy, dùng cho tùy chọn giao diện người dùng.
* `ALL_TEX_LIVE_DOCKER_IMAGES` **(bắt buộc),** Danh sách các ảnh TeX Live dùng, phân tách bằng dấu phẩy. Nếu dùng Overleaf Toolkit để triển khai, các ảnh này sẽ được tải xuống hoặc cập nhật. Để bỏ qua việc tải xuống, đặt `SIBLING_CONTAINERS_PULL=false` trong `config/overleaf.rc`.

Khi khởi động phiên bản Overleaf Pro của bạn bằng lệnh `bin/up` lệnh, Toolkit sẽ tự động kéo tất cả các ảnh được liệt kê trong `ALL_TEX_LIVE_DOCKER_IMAGES`.

Đây là một ví dụ trong đó chúng tôi mặc định dùng TeX Live 2025 cho các dự án mới, và giữ 2024 để dùng cho các dự án hiện có.

{% tabs %}
{% tab title="cài đặt phổ biến" %}
Cấu hình sau đây cài đặt tất cả các ảnh Docker TeX Live đầy đủ từ 2025 đến 2026. Chúng tôi khuyến nghị có ít nhất 80 GB dung lượng lưu trữ khả dụng trước khi dùng cấu hình này.

{% code title="config/variables.env" overflow="wrap" %}

```dotenv
ALL_TEX_LIVE_DOCKER_IMAGES=ghcr.io/ayaka-notes/texlive-full:2026.1, ghcr.io/ayaka-notes/texlive-full:2025.1
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=Texlive 2026, Texlive 2025
TEX_LIVE_DOCKER_IMAGE=ghcr.io/ayaka-notes/texlive-full:2026.1
```

{% endcode %}
{% endtab %}

{% tab title="cài đặt đầy đủ" %}
Cấu hình sau đây cài đặt tất cả các ảnh Docker TeX Live đầy đủ từ 2020 đến 2026. Chúng tôi khuyến nghị có ít nhất 256 GB dung lượng lưu trữ khả dụng trước khi dùng cấu hình này.

{% code title="config/variables.env" overflow="wrap" %}

```dotenv
ALL_TEX_LIVE_DOCKER_IMAGES=ghcr.io/ayaka-notes/texlive-full:2026.1,ghcr.io/ayaka-notes/texlive-full:2025.1,ghcr.io/ayaka-notes/texlive-full:2024.1,ghcr.io/ayaka-notes/texlive-full:2023.1,ghcr.io/ayaka-notes/texlive-full:2022.1,ghcr.io/ayaka-notes/texlive-full:2021.1,ghcr.io/ayaka-notes/texlive-full:2020.1
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=Texlive 2026,Texlive 2025,Texlive 2024,Texlive 2023,Texlive 2022,Texlive 2021,Texlive 2020
TEX_LIVE_DOCKER_IMAGE=ghcr.io/ayaka-notes/texlive-full:2026.1
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Bạn rất được khuyến nghị đặt **ít nhất 2 ảnh texlive-full**. Để biết lý do chi tiết, xem [#known-issues](#known-issues "mention")
{% endhint %}

### Các ảnh TeX Live khả dụng

Đây là một loạt ảnh TeX Live được tối ưu hóa đặc biệt cho Overleaf, cũng có thể được thêm vào `TEX_LIVE_DOCKER_IMAGE` và `ALL_TEX_LIVE_DOCKER_IMAGES`:

* `ghcr.io/ayaka-notes/texlive-full:2026.1` (Cũng là `latest` thẻ)
* `ghcr.io/ayaka-notes/texlive-full:2025.1`
* `ghcr.io/ayaka-notes/texlive-full:2024.1`
* `ghcr.io/ayaka-notes/texlive-full:2023.1`
* `ghcr.io/ayaka-notes/texlive-full:2022.1`
* `ghcr.io/ayaka-notes/texlive-full:2021.1`
* `ghcr.io/ayaka-notes/texlive-full:2020.1`

{% hint style="warning" %}
Có một lược đồ nghiêm ngặt về cách các ảnh **phải** được gắn thẻ (biểu thức chính quy sau được áp dụng `^[0-9]+.[0-9]+`, trong đó số đầu tiên xác định năm TeX Live và số thứ hai xác định phiên bản vá).
{% endhint %}

### Tôi có thể dùng registry ảnh khác không

> Một số người có thể thắc mắc liệu tôi có thể thay thế `ghcr.io` bằng một trang mirror khác, hoặc chuyển texlive sang ảnh khác từ docker hub không?

Không, chúng tôi không khuyến nghị vì cấu hình khá phức tạp. Nếu bạn đang tải xuống từ một mirror, bạn có thể đổi tên ảnh của mình thành `ghcr.io/ayaka-notes/texlive-full`.

Nhưng nếu bạn thực sự muốn dùng Registry ảnh riêng của mình, vui lòng thêm:

{% code title="config/variables.env" overflow="wrap" %}

```dotenv
IMAGE_ROOT=hub.your.com/your-repo
```

{% endcode %}

Sau đó, bạn cần đảm bảo tất cả các ảnh texlive đều nằm trong `your-repo`, như

* `hub.your.com/your-repo/texlive-full:2025.1`
* `hub.your.com/your-repo/texlive-full:2024.1`

Để biết thông tin chi tiết, hãy đọc mã nguồn bên dưới để hiểu cách chúng tôi phân tích biến môi trường của bạn:

{% code title="sandboxed-compiles/index.mjs" overflow="wrap" expandable="true" %}

```mjs
if (process.env.SANDBOXED_COMPILES === 'true') {
  // Đặt ảnh gốc mặc định nếu chưa được cung cấp
  let imageRootPath = process.env.IMAGE_ROOT || "ghcr.io/ayaka-notes";
  // Xuất imageRoot sang Settings
  Settings.imageRoot = imageRootPath

  // allowedImageNames nên là:
  // [
  //  { imageName: "texlive-2023:latest", imageDesc: "TeX Live 2023" },
  //  { imageName: "texlive-2022:latest", imageDesc: "TeX Live 2022" },
  // ]
  Settings.allowedImageNames = parseTextExtensions(process.env.ALL_TEX_LIVE_DOCKER_IMAGES)
    .map((texImage, index) => ({
      imageName: texImage.split("/")[texImage.split("/").length - 1],
      imageDesc: parseTextExtensions(process.env.ALL_TEX_LIVE_DOCKER_IMAGE_NAMES)[index]
        || texImage.split(':')[1],
    }))
  
  // Cuối cùng, imageName sẽ được ghép với imageRoot để tạo thành đường dẫn ảnh đầy đủ
  // Tên đầy đủ sẽ như sau: ghcr.io/ayaka-notes/texlive-2023:latest

  // Đặt tên ảnh mặc định nếu chưa được cung cấp
  if(!process.env.TEX_LIVE_DOCKER_IMAGE) {
    process.env.TEX_LIVE_DOCKER_IMAGE = imageRootPath + "/" + Settings.allowedImageNames[0].imageName
  }

  // Xuất currentImageName sang Settings
  // Đây là tên ảnh của các dự án mới được tạo
  Settings.currentImageName = process.env.TEX_LIVE_DOCKER_IMAGE
}
```

{% endcode %}

### Các vấn đề đã biết

Đây là một trường hợp thực tế từ cộng đồng overleaf:

> Sử dụng `6.0.1-ext-v3.3`, tôi có các cài đặt sau trong `variables.env`:
>
> ```dotenv
> TEX_LIVE_DOCKER_IMAGE=texlive/texlive:latest-full
> ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texlive:latest-full
> ```
>
> Cái này hoạt động bình thường với `texlive/texlive:latest-full`. Tuy nhiên, tôi đã kéo một ảnh texlive khác `danteev/texlive:2025-10-15` và đã thay đổi cả hai biến này thành tên ảnh mới nhưng nó không hoạt động:
>
> ```dotenv
> TEX_LIVE_DOCKER_IMAGE=danteev/texlive:2025-10-15
> ALL_TEX_LIVE_DOCKER_IMAGES=danteev/texlive:2025-10-15
> ```
>
> Trong nhật ký, tôi thấy như sau:
>
> {% code overflow="wrap" %}
>
> ```
> {"name":"clsi","level":50,"err":{"message":"(HTTP code 404) không có container - Không có ảnh: texlive/texlive:latest-full ","name":"Error","stack":"Error: (HTTP code 404) không có container - Không có ảnh: texlive/texlive:latest-full ..."}} 
> ```
>
> {% endcode %}
>
> Có vẻ như các cài đặt đã cập nhật trong `variables.env` không có hiệu lực. Trình biên dịch vẫn cố chạy `texlive/texlive:latest-full` ảnh này, chứ không phải ảnh mới.
>
> Tôi đã thử khởi động lại, xóa các container và chạy lại, nhưng vấn đề vẫn vậy.
>
> Có giải pháp nào không?

Do một số hạn chế kỹ thuật, nếu bạn chỉ thiết lập một ảnh Docker TeXLive duy nhất, chẳng hạn như `texlive-fullA:latest`

```
ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texliveA:latest-full
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=TeXLiveA
TEX_LIVE_DOCKER_IMAGE=texlive/texliveA:latest-full
```

Và sau khi chạy phiên bản overleaf của bạn một thời gian, bạn có thể muốn sửa đổi ảnh TeXLive thành `texlive-fullB:latest`. Khi đó, bạn sẽ thấy rằng người dùng của bạn không thể biên dịch tất cả các dự án.

```
ALL_TEX_LIVE_DOCKER_IMAGES=texlive/texliveA:latest-full
ALL_TEX_LIVE_DOCKER_IMAGE_NAMES=TeXLiveA
TEX_LIVE_DOCKER_IMAGE=texlive/texliveA:latest-full
```

Đó là vì tên của ảnh TeXLive-Full (cho biên dịch trong hộp cát) trong mỗi dự án được lưu bền trong cơ sở dữ liệu. *Chỉ khi người dùng chuyển phiên bản TeXLive của dự án, ví dụ từ 2024 sang 2025, thì tên ảnh mới được thay đổi trong cơ sở dữ liệu*.

Khi CLSI biên dịch một dự án, nó sử dụng tên ảnh container được tìm thấy trong cơ sở dữ liệu để biên dịch trực tiếp dự án.

Nếu bạn chỉ cung cấp một ảnh Docker, người dùng sẽ không thể sửa đổi ảnh được dùng để biên dịch dự án. Trong trường hợp này, bạn cần viết một script để **thay đổi thủ công** ảnh TeXLive cho tất cả các dự án của người dùng trong mongoDB.

### Gỡ lỗi

Chạy lệnh sau để kiểm tra log clsi từ toolkit:

{% code overflow="wrap" %}

```bash
bin/logs clsi
```

{% endcode %}


---

# 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/cau-hinh/overleaf-toolkit/sandboxed-compiles.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.
