> ## 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

> احتفظ بملفات المشاريع وسجلّها في تخزين متوافق مع S3 في نشر قائم على Kubernetes.

تخزّن خدمة **history-v1** ملفات المشاريع وسجلّها، وتخزّن خدمة **filestore** ملفات القوالب، وكلتاهما داخل كل pod من Ayakaleaf Pro. افتراضيًا تكتبان إلى وحدة تخزين البيانات؛ أما مع S3 فتكتبان إلى حاويات التخزين (buckets). الحاويات والصلاحيات المطلوبة موضّحة في [S3](https://ayakaleaf-pro.mintlify.site/ar/on-premises/configuration/overleaf-toolkit/s3.md).

| | |
| - | - |
| الخدمات | history-v1 (ملفات المشاريع وسجلّها)، وfilestore (ملفات القوالب)، في كل pod من Ayakaleaf Pro |
| Pod → S3 | نقطة نهاية S3، عند كل قراءة أو كتابة لملف |
| مطلوب | لـ [عدة نسخ متماثلة](https://ayakaleaf-pro.mintlify.site/ar/on-premises/configuration/kubernetes/horizontal-scaling.md): وحدات تخزين البيانات الخاصة بها غير مشتركة، أما حاويات التخزين فمشتركة |
| المهام الدورية | لا شيء |

> [!WARNING]
>
> اختر S3 قبل أن ينشئ المستخدمون مشاريع. أما المثيل الذي يحتفظ بالفعل بالملفات على وحدة التخزين الخاصة به فيحتاج أولًا إلى [الترحيل إلى S3](https://ayakaleaf-pro.mintlify.site/ar/on-premises/maintenance/s3-migration.md).

### الإعداد

**1. حاويات التخزين والمفاتيح**

أنشئ حاويات التخزين الثلاث `overleaf-template-files` و`overleaf-project-blobs` و`overleaf-chunks` والمستخدمَين المقيّدَين لدى خدمة S3 الخاصة بك كما هو موضّح في [إعداد S3](https://ayakaleaf-pro.mintlify.site/ar/on-premises/configuration/overleaf-toolkit/s3.md#s3-setup)، أو شغّل Garage داخل العنقود كما هو موضّح أدناه. ضع المفاتيح الأربعة في 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. أضف الـ Secret إلى الـ pod وأعد التشغيل**

في الـ Deployment (أو الـ StatefulSet)، أضف الـ Secret بجانب الأخرى:

```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 داخل العنقود

في حال عدم توفّر خدمة S3، فإن [Garage](https://garagehq.deuxfleurs.fr/) خادم S3 صغير يعمل داخل العنقود (cluster). وقد اختُبر إعداد [التوسّع الأفقي](https://ayakaleaf-pro.mintlify.site/ar/on-premises/configuration/kubernetes/horizontal-scaling.md) باستخدامه. تُولّد الأوامر أدناه المفاتيح وتُنشئ الـ Secret المسمّى `overleaf-s3` بنفسها، لذا استخدمها بدلًا من أمر الـ Secret في الخطوة 1.

> [!NOTE]
>
> لم يعد MinIO، المستخدم في النموذج الذي يقدّمه Overleaf، ينشر صور حاويات: فقد أُزيلت `minio/minio` من Docker Hub ومن 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
```

ولّد الأسرار، وشغّل Garage، ثم أنشئ التخطيط (layout) وحاويات التخزين والمفتاحين المقيّدين. تتكوّن معرّفات مفاتيح Garage من `GK` متبوعة بـ 24 حرفًا ست عشريًا، والأسرار من 64 حرفًا ست عشريًا:

```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
```

تطابق هذه الصلاحيات السياسات الواردة في [S3](https://ayakaleaf-pro.mintlify.site/ar/on-premises/configuration/overleaf-toolkit/s3.md#access-policies). يتحقّق Garage من المنطقة (region): وهي هنا `garage`، ويجب أن تكون قيمة `OVERLEAF_*_S3_REGION` هي نفسها.

مع Garage، اضبط نقطة النهاية، و`PATH_STYLE: "true"`، والمنطقة `garage` لكلتا الخدمتين في الـ ConfigMap، كما في `60-config.yaml` من [التوسّع الأفقي](https://ayakaleaf-pro.mintlify.site/ar/on-premises/configuration/kubernetes/horizontal-scaling.md).

### عدة نسخ متماثلة

يجب أن تستخدم كل النسخ المتماثلة (replicas) حاويات التخزين والمفاتيح نفسها. انسخ حاويات التخزين احتياطيًا باستخدام أدوات مزوّد S3 لديك؛ وعندئذٍ لا تحتوي الأقراص الخاصة بالنسخ المتماثلة على أي بيانات تحتاج إلى نسخ احتياطي.

### الاختبار على Kubernetes

على Kubernetes 1.37 مع ثلاث نسخ متماثلة وGarage كما هو موضّح أعلاه، نجح كل اختبار شامل (end-to-end) في هذه الصفحات يُنشئ مشاريع أو يرفع ملفات أو يستخدم السجلّ أو ينشر قوالب، وبعد ذلك احتوت حاويات التخزين `overleaf-project-blobs` و`overleaf-chunks` و`overleaf-template-files` على الكائنات، بينما بقي المجلد `/var/lib/overleaf/data/history` الخاص بالنسخ المتماثلة فارغًا.


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