Nextcloud على VPS: Docker وTLS والنسخ الاحتياطي
شغّل Nextcloud على VPS خاص بك بـ Docker Compose وPostgres وRedis ووكيل TLS عكسي، مع خطوات النسخ الاحتياطي والترقية التي تُبقي بياناتك قابلة للاستعادة.
ما الذي تبنيه فعلًا
سنشغّل في هذا الدليل Nextcloud على خادم VPS باستخدام Docker Compose، ونضع طبقة TLS من Let's Encrypt أمامه، ونأخذ نسخة احتياطية تُستعاد فعلًا عند الحاجة. أربع حاويات (containers) ووكيل واحد: صورة nextcloud الرسمية تستمع على الحلقة المحلية (loopback)، وPostgres يحمل كل قطعة من بيانات الملفات الوصفية (metadata)، وRedis يحمل أقفال الملفات، ونسخة ثانية من صورة Nextcloud لا تشغّل شيئًا سوى حلقة cron، وnginx على المضيف يُنهي TLS أمام كل ذلك. التثبيت نفسه يستغرق عشرين دقيقة، وهذا ليس الجزء المهم. قراران يُتَّخذان في الساعة الأولى يحسمان ما إذا كانت ملفاتك ستبقى موجودة بعد سنة: قاعدة بيانات حقيقية بدلًا من SQLite، ونسخة احتياطية تلتقط دليل البيانات وقاعدة البيانات وملف config.php كمجموعة واحدة متسقة.
يفترض هذا الدليل أن لديك Ubuntu 24.04 LTS أو Debian 13، وDocker Engine مع إضافة Compose v2 مثبَّتة من مستودع Docker نفسه، وسجل DNS من نوع A (وسجل AAAA أيضًا إن كان لديك IPv6) يشير مسبقًا من cloud.example.com إلى الخادم. كل هذا يحتاج إلى خادم تتحكم فيه أنت — فلا سبيل إلى إنهاء TLS وتفريغ قاعدة بيانات (database dump) على خدمة SaaS يملكها طرف آخر.
تحديد الحجم: ما الذي يستهلك الذاكرة فعلًا
تهيمن ثلاثة أشياء على استخدام Nextcloud للذاكرة، وليس أي منها هو «Nextcloud» بحد ذاته.
عمّال PHP (workers). صورة -apache تخدم كل طلب متزامن من عملية عامل تستضيف مفسِّر PHP. وقد ينمو كل عامل حتى PHP_MEMORY_LIMIT قبل أن يقتل PHP الطلب. أسوأ حالة لذاكرتك المقيمة هي تقريبًا عدد الطلبات المتزامنة × حد الذاكرة، وعميل المزامنة على سطح المكتب يفتح عدة اتصالات متوازية لكل مستخدم. التزامن (concurrency)، لا عدد المستخدمين، هو ما يحدد السقف.
قاعدة البيانات. يُنشئ Postgres عملية خلفية (backend) منفصلة (fork) لكل اتصال، ويبقي المخازن المؤقتة المشتركة (shared buffers) مقيمة في الذاكرة. مجموعة العمل الخاصة به تتضخم مع عدد الملفات، لا عدد البايتات: الجدول oc_filecache يحمل صفًّا لكل ملف ولكل مستخدم. مئة ألف ملف صغير تُشكِّل قاعدة بيانات أثقل من مئة ملف كبير.
توليد المعاينات (previews). توليد صورة مصغّرة (thumbnail) يفكّ ترميز الصورة المصدر في الذاكرة بدقتها الكاملة. أما معاينات الفيديو فتستدعي ffmpeg من خارج العملية. تنفيذ occ preview:generate-all يكرر ذلك الارتفاع الحاد في الاستهلاك مرة تلو الأخرى، تباعًا، وهو الطريقة الأكثر شيوعًا على الإطلاق لدفع خادم VPS صغير إلى براثن OOM killer.
Redis رخيص نسبيًّا. أما أي شيء تضيفه لاحقًا — Collabora، أو البحث في النص الكامل، أو ماسح مضاد للفيروسات — فهو خدمة مقيمة منفصلة لها بصمتها الخاصة في الذاكرة، ويجب أن تدخل في خطة تحديد الحجم لديك قبل أن تفعّلها.
الروافع المتاحة إن كانت ذاكرتك محدودة: اخفض PHP_MEMORY_LIMIT، وحدِّد سقفًا لـ preview_max_x / preview_max_y / preview_max_filesize_image، وقلِّص enabledPreviewProviders إلى الصيغ التي تتصفحها فعلًا، واضبط trashbin_retention_obligation وversions_retention_obligation حتى لا يتضخم دليل البيانات بصمت إلى أضعاف حجم ملفاتك. أضف ملف تبديل (swap). فالـ swap بطيء، لكن OOM kill في منتصف ترقية أسوأ منه.
لماذا يتعطل SQLite
يأتي Nextcloud بدعم SQLite، والصورة الرسمية تستخدمه عن طيب خاطر. لا تفعل ذلك. SQLite يسلسل الكتابات بقفل يشمل قاعدة البيانات كلها: كاتب واحد في كل مرة، للملف بأكمله. أما Nextcloud فيكتب باستمرار — أقفال ملفات، وصفوف نشاط، ومدخلات ذاكرة تخزين مؤقت (cache)، وحالة مهام — وعميل سطح مكتب واحد يزامن شجرة أدلة يصدر عددًا كبيرًا من الطلبات المتوازية. تحت هذا النمط تحصل على SQLSTATE[HY000]: General error: 5 database is locked وأخطاء HTTP 500، وتظهر هذه العلة بالضبط حين تبدأ نسختك في أن تصبح مفيدة.
التحويل لاحقًا ممكن عبر occ db:convert-type، لكنها عملية ترحيل طويلة وقائمة على مبدأ الكل أو لا شيء (all-or-nothing) على بيانات حية. ابدأ بـ Postgres أو MariaDB.
ملف Compose
ضع هذا في /srv/nextcloud/compose.yaml، مع الأسرار (secrets) في ملف .env مجاور بصلاحيات 600.
services:
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db:/var/lib/postgresql/data
environment:
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
app:
image: nextcloud:31-apache
restart: unless-stopped
depends_on: [db, redis]
ports:
- "127.0.0.1:8080:80"
volumes:
- html:/var/www/html
- /srv/nextcloud/data:/var/www/html/data
environment:
POSTGRES_HOST: db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
REDIS_HOST_PASSWORD: ${REDIS_PASSWORD}
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: ${ADMIN_PASSWORD}
NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com
TRUSTED_PROXIES: 172.16.0.0/12
OVERWRITEPROTOCOL: https
OVERWRITECLIURL: https://cloud.example.com
APACHE_DISABLE_REWRITE_IP: "1"
PHP_MEMORY_LIMIT: 512M
PHP_UPLOAD_LIMIT: 10G
cron:
image: nextcloud:31-apache
restart: unless-stopped
entrypoint: /cron.sh
depends_on: [db, redis]
volumes:
- html:/var/www/html
- /srv/nextcloud/data:/var/www/html/data
volumes:
db:
html:ثبّت رقم الإصدار الرئيسي (tag) وتحقق من الإصدار الحالي على Docker Hub قبل أن تنسخ 31 حرفيًّا. فاستخدام latest سينقلك عبر حدٍّ إصداري رئيسي (major) في أي docker compose pull مستقبلي، وNextcloud لا يدعم ذلك.
دليل البيانات هو ربط مسار (bind mount)، لا وحدة تخزين مسمّاة (named volume)، وذلك عن قصد: فمسار يمكنك توجيه أداة نسخ احتياطي إليه مباشرة يساوي أكثر من مجرد الترتيب. أنشئه بمعرّف المستخدم (UID) الخاص بـ www-data في الصورة وبالأذونات التي يطلبها Nextcloud:
sudo mkdir -p /srv/nextcloud/data
sudo chown -R 33:33 /srv/nextcloud/data
sudo chmod 0770 /srv/nextcloud/dataلاحظ نشر المنفذ: 127.0.0.1:8080:80. ينشر Docker المنافذ بكتابة قواعد DNAT تُقيَّم قبل أن تصل الحزمة أصلًا إلى سلسلة INPUT في ufw — فمجرد 8080:80 يضع نسخة Nextcloud غير المشفَّرة على الإنترنت العام مهما قال ufw. الربط بالحلقة المحلية يبقيها بعيدة عن الواجهة العامة. عندئذ لا يحتاج جدار الحماية إلا للسماح للوكيل (proxy)، وإن كنت تفضّل ألا تترك SSH مفتوحًا أمام الإنترنت كله، فإن الوصول إلى الخادم عبر شبكة WireGuard VPN مستضافة ذاتيًا يتيح لك إسقاط المنفذ 22 كليًّا من القواعد العامة:
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enableشغّله بالأمر docker compose up -d، ثم راقب docker compose logs -f app. الإقلاع الأول ينسخ شجرة التطبيق كاملة إلى وحدة التخزين وينفّذ المثبِّت؛ ولا تستجيب الحاوية لأي شيء حتى تنتهي هذه العملية.
TLS والوكيل العكسي
ثبّت nginx وcertbot من مستودع التوزيعة، وأنشئ كتلة خادم (server block) بسيطة على المنفذ 80 بقيمة server_name الصحيحة، ثم دع certbot يعيد كتابتها. آليات تحدي HTTP-01، ومؤقت التجديد (renewal timer)، وأنماط الفشل مشروحة بالكامل في إصدار شهادات Let's Encrypt باستخدام certbot وnginx على Ubuntu 24.04:
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d cloud.example.comيضيف certbot أسطر ssl_certificate وإعادة التوجيه من :80 إلى :443، ويثبّت مؤقت systemd يجدّد الشهادة ذات الصلاحية 90 يومًا. تأكد من وجوده بالأمر systemctl list-timers | grep certbot — فمؤقت تجديد لم يُفعَّل قط هو فتيل ينفجر بعد 90 يومًا.
كتلة الوكيل نفسها:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name cloud.example.com;
# certbot manages ssl_certificate / ssl_certificate_key here
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
client_max_body_size 10G;
client_body_timeout 300s;
location = /.well-known/carddav { return 301 /remote.php/dav; }
location = /.well-known/caldav { return 301 /remote.php/dav; }
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}على nginx 1.25 وما بعده، أضف http2 on;. أما Ubuntu 24.04 فيأتي بإصدار أقدم يكون فيه المكافئ هو listen 443 ssl http2;. الأمر nginx -t سيخبرك أيّهما يقبله إصدارك.
client_max_body_size ومهلات القراءة الطويلة هي ما يمنع الرفعات الكبيرة من التوقف في منتصف الطريق. proxy_request_buffering off يبث الرفعة تدفقًا (stream) بدلًا من تخزين الملف بأكمله أولًا على قرص الوكيل.
nginx على المضيف هو أبسط ما ينجح لتطبيق واحد. أما إذا كان Nextcloud سيشارك الخادم مع حاويات أخرى، فإن تشغيل Traefik كوكيل عكسي بـ Docker Compose لعدة تطبيقات ينقل التوجيه وإصدار الشهادات إلى تسميات (labels) الحاويات، وتظهر همومك نفسها بشأن client_max_body_size والمهلات هناك مجددًا في صورة إعدادات middleware ونقل (transport).
trusted_proxies وoverwriteprotocol
هنا يخطئ معظم من يستضيف Nextcloud بنفسه، وتبدو الأعراض غير ذات صلة بالسبب.
لا يُؤخذ X-Forwarded-Proto: https في الاعتبار إلا حين يصل الطلب من عنوان مدرج في trusted_proxies. وحين لا يُؤخذ في الاعتبار، يعتقد Nextcloud أن الطلب HTTP عادي فيصدر روابط http://؛ فيعيد الوكيل توجيهها إلى HTTPS؛ ويتبع المتصفح ذلك؛ ثم يصدر Nextcloud http:// من جديد. هذه هي حلقة إعادة التوجيه (redirect loop). أما OVERWRITEPROTOCOL: https فيثبّت المخطط (scheme) بصرف النظر عمّا سبق.
الفخ في TRUSTED_PROXIES هو أن العنوان الذي يراه Nextcloud ليس 127.0.0.1. فـ nginx يعمل على المضيف ويتصل بمنفذ منشور، لذا ترى الحاوية بوابة جسر Docker (bridge gateway) — شيئًا ما ضمن 172.x. اعثر على الشبكة الفرعية الحقيقية:
docker network inspect nextcloud_default \
-f '{{range .IPAM.Config}}{{.Subnet}}{{end}}'ضع ذلك النطاق (CIDR) — أو النطاق الأشمل 172.16.0.0/12 — في TRUSTED_PROXIES. اجعله واسعًا أكثر مما ينبغي وسيتمكن أي عميل من انتحال X-Forwarded-For؛ واضبطه خطأً وستبدو كل عمليات تسجيل الدخول وكأنها قادمة من عنوان البوابة، فتحظر حماية القوة الغاشمة نسختك كلها دفعة واحدة، وتعرض لوحة الإدارة الرسالة: «The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy.»
يهم OVERWRITECLIURL بالنسبة لحاوية cron، التي لا يصلها أي طلب وارد يمكن أن تستنتج منه اسم مضيف. من دونه، تولّد المهام الخلفية روابط إلى localhost وتُرسل إشعارات البريد الإلكتروني روابط غير قابلة للاستخدام.
المهام الخلفية: cron لا AJAX
مشغّل المهام الافتراضي في Nextcloud هو AJAX: تُنفَّذ المهام كأثر جانبي لتحميل شخص ما صفحة. لا أحد يتصفح الساعة 04:00 صباحًا، فتتوقف عمليات انتهاء صلاحية سلة المحذوفات، وتنظيف الإصدارات، والمعاينات، ومحاولات الاتحاد (federated retries) المتكررة، ويكون العَرَض الأول دليل بيانات لا يتوقف عن النمو أبدًا. خدمة cron أعلاه تشغّل حلقة /cron.sh الرسمية على وحدات التخزين نفسها. أخبر Nextcloud بأن يتوقعها:
docker compose exec -u www-data app php occ background:cronكل أمر occ يتبع هذا الشكل: docker compose exec -u www-data app php occ <command>. يستحق الأمر أن تصنع له اختصارًا (alias).
النسخ الاحتياطي: ثلاثة أشياء، أو لا شيء
النسخة الاحتياطية المقتصرة على نظام الملفات تُستعاد إلى نسخة معطوبة. دليل البيانات يخزّن البايتات؛ وPostgres يحتفظ بذاكرة تخزين الملفات المؤقتة، والمشاركات، والمستخدمين، وحالة التطبيقات؛ وملف config.php يتضمن بيانات اعتماد قاعدة البيانات، ومعرّف النسخة (instance ID)، وملح كلمة المرور (password salt). استعد الملفات دون قاعدة البيانات ولن يستطيع Nextcloud رؤيتها. استعد قاعدة البيانات دون config.php ولن يستطيع فتحها. استعد قاعدة بيانات قديمة مقابل دليل بيانات أحدث وستحصل على مشاركات تشير إلى ملفات انتقلت من مكانها.
خذ نسخة احتياطية من الأشياء الثلاثة معًا، من نسخة موقوفة مؤقتًا (quiesced):
#!/usr/bin/env bash
set -euo pipefail
cd /srv/nextcloud
DEST="/var/backups/nextcloud/$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$DEST"
occ() { docker compose exec -T -u www-data app php occ "$@"; }
occ maintenance:mode --on
trap 'occ maintenance:mode --off' EXIT
docker compose exec -T db \
pg_dump -U nextcloud --clean --if-exists nextcloud | gzip > "$DEST/db.sql.gz"
docker compose exec -T app \
tar -C /var/www/html -cf - config custom_apps themes > "$DEST/app.tar"
rsync -a --delete /srv/nextcloud/data/ /var/backups/nextcloud/data/وضع الصيانة (maintenance mode) هو ما يجعل التفريغ ونسخ الملفات متسقين مع بعضهما. تخطَّه وستنتهي في وقت ما بالتقاط قاعدة بيانات تشير إلى ملف لم يصل إليه rsync بعد. لاحظ أن السكربت يحتفظ بتفريغات قاعدة بيانات مختومة بالوقت (timestamped) لكن بمرآة واحدة متجددة فقط لدليل البيانات — إذ يستبدلها rsync --delete في كل تشغيل — فلا يتطابق مع نسخة الملفات إلا أحدث تفريغ.
ثم انقلها خارج الخادم. النسخة الاحتياطية المخزَّنة على نفس خادم VPS الذي أُخذت منه هي مجرد نسخة، لا نسخة احتياطية. restic موجَّهًا نحو تخزين كائنات (object storage) أو مضيف ثانٍ هو الحل المعتاد، وإزالة التكرار (deduplication) فيه تتعامل مع دليل البيانات أفضل بكثير من أرشيف tar ليلي. الإعداد الكامل، من تهيئة المستودع إلى المؤقت الليلي وتمرين الاستعادة، موجود في النسخ الاحتياطي لخادم VPS خارج الجهاز باستخدام restic.
الاستعادة ليست ببساطة العملية العكسية. فالمكدس (stack) المُشغَّل حديثًا ينفّذ المثبِّت ويكتب ملف config.php جديدًا تمامًا — بمعرّف نسخة وملح كلمة مرور جديدين — واستيراد التفريغ فوق تلك الهوية الجديدة يترك جلسات ورموز مشاركة (share tokens) معطوبة. أعد الهوية القديمة أولًا، بهذا الترتيب:
docker compose up -d && docker compose stop app cron # create the volumes, then halt the app
sudo rsync -a --delete /var/backups/nextcloud/data/ /srv/nextcloud/data/
docker compose run --rm -T --entrypoint "" app \
tar -C /var/www/html -xf - < app.tar # the original config.php returns
gunzip -c db.sql.gz | docker compose exec -T db psql -U nextcloud -d nextcloud
docker compose start app cron
docker compose exec -T -u www-data app php occ maintenance:mode --off
docker compose exec -T -u www-data app php occ files:scan --allيوفّق files:scan ذاكرة تخزين الملفات المؤقتة مع ما هو موجود فعلًا على القرص. تدرّب على هذا مرة واحدة، على خادم VPS احتياطي، قبل أن تحتاج إليه فعلًا.
الترقيات: إصدار رئيسي واحد في كل مرة
يدعم Nextcloud ترقية إصدار رئيسي واحد بالضبط في كل مرة. القفز من 29 إلى 31 لا يفشل بسلاسة — بل يفشل برسالة Exception: Updates between multiple major versions and downgrades are unsupported. ويتركك في وضع الصيانة.
ترقية Docker تكون كالتالي: خذ نسخة احتياطية، وعدّل رقم الإصدار من 31 إلى 32 في كلتا الخدمتين app وcron، ثم نفّذ docker compose pull && docker compose up -d، ثم docker compose logs -f app. نقطة الدخول (entrypoint) في الصورة تكتشف الشيفرة الأحدث مقابل البيانات الموجودة وتنفّذ occ upgrade بنفسها. لا تقاطعها. حين تهدأ السجلّات، نفّذ docker compose exec -u www-data app php occ status وتحقق من versionstring ومن أن التطبيقات عادت مفعّلة.
قاعدتان تنقذانك: ارفع إصدارًا رئيسيًّا واحدًا، تحقّق، ثم ارفع التالي. ولا تعدّل أبدًا رقم الإصدار على خدمة app دون تعديل cron ليطابقه — فإصداران مختلفان من Nextcloud مقابل قاعدة بيانات واحدة هما طريق نحو التلف.
الأخطاء التي سترها فعلًا
«Your data directory is readable by other users. Please change the permissions to 0770.» الدليل المربوط بربط مسار لديه بتات قراءة للمجموعة أو للجميع. نفّذ sudo chmod 0770 /srv/nextcloud/data وsudo chown -R 33:33 /srv/nextcloud/data.
«Your data directory is invalid. Ensure there is a file called .ocdata in the root.» ربط المسار يشير إلى مكان لم يهيّئه Nextcloud قط — خطأ إملائي في المسار، أو دليل فارغ جديد استُبدل تحت نسخة كانت تعمل. تحقق من أن مسار المضيف يطابق سطر وحدة التخزين.
«Access through untrusted domain.» اسم المضيف في الطلب غير موجود في trusted_domains. تنطبق NEXTCLOUD_TRUSTED_DOMAINS عند التثبيت الأول فقط؛ وبعد ذلك اضبطها مباشرة: occ config:system:set trusted_domains 1 --value=cloud.example.com.
502 Bad Gateway، مع connect() failed (111: Connection refused) while connecting to upstream في /var/log/nginx/error.log. لم يصل nginx إلى أي شيء على 127.0.0.1:8080. إما أن الحاوية ما زالت قيد التهيئة (تحقق بـ docker compose logs app)، أو أنها خرجت (docker compose ps)، أو أن سطر النشر لا يطابق منفذ proxy_pass. تأكد بالأمر ss -ltnp | grep 8080.
حلقة إعادة توجيه، أو تحذيرات «insecure» في لوحة الإدارة. إما أن OVERWRITEPROTOCOL: https مفقودة، أو أن TRUSTED_PROXIES لا يحتوي على الشبكة الفرعية لبوابة Docker. راجع قسم الوكيل أعلاه.
LockedException: "files/..." is locked. مع ضبط REDIS_HOST، تعتمد الصورة على Redis كخلفية للأقفال، وتصبح الأقفال العالقة (stale locks) نادرة. أما من دونه، فتوجد الأقفال في جدول قاعدة البيانات oc_file_locks، ويترك طلب قُتل في منتصف الكتابة صفوفًا خلفه. تأكد من أن Redis مستخدَم فعلًا — يجب أن يعيد occ config:system:get memcache.locking صنف Redis — قبل مسح صفوف الأقفال يدويًّا.
«The PHP memory limit is below the recommended value of 512MB.» ارفع PHP_MEMORY_LIMIT وأعد إنشاء الحاوية. تذكّر ما يفعله ذلك بسقفك في أسوأ الحالات.
ما الذي يتعطل عند التوسع
الجدار الأول هو دليل البيانات وهو يتجاوز حجم وحدة التخزين. توسيع وحدة تخزين على خادم VPS هو عملية تغيير حجم (resize) بالإضافة إلى توسيع نظام الملفات، وهي أقل إيلامًا بكثير عند جدولتها مسبقًا منها عند الوصول إلى امتلاء القرص 100% — فعّل تنبيهًا على استخدام القرص الآن، لا لاحقًا.
الجدار الثاني هو oc_filecache. سرد الملفات ومسح المزامنة يتباطآن مع تزايد عدد الصفوف، والحل يكمن في العمل على قاعدة البيانات: أبقِ Postgres على تخزين سريع، ودعه يستخدم ذاكرة مشتركة كافية، وقلّم سلة المحذوفات والإصدارات بإعدادات الاحتفاظ (retention) بدلًا من تركها تتراكم إلى الأبد.
الثالث هو توليد المعاينات وهو يزاحم كل شيء آخر. على جهاز صغير، أبقِ موفّري المعاينات محدودين ولا تنفّذ أبدًا occ preview:generate-all خلال ساعات العمل.
وفيما وراء ذلك، فالإجابة الصادقة هي أن الإضافات تريد جهازها الخاص. Collabora والبحث في النص الكامل خدمتان مقيمتان منفصلتان بملفات استهلاك ذاكرة خاصة بهما، ووضعهما على نفس الجهاز الذي يحمل أيضًا نسختك الوحيدة من ملفاتك يوسّع نطاق الفشل دون أي فائدة. انقل تخزين الملفات إلى تخزين أساسي متوافق مع S3 حين تتوقف وحدة التخزين عن أن تكون الشكل المناسب — ولاحظ أن هذا يجعل النسخ الاحتياطي أصعب، لا أسهل: فقاعدة البيانات ما زالت تحمل البيانات الوصفية، ويجب تفريغها بالتزامن مع الـ bucket.
حين تبدأ نسختك بخدمة مستخدمين حقيقيين، ضع Uptime Kuma أمامها لتعرف بانقطاع الخدمة قبل أن يعرف به عملاء المزامنة. السحابة الخاصة تتوافق جيدًا مع خادم بريدك الخاص، وإن كنت تفضّل ألا تربط الخدمات ببعضها يدويًّا، فإن Cloudron وCasaOS وCoolify تقارن بين المنصات التي تقوم بذلك نيابة عنك.
FAQ
هل يمكنني تشغيل Nextcloud على SQLite بدلًا من Postgres؟
يمكنك ذلك، والصورة الرسمية ستسمح لك به، لكن عميل مزامنة سطح مكتب واحد يصدر طلبات متوازية سيصطدم بـ SQLSTATE[HY000]: General error: 5 database is locked وأخطاء HTTP 500. يأخذ SQLite قفل كتابة يشمل قاعدة البيانات كلها، وNextcloud يكتب باستمرار — أقفال ملفات، وصفوف نشاط، وحالة مهام. ابدأ بـ Postgres أو MariaDB؛ يوجد occ db:convert-type لكنه ترحيل طويل وقائم على مبدأ الكل أو لا شيء على بيانات حية.
كم من ذاكرة RAM يحتاجها فعلًا خادم VPS لـ Nextcloud؟
حدّد الحجم بحسب التزامن، لا عدد المستخدمين. أسوأ حالة للذاكرة المقيمة هي تقريبًا عدد الطلبات المتزامنة مضروبًا في PHP_MEMORY_LIMIT، بالإضافة إلى المخازن المؤقتة المشتركة لـ Postgres وعملية خلفية لكل اتصال، بالإضافة إلى ما يصل إليه توليد المعاينات من ارتفاع حاد. جهاز بذاكرة 2 غيغابايت يشغّل نسخة منزلية صغيرة إن حددت سقفًا للمعاينات وأضفت swap؛ أضف Collabora أو البحث في النص الكامل وستكون بصدد تحديد حجم مجموعة ثانية من الخدمات المقيمة.
لماذا تفشل الرفعات الكبيرة خلف وكيل nginx العكسي؟
عادة ما يفسّر ذلك إعدادان في الوكيل: client_max_body_size متروك على القيمة الافتراضية 1 ميغابايت فيقطع الطلب، وقيم قصيرة لـ proxy_read_timeout / proxy_send_timeout تقتل عمليات النقل الطويلة في منتصف الطريق. اضبط كليهما بسخاء، واجعل proxy_request_buffering off ليتم البث تدفقًا بدلًا من التخزين المؤقت، وارفع PHP_UPLOAD_LIMIT على حاوية التطبيق ليطابق ذلك.
لماذا يعيد Nextcloud التوجيه في حلقة أو يحذّر بشأن الوكيل العكسي؟
لا ترى الحاوية nginx على 127.0.0.1 — بل ترى بوابة جسر Docker، في مكان ما ضمن 172.x. حين يكون ذلك العنوان غائبًا عن TRUSTED_PROXIES، تُتجاهل ترويسة X-Forwarded-Proto: https، فيصدر Nextcloud روابط http://، ويعيدها الوكيل مرة أخرى. اضبط TRUSTED_PROXIES على الشبكة الفرعية الحقيقية للجسر، وثبّت OVERWRITEPROTOCOL: https.
هل يمكنني ترقية Nextcloud من 29 مباشرة إلى 31؟
لا. يدعم Nextcloud إصدارًا رئيسيًّا واحدًا فقط لكل ترقية، وتخطي إصدار يتوقف برسالة Updates between multiple major versions and downgrades are unsupported.، تاركًا النسخة في وضع الصيانة. خذ نسخة احتياطية، وارفع رقم الإصدار إصدارًا رئيسيًّا واحدًا في كلتا الخدمتين app وcron، ونفّذ docker compose pull && docker compose up -d، وتحقق بـ occ status، ثم كرر العملية.