> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# تثبيت Seafile 13 لمزامنة الملفات ومشاركتها على خادمك
- URL: https://arabroot.io/articles/تثبيت-seafile-لمزامنة-الملفات/
- Published: 2026-09-20T15:05:00.000Z
- Updated: 2026-10-04T20:05:49.000Z
- Description: إذا كانت ملفات فريقك على Dropbox أو OneDrive فالمساحة والأسعار والشروط بيد غيرك. في هذا الدليل نثبت Seafile 13 على سيرفرك بالملفات الرسمية، ونجهز المكتبات والمشاركة وعميل المزامنة، ثم نأخذ نسخة احتياطية ونستعيدها على سيرفر جديد.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, تطبيقات لفريقك, الاستضافة الذاتية, Seafile

لنفرض أن ملفات فريقك اليوم موجودة على Dropbox أو OneDrive، فسوف تجد أن الأمر يعمل بشكل جيد في البداية، فكل شخص يثبت التطبيق على جهازه وتتزامن الملفات Sync بين الأجهزة دون أن يفكر أحد في السيرفر Server الذي يحملها، ولكن مع الوقت يكبر حجم الملفات ويزيد عدد المستخدمين فترتفع الفاتورة مع كل حساب جديد، وتكتشف أن المزود هو الذي يحدد المساحة والأسعار ومدة الاحتفاظ بالإصدارات القديمة، وأن ملفات فريقك موجودة على سيرفرات لا تعرف أين هي، وقد تفرض عليك الأنظمة أو العقود في مؤسستك أن تبقى هذه البيانات داخلها.

والحل الأول الذي يخطر على البال هو أن تضع مجلداً مشتركاً Shared Folder على سيرفر في الشبكة يصل إليه الجميع عبر SMB أو FTP، وهذا الحل يعمل داخل المكتب فقط، فلا توجد مزامنة حقيقية بين الأجهزة عندما يعمل أحدهم من البيت، ولا يوجد سجل إصدارات Version History تعود إليه إذا عدل أحدهم ملفاً بالخطأ، ولا توجد روابط مشاركة Share Links ترسلها لشخص من خارج الفريق، ولذلك فالحل الأنسب هو أن تشغل سيرفر مزامنة خاصاً بك يعطي فريقك تجربة قريبة من Dropbox، والملفات فيه على سيرفرك أنت، وأشهر خيارين لذلك هما [Nextcloud](https://nextcloud.com/?ref=arabroot.io) و[**Seafile**](https://www.seafile.com/en/home/?ref=arabroot.io).

وقد يتساءل البعض: لماذا Seafile وليس Nextcloud وهو الأشهر بينهما؟ والإجابة أن Nextcloud منصة متكاملة فيها التقويم والبريد والتطبيقات المكتبية وعشرات الإضافات Plugins، وهذا مفيد إذا كنت تحتاج إلى كل ذلك، وأما إذا كانت حاجتك الأساسية هي مزامنة الملفات ومشاركتها فإن Seafile يركز على هذه المهمة وحدها، ولذلك فهو أخف على السيرفر وأسرع مع آلاف الملفات ومع الملفات الكبيرة، والسبب أنه يخزن الملفات أجزاء Blocks بطريقة تشبه Git، فلا يرفع عند كل تعديل إلا الأجزاء التي تغيرت.

ويرتب Seafile الملفات في مكتبات Libraries، ولكل مكتبة سجل إصدارات وسلة محذوفات Trash وصلاحيات مشاركة Permissions خاصة بها، وتستطيع أيضاً أن تشفر المكتبة Encryption من جهة الجهاز Client-Side Encryption فلا يقرأ محتواها حتى مدير السيرفر، كما يشرح [توثيق ميزات الأمان](https://manual.seafile.com/13.0/administration/security%5Ffeatures/?ref=arabroot.io). وله [عميل مزامنة](https://www.seafile.com/en/download/?ref=arabroot.io) Sync Client لأنظمة Windows وmacOS وLinux، وتطبيقات للهواتف، ودعم لبروتوكول WebDAV.

**لكن تذكر:** Seafile لا يحفظ الملفات على القرص بشكلها العادي، وإنما يحفظها أجزاء داخلية، وبالتالي لا تستطيع أن تفتح مجلد البيانات Data Directory وتتصفح الملفات منه مباشرة، فالوصول إليها يكون دائماً عبر Seafile نفسه أو عبر WebDAV، وهذا يغير طريقة تفكيرك في النسخ الاحتياطي كما سيأتي.

وسوف نناقش في هذا المقال ما يلي:

- تثبيت Seafile 13 بالملفات الرسمية `.env` و`seafile-server.yml`، مع MariaDB وRedis وSeaDoc، وشرح ما في كل ملف.
- الإعداد الأول: حساب المدير، والمكتبات، والمشاركة، والمستخدمين، والبريد، وعميل المزامنة، وWebDAV.
- إصدار شهادة TLS بـ Caddy المرفق مع Seafile، أو تشغيله خلف Reverse Proxy يعمل لديك مسبقاً.
- النسخ الاحتياطي والاستعادة على سيرفر جديد بالترتيب الصحيح، ثم التحديث وأشهر المشكلات وحلولها.

## ما تحتاجه قبل أن تبدأ Requirements

- سيرفر Linux بمعالجين CPU وذاكرة RAM بحجم 4 GB لفريق صغير، و2 GB تكفي للتجربة، ومساحة قرص Disk تتسع لملفاتك مع هامش للإصدارات القديمة وسلة المحذوفات، والسبب أن Seafile يحتفظ بالأجزاء القديمة حتى تنتهي مدة الاحتفاظ بها.
- Docker Engine مع ملحق Docker Compose، وإذا لم يكونا مثبتين فاتبع [دليل تثبيت Docker على Ubuntu](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-docker-%D8%B9%D9%84%D9%89-ubuntu/).
- نطاق فرعي Subdomain مثل `seafile.example.com` عليه سجل A يشير إلى عنوان السيرفر (`203.0.113.10`).
- المنفذان Ports رقم 80 و443 مفتوحان، سواءً استخدمت Caddy المرفق مع Seafile لإصدار الشهادة Certificate، أو Reverse Proxy يعمل لديك أصلاً.
- سيرفر بريد SMTP لرسائل إعادة تعيين كلمة المرور Password Reset والإشعارات Notifications، وهو اختياري ولكننا ننصح به.

## مم يتكون النظام؟

تغيرت طريقة التثبيت الرسمية منذ الإصدار 12، فلم يعد هناك ملف `docker-compose.yml` واحد، وإنما ملف `.env` فيه كل الإعدادات، وعدة ملفات YAML تختار منها ما تحتاجه عبر المتغير `COMPOSE_FILE`. وفي الإصدار 13 صار Seafile يقرأ معظم إعداداته من [متغيرات البيئة](https://manual.seafile.com/13.0/config/env/?ref=arabroot.io) Environment Variables بدلاً من ملفات الإعداد Configuration Files، وصار Redis هو ذاكرة التخزين المؤقت Cache الافتراضية بدلاً من Memcached، كما تذكر [ملاحظات الترقية إلى 13.0](https://manual.seafile.com/13.0/upgrade/upgrade%5Fnotes%5Ffor%5F13.0.x/?ref=arabroot.io) Upgrade Notes. والجدول التالي يبين الملفات التي سوف نستخدمها:

| الملف                   | الخدمات             | الدور                                                                                                                                                       |
| ----------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| seafile-server.yml      | seafile وdb وredis  | السيرفر نفسه (Seahub وسيرفر الملفات)، وقاعدة البيانات Database من نوع MariaDB، وRedis للتخزين المؤقت                                                        |
| caddy.yml               | caddy               | Reverse Proxy يقرأ إعداداته من labels الـ Containers، ويصدر شهادة Let's Encrypt تلقائياً                                                                    |
| seadoc.yml              | seadoc              | محرر المستندات التعاوني Collaborative Editor المسمى [SeaDoc](https://manual.seafile.com/13.0/extension/setup%5Fseadoc/?ref=arabroot.io) (اختياري)           |
| notification-server.yml | notification-server | [إشعارات فورية](https://manual.seafile.com/13.0/extension/notification-server/?ref=arabroot.io) لعملاء المزامنة بدلاً من الاستعلام الدوري Polling (اختياري) |

## تثبيت Seafile خطوة بخطوة Installation

### مجلد التثبيت وتنزيل الملفات الرسمية

سوف نضع ملفات Compose في `/opt/seafile`، والبيانات في `/opt/seafile-data` و`/opt/seafile-mysql`، وهذه هي المسارات الافتراضية في [دليل التثبيت الرسمي](https://manual.seafile.com/13.0/setup/setup%5Fce%5Fby%5Fdocker/?ref=arabroot.io)، والسبب أننا نريد أن تطابق أوامرك ما تقرؤه في التوثيق عندما تحتاج إليه لاحقاً:

```bash
sudo mkdir -p /opt/seafile
cd /opt/seafile
```

بعد ذلك نقوم بتنزيل الملفات الرسمية للإصدار 13.0 من موقع Seafile:

```bash
sudo curl -fLO https://manual.seafile.com/13.0/repo/docker/ce/seafile-server.yml
sudo curl -fLO https://manual.seafile.com/13.0/repo/docker/caddy.yml
sudo curl -fLO https://manual.seafile.com/13.0/repo/docker/seadoc.yml
sudo curl -fL -o .env https://manual.seafile.com/13.0/repo/docker/ce/env
```

لاحظ أن هذه الملفات تستخدم وسوماً Tags متحركة مثل `13.0-latest`، أو `redis` دون رقم إصدار، وهذا يعني أن أي `docker compose pull` قد يأتيك بإصدار جديد لم تقرأ ملاحظاته، ولذلك سوف نثبت كل Docker Image على إصدار محدد من داخل `.env`، فلا يتغير شيء إلا عندما تقرر أنت التحديث Upgrade.

### توليد كلمات المرور والمفاتيح Secrets

تحتاج إلى أربع قيم عشوائية: كلمة مرور مستخدم قاعدة البيانات، وكلمة مرور المستخدم root في قاعدة البيانات، وكلمة مرور Redis، ومفتاح JWT الذي تتبادل به الخدمات الرموز Tokens فيما بينها، والأمر التالي يولدها كلها:

```bash
for n in DB_PASSWORD DB_ROOT_PASSWORD REDIS_PASSWORD JWT_PRIVATE_KEY; do echo "$n=$(openssl rand -hex 32)"; done
```

احتفظ بالمخرج مؤقتاً، فسوف تنسخه في الخطوة التالية.

### ملف .env وشرح ما فيه

افتح الملف `.env` وعدل القيم التالية فقط، واترك بقية الملف كما هو:

```bash
sudo nano /opt/seafile/.env
```

```ini
COMPOSE_FILE='seafile-server.yml,caddy.yml,seadoc.yml'
COMPOSE_PATH_SEPARATOR=','

## Docker Images بإصدارات مثبتة
SEAFILE_IMAGE=seafileltd/seafile-mc:13.0.28
SEAFILE_DB_IMAGE=mariadb:10.11.19
SEAFILE_REDIS_IMAGE=redis:8.10.2-alpine
SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.12.1-alpine
SEADOC_IMAGE=seafileltd/sdoc-server:2.0.9
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:13.0.21

## مسارات التخزين
BASIC_STORAGE_PATH=/opt
SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-data
SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db
SEAFILE_CADDY_VOLUME=$BASIC_STORAGE_PATH/seafile-caddy
SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data

## عنوان الخدمة
SEAFILE_SERVER_HOSTNAME=seafile.example.com
SEAFILE_SERVER_PROTOCOL=https
TIME_ZONE=Etc/UTC
JWT_PRIVATE_KEY=ضع_قيمة_JWT_PRIVATE_KEY_المولدة

## قاعدة البيانات
SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=ضع_قيمة_DB_PASSWORD_المولدة
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db

## التخزين المؤقت
CACHE_PROVIDER=redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=ضع_قيمة_REDIS_PASSWORD_المولدة

## قيم التشغيل الأول فقط
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=ضع_قيمة_DB_ROOT_PASSWORD_المولدة
INIT_SEAFILE_ADMIN_EMAIL=admin@example.com
INIT_SEAFILE_ADMIN_PASSWORD=كلمة_مرور_مؤقتة_قوية

## الإضافات
ENABLE_SEADOC=true
ENABLE_NOTIFICATION_SERVER=false
NOTIFICATION_SERVER_URL=
```

في الإعداد أعلاه لاحظ التالي:

- `SEAFILE_SERVER_HOSTNAME` يقبل اسم نطاق Domain أو عنوان IP فقط، دون رقم منفذ ودون `https://`، وفي التهيئة الأولى Initialization يرفض الـ Container قيمة مثل `localhost` أو `localhost:8080`.
- المتغيرات التي تبدأ بـ `INIT_` يقرؤها الـ Container في التشغيل الأول فقط لينشئ قواعد البيانات وحساب المدير Admin Account، وبالتالي فإن تغييرها بعد ذلك ليس له أي أثر، فإذا أردت تغيير كلمة مرور المدير فغيرها من الواجهة.
- لا تقم بتغيير `SEAFILE_MYSQL_DB_PASSWORD` و`JWT_PRIVATE_KEY` بعد التشغيل الأول، إلا إذا غيرتهما أيضاً في قاعدة البيانات وفي بقية الخدمات، والسبب أن MariaDB وSeaDoc يحتفظان بالقيمة القديمة.
- إذا لم تكن تحتاج إلى SeaDoc فاحذف `seadoc.yml` من `COMPOSE_FILE`، واجعل `ENABLE_SEADOC=false`.

وهذا الملف يحمل كل كلمات المرور، ولذلك نجعله مقروءاً للمالك فقط:

```bash
sudo chmod 600 /opt/seafile/.env
```

### ماذا يوجد داخل ملفات Compose؟

لن تحتاج إلى تعديل ملفات YAML، فكل القيم تأتي من `.env`، ولكن من المفيد أن تعرف ما فيها حتى تفهم ما يحدث عندما تظهر مشكلة. وهذه الأجزاء الأساسية من `seafile-server.yml` في الإصدار 13.0، بعد اختصار المتغيرات المتشابهة:

```yaml
services:
  db:
    image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
    container_name: seafile-mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
    networks:
      - seafile-net
    healthcheck:
      test: ["CMD", "/usr/local/bin/healthcheck.sh", "--connect", "--mariadbupgrade", "--innodb_initialized"]
      interval: 20s
      start_period: 30s
      timeout: 5s
      retries: 10

  redis:
    image: ${SEAFILE_REDIS_IMAGE:-redis}
    container_name: seafile-redis
    restart: unless-stopped
    command:
      - /bin/sh
      - -c
      - exec redis-server --requirepass "$$REDIS_PASSWORD" --save "" --appendonly no
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
    networks:
      - seafile-net

  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:13.0-latest}
    container_name: seafile
    restart: unless-stopped
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    environment:
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
      - INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - ENABLE_SEADOC=${ENABLE_SEADOC:-true}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
      - CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
      # ... بقية متغيرات قاعدة البيانات والإضافات
    labels:
      caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy.reverse_proxy: "{{upstreams 80}}"
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net
```

في الإعداد أعلاه لاحظ التالي:

- الخدمة `seafile` لا تبدأ إلا بعد أن تصبح MariaDB سليمة `service_healthy`، والسبب أن التهيئة الأولى تنشئ قواعد البيانات الثلاث وتفشل إذا لم تجد MariaDB جاهزة.
- Redis يعمل بكلمة مرور ودون حفظ على القرص (`--save ""`)، لأنه هنا ذاكرة مؤقتة فقط، وفقدان محتواه عند إعادة التشغيل لا يضر.
- labels الخاصة بـ `caddy` هي التي يقرؤها Caddy ليعرف النطاق ويوجه الطلبات إلى المنفذ 80 داخل الـ Container.

أما الملف `caddy.yml` فيشغل [caddy-docker-proxy](https://github.com/lucaslorentz/caddy-docker-proxy?ref=arabroot.io) على المنفذين 80 و443، وهو يقرأ labels الـ Containers عبر Docker socket ويبني إعداداته منها تلقائياً، فإذا كانت قيمة `SEAFILE_SERVER_PROTOCOL` هي `https` فإنه يصدر شهادة Let's Encrypt للنطاق ويجددها Renewal بنفسه:

```yaml
services:
  caddy:
    image: ${SEAFILE_CADDY_IMAGE:-lucaslorentz/caddy-docker-proxy:2.12-alpine}
    restart: unless-stopped
    container_name: seafile-caddy
    ports:
      - 80:80
      - 443:443
    environment:
      - CADDY_INGRESS_NETWORKS=seafile-net
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy
    networks:
      - seafile-net
    healthcheck:
      test: ["CMD-SHELL", "curl --fail http://localhost:2019/metrics || exit 1"]
      start_period: 20s
      interval: 20s
      timeout: 5s
      retries: 3

networks:
  seafile-net:
    name: seafile-net
```

والملف `seadoc.yml` يضيف خدمة SeaDoc، مع labels توجه إليها المسارين `/sdoc-server/` و`/socket.io/` عبر Caddy نفسه.

### تشغيل الخدمات

الآن سوف نقوم بسحب الـ Images وتشغيل الخدمات:

```bash
cd /opt/seafile
sudo docker compose pull
sudo docker compose up -d
```

ينتظر الـ Container `seafile` حتى تصبح MariaDB سليمة، ثم ينشئ في التشغيل الأول قواعد البيانات الثلاث وحساب المدير، وتستطيع متابعة ذلك في السجل Log حتى تظهر الرسالة `Seahub is started` ثم `Done.`:

```bash
sudo docker logs -f seafile
```

وبعد ذلك تأكد أن كل الخدمات تعمل:

```bash
sudo docker compose ps
```

## الإعداد الأول بعد التثبيت

### الدخول وتغيير كلمة المرور

افتح `https://seafile.example.com`، وادخل بالبريد وكلمة المرور اللذين وضعتهما في `INIT_SEAFILE_ADMIN_EMAIL` و`INIT_SEAFILE_ADMIN_PASSWORD`، ثم قم بتغيير كلمة المرور فوراً من صورة الحساب Avatar ثم **Settings** ثم **Password**، وبعد ذلك احذف القيمة المؤقتة من `.env` فلم تعد لها حاجة.

![صفحة تسجيل الدخول في Seafile](https://arabroot.io/content/images/2026/09/seafile-01-login.webp)

صفحة الدخول في Seafile 13

### تنظيم الملفات في مكتبات

بعد الدخول سوف تظهر صفحة **Files** بثلاثة أقسام: مكتباتك، والمكتبات التي شاركها معك الآخرون، والمكتبات المشاركة مع الجميع، ولكل مستخدم مكتبة شخصية ينشئها Seafile تلقائياً باسم **My Library**.

![قائمة المكتبات في Seafile](https://arabroot.io/content/images/2026/09/seafile-02-libraries.webp)

قائمة المكتبات، ويؤدي الزر + بجوار My Libraries إلى إنشاء مكتبة جديدة

والمكتبة هي الوحدة التي تتم عليها المزامنة والمشاركة والتشفير، ولذلك خطط لها بحسب طريقة عمل فريقك، فمكتبة لكل قسم أو مشروع أفضل من مكتبة واحدة ضخمة، والسبب أن المستخدم يختار المكتبات التي يزامنها على جهازه، وأن الصلاحيات تعطى على مستوى المكتبة أو المجلد. ولإنشاء مكتبة اضغط **+** ثم **New Library**:

![نافذة إنشاء مكتبة جديدة](https://arabroot.io/content/images/2026/09/seafile-03-new-library.webp)

إنشاء مكتبة جديدة، ويشفر خيار Encrypt المكتبة بكلمة مرور من جهة العميل

⚠️

لا يحفظ السيرفر كلمة مرور المكتبة المشفرة، ولا توجد أي طريقة لاسترجاعها، فإذا ضاعت ضاعت الملفات معها، ولن تساعدك النسخ الاحتياطية Backups على فك تشفيرها، ولذلك احفظها في مدير كلمات المرور Password Manager الخاص بالفريق.

وداخل المكتبة ترفع الملفات Upload بالسحب والإفلات، وتنشئ المجلدات، وتعاين ملفات Markdown والنصوص والصور وPDF مباشرة من المتصفح. ومن القائمة الجانبية تفتح **History** لتستعيد Restore أي نسخة سابقة من المكتبة، و**Trash** للملفات المحذوفة، و**Settings** لتحدد مدة الاحتفاظ بالإصدارات القديمة.

![محتوى مكتبة Team Docs مع مجلدات وملفات](https://arabroot.io/content/images/2026/09/seafile-04-library.webp)

مكتبة Team Docs مع مجلدين وثلاثة ملفات، ويتاح الوصول إلى History وTrash من الشريط الجانبي

### مشاركة الملفات داخل الفريق وخارجه

حدد ملفاً أو مجلداً ثم اضغط **Share**، ومن النافذة تستطيع أن تنشئ رابط مشاركة عاماً Share Link بكلمة مرور ومدة صلاحية Expiration، يسمح بالمعاينة فقط أو بالمعاينة والتنزيل، أو رابطاً داخلياً Internal Link لا يفتحه إلا من لديه صلاحية على المكتبة. وللمجلدات أيضاً رابط رفع Upload Link يرفع منه شخص من خارج النظام ملفات إليك دون أن يحتاج إلى حساب.

![نافذة إنشاء رابط مشاركة لملف في Seafile](https://arabroot.io/content/images/2026/09/seafile-05-share-link.webp)

إنشاء رابط مشاركة مع خيارات كلمة المرور وانتهاء الصلاحية ونطاق الوصول

أما المشاركة داخل الفريق فتتم من قائمة المكتبة نفسها، حيث تشاركها مع مستخدم أو مع مجموعة Group، بصلاحية القراءة فقط أو القراءة والكتابة، وفي الفرق التي يتغير أعضاؤها باستمرار فإن المجموعات هي الطريقة العملية لإدارة [الصلاحيات](https://manual.seafile.com/13.0/introduction/file%5Fpermission%5Fmanagement/?ref=arabroot.io)، والسبب أنك تضيف الموظف الجديد إلى المجموعة مرة واحدة بدلاً من أن تشارك معه كل مكتبة على حدة.

### لوحة إدارة النظام Admin Panel

تفتح لوحة الإدارة من صورة الحساب ثم **System Admin**، وصفحة **Info** فيها تعرض الإصدار، وعدد المكتبات والملفات، والمساحة المستخدمة، وعدد الأجهزة المتصلة:

![صفحة معلومات النظام في لوحة إدارة Seafile](https://arabroot.io/content/images/2026/09/seafile-06-sys-info.webp)

صفحة System Info، وتظهر فيها Community Edition بالإصدار 13.0.28

ومن **Users ← Add User** تنشئ حسابات الفريق، ومن صفحة كل مستخدم تحدد حصته من المساحة Quota، أو تعطيه صلاحية المدير:

![نافذة إضافة مستخدم جديد](https://arabroot.io/content/images/2026/09/seafile-07-add-user.webp)

إضافة مستخدم بالبريد والاسم وكلمة مرور مؤقتة

![قائمة المستخدمين في لوحة الإدارة](https://arabroot.io/content/images/2026/09/seafile-08-sys-users.webp)

قائمة المستخدمين مع المساحة المستخدمة وآخر دخول

ومن **Settings** في لوحة الإدارة تقوم بضبط اسم الموقع وشعاره، وتفعيل التسجيل الذاتي Self-Registration أو إيقافه، وتحديد قواعد كلمات المرور. وإذا كان لديك نظام دخول موحد SSO مثل [Authentik](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-authentik-%D9%84%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%A7%D9%84%D9%85%D9%88%D8%AD%D8%AF/) فاربط Seafile به عبر [OAuth](https://manual.seafile.com/13.0/config/oauth/?ref=arabroot.io) من ملف [seahub\_settings.py](https://manual.seafile.com/13.0/config/seahub%5Fsettings%5Fpy/?ref=arabroot.io)، فيدخل الموظف بحسابه المعتاد، ويغلق حسابه في مكان واحد عندما يترك العمل.

### إعداد البريد

يرسل Seafile رسائل إعادة تعيين كلمة المرور وإشعارات المشاركة، وبدون بريد لن يستطيع المستخدم أن يستعيد كلمة مروره بنفسه، ولذلك أضف [إعدادات SMTP](https://manual.seafile.com/13.0/config/sending%5Femail/?ref=arabroot.io) في آخر الملف `/opt/seafile-data/seafile/conf/seahub_settings.py`:

```bash
sudo nano /opt/seafile-data/seafile/conf/seahub_settings.py
```

```python
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.example.com'
EMAIL_HOST_USER = 'noreply@example.com'
EMAIL_HOST_PASSWORD = 'SMTP_PASSWORD'
EMAIL_PORT = 587
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER
```

ثم أعد تشغيل الخدمة حتى تقرأ الإعدادات الجديدة:

```bash
cd /opt/seafile
sudo docker compose restart seafile
```

وإذا كنت تدير بريدك بنفسك فراجع [دليل mailcow](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D8%AE%D8%A7%D8%AF%D9%85-%D8%A8%D8%B1%D9%8A%D8%AF-mailcow/) لتنشئ صندوق بريد مخصصاً للإرسال.

### تثبيت عميل المزامنة على الأجهزة والهواتف

في **Clients** بالقائمة الجانبية سوف تجد روابط عميل Seafile لسطح المكتب Desktop وتطبيقات iOS وAndroid، وهي أيضاً في [صفحة التنزيل الرسمية](https://www.seafile.com/en/download/?ref=arabroot.io). وعندما تضيف الحساب في العميل اكتب عنوان السيرفر كاملاً `https://seafile.example.com`، ثم البريد وكلمة المرور، واختر المكتبات التي تريد مزامنتها. وإذا كنت تريد أن تظهر الملفات على شكل قرص شبكي Network Drive دون أن تنزلها كلها على الجهاز، فاستخدم تطبيق SeaDrive لنظامي Windows وmacOS، وهو مناسب للأجهزة ذات المساحة الصغيرة.

### تفعيل WebDAV

تحتاج إلى WebDAV للتطبيقات التي لا تدعم عميل Seafile، مثل بعض تطبيقات الهاتف أو برامج النسخ الاحتياطي Backup. وفي النشر Deployment عبر Docker يكون المسار `/seafdav` جاهزاً داخل الـ Container، ولكن الخدمة نفسها معطلة افتراضياً في الملف `seafdav.conf`، ولذلك يكفي أن [تقوم بتفعيلها](https://manual.seafile.com/13.0/extension/webdav/?ref=arabroot.io) ثم تعيد التشغيل:

```bash
sudo sed -i 's/^enabled = false/enabled = true/' /opt/seafile-data/seafile/conf/seafdav.conf
cd /opt/seafile
sudo docker compose restart seafile
```

بعد ذلك اتصل من أي عميل WebDAV بالعنوان `https://seafile.example.com/seafdav/` ببريدك وكلمة مرورك، وللتحقق من الطرفية Terminal نفذ الأمر التالي:

```bash
curl -s -u admin@example.com -X PROPFIND -H "Depth: 1" https://seafile.example.com/seafdav/ -o /dev/null -w '%{http_code}\n'
```

والمخرج سوف يكون `207`، وهذا يعني أن الخدمة تعمل، وسوف تظهر المكتبات في عميل WebDAV على شكل مجلدات. ولاحظ أن Seafile 13 لا يقبل في WebDAV تسجيل الدخول بحساب LDAP لأسباب أمنية، كما تذكر [ملاحظات الترقية](https://manual.seafile.com/13.0/upgrade/upgrade%5Fnotes%5Ffor%5F13.0.x/?ref=arabroot.io)، فإذا كان فريقك يدخل عبر LDAP فسوف يحتاج كل مستخدم إلى إنشاء رمز WebDAV خاص به من صفحة حسابه.

## ربط النطاق وإصدار شهادة TLS

### ترك Caddy المرفق يصدر الشهادة بنفسه

إذا كان السيرفر مخصصاً لـ Seafile فإن الإعداد الذي كتبناه في `.env` (`SEAFILE_SERVER_PROTOCOL=https` مع `caddy.yml`) يكفي، حيث يستمع Caddy على المنفذين 80 و443، ويصدر شهادة Let's Encrypt للنطاق `seafile.example.com` عند أول طلب، ثم يجددها تلقائياً، وكل ما عليك هو أن تتأكد قبل التشغيل أن السجل A يشير إلى السيرفر، والسبب أن Let's Encrypt يتحقق من ملكيتك للنطاق عبر HTTP (HTTP Challenge) على المنفذ 80\. وإذا لم تصدر الشهادة فراجع سجل Caddy:

```bash
sudo docker logs --tail=50 seafile-caddy
```

### إذا كان لديك Reverse Proxy يعمل مسبقاً

إذا كان المنفذان 80 و443 مشغولين بـ Reverse Proxy لديك مثل [Nginx Proxy Manager](https://arabroot.io/articles/nginx-proxy-manager-%D9%86%D8%B7%D8%A7%D9%82%D8%A7%D8%AA-%D9%88%D8%B4%D9%87%D8%A7%D8%AF%D8%A7%D8%AA-tls/)، فلا تقم بتشغيل Caddy بجانبه، والسبب أن الاثنين سوف يتنافسان على المنفذين نفسيهما ولن يبدأ أحدهما، وبدلاً من ذلك اجعل NPM يصل إلى الـ Containers عبر الشبكة `seafile-net`، كما يشرح [التوثيق الخاص بأنواع Reverse Proxy الأخرى](https://manual.seafile.com/13.0/setup/use%5Fother%5Freverse%5Fproxy/?ref=arabroot.io). ابدأ بحذف `caddy.yml` من `COMPOSE_FILE` في `.env`، وأبق البروتوكول `https` لأنه العنوان الذي يراه المستخدمون في المتصفح:

```ini
COMPOSE_FILE='seafile-server.yml,seadoc.yml'
SEAFILE_SERVER_PROTOCOL=https
```

ثم أوقف Caddy وأعد إنشاء بقية الـ Containers:

```bash
cd /opt/seafile
sudo docker compose up -d --remove-orphans
```

بعد ذلك اربط NPM بالشبكة من ملف Compose الخاص به:

```yaml
services:
  app:
    networks:
      - default
      - seafile-net

networks:
  seafile-net:
    external: true
```

والآن أنشئ في NPM مضيفاً من نوع Proxy Host للنطاق `seafile.example.com` يوجه إلى `http://seafile:80`، وفعل Websockets Support وForce SSL، واطلب شهادة Let's Encrypt، ثم أضف في تبويب **Advanced** توجيه Routing المسارات الخاصة بـ SeaDoc وحد حجم الرفع Upload Size Limit:

```nginx
client_max_body_size 0;

location /sdoc-server/ {
    proxy_pass http://seadoc:80/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

location /socket.io {
    proxy_pass http://seadoc:80;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}
```

في الإعداد أعلاه لاحظ أن التوجيه Directive `client_max_body_size 0` يلغي حد حجم الطلب في Nginx، وبدونه يفشل رفع الملفات الكبيرة من المتصفح بالخطأ `413`، وأن المسار `/socket.io` يحتاج إلى ترقية الاتصال إلى WebSocket، ولذلك فيه السطران `Upgrade` و`Connection`.

## كيف تتأكد أن كل شيء يعمل؟

- الشهادة صالحة، فالأمر `curl -sI https://seafile.example.com/accounts/login/` يعيد الرمز `200` دون أي خطأ في الشهادة.
- ارفع ملفاً كبيراً بحجم مئات الميغابايتات من المتصفح، ثم زامن مكتبة من عميل سطح المكتب، وعدل ملفاً فيها، وتأكد أن التعديل يظهر في الويب وفي **History**.
- أنشئ رابط مشاركة وافتحه من نافذة تصفح خاصة Private Window، حتى ترى ما يراه شخص من خارج الفريق.

واجهة API تعيد رقم الإصدار:

```bash
curl -s https://seafile.example.com/api2/server-info/
```

والمخرج المتوقع يتضمن `"version": "13.0.28"`.

كل الـ Containers تعمل، و`seafile` و`seafile-mysql` بحالة `healthy`:

```bash
cd /opt/seafile
sudo docker compose ps
```

## النسخ الاحتياطي والاستعادة

قد يبدو من الوهلة الأولى أن عميل المزامنة نفسه نسخة احتياطية، فالملفات موجودة على السيرفر وعلى أجهزة الفريق، ولكن في الواقع فهو غير ذلك، فالمزامنة تنقل الحذف والتعديل الخاطئ والملف المشفر من برنامج فدية Ransomware إلى كل الأجهزة كما تنقل التعديل الصحيح، ولذلك تحتاج إلى نسخة احتياطية مستقلة عن Seafile نفسه.

📌

في 7 ديسمبر 2023 أصدرت Google الإصدار 85.0 من تطبيق Google Drive for desktop، وذكرت في [ملاحظات الإصدار](https://knowledge.workspace.google.com/admin/drive/google-drive-for-desktop-release-notes-archive?ref=arabroot.io) أنه يصلح خللاً جعل عدداً من مستخدمي الإصدار 84 لا يصلون إلى ملفات محلية لم تكن قد وصلت إلى Drive بعد، أي أن ملفات ظن أصحابها أنها في أمان داخل مجلد المزامنة كانت في الحقيقة على أجهزتهم فقط. والدرس هنا أن تطبيق المزامنة ليس نسخة احتياطية مهما كان المزود كبيراً، وأن السيرفر الذي تشغله أنت يحتاج إلى نسخة خارجه تختبر استعادتها.

وفي Seafile جزءان يجب أن تنسخهما معاً: الأول هو **قواعد البيانات الثلاث**، أي `ccnet_db` للمستخدمين والمجموعات، و`seafile_db` للمكتبات، و`seahub_db` للواجهة والروابط، والثاني هو **مجلد البيانات** `/opt/seafile-data` وفيه أجزاء الملفات والإعدادات.

والترتيب هنا مهم، حيث [يوصي التوثيق](https://manual.seafile.com/13.0/administration/backup%5Frecovery/?ref=arabroot.io) بأن تنسخ قاعدة البيانات أولاً ثم مجلد البيانات، والسبب أن كل سجل في قاعدة البيانات سوف يجد الأجزاء التي يشير إليها في مجلد البيانات، وأما الأجزاء الجديدة التي يكتبها Seafile أثناء النسخ فلا تضر، ولو عكست الترتيب فقد تحصل على قاعدة بيانات تشير إلى أجزاء غير موجودة في النسخة فتتلف المكتبات عند الاستعادة. والأوامر التالية تنسخ القواعد الثلاث:

```bash
sudo mkdir -p /opt/backup/seafile
cd /opt/backup/seafile
for db in ccnet_db seafile_db seahub_db; do
  sudo docker exec seafile-mysql sh -c "mariadb-dump -uroot -p\"\$MYSQL_ROOT_PASSWORD\" --opt --single-transaction $db" | sudo tee "$db-$(date +%F).sql" >/dev/null
done
```

ثم انسخ مجلد البيانات نسخاً تزايدياً Incremental Backup، ومعه ملفات Compose و`.env`:

```bash
sudo rsync -a --delete /opt/seafile-data/ /opt/backup/seafile/seafile-data/
sudo cp /opt/seafile/.env /opt/seafile/*.yml /opt/backup/seafile/
```

ضع أوامر نسخ قواعد البيانات في سكربت Script تشغله المهام المجدولة Cron Jobs يومياً، وانقل `/opt/backup/seafile` إلى تخزين خارج السيرفر Offsite Storage، والسبب أن نسخة على السيرفر نفسه تضيع معه إذا تعطل القرص أو اخترق السيرفر، وأدوات مثل [restic](https://restic.net/?ref=arabroot.io) تناسب هذه المهمة لأنها لا تنقل إلا الأجزاء التي تغيرت.

**الاستعادة** على سيرفر جديد تتم بالترتيب التالي: ضع ملفات Compose و`.env` في `/opt/seafile`، والبيانات في `/opt/seafile-data`، ثم شغل قاعدة البيانات وحدها وانتظر حتى تصبح سليمة، واستورد Import القواعد الثلاث، ثم أنشئ المستخدم `seafile` بكلمة المرور الموجودة في `.env`، والسبب أن ملفات النسخ تحمل الجداول فقط ولا تحمل مستخدمي MariaDB، فإذا تجاوزت هذه الخطوة فسوف يبدأ Seafile ولكن كل طلب إليه يفشل بخطأ داخلي، وبعد ذلك شغل كل الخدمات:

```bash
cd /opt/seafile
sudo docker compose up -d --wait db
for db in ccnet_db seafile_db seahub_db; do
  sudo docker exec seafile-mysql sh -c "mariadb -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -e 'CREATE DATABASE IF NOT EXISTS $db CHARACTER SET utf8mb4'"
  sudo docker exec -i seafile-mysql sh -c "mariadb -uroot -p\"\$MYSQL_ROOT_PASSWORD\" $db" < /opt/backup/seafile/$db-2026-09-26.sql
done
DB_PASS=$(sudo grep '^SEAFILE_MYSQL_DB_PASSWORD=' .env | cut -d= -f2-)
sudo docker exec seafile-mysql sh -c "mariadb -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -e \"CREATE USER IF NOT EXISTS 'seafile'@'%' IDENTIFIED BY '$DB_PASS'; GRANT ALL PRIVILEGES ON ccnet_db.* TO 'seafile'@'%'; GRANT ALL PRIVILEGES ON seafile_db.* TO 'seafile'@'%'; GRANT ALL PRIVILEGES ON seahub_db.* TO 'seafile'@'%';\""
sudo docker compose up -d
```

ضع مكان التاريخ اسم ملفات النسخة التي تستعيدها، وبعد الاستعادة شغل [فحص السلامة](https://manual.seafile.com/13.0/administration/seafile%5Ffsck/?ref=arabroot.io) Integrity Check لتتأكد أن المكتبات متسقة، لأن قاعدة البيانات والملفات نسخت في وقتين مختلفين:

```bash
sudo docker exec seafile /opt/seafile/seafile-server-latest/seaf-fsck.sh
```

💡

حذف الملفات أو المكتبات لا يحرر المساحة فوراً، لأن الأجزاء تبقى حتى تنتهي مدة الاحتفاظ بالإصدارات، ولذلك شغل [جامع المهملات (Garbage Collector)](https://manual.seafile.com/13.0/administration/seafile%5Fgc/?ref=arabroot.io) دورياً في وقت يقل فيه الاستخدام: `sudo docker exec seafile /opt/seafile/seafile-server-latest/seaf-gc.sh`، وأضف الخيار `--dry-run` لترى ما سوف يحذفه دون أن يحذف شيئاً.

## التحديث إلى إصدار أحدث Upgrade

التحديث داخل السلسلة نفسها بسيط، مثل الانتقال من 13.0.28 إلى إصدار أحدث من 13.0، فتأخذ نسخة احتياطية، وتغير الوسم في `.env`، وتسحب الـ Image الجديدة، وتعيد التشغيل، وعند الإقلاع يشغل الـ Container سكربتات ترقية قاعدة البيانات تلقائياً:

```bash
cd /opt/seafile
sudo sed -i 's|^SEAFILE_IMAGE=.*|SEAFILE_IMAGE=seafileltd/seafile-mc:13.0.30|' .env
sudo docker compose pull
sudo docker compose up -d
sudo docker logs -f seafile
```

ضع مكان `13.0.30` الإصدار المستقر Stable الذي تريده من [صفحة الوسوم على Docker Hub](https://hub.docker.com/r/seafileltd/seafile-mc/tags?ref=arabroot.io)، ولا تستخدم الوسوم المنتهية بـ `-testing` لأنها إصدارات تجريبية لم تعتمد بعد، وهذا ينطبق اليوم على وسوم 14.0 أيضاً. وحدث `sdoc-server` بالطريقة نفسها بحسب جدول التوافق Compatibility في [ملاحظات الإصدار](https://manual.seafile.com/13.0/changelog/server-changelog/?ref=arabroot.io).

أما الانتقال بين الإصدارات الرئيسية Major Versions، من 12.0 إلى 13.0 أو لاحقاً إلى 14.0، فيحتاج إلى خطوات إضافية تشرحها [صفحة الترقية الرسمية](https://manual.seafile.com/13.0/upgrade/upgrade%5Fdocker/?ref=arabroot.io) لكل إصدار، ففي الانتقال إلى 13.0 مثلاً تنزل ملفات YAML الجديدة، وتضيف إلى `.env` متغيرات قاعدة البيانات والتخزين المؤقت (`CACHE_PROVIDER` مع Redis أو Memcached) و`JWT_PRIVATE_KEY`، ثم تحذف الأقسام المكررة من ملفات الإعداد القديمة مثل `[database]` و`[memcached]` من `seafile.conf` و`DATABASES` و`CACHES` من `seahub_settings.py`، والسبب أن الإعداد صار يأتي من متغيرات البيئة.

**لكن تذكر:** لا تتخط أي إصدار رئيسي، وجرب الترقية على نسخة من البيانات قبل أن تطبقها على بيئة الإنتاج Production، لأن الترقية تغير جداول قاعدة البيانات ولا رجوع عنها إلا من النسخة الاحتياطية.

## مشكلات شائعة وحلولها

### الـ Container يتوقف بالخطأ is not a valid ip or domain

والسبب أن قيمة `SEAFILE_SERVER_HOSTNAME` فيها رقم منفذ، أو `http://`، أو اسم دون نقطة مثل `localhost`، والحل أن تصححها إلى اسم نطاق كامل FQDN. وإذا كانت هذه أول محاولة تشغيل ولم تكتمل التهيئة، فاحذف مجلدي البيانات `/opt/seafile-data` و`/opt/seafile-mysql` ثم شغل من جديد، ولا تقم بذلك أبداً على سيرفر فيه بيانات حقيقية.

### خطأ CSRF أو روابط تنزيل خاطئة

يظهر هذا الخطأ عندما يختلف العنوان الذي يفتحه المستخدم عن `SEAFILE_SERVER_PROTOCOL` و`SEAFILE_SERVER_HOSTNAME`، مثلاً يفتح المستخدم الموقع عبر HTTPS بينما البروتوكول في `.env` هو `http`، والحل أن تجعل القيمتين مطابقتين للعنوان العام تماماً، ثم تنفذ `docker compose up -d`.

### رفع الملفات الكبيرة يفشل

الخطأ `413 Request Entity Too Large` يأتي من الـ Reverse Proxy، وحله أن تضيف `client_max_body_size 0;` في إعداد Nginx أو NPM. وإذا انقطع الرفع بعد دقيقة تقريباً فهناك مهلة Timeout قصيرة في الـ Reverse Proxy أو في جدار حماية Firewall مثل Cloudflare، والحل أن ترفع مهلة القراءة، أو أن تستخدم عميل المزامنة للملفات الضخمة لأنه يرفعها أجزاء.

### SeaDoc لا يفتح المستندات

تحقق أن `ENABLE_SEADOC=true`، وأن المسارين `/sdoc-server/` و`/socket.io` يصلان إلى الـ Container `seadoc`، فمع Caddy يحدث هذا تلقائياً، ومع أي Reverse Proxy آخر تقوم بإعداده يدوياً. وتحقق أيضاً أن قيمة `JWT_PRIVATE_KEY` واحدة في الخدمتين، ولقراءة سجل الخدمة نفذ `sudo docker logs --tail=50 seadoc`.

### Seafile لا يتصل بقاعدة البيانات بعد تغيير كلمة المرور

تحفظ MariaDB كلمة مرور المستخدم `seafile` منذ التهيئة الأولى، فإذا غيرت `SEAFILE_MYSQL_DB_PASSWORD` في `.env` فيجب أن تغيرها في قاعدة البيانات أيضاً بالأمر `ALTER USER 'seafile'@'%' IDENTIFIED BY '…';` من داخل الـ Container `seafile-mysql`.

### المساحة لا تنخفض بعد حذف الملفات

وهذا أمر متوقع، فالأجزاء المحذوفة تبقى حتى يعمل جامع المهملات `seaf-gc.sh`، والإصدارات القديمة تبقى بحسب مدة الاحتفاظ المحددة في إعدادات كل مكتبة، ولذلك قلل المدة في المكتبات التي تتغير ملفاتها كثيراً، وشغل جامع المهملات دورياً.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- المجلد المشترك على الشبكة لا يعطيك مزامنة ولا سجل إصدارات، وSeafile يعطي فريقك تجربة قريبة من Dropbox والملفات على سيرفرك، وهو أخف من Nextcloud إذا كانت حاجتك هي الملفات فقط.
- ثبت كل Docker Image على إصدار محدد في `.env`، واجعل `SEAFILE_SERVER_HOSTNAME` و`SEAFILE_SERVER_PROTOCOL` مطابقين للعنوان العام تماماً، ولا تغير `JWT_PRIVATE_KEY` وكلمة مرور قاعدة البيانات بعد التشغيل الأول.
- استخدم Caddy المرفق إذا كان السيرفر لـ Seafile وحده، وإذا كان لديك Reverse Proxy فاحذف `caddy.yml` ووجه المسارات الخاصة بـ SeaDoc يدوياً.
- كلمة مرور المكتبة المشفرة لا يمكن استرجاعها، فاحفظها في مدير كلمات المرور.
- المزامنة ليست نسخة احتياطية: انسخ قواعد البيانات أولاً ثم مجلد البيانات، وانقل النسخة خارج السيرفر، وعند الاستعادة أنشئ المستخدم `seafile` في MariaDB ثم شغل `seaf-fsck.sh`.

## سجل التحديثات

- سبتمبر 2026: كتابة الدليل واختباره على Seafile 13.0.28.
- أكتوبر 2026: مراجعة الدليل وإعادة اختباره على Seafile 13.0.28، وإضافة خطوة إنشاء المستخدم `seafile` وانتظار MariaDB إلى الاستعادة على سيرفر جديد، وملاحظة تسجيل الدخول بحساب LDAP في WebDAV، وتفاصيل الترقية من 12.0 إلى 13.0.