התקנת Nextcloud על VPS עם Docker Compose וגיבויים
למדו להריץ Nextcloud על VPS עם Docker Compose, Postgres ו-Redis. המדריך כולל הגדרת TLS, ניהול גיבויים עקביים ושדרוג בטוח למערכת יציבה על Ubuntu 24.04 או Debian 13.
מה אתם בונים בפועל
מדריך זה מריץ Nextcloud על גבי VPS באמצעות Docker Compose, מציב לפניו TLS של Let's Encrypt, ומגדיר גיבוי שניתן לשחזור בפועל. המערכת כוללת ארבע מכולות ו־proxy: התמונה הרשמית של nextcloud המאזינה ב-loopback, מסד נתונים Postgres המאחסן את כל המטא-דאטה של הקבצים, Redis המנהל את נעילות הקבצים, עותק שני של תמונת Nextcloud המריץ אך ורק את לולאת ה-cron, ו-nginx על המארח המבצע TLS termination לפני כולם. ההתקנה עצמה אורכת עשרים דקות, אך היא אינה החלק החשוב. שתי החלטות שמתקבלות בשעה הראשונה יקבעו אם הקבצים שלכם עדיין יהיו זמינים בעוד שנה: שימוש במסד נתונים אמיתי במקום SQLite, וגיבוי המאחד את תיקיית הנתונים, מסד הנתונים ו-config.php כסט עקבי אחד.
מדריך זה מניח שברשותכם Ubuntu 24.04 LTS או Debian 13, מנוע Docker עם תוסף Compose v2 מותקן מהמאגר הרשמי של Docker, ורשומת DNS מסוג A (בתוספת AAAA אם יש לכם IPv6) שכבר מצביעה ב-cloud.example.com על ה-VPS. כל אלו מחייבים שרת שבשליטתכם; לא ניתן לבצע TLS termination וגיבוי מסד נתונים בשירות SaaS של צד שלישי.
תכנון משאבים: מה באמת צורך זיכרון
צריכת הזיכרון של Nextcloud מושפעת משלושה גורמים עיקריים, ואף אחד מהם אינו "Nextcloud" כשלעצמו.
תהליכי עבודה (Workers) של PHP. התמונה -apache משרתת כל בקשה בו-זמנית באמצעות תהליך עבודה שמריץ מפרש PHP. כל תהליך עבודה עלול לצרוך זיכרון עד לגבול של PHP_MEMORY_LIMIT לפני ש-PHP תפסיק את הבקשה. צריכת הזיכרון המקסימלית (Resident memory) היא בקירוב מספר הבקשות במקביל × מגבלת הזיכרון, ולקוח הסנכרון לשולחן העבודה פותח כמה חיבורים מקבילים לכל משתמש. רמת העומס (Concurrency), ולא מספר המשתמשים, היא שקובעת את התקרה.
מסד הנתונים. Postgres מפצל תהליך backend לכל חיבור ושומר את ה-shared buffers בזיכרון. סט העבודה שלו גדל בהתאם למספר הקבצים, לא למספר הבייטים: oc_filecache מחזיק שורה אחת לכל קובץ לכל משתמש. מאה אלף קבצים קטנים יוצרים עומס כבד יותר על מסד הנתונים מאשר מאה קבצים גדולים.
יצירת תצוגה מקדימה (Previews). יצירת תמונה ממוזערת מפענחת את קובץ המקור לזיכרון ברזולוציה מלאה. תצוגות מקדימות של וידאו מפעילות את 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 באמצע שדרוג היא גרועה יותר.
מדוע SQLite נכשל
Nextcloud מגיע עם תמיכה ב-SQLite וה-image הרשמי ישתמש בו בשמחה. אל תעשו זאת. SQLite מבצע סריאליזציה לכתיבות באמצעות נעילה ברמת מסד הנתונים כולו: כותב אחד בכל פעם, עבור כל הקובץ. Nextcloud כותב ללא הרף – נעילות קבצים, שורות פעילות, רשומות cache, מצב משימות – ולקוח שולחני יחיד שמסנכרן עץ תיקיות מייצר בקשות מקביליות רבות. תחת דפוס עבודה זה תקבלו SQLSTATE[HY000]: General error: 5 database is locked ושגיאות HTTP 500, והכשל יופיע בדיוק ברגע שהמופע מתחיל להיות שימושי.
המרה מאוחרת יותר אפשרית באמצעות occ db:convert-type, אך מדובר בתהליך הגירה ארוך של "הכל או כלום" על נתונים חיים. התחילו עם Postgres או MariaDB.
קובץ ה-Compose
מקמו תוכן זה ב-/srv/nextcloud/compose.yaml, כאשר הסודות נמצאים בקובץ .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, וזאת במכוון: נתיב שניתן להפנות אליו כלי גיבוי ישירות עדיף על סדר אסתטי. צרו אותה עם ה-UID של ה-www-data של ה-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 מונע גישה מהממשק הציבורי. לאחר מכן, ה-firewall צריך לאפשר גישה רק ל-proxy, ואם אינכם מעוניינים להשאיר את SSH פתוח לכל האינטרנט, גישה ל-VPS דרך WireGuard VPN בניהול עצמי מאפשרת לכם להסיר את פורט 22 מחוקי ה-firewall הציבוריים לחלוטין:
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 ומריץ את תוכנית ההתקנה; ה-container לא יגיב לדבר עד לסיום פעולה זו.
TLS ו־reverse proxy
התקינו את nginx ואת certbot ממאגרי ההפצה, צרו בלוק server בסיסי בפורט 80 עם ה־server_name המתאים, ולאחר מכן אפשרו ל־certbot לשכתב אותו. המכניקה של אתגר HTTP-01, טיימר החידוש ומצבי הכשל מפורטים במלואם ב־הנפקת תעודות Let's Encrypt עם certbot ו־nginx ב־Ubuntu 24.04:
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d cloud.example.comCertbot מוסיף את שורות ה־ssl_certificate ואת ההפניה (redirect) מ־:80 ל־:443, ומתקין טיימר של systemd שמחדש את התעודה בת 90 הימים. ודאו שהוא קיים באמצעות systemctl list-timers | grep certbot; טיימר חידוש שלא הופעל הוא פצצת זמן של 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 וזמני ה־read timeout הארוכים מונעים מהעלאות קבצים גדולים להיקטע באמצע. ההגדרה proxy_request_buffering off מעבירה את הזרם (stream) של ההעלאה ישירות במקום לשמור את כל הקובץ בדיסק של ה־proxy תחילה.
שימוש ב־nginx על ה־host הוא הפתרון הפשוט ביותר שעובד עבור יישום יחיד. אם Nextcloud עומד לחלוק את ה־VPS עם מכולות (containers) אחרות, המדריך הרצת Traefik כ־reverse proxy ב־Docker Compose עבור מספר יישומים מעביר את הניתוב ואת הנפקת התעודות לתוך תוויות (labels) של המכולה, ושם מופיעים מחדש אותם שיקולי client_max_body_size וזמני ה־timeout כהגדרות middleware ותעבורה.
trusted_proxies ו-overwriteprotocol
כאן רוב ההתקנות של Nextcloud באירוח עצמי נכשלות, והתסמינים נראים לא קשורים לסיבה האמיתית.
ההגדרה X-Forwarded-Proto: https מכובדת רק כאשר הבקשה מגיעה מכתובת המופיעה ב-trusted_proxies. כאשר היא אינה מכובדת, Nextcloud סבור שהבקשה היא HTTP רגיל ומנפיק כתובות http://; ה-proxy מפנה אותן ל-HTTPS; הדפדפן עוקב; ו-Nextcloud מנפיק שוב http://. זהו לולאת הפניה (redirect loop). ההגדרה OVERWRITEPROTOCOL: https מקבעת את ה-scheme ללא קשר למצב.
המלכודת ב-TRUSTED_PROXIES היא שהכתובת ש-Nextcloud רואה אינה 127.0.0.1. nginx רץ על ה-host ומתחבר לפורט מפורסם, לכן ה-container רואה את ה-gateway של ה-Docker bridge, כתובת שנמצאת ב-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 תציג: "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy."
ההגדרה OVERWRITECLIURL חשובה עבור ה-cron container, שאין לו בקשה נכנסת כדי להסיק ממנה את ה-hostname. בלעדיה, משימות רקע מייצרות קישורים ל-localhost והתראות בדוא"ל שולחות כתובות URL שאינן שמישות.
משימות רקע: שימוש ב-cron במקום ב-AJAX
מנגנון הרצת המשימות המוגדר כברירת מחדל ב-Nextcloud הוא AJAX: המשימות מתבצעות כתוצאת לוואי של טעינת דף על ידי משתמש. מכיוון שאף אחד לא גולש בשעה 04:00, משימות כמו מחיקת קבצים זמניים, ניקוי גרסאות, יצירת תצוגות מקדימות וניסיונות חוזרים של שירותים מאוחדים (federated) נתקעות, והסימפטום הראשון לכך הוא ספריית נתונים שגודלה אינו מפסיק לתפוח. השירות 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 מחזיק את ה-file cache, השיתופים, המשתמשים ומצב היישום; 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) הוא מה שגורם ל-dump ולהעתק הקבצים להיות מסונכרנים זה עם זה. אם תדלגו עליו, אתם עלולים בסופו של דבר לתעד מסד נתונים שמפנה לקובץ ש-rsync טרם הגיע אליו. שימו לב שהסקריפט שומר dumps של מסד הנתונים עם חותמת זמן, אך רק מראה (mirror) מתגלגל אחד של ספריית הנתונים; rsync --delete דורס אותו בכל הרצה, כך שרק ה-dump החדש ביותר תואם להעתק הקבצים.
לאחר מכן, הוציאו את הגיבוי מהשרת. גיבוי שנמצא על אותו VPS שבו נמצא המידע המגובה הוא העתק, לא גיבוי. restic מול אחסון אובייקטים או מארח שני הוא הפתרון המקובל, ויכולת ה-deduplication שלו מטפלת בספריית הנתונים הרבה יותר טוב מאשר tarball לילי. ההגדרה המלאה, החל מאתחול ה-repository ועד ל-timer הלילי ותרגול השחזור, נמצאת ב-גיבויי VPS מחוץ לשרת עם restic.
שחזור אינו פשוט הפעולה ההפוכה. Stack שהופעל זה עתה מריץ את תוכנית ההתקנה וכותב config.php חדש לגמרי, מזהה מופע חדש ו-password salt חדש; ייבוא ה-dump על גבי הזהות החדשה הזו ישאיר סשנים שבורים ו-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 מסנכרן את ה-file cache עם מה שנמצא בפועל על הדיסק. תרגלו זאת פעם אחת, על VPS פנוי, לפני שתזדקקו לכך. אותה הפרדה בין בתים על הדיסק לבין מטא-דאטה ב-Postgres קיימת בכל יישום אחר במבנה דומה, וזו הסיבה ש-גיבוי של Immich שמתעד את הספרייה אך לא את מסד הנתונים משוחזר לציר זמן ריק.
שדרוגים: גרסה ראשית אחת בכל פעם
Nextcloud תומכת בשדרוג של גרסה ראשית אחת בלבד בכל פעם. קפיצה מגרסה 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 שהיישומים חזרו למצב פעיל.
שני כללים ימנעו מכם תקלות: שדרגו גרסה ראשית אחת, ודאו תקינות, ורק אז שדרגו לגרסה הבאה. לעולם אל תשנו את ה-tag בשירות app מבלי לעדכן את cron בהתאם; הרצת שתי גרסאות Nextcloud שונות מול אותו מסד נתונים תוביל להשחתת נתונים.
השגיאות שתיתקל בהן בפועל
"Your data directory is readable by other users. Please change the permissions to 0770." ספריית ה-bind-mount כוללת הרשאות קריאה לקבוצה או לכלל המשתמשים. השתמש ב-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 מעולם לא אתחל, קיימת שגיאת הקלדה בנתיב, או שהוחלפה ספרייה ריקה וחדשה תחת מופע פעיל. ודא שנתיב המארח תואם לשורת ה-volume.
"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), או ששורת ה-publish אינה תואמת לפורט ב-proxy_pass. אשר זאת באמצעות ss -ltnp | grep 8080.
לולאת הפניות (redirect loop), או אזהרות "insecure" בסקירת הניהול. OVERWRITEPROTOCOL: https חסר, או ש-TRUSTED_PROXIES אינו מכיל את רשת ה-gateway של Docker. עיין בסעיף ה-proxy לעיל.
LockedException: "files/..." is locked. כאשר REDIS_HOST מוגדר, התמונה מגדירה את Redis כ-backend לנעילות, ונעילות תקועות הן נדירות. בלעדיו, הנעילות נשמרות בטבלת מסד הנתונים 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 והקם מחדש את המכולה. זכור את ההשפעה של פעולה זו על צריכת הזיכרון המקסימלית במקרה הגרוע ביותר.
מה משתבש בקנה מידה גדול
המחסום הראשון הוא ספריית הנתונים שחורגת מנפח ה-volume. הגדלת volume ב-VPS דורשת שינוי גודל והרחבת מערכת הקבצים; זה הרבה פחות כואב כשזה מתוזמן מאשר כשהדיסק מלא ב-100%. הגדירו התראות על ניצול דיסק עכשיו, לא אחר כך.
המחסום השני הוא oc_filecache. רשימות קבצים וסריקות סנכרון מאטות ככל שמספר השורות גדל. הפתרון הוא עבודה על מסד הנתונים: שמרו את Postgres על אחסון מהיר, אפשרו לו להשתמש ב-shared memory מספיק, ונקו נתונים מיותרים וגרסאות ישנות באמצעות הגדרות retention במקום לתת להם להצטבר לנצח.
המחסום השלישי הוא יצירת תצוגות מקדימות (previews) שמתחרה על משאבים עם כל השאר. בשרת קטן, הגבילו את ספקי ה-preview ואל תריצו occ preview:generate-all בשעות העבודה. אם גלריית תמונות מהטלפון היא עיקר האחסון שלכם, עבודת יצירת ה-thumbnails צריכה להתבצע בשרת תמונות ייעודי. המאמר השוואה בין PhotoPrism ל-Immich מבחינת RAM, אפליקציות טלפון ופקודות גיבוי מפרט את העלויות של כל אחד מהם בהשוואה לשרת Nextcloud.
מעבר לכך, התשובה הכנה היא שהתוספות דורשות מכונה משלהן. Collabora וחיפוש טקסט מלא הם שירותים נפרדים שרצים ברקע עם דרישות זיכרון משלהם. הצבתם על השרת שמחזיק את העותק היחיד של הקבצים שלכם מגדילה את טווח הכשל ללא תועלת. אם עריכת מסמכים בדפדפן היא התוספת שאתם מחפשים, דרישות ה-RAM ומגבלות החיבורים שמבדילות בין OnlyOffice ל-Collabora יקבעו איזה מהם VPS עם 2 עד 4 GB RAM מסוגל להריץ. העבירו את אחסון הקבצים לאחסון תואם S3 כאשר ה-volume מפסיק להתאים לצרכים, ושימו לב שזה הופך את הגיבויים למורכבים יותר, לא לקלים יותר: מסד הנתונים עדיין מחזיק את המטא-דאטה, ויש לבצע לו dump מסונכרן עם ה-bucket.
ברגע שהמופע משרת משתמשים אמיתיים, הציבו לפניו את Uptime Kuma כדי שתשמעו על זמן השבתה לפני לקוחות הסנכרון. ענן פרטי משתלב היטב עם שרת דואר עצמאי, ואם אתם מעדיפים לא לחבר שירותים ידנית, Cloudron, CasaOS ו-Coolify משווים בין הפלטפורמות שעושות זאת עבורכם. אם מנוע חיפוש בניהול עצמי הוא הבא בתור ברשימה, צפו לסוג בעיות שונה מאלו שלעיל: שגיאות 429 ב-SearXNG נובעות או ממגביל הקצב (rate limiter) שלו או ממנועים חיצוניים שחוסמים את כתובת ה-IP של ה-VPS שלכם, ורק הלוגים יגלו לכם מהי הסיבה.
FAQ
האם ניתן להריץ את Nextcloud על SQLite במקום על Postgres?
ניתן לעשות זאת, וה-image הרשמי יאפשר זאת, אך לקוח סנכרון שולחני בודד המבצע בקשות מקבילות ייתקל ב-SQLSTATE[HY000]: General error: 5 database is locked ובשגיאות HTTP 500. SQLite נועל את מסד הנתונים כולו בזמן כתיבה, ו-Nextcloud מבצע כתיבות בתדירות גבוהה עבור נעילת קבצים, שורות פעילות ומצב משימות. התחילו עם Postgres או MariaDB; הכלי occ db:convert-type קיים, אך מדובר בתהליך הגירה ארוך ומורכב על נתונים חיים.
כמה זיכרון RAM דורש בפועל שרת VPS עבור Nextcloud?
יש לתכנן את הגודל לפי רמת העומס (concurrency), לא לפי מספר המשתמשים. צריכת הזיכרון המקסימלית היא בערך מספר הבקשות המקבילות כפול PHP_MEMORY_LIMIT, בתוספת ה-shared buffers של Postgres, תהליך backend אחד לכל חיבור, ושיאי צריכה של יצירת תצוגה מקדימה (preview). שרת עם 2 GB זיכרון יריץ מופע ביתי קטן אם תגבילו את ה-previews ותוסיפו swap; הוספת Collabora או חיפוש טקסט מלא דורשת הקצאת משאבים נוספת עבור סט שירותים נוסף.
מדוע העלאות קבצים גדולות נכשלות מאחורי ה-reverse proxy של nginx?
שתי הגדרות ב-proxy הן בדרך כלל הסיבה לכך: client_max_body_size שנותר על ערך ברירת המחדל של 1 MB קוטע את הבקשה, וערכים נמוכים מדי של proxy_read_timeout / proxy_send_timeout גורמים לניתוק העברות ארוכות באמצע. הגדירו את שניהם בנדיבות, שנו את proxy_request_buffering off ל-stream במקום ל-spool, והעלו את PHP_UPLOAD_LIMIT ב-container של היישום בהתאם.
מדוע Nextcloud מבצע הפניה בלולאה או מציג אזהרה לגבי ה-reverse proxy?
ה-container אינו רואה את nginx ב-127.0.0.1, הוא רואה את ה-gateway של ה-Docker bridge, שנמצא בטווח 172.x. כאשר כתובת זו חסרה ב-TRUSTED_PROXIES, ה-header של X-Forwarded-Proto: https מתעלם ממנה, Nextcloud מנפיק כתובות 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, ולאחר מכן חזרו על התהליך.