> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# S3

> Lưu trữ tệp dự án và lịch sử trong bộ lưu trữ tương thích S3 trên một bản triển khai Kubernetes.

Tệp dự án và lịch sử của chúng được lưu trữ bởi dịch vụ **history-v1**, còn tệp mẫu được lưu bởi dịch vụ **filestore**, cả hai đều nằm trong mọi pod Ayakaleaf Pro. Theo mặc định, chúng ghi vào volume dữ liệu; với S3, chúng ghi vào các bucket. Những bucket và quyền cần thiết được mô tả trong [S3](https://ayakaleaf-pro.mintlify.site/vi/on-premises/configuration/overleaf-toolkit/s3.md).

| | |
| - | - |
| Dịch vụ | history-v1 (tệp dự án và lịch sử), filestore (tệp mẫu), trong mọi pod Ayakaleaf Pro |
| Pod → S3 | endpoint S3, cho mỗi lần đọc hoặc ghi tệp |
| Bắt buộc | đối với [nhiều replica](https://ayakaleaf-pro.mintlify.site/vi/on-premises/configuration/kubernetes/horizontal-scaling.md): các volume dữ liệu của chúng không được chia sẻ, còn các bucket thì có |
| Tác vụ định kỳ | không có |

> [!WARNING]
>
> Hãy chọn S3 trước khi người dùng tạo dự án. Một phiên bản đã lưu tệp trên volume của nó cần thực hiện [di chuyển sang S3](https://ayakaleaf-pro.mintlify.site/vi/on-premises/maintenance/s3-migration.md) trước.

### Cấu hình

**1. Bucket và khóa**

Tạo ba bucket `overleaf-template-files`, `overleaf-project-blobs` và `overleaf-chunks` cùng hai người dùng bị giới hạn quyền trên dịch vụ S3 của bạn như mô tả trong [Thiết lập S3](https://ayakaleaf-pro.mintlify.site/vi/on-premises/configuration/overleaf-toolkit/s3.md#s3-setup), hoặc chạy Garage trong cluster như hướng dẫn bên dưới. Đưa bốn khóa vào một Secret:

```bash wrap theme={null}
kubectl -n overleaf create secret generic overleaf-s3 \
  --from-literal=OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID=<filestore key> \
  --from-literal=OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY=<filestore secret> \
  --from-literal=OVERLEAF_HISTORY_S3_ACCESS_KEY_ID=<history key> \
  --from-literal=OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY=<history secret>
```

**2. ConfigMap**

```yaml title="30-config.yaml (additions)" wrap theme={null}
  OVERLEAF_FILESTORE_BACKEND: s3
  OVERLEAF_FILESTORE_TEMPLATE_FILES_BUCKET_NAME: overleaf-template-files
  OVERLEAF_FILESTORE_S3_REGION: eu-west-1
  OVERLEAF_HISTORY_BACKEND: s3
  OVERLEAF_HISTORY_PROJECT_BLOBS_BUCKET: overleaf-project-blobs
  OVERLEAF_HISTORY_CHUNKS_BUCKET: overleaf-chunks
  OVERLEAF_HISTORY_S3_REGION: eu-west-1
  # a self-hosted S3 service also needs its endpoint and path-style addressing
  # OVERLEAF_FILESTORE_S3_ENDPOINT: http://garage:3900
  # OVERLEAF_FILESTORE_S3_PATH_STYLE: "true"
  # OVERLEAF_HISTORY_S3_ENDPOINT: http://garage:3900
  # OVERLEAF_HISTORY_S3_PATH_STYLE: "true"
```

**3. Thêm Secret vào pod và khởi động lại**

Trong Deployment (hoặc StatefulSet), thêm Secret bên cạnh các Secret khác:

```yaml theme={null}
          envFrom:
            - configMapRef: {name: overleaf-env}
            - secretRef: {name: overleaf-secrets}
            - secretRef: {name: overleaf-s3}
```

```bash theme={null}
kubectl apply -f 30-config.yaml -f 40-overleaf.yaml
kubectl -n overleaf rollout restart deployment/overleaf     # or statefulset/overleaf
```

### Garage trong cluster

Nếu không có dịch vụ S3, [Garage](https://garagehq.deuxfleurs.fr/) là một máy chủ S3 nhỏ chạy trong cluster. Thiết lập [Mở rộng theo chiều ngang](https://ayakaleaf-pro.mintlify.site/vi/on-premises/configuration/kubernetes/horizontal-scaling.md) đã được kiểm thử với nó. Các lệnh bên dưới tự tạo các khóa và Secret `overleaf-s3`, vì vậy hãy dùng chúng thay cho lệnh tạo Secret ở bước 1.

> [!NOTE]
>
> MinIO, được dùng trong ví dụ mẫu của Overleaf, không còn phát hành container image: `minio/minio` đã không còn trên Docker Hub và quay.io.

```yaml title="50-garage.yaml" wrap theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: garage-config
  namespace: overleaf
data:
  garage.toml: |
    metadata_dir = "/var/lib/garage/meta"
    data_dir = "/var/lib/garage/data"
    db_engine = "lmdb"
    replication_factor = 1
    rpc_bind_addr = "[::]:3901"
    rpc_public_addr = "127.0.0.1:3901"
    # rpc_secret and admin_token come from GARAGE_RPC_SECRET / GARAGE_ADMIN_TOKEN
    [s3_api]
    s3_region = "garage"          # Overleaf's OVERLEAF_*_S3_REGION must match
    api_bind_addr = "[::]:3900"
    [admin]
    api_bind_addr = "[::]:3903"
---
apiVersion: v1
kind: Service
metadata:
  name: garage
  namespace: overleaf
spec:
  selector:
    app: garage
  ports:
    - name: s3
      port: 3900
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: garage
  namespace: overleaf
spec:
  serviceName: garage
  replicas: 1
  selector:
    matchLabels:
      app: garage
  template:
    metadata:
      labels:
        app: garage
    spec:
      containers:
        - name: garage
          image: dxflrs/garage:v2.5.0
          env:
            - name: GARAGE_RPC_SECRET
              valueFrom: {secretKeyRef: {name: garage-secrets, key: rpc_secret}}
            - name: GARAGE_ADMIN_TOKEN
              valueFrom: {secretKeyRef: {name: garage-secrets, key: admin_token}}
          ports:
            - containerPort: 3900
          readinessProbe:
            tcpSocket:
              port: 3900
          resources:
            requests: {cpu: 50m, memory: 64Mi}
            limits: {memory: 512Mi}
          volumeMounts:
            - {name: config, mountPath: /etc/garage.toml, subPath: garage.toml}
            - {name: data, mountPath: /var/lib/garage}
      volumes:
        - name: config
          configMap:
            name: garage-config
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 10Gi
```

Tạo các secret, khởi động Garage, sau đó tạo layout, các bucket và hai khóa bị giới hạn quyền. ID khóa Garage gồm `GK` cộng 24 ký tự hex, secret gồm 64 ký tự hex:

```bash wrap theme={null}
kubectl -n overleaf create secret generic garage-secrets \
  --from-literal=rpc_secret="$(openssl rand -hex 32)" \
  --from-literal=admin_token="$(openssl rand -base64 32)"
kubectl -n overleaf create secret generic overleaf-s3 \
  --from-literal=OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID="GK$(openssl rand -hex 12)" \
  --from-literal=OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY="$(openssl rand -hex 32)" \
  --from-literal=OVERLEAF_HISTORY_S3_ACCESS_KEY_ID="GK$(openssl rand -hex 12)" \
  --from-literal=OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY="$(openssl rand -hex 32)"
kubectl apply -f 50-garage.yaml
kubectl -n overleaf rollout status statefulset/garage

g() { kubectl -n overleaf exec garage-0 -- /garage "$@"; }
s() { kubectl -n overleaf get secret overleaf-s3 -o jsonpath="{.data.$1}" | base64 -d; }
g layout assign -z dc1 -c 8G "$(g status 2>/dev/null | awk '/^[0-9a-f]{16}/{print $1; exit}')"
g layout apply --version 1
for b in overleaf-template-files overleaf-project-blobs overleaf-chunks; do g bucket create "$b"; done
g key import --yes -n overleaf-filestore "$(s OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID)" "$(s OVERLEAF_FILESTORE_S3_SECRET_ACCESS_KEY)"
g key import --yes -n overleaf-history "$(s OVERLEAF_HISTORY_S3_ACCESS_KEY_ID)" "$(s OVERLEAF_HISTORY_S3_SECRET_ACCESS_KEY)"
g bucket allow --read --write overleaf-template-files --key overleaf-filestore
g bucket allow --read overleaf-project-blobs --key overleaf-filestore
g bucket allow --read --write overleaf-project-blobs --key overleaf-history
g bucket allow --read --write overleaf-chunks --key overleaf-history
```

Các quyền này khớp với các chính sách trong [S3](https://ayakaleaf-pro.mintlify.site/vi/on-premises/configuration/overleaf-toolkit/s3.md#access-policies). Garage kiểm tra region: ở đây là `garage`, và `OVERLEAF_*_S3_REGION` phải giống như vậy.

Với Garage, hãy đặt endpoint, `PATH_STYLE: "true"` và region `garage` cho cả hai dịch vụ trong ConfigMap, như trong `60-config.yaml` của [Mở rộng theo chiều ngang](https://ayakaleaf-pro.mintlify.site/vi/on-premises/configuration/kubernetes/horizontal-scaling.md).

### Nhiều replica

Tất cả các replica phải dùng cùng các bucket và khóa. Hãy sao lưu các bucket bằng công cụ của nhà cung cấp S3; khi đó ổ đĩa riêng của các replica không chứa dữ liệu nào cần sao lưu.

### Đã kiểm thử trên Kubernetes

Trên Kubernetes 1.37 với ba replica và Garage như trên, mọi bài kiểm thử end-to-end trong các trang này có tạo dự án, tải tệp lên, dùng lịch sử hoặc xuất bản mẫu đều đạt, và sau đó các bucket `overleaf-project-blobs`, `overleaf-chunks` và `overleaf-template-files` chứa các đối tượng, trong khi `/var/lib/overleaf/data/history` riêng của các replica vẫn trống.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.