התקנת Nextcloud ב-VPS עם Docker
מדריך להרצת Nextcloud ב-VPS באמצעות Docker Compose, Postgres ו-Redis. כולל הגדרת TLS ושיטות גיבוי מלאות למניעת אובדן נתונים בשימוש ב-Ubuntu או Debian.
מה אתם בונים בפועל
מדריך זה מריץ Nextcloud על VPS באמצעות Docker Compose, מגדיר Let's Encrypt TLS לפניו, ומקים גיבוי שניתן לשחזר בפועל. ארבעה קונטיינרים ופרוקסי: אימג' ה-nextcloud הרשמי המאזין ל-loopback, Postgres המכיל את כל המטא-דאטה של הקבצים, Redis המנהל את נעילת הקבצים (file locks), עותק שני של אימג' Nextcloud המריץ אך ורק את לולאת ה-cron, ו-nginx על ה-host המבצע TLS termination לפני כולם. ההתקנה עצמה אורכת עשרים דקות, וזה אינו החלק החשוב. שתי החלטות בשעה הראשונה יקבעו אם הקבצים שלכם יישארו קיימים בעוד שנה: שימוש במסד נתונים אמיתי במקום SQLite, וגיבוי שכולל את ספריית הנתונים (data directory), את מסד הנתונים ואת config.php כסט עקבי אחד.
המדריך מניח שימוש ב-Ubuntu 24.04 LTS או Debian 13, ב-Docker Engine עם תוסף Compose v2 המותקן מהמאגר הרשמי של Docker, ורשומת DNS מסוג A (בתוספת AAAA אם יש לכם IPv6) המכוונת כבר את cloud.example.com ל-VPS. כל התהליך דורש שרת שנמצא תחת שליטתכם — אין אפשרות לבצע TLS termination וגיבוי של מסד הנתונים (database dump) על שירות SaaS של מישהו אחר.
Sizing: מה באמת צורך את הזיכרון
צריכת הזיכרון של Nextcloud נשלטת על ידי שלושה גורמים, ואף אחד מהם אינו "Nextcloud" כשלעצמו.
PHP workers. ה-image של -apache משרתת כל בקשה מקבילה באמצעות תהליך worker שמחזיק PHP interpreter. כל worker עשוי להגיע לנפח של PHP_MEMORY_LIMIT לפני ש-PHP תסגור את הבקשה. זיכרון ה-resident במקרה הגרוע ביותר הוא בערך מספר הבקשות המקבילות × מגבלת הזיכרון, וכלי סנכרון בשולחן העבודה פותח מספר חיבורים מקבילים לכל משתמש. מספר החיבורים המקבילים, ולא מספר המשתמשים, הוא שקובע את התקרה.
The database. Postgres יוצר backend נפרד לכל חיבור ושומר את ה-shared buffers בזיכרון. סט העבודה שלו גדל בהתאם למספר ה-files, ולא לפי מספר הבתים: oc_filecache מחזיקה שורה עבור כל קובץ עבור כל משתמש. מאה אלף קבצים קטנים יוצרים בסיס נתונים כבד יותר מאשר מאה קבצים גדולים.
Preview generation. יצירת תמונת תצוגה מקדימה (thumbnail) מפעילה פעולה של decoding לתמונת המקור בזיכרון ברזולוציה מלאה. תצוגות מקדימות של וידאו משתמשות ב-ffmpeg. הרצת occ preview:generate-all מבצעת את קפיצת הצריכה הזו שוב ושוב, ברצף, וזו הדרך הנפוצה ביותר לגרום ל-VPS קטן להיכנס ל-OOM killer.
Redis הוא זול יחסית. כל רכיב נוסף שתתקין מאוחר יותר — Collabora, full-text search, או סורק אנטי-וירוס — הוא שירות resident נפרד עם טביעת רגל משלו, ויש לתכנן אותו בתוכנית ה-sizing לפני ההפעלה.
הכלים לניהול, אם ה-RAM מוגבל: הורד את PHP_MEMORY_LIMIT, הגבל את preview_max_x / preview_max_y / preview_max_filesize_image, צמצם את enabledPreviewProviders רק לפורמטים שאתם באמת צורכים, והגדר את trashbin_retention_obligation ו-versions_retention_obligation כך שספריית הנתונים לא תגדל בשקט לגודל הגבוה פי כמה מגודל הקבצים שלכם. הוסף swap file. swap הוא איטי, ו-OOM kill באמצע שדרוג הוא גרוע יותר.
Why SQLite breaks
Nextcloud כולל תמיכה ב-SQLite, וה-image הרשמי ישתמש בה ללא בעיה. אל תעשו זאת. SQLite מבצע סדרת פעולות כתיבה (serialises) באמצעות נעילה של כל בסיס הנתונים: כותב אחד בכל פעם, עבור כל הקובץ. Nextcloud מבצע פעולות כתיבה ללא הרף — נעילות קבצים, שורות activity, רשומות cache ומצב job — ולקוח desktop בודד שמסנכרן עץ תיקיות שולח בקשות מקבילות רבות. תחת דפוס זה תיתקלו ב-SQLSTATE[HY000]: General error: 5 database is locked ובשגיאות HTTP 500, והכשל יופיע בדיוק כשהמערכת תתחיל להיות שימושית.
מעבר מאוחר יותר אפשרי באמצעות occ db:convert-type, אך מדובר בהגירה ארוכה ומוחלטת על מערך נתונים פעיל. התחילו עם Postgres או MariaDB.
The Compose file
הניחו את הקובץ הזה ב-/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:קבעו את ה-major tag ובדקו את הגרסה הנוכחית ב-Docker Hub לפני שתעתיקו את 31 מילה במילה. latest עלולה להעביר אתכם בין גרסאות major ב-docker compose pull עתידי, ו-Nextcloud אינו תומך בכך.
ספריית הנתונים היא bind mount ולא named volume, בכוונה: נתיב שניתן להפנות אליו כלי גיבוי ישירות שווה יותר מסדר וניקיון. צרו אותה עם ה-www-data UID של ה-image וההרשאות ש-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 קובע. קישור ל-loopback שומר עליו מחוץ לממשק הציבורי. במצב זה, חומת האש צריכה לאפשר רק ל-proxy — ואם אינכם מעוניינים להשאיר את SSH פתוח לכל האינטרנט, התחברות ל-VPS דרך 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. העלייה הראשונה מעתיקה את עץ האפליקציה כולו אל ה-volume ומפעילה את המתקין; הקונטיינר לא יגיב לשום דבר עד לסיום התהליך.
TLS ו-reverse proxy
התקן את nginx ואת certbot מה-distro, צור server block פשוט ב-port-80 עם ה-server_name המתאים, ולאחר מכן אפשר ל-certbot לבצע לו rewrite. המנגנון של HTTP-01 challenge, טיימר ה-renewal ומצבי הכשל מפורטים במלואם בתוך issuing Let's Encrypt certificates with certbot and nginx on Ubuntu 24.04:
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d cloud.example.comCertbot מוסיף את שורות ה-ssl_certificate ואת ה-redirect של :80 ← :443, ומתקין systemd timer המחדש את התעודה כל 90 יום. ודא שהוא קיים באמצעות systemctl list-timers | grep certbot — טיימר renewal שלא הופעל הוא כמו פצצה מתקתקת ל-90 יום.
בלוק ה-proxy עצמו:
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 ו-long read timeouts הם אלו שמונעים מעליות קבצים גדולות להיכשל באמצע. proxy_request_buffering off מעביר את העלאת הקובץ ב-stream במקום לשמור את כל הקובץ בדיסק של ה-proxy תחילה.
שימוש ב-nginx על ה-host הוא הפתרון הפשוט ביותר עבור אפליקציה אחת. אם Nextcloud אמור לחלוק את ה-VPS עם קונטיינרים אחרים, running Traefik as a Docker Compose reverse proxy for multiple apps מעביר את הניתוב והנפקת התעודות לתוך container labels, וההתייחסות ל-client_max_body_size ול-timeouts חוזרת שם כהגדרות middleware ו-transport.
trusted_proxies ו-overwriteprotocol
כאן רוב מופעי ה-self-hosted של Nextcloud נכשלים, והתסמינים נראים ללא קשר לגורם.
הערך X-Forwarded-Proto: https נלקח בחשבון רק כאשר הבקשה מגיעה מכתובת המופיעה ב-trusted_proxies. כאשר הוא אינו נלקח בחשבון, Nextcloud סבור שהבקשה היא ב-HTTP רגיל ומייצרת כתובות URL עם http://; ה-proxy מפנה אותן ל-HTTPS; הדפדפן מבצע את ההפניה; Nextcloud מייצר שוב את http://. זוהי לולאת הפניה (redirect loop). הפרמטר OVERWRITEPROTOCOL: https קובע את ה-scheme ללא קשר.
המלכוד ב-TRUSTED_PROXIES הוא שהכתובת ש-Nextcloud רואה אינה 127.0.0.1. nginx רץ על ה-host ומתחבר לפורט שפורסם, לכן הקונטיינר רואה את ה-Docker bridge gateway — משהו בטווח 172.x. מצא את ה-subnet האמיתי:
docker network inspect nextcloud_default \
-f '{{range .IPAM.Config}}{{.Subnet}}{{end}}'הכנס את ה-CIDR הזה (או את ה-172.16.0.0/12 המכסה אותו) בתוך TRUSTED_PROXIES. אם הגדרת טווח רחב מדי, כל לקוח יוכל לזייף את X-Forwarded-For; אם הגדרת טווח שגוי, כל ההתחברויות ייראו כאילו הן מגיעות מכתובת ה-gateway, מנגנון ה-brute-force יחסום את כל המופע בבת אחת, וסקירת המנהל (admin overview) תציג: "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy."
הפרמטר OVERWRITECLIURL חשוב עבור קונטיינר ה-cron, שאין לו בקשות נכנסות כדי להסיק מהם את שם המארח (hostname). ללא הפרמטר הזה, משימות רקע ייצרו קישורים ל-localhost והתראות אימייל ישלחו עם כתובות URL שאינן ניתנות לשימוש.
Background jobs: cron, not AJAX
מריץ המשימות (job runner) الافتراضي של Nextcloud הוא AJAX: המשימות מבוצעות כתוצאה מהטעינה של דף על ידי משתמש. מכיוון שאיש אינו גולש בשעה 04:00, תהליכים כמו פקיעת תוקף של פח אשפה, ניקוי גרסאות, יצירת תצ previews וניסויים חוזרים של federated נתקעים. התסmind הראשון הוא ספריית נתונים (data directory) שגדלה ללא הפסקה. שירות ה-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.
Backups: שלושה דברים, או אף אחד מהם
גיבוי של מערכת הקבצים בלבד משחזר מופע (instance) שבור. ספריית הנתונים מכילה את הבייטים; Postgres מחזיק את זיכרון המטמון של הקבצים (file cache), שיתופים, משתמשים ומצב האפליקציה; config.php מחזיק את פרטי הגישה למסד הנתונים, את ה-instance ID ואת ה-password salt. אם תשחזר את הקבצים ללא מסד הנתונים, Nextcloud לא יוכל לזהות אותם. אם תשחזר את מסד הנתונים ללא config.php, הוא לא יוכל לפתוח את מסד הנתונים. אם תשחזר מסד נתונים ישן על ספריית נתונים חדשה יותר, תקבל שיתופים שמצביעים על קבצים שנדדו ממקומם.
גבה את שלושתם, מתוך מופע במצב שקט (quiesced instance):
#!/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) מבטיח התאמה בין ה-dump לבין העתקת הקבצים. אם תדלג עליו, בסופו של דבר תלכוד מסד נתונים שמפנה לקובץ ש-rsync טרם הגיע אליו. שים לב שהסקריפט שומר גיבויים של מסד הנתונים עם חותמת זמן, אך שומר רק עותק אחד מתגלגל (rolling mirror) של ספריית הנתונים — rsync --delete דורס אותו בכל הרצה — לכן רק ה-dump החדש ביותר תואם לעתקת הקבצים.
לאחר מכן, העבר את הגיבוי אל מחוץ למכונה. גיבוי שנשמר על אותו VPS שבו נמצא המקור הוא עותק, לא גיבוי. הפתרון המקובל הוא שימוש ב-restic מול object storage או מארח שני; מנגנון ה-deduplication שלו מטפל בספריית הנתונים בצורה טובה בהרבה מקובץ tarball יומי. ההגדרה המלאה, מתחילת ה-repository init ועד ל-nightly timer ולתרגול השחזור, נמצאת ב off-box VPS backups with restic.
שחזור אינו פשוט פעולה הפוכה. סטאק שהופעל מחדש מריץ את המתקין וכותב config.php חדש — instance ID חדש ו-password salt חדש — וייבוא ה-dump על גבי הזהות החדשה הזו ישאיר סשנים ושיתופי שירות (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 --allfiles:scan מסנכרן את זיכרון המטמון של הקבצים עם מה שקיים בפועל על הדיסק. תרגל זאת פעם אחת, על VPS רזרבי, לפני שתזדקק לכך.
Upgrades: one major at a time
Nextcloud תומכת בשדרוג של גרסה ראשית (major version) אחת בלבד בכל פעם. קפיצה מגרסה 29 ל-31 אינה מתבצעת בצורה תקינה — היא נכשלת עם Exception: Updates between multiple major versions and downgrades are unsupported. ומעבירה את המערכת למצב תחזוקה (maintenance mode).
תהליך השדרוג ב-Docker הוא: בצע גיבוי, שנה את ה-tag מ-31 ל-32 בשירותי app ו-cron, לאחר מכן הרץ docker compose pull && docker compose up -d ואז את docker compose logs -f app. ה-entrypoint של ה-image מזהה את הקוד החדש מול הנתונים הקיימים ומריץ את occ upgrade באופן אוטומטי. אין להפריע לתהליך. כאשר הלוגים מפסיקים להתעדכן, הרץ את docker compose exec -u www-data app php occ status וודא את versionstring ואת חזרה האפליקציות למצב פעיל (enabled).
שתי כללים שיחסכו לך זמן: שדרג גרסה ראשית אחת, וודא שהכל תקין, ואז שדרג את הגרסה הבאה. לעולם אל תשנה את ה-tag בשירות app מבלי לשנות גם את cron כדי שיתאימו — שימוש בשתי גרסאות Nextcloud שונות מול בסיס נתונים אחד עלול לגרום לשחיתות נתונים (corruption).
השגיאות שבהן תיתקלו בפועל
"Your data directory is readable by other users. Please change the permissions to 0770." לספרייה המחוברת ב-bind-mount יש הרשאות קריאה לקבוצה או לכל המשתמשים (world). 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." ה-bind mount מצביע לנתיב ש-Nextcloud מעולם לא אתחל — טעות כתיב בנתיב, או ספרייה ריקה חדשה שהוחלפה תחת מופע (instance) פעיל. ודאו שהנתיב ב-host תואם לשורת ה-volume.
"Access through untrusted domain." שם המארח (hostname) בבקשה אינו מופיע ב-trusted_domains. NEXTCLOUD_TRUSTED_DOMAINS תקף רק בהתקנה הראשונית; לאחר מכן יש להגדיר אותו ב-live: 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), או ששורת ה-publish אינה תואמת לפורט proxy_pass. ודאו זאת באמצעות ss -ltnp | grep 8080.
לולאת הפניה (redirect loop), או אזהרות "insecure" ב-admin overview. OVERWRITEPROTOCOL: https חסר, או ש-TRUSTED_PROXIES אינו מכיל את ה-subnet של ה-Docker gateway. ראו את סעיף ה-proxy לעיל.
LockedException: "files/..." is locked. כאשר REDIS_HOST מוגדר, האימג' מגדיר את Redis כ-locking backend ונעילות ישנות (stale locks) הן נדירות. ללא הגדרה זו, הנעילות נשמרות בטבלת מסד הנתונים oc_file_locks, ובקשה שנקטעה באמצע כתיבה תשאיר שורות מיותרות. ודאו ש-Redis אכן בשימוש — occ config:system:get memcache.locking אמור להחזיר את ה-Redis class — לפני שתנסו למחוק שורות נעילה באופן ידני.
"The PHP memory limit is below the recommended value of 512MB." הגדילו את PHP_MEMORY_LIMIT וצרו מחדש את הקונטיינר. זכרו מה ההשפעה של כך על תקרת המקסימום במקרה הגרוע ביותר.
מה נשבר בקנה מידה גדול (at scale)
החסם הראשון הוא ספריית הנתונים (data directory) שגדלה מעבר לנפח הדיסק (volume). הגדלת volume ב-VPS דורשת שינוי גודל (resize) והרחבת מערכת הקבצים (filesystem grow). תזמון הפעולה קשה הרבה יותר כשהדיסק מלא ב-100% — הגדר התרעה על ניצול דיסק כבר עכשיו, לא מאוחר יותר.
החסם השני הוא oc_filecache. פעולות של רשימת קבצים וסריקות סנכרון (sync scans) מואטות ככל שמספר השורות עולה. הפתרון הוא עבודה מול מסד הנתונים: שמור את Postgres על אחסון מהיר, הקצה לו מספיק זיכרון משותף (shared memory), ונקה נתונים מיותרים וגרסאות באמצעות הגדרות שמירה (retention settings) במקום לאפשר להם להצטבר לנצח.
החסם השלישי הוא יצירת תצוגה מקדימה (preview generation) שמתחרה על משאבים עם שירותים אחרים. במחשב קטן, הגבל את ספקי התצוגה המקדימה ושלא תריץ את occ preview:generate-all במהלך שעות העבודה.
מעבר לכך, התשובה הכנה היא ששירותים נוספים זקוקים למכונה משלהם. Collabora וחיפוש בטקסט מלא (full-text search) הם שירותים קבועים (resident services) עם פרופילי זיכרון משלהם. הרצתם על אותה מכונה שמחזיקה את עותק הקבצים היחיד שלך מגדילה את תחום הכשל (failure domain) ללא תועלת. העבר את אחסון הקבצים לאחסון ראשי תואם S3 כאשר ה-volume אינו מתאים יותר — שים לב שזה מקשה על הגיבויים ולא מקל עליהם: מסד הנתונים עדיין מחזיק את המטא-דאטה, ויש לגבות אותו במקביל ל-bucket.
ברגע שה-instance משרת משתמשים אמיתיים, הצב את Uptime Kuma לפניו כדי שתדע על השבתה לפני שתוכנות הסנכרון יזהו זאת. ענן פרטי משתלב היטב עם שרת המייל שלך, ואם אינך מעוניין לחבר שירותים באופן ידני, Cloudron, CasaOS and Coolify הן פלטפורמות שעושות זאת עבורך.
FAQ
האם ניתן להריץ Nextcloud על SQLite במקום Postgres?
ניתן לעשות זאת, וה-image הרשמי מאפשר זאת, אך client סנכרון בודד המבצע בקשות מקבילות יגרום לשגיאות SQLSTATE[HY000]: General error: 5 database is locked ו-HTTP 500s. SQLite נועל את כל מסד הנתונים לכתיבה, ו-Nextcloud מבצעת כתיבות תכופות — נעילת קבצים, שורות activity ומצב job. מומלץ להתחיל עם Postgres או MariaDB; קיימת אפשרות occ db:convert-type אך מדובר בהגירה ארוכה ומוחלטת (all-or-nothing) על נתונים פעילים.
כמה RAM באמת דורש שרת VPS עבור Nextcloud?
הגדר את הזיכרון לפי כמות הבקשות המקבילות, לא לפי מספר המשתמשים. במקרה הגרוע, הזיכרון הסטטי (resident memory) הוא בערך מספר הבקשות המקבילות כפול PHP_MEMORY_LIMIT, בתוספת Postgres shared buffers ו-backend אחד לכל חיבור, ועוד כמות הזיכרון הנדרשת לשיאים (spikes) של יצירת previews. שרת של 2 GB יכול להריץ מופע ביתי קטן אם מגבילים את ה-previews ומוסיפים swap; הוספת Collabora או חיפוש טקסט מלא (full-text search) מחייבת הקצאת זיכרון נוספת לשירותים אלו.
מדוע העלאות גדולות נכשלות מאחורי nginx reverse proxy?
בדרך כלל שתי הגדרות ב-proxy מסבירות זאת: client_max_body_size שמוגדר על ברירת המחדל של 1 MB יקטע את הבקשה, וערכים קצרים של proxy_read_timeout / proxy_send_timeout יקטעו העברות ארוכות באמצע. הגדר את שניהם עם ערכים נדיבים, הגדר את proxy_request_buffering off כ-stream במקום spool, והעלה את PHP_UPLOAD_LIMIT ב-app container בהתאם.
מדוע Nextcloud נכנס ללולאת הפניה (redirect loop) או מציג אזהרה לגבי ה-reverse proxy?
ה-container אינו רואה את nginx בכתובת 127.0.0.1 — הוא רואה את ה-Docker bridge gateway בטווח 172.x. כאשר כתובת זו חסרה ב-TRUSTED_PROXIES, ה-header של X-Forwarded-Proto: https אינו זוכה להתייחסות, Nextcloud מייצרת כתובות URL מסוג http://, וה-proxy מחזיר אותן בלולאה. הגדר את TRUSTED_PROXIES לסאבנט (subnet) האמיתי של ה-bridge וקבע את OVERWRITEPROTOCOL: https.
האם ניתן לשדרג Nextcloud מגרסה 29 ישירות ל-31?
לא. Nextcloud תומכת בשדרוג של גרסה ראשית אחת בכל פעם, ודילוג על גרסה יגרום לעצירה ב-Updates between multiple major versions and downgrades are unsupported. ולהשארת המופע במצב תחזוקה (maintenance mode). בצע גיבוי, עדכן את ה-tag בגרסה ראשית אחת בשירותי app ו-cron, בצע docker compose pull && docker compose up -d, ודא באמצעות occ status, ולאחר מכן חזור על הפעולה.