VPS पर Docker के साथ Nextcloud कैसे सेटअप करें
Docker Compose, Postgres और Redis का उपयोग करके अपने VPS पर Nextcloud इंस्टॉल करने का तरीका जानें। इसमें TLS प्रॉक्सी, डेटा बैकअप और अपग्रेड के लिए सटीक चरण शामिल हैं।
आप वास्तव में क्या बना रहे हैं
यह गाइड एक VPS पर Docker Compose के साथ Nextcloud चलाती है, इसके सामने Let's Encrypt TLS लगाती है, और एक ऐसा बैकअप सेटअप करती है जो वास्तव में रिस्टोर होता है। इसमें चार कंटेनर और एक प्रॉक्सी शामिल हैं: आधिकारिक nextcloud इमेज जो लूपबैक पर लिसन करती है, Postgres जो हर फाइल मेटाडेटा को रखती है, Redis जो फाइल लॉक्स को संभालती है, Nextcloud इमेज की एक दूसरी कॉपी जो केवल क्रॉन लूप चलाती है, और होस्ट पर nginx जो इन सबके सामने TLS टर्मिनेशन करती है। इंस्टॉलेशन में बीस मिनट लगते हैं, और यह वह हिस्सा नहीं है जो मायने रखता है। पहले घंटे में लिए गए दो निर्णय यह तय करते हैं कि क्या एक साल बाद भी आपकी फाइलें सुरक्षित रहेंगी: SQLite के बजाय एक वास्तविक डेटाबेस, और एक ऐसा बैकअप जो डेटा डायरेक्टरी, डेटाबेस और config.php को एक सुसंगत सेट के रूप में कैप्चर करता है।
यह गाइड मानती है कि आपके पास Ubuntu 24.04 LTS या Debian 13 है, Docker का अपना रिपॉजिटरी से इंस्टॉल किया गया Docker Engine और Compose v2 प्लगइन है, और एक DNS A रिकॉर्ड (यदि आपके पास IPv6 है तो AAAA भी) पहले से ही cloud.example.com को VPS की ओर पॉइंट कर रहा है। इसके लिए आपको एक ऐसे सर्वर की आवश्यकता है जिसे आप नियंत्रित करते हैं, क्योंकि किसी और के SaaS पर TLS टर्मिनेशन और डेटाबेस डंप करने का कोई तरीका नहीं है।
Sizing: वास्तव में मेमोरी का उपयोग क्या करता है
Nextcloud की मेमोरी खपत मुख्य रूप से तीन चीजों पर निर्भर करती है, और इनमें से कोई भी स्वयं "Nextcloud" नहीं है।
PHP workers. -apache इमेज प्रत्येक concurrent request को एक वर्कर प्रोसेस से सर्व करती है, जिसमें PHP इंटरप्रेटर होता है। PHP द्वारा रिक्वेस्ट को समाप्त करने से पहले प्रत्येक वर्कर PHP_MEMORY_LIMIT तक बढ़ सकता है। आपकी सबसे खराब स्थिति (worst-case) की रेजिडेंट मेमोरी लगभग concurrent requests × memory limit होती है, और डेस्कटॉप सिंक क्लाइंट प्रति उपयोगकर्ता कई समानांतर कनेक्शन खोलता है। मेमोरी की सीमा उपयोगकर्ता की संख्या नहीं, बल्कि concurrency तय करती है।
डेटाबेस. Postgres प्रत्येक कनेक्शन के लिए एक बैकएंड फोर्क करता है और शेयर्ड बफ़र्स को रेजिडेंट रखता है। इसका वर्किंग सेट बाइट्स की संख्या के बजाय files की संख्या के साथ स्केल होता है: oc_filecache में प्रति उपयोगकर्ता प्रति फ़ाइल एक रो (row) होती है। एक लाख छोटी फ़ाइलें, सौ बड़ी फ़ाइलों की तुलना में डेटाबेस पर अधिक भारी पड़ती हैं।
Preview generation. थंबनेल जनरेट करने के लिए सोर्स इमेज को पूरी रिज़ॉल्यूशन पर मेमोरी में डिकोड किया जाता है। वीडियो प्रीव्यू ffmpeg का उपयोग करते हैं। occ preview:generate-all को चलाने से यह स्पाइक बार-बार होता है, और यह एक छोटे VPS को OOM killer की स्थिति में धकेलने का सबसे सामान्य कारण है।
Redis की तुलनात्मक लागत कम है। बाद में आप जो कुछ भी जोड़ते हैं, जैसे Collabora, full-text search, या antivirus scanner, वे अपने स्वयं के फुटप्रिंट वाली अलग रेजिडेंट सर्विसेज होती हैं, और उन्हें इनेबल करने से पहले आपकी साइजिंग योजना में शामिल होना चाहिए।
यदि आपके पास 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 होना उससे भी बुरा है।
SQLite क्यों विफल होता है
Nextcloud में SQLite का समर्थन शामिल है और इसका आधिकारिक image इसे आसानी से उपयोग कर लेगा। ऐसा न करें। SQLite डेटाबेस-व्यापी लॉक के साथ writes को क्रमबद्ध (serialise) करता है: पूरी फ़ाइल के लिए एक समय में केवल एक ही writer। Nextcloud लगातार लिखता रहता है, जैसे फ़ाइल लॉक, गतिविधि पंक्तियाँ, कैश प्रविष्टियाँ, जॉब स्टेट, और एक डेस्कटॉप क्लाइंट जो डायरेक्टरी ट्री को सिंक करते समय कई समानांतर अनुरोध (parallel requests) भेजता है। इस पैटर्न के तहत आपको SQLSTATE[HY000]: General error: 5 database is locked और HTTP 500 त्रुटियाँ मिलेंगी, और विफलता ठीक उसी समय होती है जब instance उपयोगी होने लगता है।
बाद में रूपांतरण occ db:convert-type के साथ संभव है, लेकिन यह एक लाइव डेटासेट पर एक लंबी, 'सब या कुछ नहीं' (all-or-nothing) वाली माइग्रेशन प्रक्रिया है। शुरुआत से ही Postgres या MariaDB का उपयोग करें।
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:35-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:35-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 पर वर्तमान tag की जाँच करें, 35 को ज्यों का त्यों न लिखें। 21 October 2026 तक, Nextcloud 33, 34 और 35 को बनाए रखता है। Version 31 का end of life February 2026 में और 32 का September 2026 में हो चुका है, इसलिए किसी पुरानी गाइड से कॉपी किया गया tag एक ऐसा release इंस्टॉल करेगा जिसे अब कोई fixes नहीं मिलते। latest आपको भविष्य के किसी docker compose pull पर major boundary के पार ले जाएगा, और Nextcloud इसका समर्थन नहीं करता है।
Data directory जानबूझकर bind mount है, न कि named volume: एक ऐसा path जिस पर आप सीधे backup tool को point कर सकें, वह सफाई से अधिक महत्वपूर्ण है। इसे image के www-data UID और Nextcloud द्वारा आवश्यक permissions के साथ बनाएँ:
sudo mkdir -p /srv/nextcloud/data
sudo chown -R 33:33 /srv/nextcloud/data
sudo chmod 0770 /srv/nextcloud/dataPort publish पर ध्यान दें: 127.0.0.1:8080:80। Docker ports को DNAT rules लिखकर publish करता है, जिनका मूल्यांकन ufw की INPUT chain द्वारा packet देखने से पहले ही हो जाता है, एक साधारण 8080:80 ufw की परवाह किए बिना Nextcloud को public internet पर unencrypted डाल देता है। Loopback पर bind करने से यह public interface से दूर रहता है। इसके बाद firewall को केवल proxy को allow करना होता है, और यदि आप SSH को पूरे internet के लिए खुला नहीं रखना चाहते हैं, तो self-hosted WireGuard VPN के माध्यम से VPS तक पहुँचना आपको public rules से port 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 को monitor करें। पहली बार boot होने पर यह पूरी application tree को volume में copy करता है और installer चलाता है; जब तक वह पूरा नहीं हो जाता, container कोई जवाब नहीं देता।
TLS और reverse proxy
Distro से nginx और certbot इंस्टॉल करें, सही server_name के साथ एक plain port-80 server block बनाएँ, और फिर certbot को इसे rewrite करने दें। HTTP-01 challenge की कार्यप्रणाली, renewal timer और failure modes के बारे में पूरी जानकारी Ubuntu 24.04 पर certbot और nginx के साथ Let's Encrypt certificates जारी करना में दी गई है:
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d cloud.example.comCertbot ssl_certificate लाइनें और :80 → :443 रीडायरेक्ट जोड़ता है, और एक systemd timer इंस्टॉल करता है जो 90-दिन के certificate को renew करता है। systemctl list-timers | grep certbot के साथ इसकी पुष्टि करें; यदि renewal timer कभी enable नहीं किया गया, तो यह 90-दिन का एक time bomb है।
Proxy block इस प्रकार है:
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.1 और उसके बाद के वर्ज़न पर, http2 on; जोड़ें। यह directive 1.25.0 में मौजूद नहीं है, और यदि nginx इसे वहाँ देखता है तो वह start नहीं होगा। Ubuntu 24.04 एक पुराना build प्रदान करता है जहाँ इसके समकक्ष listen 443 ssl http2; है। nginx -t आपको बताएगा कि आपका build कौन सा विकल्प स्वीकार करता है।
यदि client_max_body_size बहुत छोटा है, तो nginx 413 error के साथ बड़ी upload को सीधे अस्वीकार कर देता है। यदि read timeouts बहुत कम हैं, तो upload बीच में ही रुक जाती है। ऊपर दिए गए मान इन दोनों समस्याओं को रोकते हैं। proxy_request_buffering off पूरी फ़ाइल को पहले proxy की डिस्क पर spool करने के बजाय upload को सीधे stream करता है।
एक app के लिए host पर nginx सबसे सरल और प्रभावी समाधान है। यदि Nextcloud को अन्य containers के साथ VPS साझा करना है, तो कई apps के लिए Docker Compose reverse proxy के रूप में Traefik चलाना routing और certificate issuance को container labels में ले जाता है, और वही client_max_body_size तथा timeout संबंधी चिंताएँ वहाँ middleware और transport settings के रूप में फिर से सामने आती हैं।
trusted_proxies और overwriteprotocol
यहीं पर अधिकांश self-hosted Nextcloud instances में गलती होती है, और इसके लक्षण मूल कारण से असंबंधित लगते हैं।
X-Forwarded-Proto: https का पालन केवल तभी किया जाता है जब अनुरोध trusted_proxies में सूचीबद्ध पते से आता है। जब इसका पालन नहीं किया जाता है, तो Nextcloud यह मानता है कि अनुरोध plain HTTP है और http:// URL जारी करता है; proxy उन्हें HTTPS पर redirect कर देता है; browser उसका अनुसरण करता है; Nextcloud फिर से http:// जारी करता है। यही redirect loop है। OVERWRITEPROTOCOL: https scheme को हर हाल में स्थिर रखता है।
TRUSTED_PROXIES में फँसने का कारण यह है कि जो पता Nextcloud देखता है, वह 127.0.0.1 नहीं है। nginx host पर चलता है और एक published port से जुड़ता है, इसलिए container 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 में डालें। यदि इसे बहुत अधिक विस्तृत सेट करेंगे, तो कोई भी client X-Forwarded-For को spoof कर सकता है; यदि इसे गलत सेट करेंगे, तो हर login gateway पते से आता हुआ दिखाई देगा, brute-force protection एक साथ आपके पूरे instance को block कर देगा, और admin overview में यह संदेश दिखेगा: "The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy."
OVERWRITECLIURL cron container के लिए महत्वपूर्ण है, जिसके पास hostname का अनुमान लगाने के लिए कोई incoming request नहीं होता है। इसके बिना, background jobs localhost के लिंक उत्पन्न करती हैं और email notifications में अनुपयोगी URL भेजे जाते हैं।
Background jobs: cron, न कि AJAX
Nextcloud का डिफ़ॉल्ट जॉब रनर AJAX है: जॉब्स तब निष्पादित होते हैं जब कोई पेज लोड करता है। रात के 04:00 बजे कोई ब्राउज़िंग नहीं करता, इसलिए ट्रैश एक्सपायरी, वर्ज़न क्लीनअप, प्रीव्यू और फ़ेडरेटेड रिट्राइज़ रुक जाते हैं, और इसका पहला लक्षण यह है कि डेटा डायरेक्टरी का आकार बढ़ना बंद नहीं होता। ऊपर दिया गया 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: तीन चीजें, या कुछ भी नहीं
केवल filesystem का backup लेने पर एक broken instance ही restore हो पाता है। data directory में bytes होते हैं; Postgres में file cache, shares, users और app state होता है; config.php में database credentials, instance ID और password salt होते हैं। database के बिना files restore करने पर Nextcloud उन्हें देख नहीं पाएगा। config.php के बिना database restore करने पर वह database को open नहीं कर पाएगा। एक पुराने database को नई data directory के साथ restore करने पर shares उन files की ओर इशारा करेंगे जो अपनी जगह बदल चुकी हैं।
एक quiesced instance से इन तीनों का backup लें:
#!/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 और file copy एक-दूसरे के साथ मेल खाते हैं। यदि आप इसे छोड़ देते हैं, तो अंततः आप ऐसा database capture कर लेंगे जो ऐसी file को reference करता है जहाँ तक rsync अभी पहुँचा ही नहीं था। ध्यान दें कि script timestamped database dumps को रखती है, लेकिन data directory का केवल एक rolling mirror ही रखती है, rsync --delete हर बार इसे overwrite कर देता है, इसलिए केवल सबसे नया dump ही file copy के साथ मेल खाता है।
इसके बाद इसे server से बाहर निकालें। जो backup उसी VPS पर रहता है जिसका वह backup है, वह केवल एक copy है, backup नहीं। object storage या किसी दूसरे host के विरुद्ध restic का उपयोग करना सामान्य समाधान है, और इसकी deduplication क्षमता nightly tarball की तुलना में data directory को कहीं बेहतर तरीके से संभालती है। repository init से लेकर nightly timer और restore drill तक का पूरा setup off-box VPS backups with restic में दिया गया है।
Restore करना केवल backup का उल्टा क्रम नहीं है। एक नया start किया गया stack installer को चलाता है और एक बिल्कुल नया config.php, एक नई instance ID और password salt लिखता है, और उस नई identity के ऊपर dump को import करने से sessions और share tokens टूट जाते हैं। पहले पुरानी identity को वापस लाएं, इस क्रम में:
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 का disk पर मौजूद वास्तविक data के साथ मिलान करता है। इसकी एक बार किसी spare VPS पर अभ्यास (rehearse) जरूर करें, इससे पहले कि आपको इसकी वास्तविक आवश्यकता पड़े। disk पर मौजूद bytes और Postgres में मौजूद metadata के बीच का यही विभाजन इस तरह के हर दूसरे app पर लागू होता है, यही कारण है कि an Immich backup that captures the library but not the database restores to an empty timeline होता है।
Upgrades: एक बार में एक ही major version
Nextcloud एक बार में केवल एक major version के upgrade का समर्थन करता है। आधिकारिक Docker image के साथ, 29 से 31 पर जाने पर upgrader कभी शुरू नहीं होता है। Entrypoint, occ upgrade चलाने से पहले major versions की तुलना करता है, Can't start Nextcloud because upgrading from <installed version> to <image version> is not supported. और उसके बाद It is only possible to upgrade one major version at a time. प्रिंट करता है, और exit कर जाता है। Container start होने से मना कर देता है (restart: unless-stopped के साथ यह बार-बार restart होता रहता है और वही लाइनें प्रिंट करता है), maintenance mode कभी चालू नहीं होता है, और data तथा database में कोई बदलाव नहीं होता है। Tag को अगले major version पर सेट करें और फिर से start करें।
Docker upgrade की प्रक्रिया यह है: backup लें, app और cron दोनों services में tag को एक major version आगे बढ़ाएं (जब 36 release होगा, जो Nextcloud की योजना के अनुसार February 2027 में है, तो 35 से 36 करें), फिर docker compose pull && docker compose up -d चलाएं, और उसके बाद docker compose logs -f app करें। Image का entrypoint मौजूदा data के मुकाबले नए code का पता लगाता है और स्वयं occ upgrade चलाता है। इसे बीच में न रोकें। जब logs शांत हो जाएं, तो docker compose exec -u www-data app php occ status चलाएं और versionstring की जांच करें कि apps वापस enabled हो गए हैं।
दो नियम जो आपको बचाएंगे: एक major version बढ़ाएं, verify करें, फिर अगला बढ़ाएं। और app service पर tag को कभी भी cron से मेल खाए बिना न बदलें, एक ही database के खिलाफ दो अलग-अलग Nextcloud versions का उपयोग करना data corruption का कारण बनता है।
वे त्रुटियाँ जो आपको वास्तव में दिखाई देंगी
"Your data directory is readable by other people. Please change the permissions to 0770 so that the directory cannot be listed by other people." डायरेक्टरी मोड का अंतिम अंक, जो अन्य उपयोगकर्ताओं के लिए होता है, शून्य नहीं है। अन्य उपयोगकर्ताओं के लिए कोई भी read, write या execute बिट इसे ट्रिगर करता है। ग्रुप बिट्स की कभी जाँच नहीं की जाती है, क्योंकि 0770 स्वयं ग्रुप को पूर्ण एक्सेस देता है। Nextcloud पहले स्वयं chmod 0770 का प्रयास करता है और केवल तभी चेतावनी देता है यदि वह विफल हो जाता है, जिसका अर्थ bind mount पर आमतौर पर यह होता है कि डायरेक्टरी का स्वामित्व UID 33 के पास नहीं है। sudo chown -R 33:33 /srv/nextcloud/data और sudo chmod 0770 /srv/nextcloud/data देखें।
"Your data directory is invalid. Ensure there is a file called ".ncdata" in the root of the data directory." bind mount किसी ऐसी जगह पॉइंट कर रहा है जहाँ Nextcloud ने कभी इनिशियलाइज़ नहीं किया, पाथ में कोई टाइपो है, या किसी वर्किंग इंस्टेंस के नीचे एक नई खाली डायरेक्टरी डाल दी गई है। जाँचें कि होस्ट पाथ वॉल्यूम लाइन से मेल खाता है या नहीं।
"Access through untrusted domain." अनुरोध में मौजूद hostname trusted_domains में नहीं है। NEXTCLOUD_TRUSTED_DOMAINS केवल पहली बार इंस्टॉल करते समय लागू होता है; उसके बाद इसे लाइव सेट करें: occ config:system:set trusted_domains 1 --value=cloud.example.com।
502 Bad Gateway, /var/log/nginx/error.log में connect() failed (111: Connection refused) while connecting to upstream के साथ। 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 को लॉकिंग बैकएंड के रूप में कॉन्फ़िगर करती है और पुराने लॉक्स दुर्लभ होते हैं। इसके बिना, लॉक्स डेटाबेस टेबल oc_file_locks में रहते हैं और राइटिंग के बीच में बंद हुआ अनुरोध पीछे पंक्तियाँ (rows) छोड़ देता है। मैन्युअल रूप से लॉक पंक्तियों को हटाने से पहले पुष्टि करें कि Redis वास्तव में उपयोग में है, occ config:system:get memcache.locking को Redis क्लास वापस करनी चाहिए।
"The PHP memory limit is below the recommended value of 512 MB." PHP_MEMORY_LIMIT को बढ़ाएं और कंटेनर को फिर से बनाएँ। याद रखें कि यह आपके worst-case सीलिंग पर क्या प्रभाव डालता है।
स्केल बढ़ने पर क्या समस्याएं आती हैं
पहली बाधा डेटा डायरेक्टरी का वॉल्यूम से बड़ा हो जाना है। VPS पर वॉल्यूम बढ़ाना एक resize और फिर filesystem को बड़ा करने की प्रक्रिया है। इसे 100% भर जाने के बाद करने के बजाय पहले से शेड्यूल करना बहुत कम कष्टदायक होता है। डिस्क उपयोग पर अभी अलर्ट सेट करें, बाद के लिए न छोड़ें।
दूसरी बाधा oc_filecache है। रो (row) की संख्या बढ़ने के साथ फाइल लिस्टिंग और सिंक स्कैन धीमे हो जाते हैं। इसका समाधान डेटाबेस का काम है: Postgres को तेज स्टोरेज पर रखें, इसे पर्याप्त shared memory का उपयोग करने दें, और कचरे व पुराने वर्ज़न्स को हमेशा जमा होने देने के बजाय retention सेटिंग्स के साथ हटाते रहें।
तीसरी बाधा प्रीव्यू जनरेशन है जो बाकी सभी चीजों के साथ प्रतिस्पर्धा करती है। एक छोटे बॉक्स पर, प्रीव्यू प्रोवाइडर्स को सीमित रखें और काम के घंटों के दौरान कभी भी occ preview:generate-all न चलाएं। यदि आप मुख्य रूप से फोन कैमरा रोल स्टोर कर रहे हैं, तो थंबनेल बनाने का काम एक अलग फोटो सर्वर पर होना चाहिए। RAM, फोन ऐप्स और बैकअप कमांड्स पर PhotoPrism और Immich की तुलना में बताया गया है कि Nextcloud बॉक्स की तुलना में इनकी लागत क्या है।
इसके अलावा, सच यह है कि अतिरिक्त सेवाओं को अपनी अलग मशीन की आवश्यकता होती है। Collabora और full-text search अलग-अलग रेजिडेंट सर्विसेज हैं जिनकी अपनी मेमोरी प्रोफाइल होती है। इन्हें उसी बॉक्स पर रखना जहाँ आपकी फाइलों की एकमात्र कॉपी मौजूद है, बिना किसी लाभ के विफलता के दायरे (failure domain) को बढ़ा देता है। यदि इन-ब्राउज़र डॉक्यूमेंट एडिटिंग वह अतिरिक्त सुविधा है जो आप चाहते हैं, तो OnlyOffice और Collabora को अलग करने वाली वेंडर RAM सीमाएं और कनेक्शन लिमिट्स यह तय करती हैं कि 2 से 4 GB का VPS किसे संभाल सकता है। जब वॉल्यूम का आकार सही न रहे, तो फाइल स्टोरेज को S3-compatible प्राइमरी स्टोरेज पर ले जाएं। ध्यान दें कि इससे बैकअप आसान होने के बजाय कठिन हो जाता है: डेटाबेस में अभी भी मेटाडेटा होता है, और इसे बकेट के साथ तालमेल बिठाकर डंप किया जाना चाहिए।
एक बार जब इंस्टेंस वास्तविक उपयोगकर्ताओं को सेवा देने लगे, तो इसके सामने Uptime Kuma लगाएं ताकि सिंक क्लाइंट्स को पता चलने से पहले आपको डाउनटाइम की जानकारी मिल जाए। एक प्राइवेट क्लाउड आपके अपने मेल सर्वर के साथ अच्छी तरह काम करता है। यदि आप सेवाओं को मैन्युअल रूप से जोड़ना नहीं चाहते हैं, तो Cloudron, CasaOS और Coolify उन प्लेटफॉर्म्स की तुलना करते हैं जो यह काम आपके लिए करते हैं। यदि उस सूची में अगला नंबर एक सेल्फ-होस्टेड सर्च इंजन का है, तो ऊपर बताई गई समस्याओं से अलग तरह की समस्याओं की अपेक्षा करें: SearXNG की 429 एरर्स या तो इसके अपने रेट लिमिटर से आती हैं या अपस्ट्रीम इंजन द्वारा आपके VPS IP को ब्लॉक करने से, और केवल लॉग ही आपको बता सकता है कि समस्या क्या है।
FAQ
क्या मैं Postgres के बजाय SQLite पर Nextcloud चला सकता हूँ?
आप ऐसा कर सकते हैं और official image आपको इसकी अनुमति भी देगी, लेकिन एक सिंगल डेस्कटॉप सिंक क्लाइंट द्वारा समानांतर अनुरोध (parallel requests) भेजने पर SQLSTATE[HY000]: General error: 5 database is locked और HTTP 500 त्रुटियाँ आएंगी। SQLite पूरे डेटाबेस पर राइट लॉक लगा देता है, जबकि Nextcloud लगातार फाइल लॉक, एक्टिविटी रो और जॉब स्टेट लिखता रहता है। Postgres या MariaDB से शुरुआत करें; occ db:convert-type मौजूद है लेकिन यह लाइव डेटा पर एक लंबी और जोखिम भरी माइग्रेशन प्रक्रिया है।
Nextcloud VPS को वास्तव में कितनी RAM की आवश्यकता होती है?
संसाधनों का निर्धारण उपयोगकर्ताओं की संख्या के बजाय समवर्ती उपयोग (concurrency) के आधार पर करें। सबसे खराब स्थिति में मेमोरी की खपत लगभग समवर्ती अनुरोधों की संख्या को PHP_MEMORY_LIMIT से गुणा करने पर प्राप्त होती है, जिसमें Postgres के shared buffers, प्रति कनेक्शन एक बैकएंड और प्रीव्यू जनरेशन के दौरान होने वाली खपत को जोड़ना होगा। यदि आप प्रीव्यू को सीमित करते हैं और swap का उपयोग करते हैं, तो 2 GB का सर्वर एक छोटे परिवार के लिए पर्याप्त है; यदि आप Collabora या full-text search जोड़ते हैं, तो आपको अतिरिक्त सेवाओं के लिए और अधिक संसाधनों की आवश्यकता होगी।
nginx reverse proxy के पीछे बड़ी फाइलें अपलोड करने पर वे विफल क्यों हो जाती हैं?
प्रॉक्सी पर मौजूद दो सेटिंग्स आमतौर पर इसका कारण होती हैं। यदि client_max_body_size को 1 MB के डिफ़ॉल्ट मान पर छोड़ दिया जाता है, तो nginx किसी भी बड़े अनुरोध को 413 (Request Entity Too Large) त्रुटि के साथ अस्वीकार कर देता है, जो आंशिक फाइल के बजाय nginx error log में दिखाई देता है। proxy_read_timeout / proxy_send_timeout के छोटे मान लंबी ट्रांसफर प्रक्रिया को बीच में ही रोक देते हैं। दोनों को पर्याप्त रूप से बढ़ाएं, proxy_request_buffering off को spool के बजाय stream पर सेट करें, और ऐप कंटेनर पर PHP_UPLOAD_LIMIT को भी उसी के अनुसार बढ़ाएं।
Nextcloud रीडायरेक्ट लूप में क्यों फंस जाता है या reverse proxy के बारे में चेतावनी क्यों देता है?
कंटेनर को 127.0.0.1 पर nginx नहीं दिखता, उसे 172.x में कहीं Docker bridge gateway दिखाई देता है। जब यह पता TRUSTED_PROXIES में मौजूद नहीं होता है, तो X-Forwarded-Proto: https हेडर को नजरअंदाज कर दिया जाता है, Nextcloud http:// URL जारी करता है, और प्रॉक्सी उन्हें वापस भेज देता है। TRUSTED_PROXIES को वास्तविक bridge subnet पर सेट करें और OVERWRITEPROTOCOL: https को पिन करें।
क्या मैं Nextcloud को सीधे 29 से 31 पर अपग्रेड कर सकता हूँ?
नहीं। Nextcloud प्रति अपग्रेड केवल एक प्रमुख संस्करण (major version) का समर्थन करता है। official Docker image पर entrypoint यह सुनिश्चित करता है कि occ upgrade चलने से पहले प्रमुख संस्करणों की जाँच हो, यदि संस्करण मेल नहीं खाते तो यह It is only possible to upgrade one major version at a time. प्रिंट करता है और बंद हो जाता है, जिससे कंटेनर शुरू नहीं होता और आपका डेटा तथा डेटाबेस सुरक्षित रहते हैं। इसके बजाय टैग को 30 पर सेट करें: बैकअप लें, app और cron दोनों सेवाओं पर टैग को एक प्रमुख संस्करण बढ़ाएं, docker compose pull && docker compose up -d करें, occ status के साथ सत्यापित करें, और फिर यही प्रक्रिया दोहराएं।