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

# Nextcloud: ملفات فريقك وتقويمه وجهات اتصاله على سيرفرك
- URL: https://arabroot.io/articles/تثبيت-nextcloud-للملفات-والتقويم-وجهات-الاتصال/
- Published: 2026-10-09T12:45:00.000Z
- Updated: 2026-10-09T13:00:43.000Z
- Description: كيف تثبت Nextcloud على سيرفرك وتربطه بأجهزة فريقك وبالدخول الموحد، ثم تحميه وتحدثه دون أن تفقد بياناتك.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الاستضافة الذاتية والتطبيقات, تطبيقات لفريقك, الاستضافة الذاتية, Nextcloud

في دليل [Seafile](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-seafile-%D9%84%D9%85%D8%B2%D8%A7%D9%85%D9%86%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA/) ذكرنا أن أشهر خيارين لمزامنة ملفات الفريق على سيرفرك هما Seafile وNextcloud، واخترنا Seafile لأنه يركز على الملفات وحدها، ولكن ماذا لو كان فريقك يحتاج أكثر من ذلك: ملفات تتزامن على الأجهزة، وتقويماً مشتركاً للاجتماعات، ودفتر جهات اتصال يصل إلى الهاتف، ودخولاً بحساب الشركة الموحد، وكل ذلك في واجهة واحدة؟ هنا يأتي دور [Nextcloud](https://nextcloud.com/?ref=arabroot.io)، وهو منصة مفتوحة المصدر برخصة [AGPL-3.0](https://github.com/nextcloud/server/blob/master/COPYING?ref=arabroot.io) تجمع هذه الأجزاء في سيرفر واحد، وهذا المقال هو الثاني في [مرحلة الملفات والتخزين السحابي](https://arabroot.io/start/#stage-files) من خريطة الطريق.

وقد يبدو التثبيت من الوهلة الأولى سهلاً، فأمر واحد يشغل Nextcloud مع قاعدة بيانات SQLite وتفتح الواجهة بعد دقيقة، ولكن في الواقع فهذا الإعداد مناسب للتجربة فقط كما يقول [توثيق متطلبات النظام](https://docs.nextcloud.com/server/35/admin%5Fmanual/installation/system%5Frequirements.html?ref=arabroot.io)، والسبب أن Nextcloud تطبيق PHP ينفذ كل طلب من جديد، فإذا لم تضع معه قاعدة بيانات حقيقية وذاكرة مؤقتة Cache وقفلاً للملفات File Locking ومهام خلفية Background Jobs منتظمة، فسوف تجده بطيئاً مع خمسة مستخدمين، وتظهر لك تحذيرات في لوحة الإدارة لا تعرف من أين جاءت. ولذلك سوف نبني التثبيت كاملاً من البداية في مختبر حقيقي، ونسجل كل مخرج كما ظهر لنا.

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

- مكونات التثبيت: Nextcloud مع PostgreSQL وRedis وContainer للمهام الخلفية خلف Reverse Proxy.
- الفحص الأول بالأمر `occ setupchecks`، والمهام الخلفية، وضبط الأداء بـ APCu وRedis وOPcache.
- المستخدمون والمجموعات والمشاركة وصلاحياتها، مع تجربة القراءة والكتابة والرابط العام.
- كيف تتصل تطبيقات الحاسوب والهاتف، وما هي كلمة مرور الجهاز App Password.
- التقويم وجهات الاتصال، ثم تجربة صادقة للغة العربية والاتجاه من اليمين لليسار RTL.
- الدخول الموحد SSO مع authentik عبر OIDC، والأخطاء الثلاثة التي ظهرت لنا.
- التشفير من جهة السيرفر SSE والتشفير من طرف إلى طرف E2EE، ومتى تختار كل منهما.
- فحص الأمان، والنسخ الاحتياطي واختبار الاستعادة، والتحديث إصداراً رئيسياً واحداً في كل مرة.

## متى تختار Nextcloud بدل Seafile؟

إذا كانت حاجتك هي مزامنة الملفات فقط فإن Seafile أخف وأسرع مع الملفات الكثيرة، وهذا ما شرحناه في [دليل Seafile](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-seafile-%D9%84%D9%85%D8%B2%D8%A7%D9%85%D9%86%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA/)، أما إذا كان الفريق يحتاج التقويم وجهات الاتصال والمحرر المكتبي في المتصفح والدخول الموحد في مكان واحد، فإن Nextcloud هو الأنسب، والسبب أن هذه الأجزاء تطبيقات Apps تعمل داخله وتشترك في نفس المستخدمين والمجموعات والصلاحيات. والثمن أن Nextcloud أثقل على السيرفر ويحتاج عناية أكثر في الأداء والتحديث كما سيأتي. والمقارنة الكاملة بين Nextcloud وSeafile وOpenCloud من المقالات المخطط لها في نفس المرحلة.

[![](https://arabroot.io/content/images/2026/10/seafile-cover-cover-1.webp)دليلSeafile: مزامنة ملفات فريقك ومشاركتها على سيرفرككيف تثبت Seafile على سيرفرك لتزامن ملفات فريقك وتشاركها بدل Dropbox وOneDrive، مع نسخة احتياطية تستطيع استعادتها.](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-seafile-%D9%84%D9%85%D8%B2%D8%A7%D9%85%D9%86%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA/)[![](https://arabroot.io/content/images/2026/10/calendar-contacts-cover-cover.webp)دليلالتقويم وجهات الاتصال على سيرفرك مع CalDAV وCardDAVكيف تبقى مواعيدك وجهات اتصالك متطابقة بين الهاتف والحاسوب على سيرفرك، وما الذي يعمل مع Outlook وما الذي لا يعمل.](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D9%82%D9%88%D9%8A%D9%85-%D9%88%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-caldav-%D9%88-carddav/)[![](https://arabroot.io/content/images/2026/10/office-suite-browser-cover-cover.webp)دليلCollabora Online أم ONLYOFFICE؟ حزمة مكتبية في المتصفحأي المحررين يتعامل مع النص العربي وملفات Word وExcel بشكل أفضل داخل Nextcloud، وماذا تسمح لك به رخصة كل منهما.](https://arabroot.io/articles/collabora-online-%D8%A7%D9%85-onlyoffice/)

## مما يتكون التثبيت؟

الصورة التالية تبين المكونات التي سوف نشغلها، وكيف يمر الطلب من جهاز المستخدم حتى يصل إلى البيانات:

![مخطط تثبيت Nextcloud: المتصفح وتطبيق الحاسوب وتطبيقات الهاتف تتصل عبر HTTPS بالمنفذ 443 إلى Caddy، ثم إلى Container تطبيق Nextcloud الذي يعمل بـ Apache وPHP مع APCu وOPcache، ويتصل بقاعدة PostgreSQL للمستخدمين والمشاركات وفهرس الملفات، وبـ Redis للذاكرة المؤقتة وأقفال الملفات، وبالـ Volume الذي يحمل الكود والإعدادات والبيانات، وContainer المهام الخلفية يشغل cron.php كل خمس دقائق على نفس الـ Volume، وauthentik يقدم الدخول عبر OIDC](https://arabroot.io/content/images/2026/10/nextcloud-01-architecture.webp)

لا يصل الإنترنت إلا إلى Caddy، وبقية المكونات على شبكة Docker الداخلية

- **الـ Reverse Proxy**: نستخدم [Caddy](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-caddy-reverse-proxy/) لأنه يصدر شهادة TLS بنفسه، ويمكنك استخدام أي Reverse Proxy آخر كما شرحنا في [دليل التطبيق خلف Reverse Proxy](https://arabroot.io/articles/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%83-%D8%AE%D9%84%D9%81-reverse-proxy/).
- **تطبيق Nextcloud**: الـ Docker Image الرسمية [nextcloud](https://github.com/nextcloud/docker?ref=arabroot.io) بنسخة `apache`، وفيها Apache وPHP والإضافات المطلوبة جاهزة.
- **قاعدة البيانات PostgreSQL**: تحفظ المستخدمين والمشاركات وفهرس الملفات File Cache، أما محتوى الملفات نفسه فيبقى على القرص. ويوصي التوثيق بالإصدار 18 من PostgreSQL، ويدعم من 14 إلى 18.
- **Redis**: ذاكرة مؤقتة مشتركة، والأهم أنه يحمل أقفال الملفات حتى لا يكتب طلبان على نفس الملف في نفس اللحظة.
- **Container المهام الخلفية Cron**: نفس الـ Docker Image ولكنه يشغل `cron.php` كل خمس دقائق، وسوف نرى لماذا لا تكفي الطريقة الافتراضية.

## التثبيت خطوة بخطوة

قمنا بتشغيل المختبر على Docker Engine 29.8.0، ونشرنا المنفذ على `127.0.0.1:28480` فقط وعبر HTTP، لأنه مختبر محلي لا يصل إليه أحد من الشبكة، وفي نهاية القسم سوف نذكر ما تغيره على سيرفرك الحقيقي حتى يعمل بنطاق Domain وشهادة TLS. والإصدارات كلها مثبتة Pinned، فلا تستخدم `latest` أبداً مع Nextcloud، والسبب أن الـ Docker Image تقوم بالترقية تلقائياً عند التشغيل، فإذا قفز الوسم `latest` إصدارين رئيسيين فسوف يرفض الـ Container أن يعمل كما سنرى في قسم التحديث.

### ملف .env والأسرار

نبدأ بمجلد التثبيت ثم نولد كلمات المرور عشوائياً بدل أن نكتبها بأيدينا:

```bash
sudo mkdir -p /opt/nextcloud && cd /opt/nextcloud
cat > .env <<EOF
NC_TAG=35.0.1-apache
POSTGRES_PASSWORD=$(openssl rand -hex 24)
NEXTCLOUD_ADMIN_PASSWORD=$(openssl rand -hex 12)
REDIS_PASSWORD=$(openssl rand -hex 24)
EOF
chmod 600 .env
```

لاحظ أن `NEXTCLOUD_ADMIN_PASSWORD` تستخدم مرة واحدة فقط في التثبيت الأول لإنشاء حساب المدير `admin`، فاحفظها في مدير كلمات المرور ثم غيرها من الواجهة.

### ملف compose.yaml

والملف التالي هو نفس الملف الذي شغلناه في المختبر:

```yaml
name: nextcloud
services:
  db:
    image: postgres:18.6
    restart: unless-stopped
    environment:
      POSTGRES_DB: nextcloud
      POSTGRES_USER: nextcloud
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - db:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d nextcloud -U nextcloud"]
      interval: 10s
      retries: 10
    networks: [nc]

  redis:
    image: redis:8.10.2-alpine
    restart: unless-stopped
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
    networks: [nc]

  app:
    image: nextcloud:${NC_TAG}
    restart: unless-stopped
    depends_on:
      db: { condition: service_healthy }
      redis: { condition: service_started }
    environment:
      POSTGRES_HOST: db
      POSTGRES_DB: nextcloud
      POSTGRES_USER: nextcloud
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      REDIS_HOST: redis
      REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
      NEXTCLOUD_ADMIN_USER: admin
      NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_ADMIN_PASSWORD}
      NEXTCLOUD_TRUSTED_DOMAINS: 127.0.0.1
      TRUSTED_PROXIES: 10.89.77.0/24
      OVERWRITECLIURL: http://127.0.0.1:28480
      OVERWRITEPROTOCOL: http
      PHP_MEMORY_LIMIT: 1G
      PHP_UPLOAD_LIMIT: 10G
    volumes:
      - html:/var/www/html
    networks: [nc]

  cron:
    image: nextcloud:${NC_TAG}
    restart: unless-stopped
    entrypoint: /cron.sh
    depends_on: [app]
    volumes:
      - html:/var/www/html
    networks: [nc]

  proxy:
    image: caddy:2.11.7-alpine
    restart: unless-stopped
    ports:
      - "127.0.0.1:28480:80"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
    networks: [nc]

volumes:
  db:
  html:

networks:
  nc:
    ipam:
      config:
        - subnet: 10.89.77.0/24
```

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

- الـ Volume الخاص بـ PostgreSQL مربوط على `/var/lib/postgresql` وليس على `/var/lib/postgresql/data` كما في الأدلة القديمة، والسبب أن الـ Docker Image الرسمية لـ [postgres](https://hub.docker.com/%5F/postgres?ref=arabroot.io) غيرت مكان البيانات ابتداء من الإصدار 18 إلى مجلد باسم الإصدار داخل `/var/lib/postgresql`، فإذا ربطت المسار القديم فقد تكتب البيانات داخل الـ Container وتضيع عند حذفه.
- المتغيرات `REDIS_HOST` و`REDIS_HOST_PASSWORD` تجعل الـ Docker Image تكتب إعداد Redis بنفسها في ملف `config/redis.config.php`، فلا تحتاج أن تعدل `config.php` يدوياً، وسوف نتحقق من ذلك في قسم الأداء.
- الـ Container المسمى `cron` يستخدم نفس الـ Docker Image ونفس الـ Volume، ولكن نقطة الدخول Entrypoint فيه هي `/cron.sh` الذي يشغل `cron.php` كل خمس دقائق.
- `TRUSTED_PROXIES` هو نطاق شبكة Docker التي ثبتناها بالقيمة `10.89.77.0/24`، حتى يثق Nextcloud بعنوان المستخدم الحقيقي الذي يرسله Caddy في الترويسة X-Forwarded-For، ولولا ذلك لظهر كل المستخدمين بعنوان Caddy نفسه، ولقامت حماية تخمين كلمات المرور Brute-force Protection بإبطاء الجميع معاً.
- `PHP_UPLOAD_LIMIT` يرفع حد الرفع في PHP، وعليه أن يتوافق مع حد الـ Reverse Proxy كما شرحنا في [دليل حدود رفع الملفات](https://arabroot.io/articles/%D8%AD%D8%AF%D9%88%D8%AF-%D8%AD%D8%AC%D9%85-%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA/)، وقد رفعنا في المختبر ملفاً حجمه 400 ميجابايت عبر Caddy دون مشكلة.

### ملف Caddyfile

```text
:80 {
	request_body {
		max_size 10GB
	}
	redir /.well-known/carddav /remote.php/dav/ 301
	redir /.well-known/caldav /remote.php/dav/ 301
	header Strict-Transport-Security "max-age=31536000;"
	reverse_proxy app:80
}
```

والسطران `redir` هما ما يذكره [توثيق الـ Reverse Proxy](https://docs.nextcloud.com/server/35/admin%5Fmanual/configuration%5Fserver/reverse%5Fproxy%5Fconfiguration.html?ref=arabroot.io) لـ Caddy، والسبب أن الهواتف وبرامج التقويم تبحث عن خدمة CalDAV وCardDAV في المسار `/.well-known/caldav` قبل أي شيء آخر، كما شرحنا في [مقال التقويم وجهات الاتصال](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D9%82%D9%88%D9%8A%D9%85-%D9%88%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-caldav-%D9%88-carddav/#discovery).

### التشغيل والتأكد من الحالة

```bash
docker compose up -d
docker compose exec -u www-data app php occ status
```

والأداة `occ` هي واجهة الأوامر التي تدير بها كل شيء في Nextcloud كما في [توثيق occ](https://docs.nextcloud.com/server/35/admin%5Fmanual/occ%5Fcommand.html?ref=arabroot.io)، ويجب أن تشغلها دائماً بالمستخدم `www-data` صاحب الملفات، والسبب أنك لو شغلتها بالمستخدم root فقد تنشئ ملفات لا يستطيع Apache قراءتها بعد ذلك. وبعد أن ينتهي التثبيت الأول، وقد استغرق في المختبر قرابة دقيقة، سوف يكون المخرج كما يلي:

```text
  - installed: true
  - version: 35.0.1.1
  - versionstring: 35.0.1
  - edition:
  - maintenance: false
  - needsDbUpgrade: false
  - productname: Nextcloud
  - extendedSupport: false
```

### ما الذي تغيره على سيرفرك الحقيقي؟

على السيرفر الحقيقي اجعل Caddy يستمع على المنفذين 80 و443 بنطاق حقيقي حتى يصدر الشهادة بنفسه، وغير ثلاثة متغيرات في خدمة `app`:

```text
cloud.example.com {
	request_body {
		max_size 10GB
	}
	redir /.well-known/carddav /remote.php/dav/ 301
	redir /.well-known/caldav /remote.php/dav/ 301
	header Strict-Transport-Security "max-age=31536000;"
	reverse_proxy app:80
}
```

```yaml
      NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com
      OVERWRITECLIURL: https://cloud.example.com
      OVERWRITEPROTOCOL: https
```

والمتغير `OVERWRITEPROTOCOL` مهم جداً خلف الـ Reverse Proxy، والسبب أن Nextcloud يستقبل الطلب من Caddy عبر HTTP داخل شبكة Docker، فإذا لم تخبره أن المستخدم يراه عبر HTTPS فسوف يولد روابط تبدأ بـ `http://`، وهذا يكسر تسجيل الدخول في التطبيقات ويظهر تحذيراً في لوحة الإدارة كما سنرى بعد قليل.

## الفحص الأول: ماذا يقول Nextcloud عن نفسه؟

في Nextcloud أداة فحص مدمجة تراجع الإعداد كله، وتجدها في الواجهة في صفحة Administration settings ثم Overview، وتشغلها من سطر الأوامر هكذا:

```bash
docker compose exec -u www-data app php occ setupchecks
```

والمخرج سوف يكون طويلاً، وهذه الأسطر المهمة منه كما ظهرت في المختبر:

```text
	system:
		✓ Cron last run: Last background job execution ran seconds ago.
		✓ Transactional File Locking
		✓ Memcache: Configured
		⚠ Mimetype migrations available: One or more mimetype migrations are available. ... Use the command `occ maintenance:repair --include-expensive` to perform the migrations.
	network:
		✓ WebDAV endpoint: Your web server is properly set up to allow file synchronization over WebDAV.
		✓ Data directory protected
		✓ .well-known URLs: Your server is correctly configured to serve `.well-known` URLs.
	database:
		✓ Database missing indices: None
		✓ Database version: 18.6 (Debian 18.6-1.pgdg13+2)
		✓ Database transaction isolation level: Read committed
	security:
		ℹ HTTPS access and URLs: Your instance is generating insecure URLs. If you access your instance over HTTPS, this likely means that your instance is behind a reverse proxy and the Nextcloud `overwrite*` config values are not set correctly.
		⚠ HTTP headers: Some headers are not set correctly on your instance
- The `Strict-Transport-Security` HTTP header is not set (should be at least `15552000` seconds). For enhanced security, it is recommended to enable HSTS.
	config:
		✓ Default phone region: SA
	php:
		✓ PHP APCu configuration
		✓ PHP memory limit: 1 GB
		✓ PHP opcache: Checking from CLI, OPcache checks have been skipped.
```

في المخرج أعلاه لاحظ التالي:

- تحذيرا HTTPS وHSTS سببهما أن المختبر يعمل عبر HTTP، فالمتصفح يتجاهل الترويسة Strict-Transport-Security على اتصال HTTP حتى لو أرسلها Caddy، وعلى السيرفر الحقيقي مع الإعداد السابق يختفي التحذيران.
- تحذير Mimetype migrations ظهر بعد التحديث من إصدار سابق، وحله هو الأمر الذي يذكره المخرج نفسه: `occ maintenance:repair --include-expensive`.
- السطر `Default phone region` أصبح سليماً بعد أن ضبطناه بالأمر `occ config:system:set default_phone_region --value=SA`، والسبب أن Nextcloud يحتاج رمز الدولة ليفهم أرقام الهاتف المكتوبة دون مفتاح دولي.

والصورة التالية تبين نفس الفحص في الواجهة، مع تحذير HTTPS باللون الأحمر لأننا في المختبر:

![صفحة Security and setup warnings في لوحة إدارة Nextcloud تعرض خطأ HTTPS access and URLs لأن الموقع يعمل عبر HTTP، وتحذيرات Errors in the log وHTTP headers، وملاحظات عن AppAPI والمصادقة الثنائية وإعداد البريد](https://arabroot.io/content/images/2026/10/nextcloud-02-setup-checks.webp)

صفحة الفحص في لوحة الإدارة، وتحذيراتها في المختبر سببها العمل عبر HTTP

## المهام الخلفية Background Jobs

يحتاج Nextcloud أن ينفذ مهاماً دورية لا يطلبها المستخدم، مثل تنظيف الملفات المؤقتة وإرسال الإشعارات وحذف الإصدارات القديمة ومزامنة دفتر العناوين، و[التوثيق](https://docs.nextcloud.com/server/35/admin%5Fmanual/configuration%5Fserver/background%5Fjobs%5Fconfiguration.html?ref=arabroot.io) يذكر ثلاث طرق لتشغيلها:

- **AJAX**: وهي الافتراضية، وفيها ينفذ مهمة واحدة مع كل صفحة يفتحها مستخدم، فإذا لم يفتح أحد الواجهة لا تنفذ أي مهمة، ولذلك يصفها التوثيق بأنها الأقل موثوقية.
- **Webcron**: خدمة خارجية تطلب `cron.php` كل خمس دقائق، وتنفذ مهمة واحدة في كل طلب، أي 288 مهمة في اليوم كحد أقصى، وهذا يكفي فقط للنسخ الصغيرة جداً.
- **Cron**: وهي الطريقة الموصى بها، حيث يشغل النظام `cron.php` كل خمس دقائق دون حدود Apache، وهذا ما يفعله الـ Container المسمى `cron`.

ووجود الـ Container لا يكفي وحده، فعليك أن تخبر Nextcloud أن يعتمد عليه، ثم تحدد نافذة الصيانة Maintenance Window التي تنفذ فيها المهام الثقيلة:

```bash
docker compose exec -u www-data app php occ background:cron
docker compose exec -u www-data app php occ config:system:set maintenance_window_start --type=integer --value=1
```

```text
Set mode for background jobs to 'cron'
System config value maintenance_window_start set to integer 1
```

والقيمة 1 تعني أن المهام غير العاجلة تنفذ بين الساعة 1:00 و5:00 بتوقيت UTC، أي بين 4:00 و8:00 صباحاً بتوقيت السعودية، والسبب أن بعض المهام اليومية ثقيلة ولا تريدها في ساعات العمل. وللتأكد أن المهام تعمل فعلاً اطلب قائمتها مع آخر وقت نفذت فيه:

```bash
docker compose exec -u www-data app php occ background-job:list --limit=5
```

```text
+--------------------+-------------------------------------------------------------------+---------------------------+----------+
| id                 | class                                                             | last_run                  | argument |
+--------------------+-------------------------------------------------------------------+---------------------------+----------+
| 138403826814185472 | OCA\UpdateNotification\BackgroundJob\UpdateAvailableNotifications | 2026-10-08T23:30:09+00:00 | null     |
| 138403826361200640 | OCA\Activity\BackgroundJob\RemoveFormerActivitySettings           | 2026-10-08T23:30:00+00:00 | null     |
| 138403815846080512 | OCA\Text\Cron\Cleanup                                             | 2026-10-09T00:20:03+00:00 | null     |
| 138403826247954432 | OCA\Activity\BackgroundJob\EmailNotification                      | 2026-10-09T00:20:03+00:00 | null     |
| 138403786632753152 | OCA\Files\BackgroundJob\CleanupDirectEditingTokens                | 2026-10-09T00:05:07+00:00 | null     |
+--------------------+-------------------------------------------------------------------+---------------------------+----------+
```

وفي الواجهة تجد نفس المعلومة في Basic settings، حيث يظهر وقت آخر تنفيذ باللون الأخضر:

![قسم Background jobs في الإعدادات الأساسية لـ Nextcloud يعرض رسالة خضراء Last job ran 4 minutes ago، والخيار Cron (Recommended) محدداً بدل AJAX وWebcron](https://arabroot.io/content/images/2026/10/nextcloud-03-background-jobs.webp)

الطريقة Cron محددة، وآخر مهمة نفذت قبل أربع دقائق

## ضبط الأداء: APCu وRedis وOPcache

كل طلب إلى Nextcloud يعني أن PHP يقرأ مئات الملفات ويسأل قاعدة البيانات عشرات المرات، ولذلك يعتمد الأداء على ثلاث طبقات من الذاكرة المؤقتة يشرحها [توثيق الذاكرة المؤقتة](https://docs.nextcloud.com/server/35/admin%5Fmanual/configuration%5Fserver/caching%5Fconfiguration.html?ref=arabroot.io) و[دليل ضبط السيرفر](https://docs.nextcloud.com/server/35/admin%5Fmanual/installation/server%5Ftuning.html?ref=arabroot.io):

- **OPcache**: يحفظ كود PHP بعد ترجمته Compiled Bytecode حتى لا يترجمه مع كل طلب، وهو مدمج في PHP.
- **APCu**: ذاكرة مؤقتة محلية Local Cache داخل عملية PHP نفسها، وهي الأسرع، ولكنها لا تشارك بين أكثر من سيرفر.
- **Redis**: ذاكرة مؤقتة موزعة Distributed Cache يراها كل PHP Worker، وتحمل أقفال الملفات Transactional File Locking.

والتوصية في التوثيق للمؤسسة التي تعمل على سيرفر واحد هي APCu للذاكرة المحلية وRedis لما سواها. وقد يتساءل البعض: لماذا لا نستخدم Redis لكل شيء ونرتاح؟ والإجابة أن التوثيق يذكر أن APCu أسرع من Redis في الذاكرة المحلية لأنه لا يمر عبر الشبكة، فإذا كانت الذاكرة كافية فاجعل APCu للذاكرة المحلية وRedis للأقفال. والآن نتحقق مما كتبته الـ Docker Image بنفسها:

```bash
for k in memcache.local memcache.distributed memcache.locking; do
  echo "$k = $(docker compose exec -u www-data app php occ config:system:get $k)"
done
```

```text
memcache.local = \OC\Memcache\APCu
memcache.distributed = \OC\Memcache\Redis
memcache.locking = \OC\Memcache\Redis
```

والإعداد كما يوصي التوثيق تماماً. ولكي ترى أقفال الملفات بعينك قمنا برفع ملف حجمه 400 ميجابايت، وأثناء الرفع طلبنا من Redis المفاتيح التي فيها كلمة lock:

```bash
docker compose exec redis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning --scan --pattern '*lock*'
```

```text
b149be05601915d593db82b2d5b5d2de/lockfiles/5c06021cf7b5333273c282481050cb26
b149be05601915d593db82b2d5b5d2de/lockfiles/daa41323d18bae5cf90b8e67be248256
```

لاحظ أن هناك قفلين أثناء الرفع، وبعد انتهائه أعاد نفس الأمر صفر مفاتيح، أي أن Nextcloud يقفل الملف ومجلده أثناء الكتابة ثم يحررهما، وهذا ما يمنع تطبيقين على جهازين من الكتابة على نفس الملف في نفس اللحظة.

أما OPcache فإعداداته تأتي من الملف `opcache-recommended.ini` داخل الـ Docker Image:

```bash
docker compose exec app sh -c 'cat /usr/local/etc/php/conf.d/opcache-recommended.ini; php -r "echo \"apc.shm_size=\".ini_get(\"apc.shm_size\").\"\n\";"'
```

```text
opcache.enable=1
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=10000
opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION}
opcache.save_comments=1
opcache.revalidate_freq=60
opcache.jit=1255
opcache.jit_buffer_size=8M
apc.shm_size=32M
```

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

- `opcache.save_comments=1` شرط إلزامي، والسبب أن Nextcloud يقرأ تعليقات الكود أثناء التشغيل كما يذكر دليل ضبط السيرفر.
- `opcache.revalidate_freq=60` يعني أن PHP يتحقق من تغير الملفات كل 60 ثانية بدل ثانيتين، وهذا أسرع، ولكنه يعني أن تعديلك على `config.php` قد يتأخر دقيقة حتى يظهر، فلا تستغرب ذلك.
- الـ JIT مفعل بالقيمتين 1255 و8M كما في التوثيق، وقيمة `opcache.memory_consumption` تأتي من المتغير `PHP_OPCACHE_MEMORY_CONSUMPTION` وقيمته الافتراضية في الـ Docker Image هي 128.
- `apc.shm_size=32M` هو الحجم الافتراضي لـ APCu، ويقول التوثيق إن 32M منخفض عادة لـ Nextcloud وإن 128M نقطة بداية جيدة، فإذا كان لديك عدد كبير من المستخدمين أو التطبيقات فارفعه بملف ini إضافي تربطه داخل `/usr/local/etc/php/conf.d/`.

ونصيحة أخيرة في الأداء جاءت من المختبر نفسه: كل مستخدم جديد حصل على ملفات أمثلة Skeleton Files حجمها قرابة 60 ميجابايت من صور وفيديو وملفات PDF، فإذا كان لديك مئات المستخدمين فهذه مساحة ضائعة في القرص وفي النسخ الاحتياطي، ويمكنك إيقافها بجعل الإعداد `skeletondirectory` فارغاً كما في [قائمة إعدادات config.php](https://docs.nextcloud.com/server/35/admin%5Fmanual/configuration%5Fserver/config%5Fsample%5Fphp%5Fparameters.html?ref=arabroot.io):

```bash
docker compose exec -u www-data app php occ config:system:set skeletondirectory --value=''
```

## المستخدمون والمجموعات والمشاركة

لنفرض أن لديك فريقاً مالياً يحتاج مجلد سياسات يقرؤه ولا يعدله، وموظفاً من خارج الفريق لا يجب أن يراه أصلاً. نبدأ بإنشاء المجموعة والمستخدمين من سطر الأوامر، وكلمة المرور تمر عبر متغير بيئة Environment Variable حتى لا تظهر في سجل الأوامر:

```bash
docker compose exec -u www-data app php occ group:add finance
docker compose exec -u www-data -e OC_PASS="$ALICE_PASS" app php occ user:add --password-from-env --display-name="Alice" --group=finance alice
docker compose exec -u www-data -e OC_PASS="$BOB_PASS" app php occ user:add --password-from-env --display-name="Bob" bob
```

```text
Created group "finance"
The account "alice" was created successfully
Display name set to "Alice"
Account "alice" added to group "finance"
The account "bob" was created successfully
Display name set to "Bob"
```

ثم ينشئ المدير المجلد `Policies` ويشاركه مع المجموعة `finance` بصلاحية القراءة فقط عبر [واجهة المشاركة OCS Share API](https://docs.nextcloud.com/server/35/developer%5Fmanual/client%5Fapis/OCS/ocs-share-api.html?ref=arabroot.io)، وهي نفس الواجهة التي تستخدمها الواجهة الرسومية:

```bash
curl -s -u admin:"$ADMIN_PASS" -H "OCS-APIRequest: true" -H "Accept: application/json" \
  -X POST https://cloud.example.com/ocs/v2.php/apps/files_sharing/api/v1/shares \
  -d path=/Policies -d shareType=1 -d shareWith=finance -d permissions=1
```

```text
200 {'id': '1', 'share_type': 1, 'share_with': 'finance', 'permissions': 1, 'path': '/Policies'}
```

والقيمة `shareType=1` تعني المشاركة مع مجموعة، و`permissions` رقم يجمع الصلاحيات كما في الجدول التالي:

| الصلاحية             | القيمة |
| -------------------- | ------ |
| القراءة Read         | 1      |
| التعديل Update       | 2      |
| الإنشاء Create       | 4      |
| الحذف Delete         | 8      |
| إعادة المشاركة Share | 16     |
| كل الصلاحيات         | 31     |

والآن نختبر ما يحدث فعلاً: Alice من المجموعة تقرأ الملف، ثم تحاول أن تكتب عليه، ثم يحاول Bob الذي ليس في المجموعة أن يقرأه:

```bash
curl -s -u alice:"$ALICE_PASS" https://cloud.example.com/remote.php/dav/files/alice/Policies/leave-policy.txt
curl -s -o /dev/null -w "alice write: %{http_code}\n" -u alice:"$ALICE_PASS" -T edit.txt \
  https://cloud.example.com/remote.php/dav/files/alice/Policies/leave-policy.txt
curl -s -o /dev/null -w "bob read: %{http_code}\n" -u bob:"$BOB_PASS" \
  https://cloud.example.com/remote.php/dav/files/bob/Policies/leave-policy.txt
```

```text
Leave policy v1
alice write: 403
bob read: 404
```

لاحظ أن Bob حصل على 404 وليس 403، أي أن Nextcloud لا يخبره حتى بوجود المجلد، وهذا هو السلوك الصحيح، والسبب أن الرد 403 كان سيكشف له أن هناك ملفاً بهذا الاسم لا يملك صلاحيته.

### رابط عام بكلمة مرور وتاريخ انتهاء

وتحتاج Alice أن ترسل التقرير السنوي لمراجع حسابات من خارج الشركة، والطريقة البسيطة هي رابط عام Public Link بلا حماية، وهذه الطريقة تعني أن أي شخص يصل إليه الرابط في بريد معاد توجيهه أو في سجل محادثة يستطيع فتح الملف إلى الأبد، ولذلك فالطريقة الأنسب هي رابط بكلمة مرور وتاريخ انتهاء. و`shareType=3` تعني رابطاً عاماً، ومسار الملف العربي نرسله بترميز URL Encoding:

```bash
enc() { python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1]))' "$1"; }
curl -s -u alice:"$ALICE_PASS" -H "OCS-APIRequest: true" -H "Accept: application/json" \
  -X POST https://cloud.example.com/ocs/v2.php/apps/files_sharing/api/v1/shares \
  -d "path=$(enc '/المالية/التقرير-السنوي-2026.txt')" -d shareType=3 -d permissions=1 \
  -d password="$LINK_PASS" -d expireDate=2026-10-16
```

والمخرج JSON طويل، وهذه أهم حقوله:

```text
"id":"3","share_type":3,"permissions":17,"expiration":"2026-10-16 23:59:59","token":"yswSx2pf7wCnHoD",
"password":"redacted","url":"http:\/\/127.0.0.1:28480\/s\/yswSx2pf7wCnHoD"
```

لاحظ أن الصلاحية أصبحت 17 وليست 1، أي القراءة مع إعادة المشاركة، وأن كلمة المرور لا تعود في الرد وإنما تظهر كلمة `redacted`. ثم نجرب الرابط من خارج الحساب بلا كلمة مرور، وبكلمة المرور الصحيحة، وبكلمة خاطئة:

```text
no password: 401
الإيرادات: 1,250,000 ريال
with password: 200
wrong password: 401
```

والصورتان التاليتان تبينان المشاركة في الواجهة: لوحة المشاركة الجانبية للملف، ثم الصفحة التي يراها من يفتح الرابط:

![واجهة الملفات في Nextcloud باللغة العربية، مجلد المالية فيه ملفان، واللوحة الجانبية للملف التقرير السنوي مفتوحة على تبويب المشاركة وفيها مشاركات داخلية ورابط داخلي ومشاركات خارجية ورابط مشاركة للعرض فقط](https://arabroot.io/content/images/2026/10/nextcloud-04-share-sidebar.webp)

لوحة المشاركة للملف، والرابط العام فيها للعرض فقط

![صفحة الرابط العام في Nextcloud بعنوان هذه المشاركة محمية بكلمة مرور، وفيها حقل كلمة المرور وزر إرسال](https://arabroot.io/content/images/2026/10/nextcloud-05-public-link.webp)

ما يراه المراجع الخارجي عند فتح الرابط

## تطبيقات الحاسوب والهاتف: كيف تتصل؟

لتطبيق Nextcloud على الحاسوب [Desktop Client](https://github.com/nextcloud/desktop?ref=arabroot.io) لأنظمة Windows وmacOS وLinux، وآخر إصدار منه وقت كتابة المقال هو v34.0.5، ويزامن مجلداً على جهازك مع حسابك عبر WebDAV، ويدعم الملفات الافتراضية Virtual Files كما في [دليل الاستخدام](https://docs.nextcloud.com/server/35/user%5Fmanual/en/desktop/usage.html?ref=arabroot.io)، أي أن الملفات تظهر في المستكشف بأسمائها دون أن تنزل فعلاً حتى تفتحها، وهذا مهم إذا كان حجم ملفات الفريق أكبر من قرص الحاسوب. وعلى الهاتف تطبيق للملفات، وأما التقويم وجهات الاتصال فيمر عبر CalDAV وCardDAV كما سيأتي.

والسؤال المهم هنا أمني: هل يحفظ التطبيق كلمة مرور حسابك؟ الإجابة لا، والسبب أن التطبيقات تستخدم [Login Flow v2](https://docs.nextcloud.com/server/35/developer%5Fmanual/client%5Fapis/LoginFlow/index.html?ref=arabroot.io) الذي يعطي كل جهاز كلمة مرور خاصة به App Password، والصورة التالية تبين خطواته:

![مخطط Login Flow v2 في خمس خطوات: تطبيق الحاسوب يطلب POST إلى index.php/login/v2 ويحصل على رابط دخول ورمز استطلاع صالح عشرين دقيقة، ثم يفتح الرابط في المتصفح، ويطلب POST إلى login/v2/poll مرة بعد مرة، ويسجل المستخدم دخوله في المتصفح ويضغط Grant access، فيعيد السيرفر اسم الدخول وكلمة مرور خاصة بالجهاز، ثم يزامن التطبيق عبر WebDAV بها](https://arabroot.io/content/images/2026/10/nextcloud-06-login-flow.webp)

كل جهاز يحصل على كلمة مرور خاصة به، وكلمة مرور الحساب لا تخرج من المتصفح

وقد نفذنا الخطوات بأنفسنا بالأمر curl كما يفعل التطبيق تماماً، فالطلب الأول يعطينا رابط الدخول ورمز الاستطلاع Poll Token:

```bash
curl -s -X POST -A "Nextcloud desktop (lab)" https://cloud.example.com/index.php/login/v2
```

```text
{"poll":{"token":"YaSbmBGshWlrO862Hz3FlN6AO2PG53Lue7LRvy73hIWjU9QyG5fODegjegZPoJ9e9ONo51DSBe4eyEOgG87FZVFTQq38KOwIEsjNZfK6IaKHm4RJ3Bon5JAaAw0B50Km","endpoint":"http:\/\/127.0.0.1:28480\/login\/v2\/poll"},"login":"http:\/\/127.0.0.1:28480\/login\/v2\/flow\/1bCoE2moa9N9bKZCC4nTHnZFwnOaubTqGDl8EXQGQ0Vcl1kvoMnva2xCUNBgB3gUqLiVKvWsMUj1ztx1AJuWOPLa21z3udJNS5skq7jDmSvi9KqSgKfbyR13irbrUCUy"}
```

ثم فتحنا رابط `login` في المتصفح، ودخل Bob بكلمة مروره، فظهرت له صفحة تطلب الموافقة، ولاحظ أنها تذكر اسم التطبيق كما أرسله في الترويسة User-Agent:

![صفحة Account access في Nextcloud تقول Currently logged in as Bob وأنك على وشك منح Nextcloud desktop (lab) الوصول إلى حسابك، مع زر Grant access](https://arabroot.io/content/images/2026/10/nextcloud-07-login-flow.webp)

المستخدم يرى اسم التطبيق الذي يطلب الوصول قبل أن يوافق

وبعد الضغط على Grant access أعاد طلب الاستطلاع كلمة المرور الخاصة بالجهاز، وقد أخفينا أولها هنا:

```bash
curl -s -X POST https://cloud.example.com/login/v2/poll -d "token=$POLL_TOKEN"
```

```text
{"server":"http:\/\/127.0.0.1:28480","loginName":"bob","appPassword":"XXXXXXLTBG7Fnb6W05lIZ3e9G1lzAeUvE6NtuqBTZZF2qplvOthz7RQ365nfdFpk7pWFMIFZ"}
```

والفائدة الحقيقية تظهر عندما يضيع حاسوب أحد الموظفين، فأنت لا تغير كلمة مروره ولا تخرجه من بقية أجهزته، وإنما تلغي كلمة مرور ذلك الجهاز وحده. وقد نفذنا ذلك في المختبر بكلمة مرور جهاز أنشأناها لحساب Bob باسم `bob-laptop (lab)`:

```bash
docker compose exec -u www-data app php occ user:auth-tokens:list bob
docker compose exec -u www-data app php occ user:auth-tokens:delete bob 12
```

```text
| 12 | bob-laptop (lab) | 2026-10-09T00:38:55+00:00 | permanent | filesystem |
PROPFIND with app password: 207
PROPFIND after revoke: 401
```

أي أن نفس الطلب بنفس كلمة مرور الجهاز نجح قبل الإلغاء بالرمز 207، ورفض بعده بالرمز 401.

## التقويم وجهات الاتصال

شرحنا البروتوكولين CalDAV وCardDAV وكيف تتزامن الأجهزة بهما في [مقال التقويم وجهات الاتصال](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D9%82%D9%88%D9%8A%D9%85-%D9%88%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-caldav-%D9%88-carddav/)، فلن نكرر ذلك هنا، والذي يخص Nextcloud أن الخادم Server لهذين البروتوكولين مدمج فيه، وأما الواجهة فتأتي من تطبيقين تثبتهما من متجر التطبيقات App Store:

```bash
docker compose exec -u www-data app php occ app:install calendar
docker compose exec -u www-data app php occ app:install contacts
```

```text
calendar 6.6.2 installed
calendar enabled
contacts 8.9.1 installed
contacts enabled
```

ثم أنشأنا تقويماً لـ Alice باسم `finance`، ورفعنا إليه موعداً عربياً بملف iCalendar عبر الطلب PUT كما يفعل أي هاتف:

```bash
docker compose exec -u www-data app php occ dav:create-calendar alice finance
curl -s -o /dev/null -w "PUT event %{http_code}\n" -u alice:"$ALICE_PASS" -T ev.ics \
  -H "Content-Type: text/calendar; charset=utf-8" \
  https://cloud.example.com/remote.php/dav/calendars/alice/finance/budget-review.ics
curl -s -o /dev/null -w "well-known caldav: %{http_code} -> %{redirect_url}\n" https://cloud.example.com/.well-known/caldav
```

```text
PUT event 201
well-known caldav: 301 -> http://127.0.0.1:28480/remote.php/dav/
```

والملف `ev.ics` فيه موعد يوم 12 أكتوبر 2026 الساعة 10:00 بتوقيت `Asia/Riyadh` بعنوان «مراجعة ميزانية الربع الرابع»، وبنفس الطريقة أضفنا جهة اتصال عربية بملف vCard إلى المسار `addressbooks/users/alice/contacts/`. والصورتان التاليتان تبينان النتيجة في الواجهة العربية:

![تطبيق التقويم في Nextcloud باللغة العربية بعرض الأسبوع 42 من 2026، والموعد مراجعة ميزانية الربع يوم الإثنين 12 أكتوبر من 10:00 إلى 11:00، والأرقام بالأرقام الهندية، وفي القائمة الجانبية تقاويم خاص وأعياد ميلاد جهات الاتصال وfinance مع عبارات إنجليزية لم تترجم مثل My calendars وMeeting proposals](https://arabroot.io/content/images/2026/10/nextcloud-08-calendar.webp)

الموعد الذي رفعناه عبر CalDAV يظهر في التقويم، مع عبارات لم تترجم بعد

![تطبيق جهات الاتصال في Nextcloud باللغة العربية يعرض جهة الاتصال سارة المحاسبة من الإدارة المالية برقم هاتف وبريد عمل، وفي القائمة دفاتر العناوين وجهات الاتصال والحسابات](https://arabroot.io/content/images/2026/10/nextcloud-09-contacts.webp)

جهة الاتصال التي رفعناها عبر CardDAV كما تظهر في تطبيق جهات الاتصال

وإذا كان الفريق يحتاج تحرير ملفات Word وExcel داخل المتصفح فهذا يحتاج محرراً منفصلاً تربطه بـ Nextcloud، وقد قارنا الخيارين في [مقال Collabora Online أم ONLYOFFICE](https://arabroot.io/articles/collabora-online-%D8%A7%D9%85-onlyoffice/).

## العربية والاتجاه من اليمين لليسار RTL: تجربة صادقة

ضبطنا لغة Alice بالأمر `occ user:setting alice core lang ar` ومنطقتها بالأمر `occ user:setting alice core locale ar_SA`، ثم فتحنا الواجهة ودققنا في كل صفحة، والصورة التالية تبين مجلد الملفات:

![واجهة الملفات في Nextcloud باللغة العربية من اليمين لليسار، مجلد المالية فيه ملفا إقرار ضريبي والتقرير السنوي 2026، والقائمة الجانبية بالعربية مع عبارات إنجليزية مثل Folder tree وSearch here في مربع البحث](https://arabroot.io/content/images/2026/10/nextcloud-10-files-rtl.webp)

الواجهة من اليمين لليسار، مع عبارات قليلة لم تترجم

وهذه النتيجة كما وجدناها، ما يعمل وما لا يعمل:

- **الاتجاه سليم**: القوائم والأزرار والجداول تنقلب من اليمين لليسار بشكل صحيح، والأسماء العربية للمجلدات والملفات تحفظ وتعرض دون مشاكل، وحتى مجلد القوالب Templates أنشأه Nextcloud لـ Alice باسم «القوالب» لأن لغتها العربية.
- **الترجمة شبه كاملة**: أغلب الواجهة بالعربية، ولكن بقيت عبارات إنجليزية مثل My calendars وMeeting proposals في التقويم وFolder tree وSearch here في الملفات وApps, files, messages, and more في البحث العام، والسبب أنها عبارات جديدة لم يترجمها المتطوعون بعد.
- **الأرقام**: مع المنطقة `ar_SA` تظهر التواريخ والساعات في التقويم بالأرقام الهندية (١٢/١٠/٢٠٢٦)، وإذا كان فريقك يفضل الأرقام العربية الغربية فاختر منطقة أخرى من إعدادات المستخدم.
- **البحث في أسماء الملفات لا يوحد الهمزات**: بحثنا عبر واجهة البحث عن «تقرير» فوجدنا الملف، وعن «إقرار» فوجدنا الملف، ولكن البحث عن «اقرار» دون همزة أعاد صفر نتائج، وهذا مهم لأن كثيراً من الناس يكتبون دون همزات.
- **معاينة الملف النصي تفصل الحروف**: الصورة المصغرة Preview التي يولدها Nextcloud لملف نصي عربي تعرض الحروف منفصلة غير متصلة، كما تراها في أعلى لوحة المشاركة في الصورة السابقة، وأما فتح الملف نفسه فيعرض النص سليماً.
- **زر الدخول الموحد**: النص «تسجيل الدخول بـ authentik» يظهر بترتيب مقلوب لأن اسم المزود إنجليزي في نهاية جملة عربية، كما سترى في صورة قسم الدخول الموحد، وهذه مشكلة اتجاه نص Bidi وليست مشكلة ترجمة.

```text
== تقرير
1 ['التقرير-السنوي-2026.txt']
== اقرار
0 []
== إقرار
1 ['إقرار-ضريبي.txt']
```

والمخرج أعلاه من واجهة البحث `/ocs/v2.php/search/providers/files/search?term=`، والخلاصة أن العربية في Nextcloud صالحة للعمل اليومي، ولكن علم فريقك أن يبحث بالهمزة كما كتبت في اسم الملف، أو اتفق معهم على تسمية الملفات دون همزات.

## الدخول الموحد SSO مع authentik

إذا كان لديك [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/) يدير حسابات الشركة، فالأنسب أن يدخل الموظفون إلى Nextcloud بنفس الحساب، فإذا غادر أحدهم الشركة توقف حسابه في مكان واحد. والربط يتم عبر OpenID Connect الذي شرحناه في [مقال OAuth وOpenID Connect](https://arabroot.io/articles/%D8%B4%D8%B1%D8%AD-oauth-%D9%88-openid-connect-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/)، وفي Nextcloud يقوم بذلك التطبيق الرسمي [user\_oidc](https://apps.nextcloud.com/apps/user%5Foidc?ref=arabroot.io).

### الإعداد في authentik

أنشئ في authentik تطبيقاً Application ومزوداً Provider من نوع OAuth2/OpenID بنفس الخطوات التي شرحناها في [دليل ربط Gitea مع authentik](https://arabroot.io/articles/%D8%B1%D8%A8%D8%B7-gitea-%D9%85%D8%B9-authentik-%D8%B9%D8%A8%D8%B1-oidc/#provider)، مع هذه القيم:

- نوع العميل Client Type هو Confidential، والمعرف Client ID هو `nextcloud`.
- رابط العودة Redirect URI هو `https://cloud.example.com/apps/user_oidc/code` بمطابقة تامة Strict.
- النطاقات Scopes هي `openid` و`email` و`profile`، ونوع الدخول Grant Types يشمل `authorization_code`.
- معرف المستخدم Subject مبني على اسم المستخدم، حتى يكون اسم الحساب في Nextcloud مفهوماً وليس رقماً طويلاً.

### الإعداد في Nextcloud

```bash
docker compose exec -u www-data app php occ app:install user_oidc
docker compose exec -u www-data -e OIDC_SECRET="$OIDC_SECRET" app php occ user_oidc:provider authentik \
  --clientid=nextcloud --clientsecret-env=OIDC_SECRET \
  --discoveryuri=https://auth.example.com/application/o/nextcloud/.well-known/openid-configuration \
  --unique-uid=0 --mapping-uid=preferred_username
docker compose exec -u www-data app php occ user_oidc:provider
```

```text
Client secret loaded from environment variable "OIDC_SECRET"
+----+------------+---------------------------------------------------------------------------------+----------------------+-----------+
| ID | Identifier | Discovery endpoint                                                              | End session endpoint | Client ID |
+----+------------+---------------------------------------------------------------------------------+----------------------+-----------+
| 1  | authentik  | http://127.0.0.1:28490/application/o/nextcloud/.well-known/openid-configuration |                      | nextcloud |
+----+------------+---------------------------------------------------------------------------------+----------------------+-----------+
```

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

- `--clientsecret-env` يقرأ السر من متغير بيئة بدل أن تكتبه في سطر الأوامر فيبقى في سجل الـ Shell.
- `--unique-uid=0` مع `--mapping-uid=preferred_username` يجعل اسم الحساب في Nextcloud هو اسم المستخدم في authentik نفسه، والقيمة الافتراضية 1 تجعل الاسم هاشاً لا يقرؤه أحد.
- يبقى الدخول بكلمة المرور المحلية متاحاً بجانب زر authentik، وهذا مفيد لحساب المدير إذا تعطل authentik، فإذا أردت أن يدخل الجميع عبر authentik وحده فاجعل الإعداد `allow_multiple_user_backends` في التطبيق `user_oidc` بالقيمة 0.

### ثلاثة أخطاء ظهرت لنا قبل أن ينجح الدخول

لم ينجح الدخول من المرة الأولى، وكل خطأ منها قد يقابلك على سيرفرك:

1. **«You must access Nextcloud with HTTPS to use OpenID Connect.»**: التطبيق `user_oidc` يرفض العمل عبر HTTP، وهذا صحيح في الإنتاج، وعلى سيرفرك مع HTTPS لن ترى الرسالة. وفي المختبر المحلي فقط سمحنا بـ HTTP بالإعداد `occ config:app:set user_oidc allow_insecure_http --value=1 --type=boolean --lazy`، فلا تقم بذلك على سيرفر حقيقي.
2. **«Could not reach the OpenID Connect provider»**: وفي سجل Nextcloud كان السبب الحقيقي `Host "127.0.0.1" violates local access rules`، والسبب أن Nextcloud يمنع افتراضياً الاتصال بالسيرفرات ذات العناوين المحلية كما في [قائمة إعدادات config.php](https://docs.nextcloud.com/server/35/admin%5Fmanual/configuration%5Fserver/config%5Fsample%5Fphp%5Fparameters.html?ref=arabroot.io)، حتى لا يستخدمه أحد للوصول إلى خدمات داخلية في شبكتك، فإذا كان authentik على نفس السيرفر أو في شبكة داخلية فسوف تحتاج `occ config:system:set allow_local_remote_servers --value=true --type=boolean`، وهذا يفتح الاتصال بكل العناوين الداخلية فقرره وأنت تعرف ذلك.
3. **«The request is otherwise malformed»**: جاءت من authentik، وفي سجله السبب `Invalid grant_type for provider`، فقد أنشأنا المزود عبر واجهة API في authentik فبقي الحقل `grant_types` فارغاً، وبعد إضافة `authorization_code` و`refresh_token` نجح الدخول.

والصور التالية تبين الدخول بعد الإصلاح: زر authentik في صفحة الدخول، ثم صفحة authentik التي تقول إنك تدخل إلى Nextcloud، ثم الصفحة الرئيسية لحساب Sara الذي أنشأه Nextcloud تلقائياً عند أول دخول:

![صفحة تسجيل الدخول إلى Nextcloud بالعربية فيها حقلا اسم الحساب وكلمة المرور وزر تسجيل الدخول، وفي الأسفل زر authentik تسجيل الدخول بـ يظهر بترتيب مقلوب](https://arabroot.io/content/images/2026/10/nextcloud-11-sso-login.webp)

زر الدخول عبر authentik أسفل الدخول المحلي، ونصه مقلوب الترتيب

![صفحة دخول authentik تقول Welcome to authentik وLog in to continue to Nextcloud مع حقل البريد الإلكتروني أو اسم المستخدم بالعربية وزر تسجيل الدخول](https://arabroot.io/content/images/2026/10/nextcloud-12-authentik.webp)

authentik يطلب اسم المستخدم ويذكر التطبيق الذي ستدخل إليه

![الصفحة الرئيسية في Nextcloud بالعربية تقول أهلاً Sara مع لوحتي الأحداث القادمة والملفات الموصى بها](https://arabroot.io/content/images/2026/10/nextcloud-13-sso-dashboard.webp)

حساب Sara أنشئ تلقائياً عند أول دخول، بلغة المتصفح العربية

وللتأكد من جهة السيرفر:

```bash
docker compose exec -u www-data app php occ user:info sara
```

```text
  - user_id: sara
  - display_name: Sara
  - email: sara@example.com
  - enabled: true
  - first_seen: 2026-10-09T00:12:24+00:00
  - backend: user_oidc
```

لاحظ أن `backend` هو `user_oidc`، أي أن هذا الحساب لا يملك كلمة مرور في Nextcloud أصلاً. وقد يتساءل البعض: كيف يدخل تطبيق الحاسوب إذن؟ والإجابة أن Login Flow v2 الذي رأيناه يفتح المتصفح، والمتصفح يمر على authentik كأي دخول عادي، ثم يحصل التطبيق على كلمة مرور الجهاز كما سبق.

## التشفير: SSE أم E2EE؟

في Nextcloud نوعان من التشفير يخلط الناس بينهما كثيراً، ويضع [توثيق التشفير من جهة السيرفر](https://docs.nextcloud.com/server/35/admin%5Fmanual/configuration%5Ffiles/encryption%5Fconfiguration.html?ref=arabroot.io) جدولاً واضحاً للفرق، والصورة التالية تلخصه مع ما رأيناه في المختبر:

![مخطط من جزأين: على اليمين التشفير من جهة السيرفر SSE حيث يصل الملف مقروءاً عبر TLS ويشفره السيرفر بمفاتيح يحتفظ بها، وعلى القرص يظهر الملف salaries-october.txt بترويسة HBEGIN وAES-256-CTR وحجمه 8320 بايت بدل 32، ومزاياه حماية التخزين الخارجي وبقاء كل الميزات، وعيوبه أن المدير والمخترق على السيرفر يقرآن الملفات وأن الأسماء تبقى مكشوفة، وعلى اليسار التشفير من طرف إلى طرف E2EE حيث يشفر الجهاز قبل الرفع ولا يخزن السيرفر إلا ما لا يستطيع قراءته، والمجلد يحدد مشفراً من تطبيق الحاسوب أو الهاتف ويجب أن يكون فارغاً، وعيوبه أن الويب للعرض والتنزيل فقط وأن التقويم وجهات الاتصال غير مشمولة](https://arabroot.io/content/images/2026/10/nextcloud-14-encryption.webp)

SSE يحمي البيانات من مزود التخزين، وE2EE يحميها من السيرفر نفسه

### التشفير من جهة السيرفر SSE كما رأيناه على القرص

فعلنا التشفير بالمفتاح الرئيسي Master Key، وهو الوضع الافتراضي الذي يوصي به التوثيق لأغلب الحالات:

```bash
docker compose exec -u www-data app php occ app:enable encryption
docker compose exec -u www-data app php occ encryption:enable
docker compose exec -u www-data app php occ encryption:status
```

```text
encryption 3.0.0-dev.0 enabled
Encryption enabled

Default module: OC_DEFAULT_MODULE
  - enabled: true
  - defaultModule: OC_DEFAULT_MODULE
```

ثم رفع Bob ملفاً نصياً حجمه 32 بايت باسم `salaries-october.txt`، ونظرنا إليه على القرص مباشرة:

```bash
docker compose exec app sh -c 'ls -la /var/www/html/data/bob/files/ | grep salaries; head -c 120 /var/www/html/data/bob/files/salaries-october.txt'
```

```text
-rw-r--r-- 1 www-data www-data     8320 Oct  9 00:32 salaries-october.txt
HBEGIN:oc_encryption_module:OC_DEFAULT_MODULE:cipher:AES-256-CTR:signed:true:useLegacyFileKey:false:encoding:binary:HEND
```

في المخرج أعلاه لاحظ التالي:

- المحتوى مشفر بـ AES-256-CTR مع توقيع، فمن يسرق نسخة من القرص لا يقرأ الرواتب.
- اسم الملف `salaries-october.txt` مكشوف تماماً، وهذا ما يقوله التوثيق: SSE يشفر المحتوى فقط ولا يشفر أسماء الملفات والمجلدات.
- الملف الذي حجمه 32 بايت أصبح 8320 بايت على القرص، فللملفات الصغيرة حجم إضافي ثابت، وأما الملفات الكبيرة فالزيادة فيها صغيرة نسبياً.
- الملفات التي كانت موجودة قبل التفعيل بقيت كما هي غير مشفرة، فقد قرأنا ملف `leave-policy.txt` القديم من القرص كنص عادي، ولتشفيرها تحتاج الأمر `occ encryption:encrypt-all`.
- عندما طلب Bob الملف عبر WebDAV حصل عليه مقروءاً، والسبب أن السيرفر يفك التشفير بنفسه، وهذا يعني أن مدير السيرفر، ومن يخترق السيرفر، يستطيع قراءة الملفات أيضاً.

ولذلك يقول التوثيق إن الهدف الأساسي من SSE هو حماية الملفات على تخزين خارجي External Storage مثل S3 أو SMB لا تثق بمزوده، وإن التخزين المحلي تحميه أدوات تشفير القرص مثل LUKS بشكل أفضل، لأنها تحمي من سرقة القرص دون أن تكلفك أي ميزة. وانتبه لأمرين قبل التفعيل: الأول أن ضياع المفاتيح في `data/files_encryption` أو قيمة `secret` في `config.php` يعني ضياع الملفات نهائياً، فهي جزء من النسخة الاحتياطية، والثاني أن وضع مفاتيح المستخدمين User Keys لا يعمل مع الدخول الموحد ولا مع كلمات مرور الأجهزة كما يذكر التوثيق، فإذا كنت تستخدم authentik فابق على المفتاح الرئيسي.

⚠️

لا يمكن إيقاف SSE من الواجهة بعد تفعيله، والطريقة الوحيدة هي الأمر `occ encryption:decrypt-all` الذي يفك تشفير كل الملفات، فلا تقم بتفعيله على سيرفر فيه بيانات حقيقية قبل أن تجربه على نسخة، وقبل أن تنسخ المفاتيح احتياطياً.

### التشفير من طرف إلى طرف E2EE

إذا كان المطلوب ألا يقرأ مدير السيرفر نفسه ملفات قسم معين، مثل ملفات الموارد البشرية، فهذا هو E2EE من التطبيق [end\_to\_end\_encryption](https://github.com/nextcloud/end%5Fto%5Fend%5Fencryption?ref=arabroot.io)، وفيه يشفر تطبيق الحاسوب أو الهاتف الملف قبل رفعه، فلا يصل إلى السيرفر إلا ما لا يستطيع قراءته. ولكن له ثمن واضح يذكره التوثيق: تحدد المجلد مشفراً من تطبيق الحاسوب أو الهاتف ويجب أن يكون فارغاً، وفي واجهة الويب تستطيع فقط عرض الملفات المشفرة وتنزيلها دون تحريرها، والتشفير يشمل الملفات فقط وليس التقويم وجهات الاتصال، وكل أجهزة المستخدم يجب أن تستخدم نفس العبارة السرية Mnemonic. ولذلك لا تجعله افتراضياً للجميع، وإنما للمجلدات الحساسة فقط.

## فحص الأمان وتقوية السيرفر

بعد أن يصبح السيرفر متاحاً على الإنترنت بنطاقه، افتح [Nextcloud Security Scan](https://scan.nextcloud.com/?ref=arabroot.io) واكتب النطاق، فيفحص من الخارج إصدار Nextcloud والترويسات الأمنية وبعض الإعدادات المعروفة ويعطيك تقييماً، ولم نستطع تشغيله على المختبر لأنه على `127.0.0.1` ولا يصل إليه الفحص الخارجي، ولذلك اعتمدنا على `occ setupchecks` الذي يغطي الجزء الداخلي. ومع الفحصين راجع [دليل تقوية السيرفر](https://docs.nextcloud.com/server/35/admin%5Fmanual/installation/harden%5Fserver.html?ref=arabroot.io)، وأهم ما فيه:

- اجعل المصادقة الثنائية Two-factor Authentication إلزامية للمدير على الأقل، وقد ذكرها الفحص في المختبر بأنها متاحة وغير مفروضة.
- تأكد أن مجلد البيانات غير متاح من الويب، وهذا ما يفحصه السطر `Data directory protected`.
- أبق حماية تخمين كلمات المرور Brute-force Protection مفعلة، ولذلك تحتاج `TRUSTED_PROXIES` صحيحاً كما ذكرنا، حتى يرى Nextcloud عنوان المهاجم وليس عنوان Caddy.
- حدث Nextcloud وتطبيقاته بانتظام، فالفحص الخارجي يعطي تقييماً منخفضاً لأي إصدار فيه ثغرات معروفة.

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

تطبيق المزامنة ليس نسخة احتياطية، فهو ينقل الحذف الخاطئ إلى كل الأجهزة كما ينقل التعديل الصحيح، وقد شرحنا القاعدة العامة في [دليل النسخ الاحتياطي بقاعدة 3-2-1](https://arabroot.io/articles/%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-3-2-1-%D9%88%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D8%A7%D8%AF%D8%A9/). وفي Nextcloud يذكر [توثيق النسخ الاحتياطي](https://docs.nextcloud.com/server/35/admin%5Fmanual/maintenance/backup.html?ref=arabroot.io) أربعة أشياء تنسخها معاً: مجلد الإعدادات `config`، ومجلد البيانات `data`، ومجلد السمات `themes`، وقاعدة البيانات، مع تفعيل وضع الصيانة Maintenance Mode أثناء النسخ، والسبب أن نسخ قاعدة البيانات والملفات في لحظتين مختلفتين بينما المستخدمون يرفعون الملفات قد يعطيك قاعدة تشير إلى ملفات غير موجودة في النسخة:

```bash
mkdir -p backup
docker compose exec -u www-data app php occ maintenance:mode --on
docker compose exec -T db pg_dump -U nextcloud -Fc nextcloud > backup/nextcloud-db.dump
docker compose exec -T app tar czf - -C /var/www/html config data themes > backup/nextcloud-files.tar.gz
docker compose exec -u www-data app php occ maintenance:mode --off
ls -la backup
```

```text
Maintenance mode enabled
Maintenance mode disabled
1530207 nextcloud-db.dump
313202393 nextcloud-files.tar.gz
```

واستغرق النسخ كله في المختبر دقيقتين ونصفاً، وهي المدة التي لا يستطيع فيها المستخدمون الوصول، ولذلك ضعه في المهام المجدولة في وقت متأخر من الليل، وإذا كبرت البيانات فانسخ مجلد `data` نسخاً تزايدياً بأداة مثل restic أو borg كما في [مقارنة أدوات النسخ الاحتياطي](https://arabroot.io/articles/restic-%D8%A3%D9%85-borg-%D8%A3%D9%85-kopia/). والنسخة التي لم تختبر استعادتها ليست نسخة، ولذلك استعدنا ملف قاعدة البيانات في قاعدة مؤقتة وقارنا عدد الملفات والمشاركات والمواعيد مع الأصل:

```bash
docker compose exec db createdb -U nextcloud restoretest
docker compose exec -T db pg_restore -U nextcloud -d restoretest --no-owner < backup/nextcloud-db.dump
for d in nextcloud restoretest; do
  echo "$d: $(docker compose exec db psql -U nextcloud -d $d -tAc "select (select count(*) from oc_filecache)||' files, '||(select count(*) from oc_share)||' shares, '||(select count(*) from oc_calendarobjects)||' events'")"
done
docker compose exec db dropdb -U nextcloud restoretest
```

```text
nextcloud: 337 files, 3 shares, 9 events
restoretest: 337 files, 3 shares, 9 events
```

والأرقام متطابقة. وخطوات الاستعادة الكاملة على سيرفر جديد في [توثيق الاستعادة](https://docs.nextcloud.com/server/35/admin%5Fmanual/maintenance/restore.html?ref=arabroot.io): تعيد المجلدات الثلاثة، ثم قاعدة البيانات، ثم تشغل `occ maintenance:data-fingerprint` حتى تعرف تطبيقات المزامنة أن البيانات استعيدت فلا تحذف ملفات جديدة من الأجهزة ظناً منها أنها حذفت من السيرفر.

## التحديث: إصدار رئيسي واحد في كل مرة

يقول [توثيق التحديث](https://docs.nextcloud.com/server/35/admin%5Fmanual/maintenance/upgrade.html?ref=arabroot.io) بوضوح إنك لا تستطيع تخطي الإصدارات الرئيسية Major Releases، وإنك تحدث إلى آخر إصدار فرعي في إصدارك الحالي ثم إلى الإصدار الرئيسي التالي، وإن الرجوع إلى إصدار أقدم Downgrade غير مدعوم وقد يتلف البيانات. ولكي نرى ذلك بأعيننا بدأنا المختبر نفسه بالإصدار 33.0.9، ثم غيرنا `NC_TAG` مباشرة إلى 35.0.1، والطريقة البسيطة هي أن تفعل هذا على سيرفرك وتنتظر، وهذا ما حدث:

```bash
sed -i 's/^NC_TAG=.*/NC_TAG=35.0.1-apache/' .env
docker compose up -d app cron
docker compose logs app
```

```text
Initializing nextcloud 35.0.1.1 ...
Can't start Nextcloud because upgrading from 33.0.9.1 to 35.0.1.1 is not supported.
It is only possible to upgrade one major version at a time. For example, if you want to upgrade from version 14 to 16, you will have to upgrade from version 14 to 15, then from 15 to 16.
```

ورفض الـ Container أن يعمل ودخل في حلقة إعادة التشغيل Restarting، وهذا من حسن الحظ لأن الفحص موجود في [نقطة دخول الـ Docker Image](https://github.com/nextcloud/docker/blob/master/docker-entrypoint.sh?ref=arabroot.io) قبل أن يلمس أي بيانات. والطريقة الصحيحة هي أن تأخذ نسخة احتياطية أولاً، ثم تمر على 34 قبل 35:

```bash
sed -i 's/^NC_TAG=.*/NC_TAG=34.0.4-apache/' .env
docker compose up -d app cron
docker compose logs -f app
```

```text
Initializing nextcloud 34.0.4.1 ...
Upgrading nextcloud from 33.0.9.1 ...
Setting log level to debug
Turned on maintenance mode
Updating database schema
Updated database
Updating <federation> ...
Updated <federation> to 1.24.0
...
Starting code integrity check...
Finished code integrity check
Update successful
Turned off maintenance mode
Resetting log level
```

وقبل الانتقال إلى الإصدار الرئيسي التالي يطلب التوثيق أن تنتظر انتهاء الترحيلات الخلفية Background Migrations بتشغيل `cron.php` مرتين أو ثلاثاً، والسبب أن بعض تغييرات قاعدة البيانات تجدول كمهام خلفية بعد التحديث، فإذا قفزت قبل أن تنتهي فقد تبدأ الترقية التالية على قاعدة لم تكتمل:

```bash
for i in 1 2 3; do docker compose exec -u www-data app php -f /var/www/html/cron.php; done
sed -i 's/^NC_TAG=.*/NC_TAG=35.0.1-apache/' .env
docker compose up -d app cron
```

```text
Initializing nextcloud 35.0.1.1 ...
Upgrading nextcloud from 34.0.4.1 ...
...
Update successful
Turned off maintenance mode
Resetting log level
The database schema does not match what is expected for the installed version:
  - missing table 'oc_federated_invites'
  - oc_taskprocessing_tasks: missing index 'taskp_status_type_upd'
Run "occ db:schema:check -v" for details.
```

واستغرقت الترقية من 34 إلى 35 قرابة دقيقة واحدة. ولاحظ الرسالة الأخيرة، فالفهرس الناقص يضيفه الأمر الذي يذكره التوثيق في خطوات ما بعد التحديث:

```bash
docker compose exec -u www-data app php occ db:add-missing-indices
docker compose exec -u www-data app php occ db:add-missing-columns
docker compose exec -u www-data app php occ db:add-missing-primary-keys
```

```text
Adding additional taskp_status_type_upd index to the oc_taskprocessing_tasks table, this can take some time...
oc_taskprocessing_tasks table updated successfully.
Done.
Done.
```

وأما الجدول `oc_federated_invites` فبقي في نتيجة `occ db:schema:check`، وقد بحثنا في كود التطبيق `cloud_federation_api` فوجدنا خطوة إصلاح باسم `DropFederatedInvitesTable` تحذف هذا الجدول عمداً إذا كان فارغاً، أي أن غيابه مقصود في هذا الإصدار، ولم يظهر في `occ setupchecks` أي تحذير عن قاعدة البيانات بعد إضافة الفهرس. وبعد كل تحديث شغل `occ setupchecks` مرة أخرى، ولا تحدث يوم الخميس قبل إجازتك.

💡

لاحظ أن الـ Docker Image للإصدار 33.0.9 جاءت بـ PHP 8.4.26، وأن 34.0.4 و35.0.1 جاءتا بـ PHP 8.5.11، فالتحديث الرئيسي يغير إصدار PHP أيضاً، وهذا سبب إضافي لتجربته على نسخة قبل الإنتاج إذا كان لديك تطبيقات من طرف ثالث.

## تدريب عملي

1. أنشئ مجلداً مشتركاً مع مجموعة بالصلاحية 5 (القراءة مع الإنشاء)، ثم جرب أن يرفع عضو من المجموعة ملفاً جديداً وأن يعدل ملفاً موجوداً، وفسر لماذا نجح أحدهما وفشل الآخر.
2. شغل Login Flow v2 بالأمر curl كما فعلنا، ثم الغ كلمة مرور الجهاز بالأمر `occ user:auth-tokens:delete`، وتأكد أن الطلب التالي يرد بالرمز 401.

## الخلاصة

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

- Nextcloud منصة برخصة AGPL-3.0 تجمع الملفات والتقويم وجهات الاتصال والمشاركة في سيرفر واحد، وهو الأنسب عندما يحتاج الفريق أكثر من مزامنة الملفات.
- التثبيت الجاد يحتاج PostgreSQL وRedis وContainer للمهام الخلفية بالطريقة Cron خلف Reverse Proxy، مع `TRUSTED_PROXIES` و`OVERWRITEPROTOCOL` صحيحين.
- APCu للذاكرة المحلية وRedis للذاكرة الموزعة وأقفال الملفات، وOPcache مع `save_comments=1`، و`occ setupchecks` يخبرك بما ينقص.
- الصلاحيات أرقام تجمعها، والروابط العامة تحتاج كلمة مرور وتاريخ انتهاء، وكل جهاز يحصل على كلمة مرور خاصة به تلغيها وحدها عند ضياعه.
- العربية صالحة للعمل اليومي مع عبارات لم تترجم، وبحث لا يوحد الهمزات، ومعاينات نصية تفصل الحروف.
- الدخول الموحد مع authentik يحتاج HTTPS، وقد يحتاج `allow_local_remote_servers` إذا كان authentik في شبكة داخلية.
- SSE يحمي التخزين الخارجي ولا يحميك من السيرفر نفسه، وE2EE يحميك من السيرفر بثمن في الميزات، وتشفير القرص يكفي للتخزين المحلي.
- انسخ الإعدادات والبيانات وقاعدة البيانات في وضع الصيانة، واختبر الاستعادة، وحدث إصداراً رئيسياً واحداً في كل مرة.

[![](https://arabroot.io/content/images/2026/10/seafile-cover-cover-1.webp)دليلSeafile: مزامنة ملفات فريقك ومشاركتها على سيرفرككيف تثبت Seafile على سيرفرك لتزامن ملفات فريقك وتشاركها بدل Dropbox وOneDrive، مع نسخة احتياطية تستطيع استعادتها.](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-seafile-%D9%84%D9%85%D8%B2%D8%A7%D9%85%D9%86%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA/)[![](https://arabroot.io/content/images/2026/10/authentik-cover-cover-1.webp)دليلتثبيت authentik للدخول الموحد 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/)[![](https://arabroot.io/content/images/2026/10/calendar-contacts-cover-cover.webp)دليلالتقويم وجهات الاتصال على سيرفرك مع CalDAV وCardDAVكيف تبقى مواعيدك وجهات اتصالك متطابقة بين الهاتف والحاسوب على سيرفرك، وما الذي يعمل مع Outlook وما الذي لا يعمل.](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D9%82%D9%88%D9%8A%D9%85-%D9%88%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-caldav-%D9%88-carddav/)[![](https://arabroot.io/content/images/2026/10/backup-321-cover-cover.webp)دليلالنسخ الاحتياطي بقاعدة 3-2-1 واختبار الاستعادةكيف تحدد كم بيانات تقبل أن تخسر، وتبني نسخاً لا يستطيع المخترق حذفها، وتتأكد أنك تستطيع استعادتها فعلاً.](https://arabroot.io/articles/%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%8A%D8%A7%D8%B7%D9%8A-%D8%A8%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-3-2-1-%D9%88%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D8%A7%D8%AF%D8%A9/)

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

- أكتوبر 2026: كتابة المقال، واختبار كل الخطوات على Docker Engine 29.8.0 مع Nextcloud 35.0.1 (nextcloud:35.0.1-apache) بعد الترقية من 33.0.9 عبر 34.0.4، وPostgreSQL 18.6 وRedis 8.10.2 وCaddy 2.11.7، والتطبيقات calendar 6.6.2 وcontacts 8.9.1 وuser\_oidc 8.11.0، وauthentik 2026.8.3.