VPS पर Docker के साथ Chatwoot कैसे install करें
Docker Compose और Traefik का उपयोग करके Chatwoot को VPS पर तैनात करने का तरीका जानें। इसमें SMTP कॉन्फ़िगरेशन, Postgres बैकअप, सुरक्षित अपग्रेड और सही वर्शन टैग्स का उपयोग शामिल है।
आप क्या बना रहे हैं
VPS पर Chatwoot को self-host करने के लिए आप चार containers चलाते हैं: एक Rails web process, एक Sidekiq background worker, pgvector extension के साथ PostgreSQL, और Redis। Chatwoot एक open source customer support desk है, इसलिए आपको अपने नियंत्रण वाले सर्वर पर एक shared team inbox और एक website chat widget मिलता है। इसे install करने में लगभग बीस मिनट लगते हैं। इसके बाद की हर चीज़, जैसे mail delivery, backups, upgrades और sizing, यह तय करती है कि क्या यह सेवा एक साल बाद भी चल रही होगी।
प्रत्येक container का एक काम होता है। Rails, agent dashboard और widget API (application programming interface) को serve करता है। Sidekiq धीमे काम करता है: email भेजना, connected channels को poll करना, automation rules चलाना और reports तैयार करना। Postgres बातचीत, contacts, agent accounts और dashboard में आपके द्वारा बदली गई हर setting को सुरक्षित रखता है। Redis, Sidekiq queues और ActionCable pub/sub channel को संभालता है, जो page reload किए बिना dashboard में नया message push करता है। यहाँ Redis केवल एक अस्थायी cache नहीं है, क्योंकि इसे खोने का मतलब है queued jobs का खो जाना।
Upstream compose file में Postgres image, stock postgres image के बजाय pgvector/pgvector:pg16 है, क्योंकि Chatwoot का schema इसके AI features के लिए vector extension को enable करता है। यदि आप stock Postgres का उपयोग करते हैं, तो पहला database run ERROR: extension "vector" is not available के साथ रुक जाएगा, क्योंकि extension की control file उस image में नहीं होती है। वही image उपयोग करें जिसे upstream प्रदान करता है।
यह guide मानती है कि Docker और reverse proxy पहले से ही सर्वर पर काम कर रहे हैं। यदि वे काम नहीं कर रहे हैं, तो Docker Compose on a VPS से शुरुआत करें और फिर वापस आएँ।
Self-hosted Chatwoot के लिए कितने VPS की आवश्यकता है?
अगस्त 2026 तक, अपस्ट्रीम आवश्यकता पृष्ठ न्यूनतम 4 GB RAM और 4 CPU cores की मांग करता है, और इसे प्रतिदिन 10,000 conversations तक के लिए उपयुक्त बताता है। यह 8 GB RAM और 8 cores को प्रतिदिन 20,000 conversations तक के लिए निर्धारित करता है। यह कम से कम 1 GB swap की भी मांग करता है, और इसका कारण स्पष्ट है: ताकि upgrade के दौरान मशीन की memory समाप्त न हो जाए। file uploads को गिनने से पहले Postgres के लिए 5 GB से 10 GB disk space की योजना बनाएं।
अब सीधी बात। एक 2 GB का VPS Chatwoot को boot कर देगा, और दो agents तथा शांत inbox के साथ यह ठीक काम करता है। यह दो स्थितियों में विफल हो जाता है। पहली Sidekiq है, जिसे अपस्ट्रीम एक व्यस्त सर्वर पर 1 GB से अधिक मापता है, इसलिए email या report job का अचानक दबाव Rails, Postgres और Redis द्वारा अपना हिस्सा लेने से पहले ही मशीन की memory को सीमा से बाहर कर देता है। दूसरी स्थिति upgrade है, क्योंकि db:chatwoot_prepare migrations लागू करने के लिए एक नया Rails process boot करता है, और इस image पर Rails boot करने में कोई भी उपयोगी काम करने से पहले ही सैकड़ों megabytes खर्च हो जाते हैं।
आपको पहले कोई विनम्र चेतावनी नहीं मिलेगी। kernel का out of memory killer सबसे बड़े process को SIGKILL भेजता है, Docker देखता है कि container मर गया है, और restart: always इसे फिर से शुरू कर देता है। docker compose ps तब एक ऐसा container दिखाता है जो बार-बार Exited (137) पर लौटता है, जहाँ 137 का अर्थ है signal 9 द्वारा मारा जाना। इसकी पुष्टि sudo dmesg -T | grep -i "killed process" से करें, जो उस process का नाम बताता है जिसे kernel ने चुना है।
यदि 4 GB आपके बजट से बाहर है, तो 2 GB swap के साथ 2 GB का box चलाएं और यह स्वीकार करें कि load बढ़ने पर service के पूरी तरह बंद होने के बजाय response times धीमे हो जाएंगे। किसी भी स्थिति में प्रति service एक hard memory ceiling सेट करना उचित है, ताकि worker अपने साथ database को न गिरा सके। देखें Docker Compose में memory limits।
File uploads वह हिस्सा है जो आपके द्वारा निर्धारित सीमा के बिना बढ़ता है। ग्राहक द्वारा attach किया गया हर screenshot storage volume में जाकर वहीं रहता है, इसलिए यह मान लेने के बजाय कि disk database ने भरी है, docker system df -v पर नज़र रखें।
Compose file प्राप्त करें और एक version tag पिन करें
mkdir -p ~/chatwoot && cd ~/chatwoot
wget -O .env https://raw.githubusercontent.com/chatwoot/chatwoot/develop/.env.example
wget -O docker-compose.yaml https://raw.githubusercontent.com/chatwoot/chatwoot/develop/docker-compose.production.yaml
chmod 600 .envआपके द्वारा अभी डाउनलोड की गई फ़ाइल में image: chatwoot/chatwoot:latest लिखा है। कुछ भी करने से पहले इसे बदलें।
services:
base: &base
image: chatwoot/chatwoot:v4.16.2
env_file: .env
volumes:
- storage_data:/app/storagelatest का अर्थ है कि अगला docker compose pull आपको वह सब कुछ दे देगा जो उस सुबह पब्लिश किया गया था, जिसमें कोई बड़ा version या ऐसे migrations हो सकते हैं जिनके बारे में आपने कभी नहीं पढ़ा। Chatwoot migrations को व्यावहारिक रूप से reverse नहीं किया जा सकता है, इसलिए गलती से version update होने का मतलब है backup से restore करना, न कि उसे undo करना। tag को पिन करें और उसे सोच-समझकर बदलें। अगस्त 2026 तक v4.16.2 वर्तमान release था; आज आपको जो tag पिन करना चाहिए, उसके लिए releases page देखें।
base service एक YAML anchor है जिसे rails और sidekiq दोनों merge करते हैं, इसलिए एक जगह tag बदलने से वह दोनों के लिए बदल जाता है। फ़ाइल में रहते हुए, सबसे ऊपर वाली version: '3' लाइन को हटा दें। आधुनिक Compose इसे ignore करता है और हर command पर the attribute 'version' is obsolete, it will be ignored प्रिंट करता है।
.env फ़ाइल भरें
सबसे पहले secret जनरेट करें। Upstream एक alphanumeric मान का अनुरोध करता है, क्योंकि जब मान किसी shell या YAML parser से गुजरता है तो विशेष वर्ण (special characters) खराब हो सकते हैं।
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''फिर इन keys को .env में सेट करें।
SECRET_KEY_BASE=<the 63 characters you just generated>
FRONTEND_URL=https://support.example.com
FORCE_SSL=true
DEFAULT_LOCALE=en
ENABLE_ACCOUNT_SIGNUP=true
POSTGRES_HOST=postgres
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=<long random string>
POSTGRES_DATABASE=chatwoot
REDIS_URL=redis://redis:6379
REDIS_PASSWORD=<a different long random string>
RAILS_ENV=production
INSTALLATION_ENV=docker
ACTIVE_STORAGE_SERVICE=localPOSTGRES_HOST=postgres और redis://redis:6379 Compose service के नाम हैं, जो project के डिफ़ॉल्ट नेटवर्क पर resolve होते हैं। FRONTEND_URL केवल दिखावट नहीं है। Chatwoot विजेट स्क्रिप्ट URL और उससे बाहर जाने वाले हर ईमेल के अंदर के लिंक को बनाता है, इसलिए गलत मान होने पर आपको ऐसे पासवर्ड रीसेट लिंक मिलेंगे जो एक ऐसे होस्ट की ओर इशारा करेंगे जो जवाब नहीं देता।
अब upstream फ़ाइल में एक जाल है। postgres सर्विस .env को नहीं पढ़ती है। इसमें अपना खुद का environment ब्लॉक है जिसमें POSTGRES_PASSWORD= खाली छोड़ा गया है, इसलिए केवल .env में पासवर्ड सेट करने से डेटाबेस बिना पासवर्ड के रह जाता है और एप्लिकेशन के पास पासवर्ड आ जाता है। सर्विस को उसी variable पर पॉइंट करें:
postgres:
image: pgvector/pgvector:pg16
restart: always
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=chatwoot
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}Compose ${...} प्रतिस्थापन (substitution) के लिए project डायरेक्टरी से .env को पढ़ता है, इसलिए अब दोनों तरफ एक ही स्ट्रिंग पहुँचती है। यदि आप इसे गलत करते हैं तो Rails PG::ConnectionBad: FATAL: password authentication failed for user "postgres" के साथ रुक जाता है।
एक व्यवहार लगभग सभी को आश्चर्यचकित करता है: Postgres इमेज केवल तभी POSTGRES_PASSWORD लागू करती है जब वह एक खाली डेटा डायरेक्टरी को इनिशियलाइज़ करती है। बाद में मान बदलने का कोई प्रभाव नहीं पड़ता, क्योंकि initdb दूसरी बार कभी नहीं चलता। यदि आपने स्टैक को एक बार शुरू कर लिया है, तो इसे डेटाबेस के अंदर बदलें।
docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"ENABLE_ACCOUNT_SIGNUP=true अस्थायी है। यह सार्वजनिक पंजीकरण फ़ॉर्म खोलता है ताकि आप पहला अकाउंट बना सकें। इसे false पर सेट करें और जैसे ही आपका अकाउंट बन जाए, docker compose up -d को फिर से चलाएं, अन्यथा जो कोई भी URL ढूंढेगा वह आपके सपोर्ट डेस्क पर रजिस्टर कर सकता है। उसके बाद एजेंट्स आमंत्रण (invitation) द्वारा आते हैं और उनके पासवर्ड केवल इसी एक ऐप में रहते हैं, जो तब तक ठीक है जब तक आप आधा दर्जन सर्विस नहीं चला रहे हैं और प्रत्येक में अलग अकाउंट लिस्ट से थक नहीं जाते, जिस बिंदु पर Authentik जैसा self-hosted identity provider वह चीज़ है जो उन्हें बदल देती है।
.env में अब इस स्टैक के सभी secrets सादे टेक्स्ट (plain text) में हैं, इसलिए इसे mode 600 पर रखें और git से बाहर रखें। Compose env फ़ाइलों को कैसे पढ़ता है, और secrets कहाँ लीक होते हैं उन बारीकियों को कवर करता है, जिसमें env_file और environment के बीच का अंतर भी शामिल है।
Chatwoot को अपने मौजूदा Traefik के पीछे रखें
एक ही application के लिए दूसरा reverse proxy न बनाएँ। यदि Traefik पहले से ही इस सर्वर पर अन्य containers के लिए TLS (transport layer security) terminate कर रहा है, तो Chatwoot को एक label block के साथ उसमें जोड़ें। यदि आपने अभी तक ऐसा नहीं किया है, तो इसे एक बार Traefik in front of several Docker Compose apps के साथ सेटअप करें, फिर यहाँ वापस आएँ।
Upstream की docker-compose.yaml को stock के करीब रखें ताकि आप बाद में इसकी तुलना एक नई copy से कर सकें, और अपने बदलावों को एक override file में रखें। Compose docker-compose.override.yaml को स्वचालित रूप से merge करता है, और splitting Compose across multiple files merge के नियमों को समझाता है।
services:
rails:
networks:
- default
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.chatwoot.rule=Host(`support.example.com`)"
- "traefik.http.routers.chatwoot.entrypoints=websecure"
- "traefik.http.routers.chatwoot.tls.certresolver=letsencrypt"
- "traefik.http.services.chatwoot.loadbalancer.server.port=3000"
networks:
proxy:
external: trueअपने स्वयं के entrypoint और certresolver नामों का उपयोग करें। Container को Traefik के समान Docker network पर होना चाहिए, जो कि proxy entry का कार्य है, और इसे default पर भी बने रहना चाहिए अन्यथा यह Postgres और Redis से संपर्क खो देगा। यह दूसरी लाइन वह है जिसे लोग अक्सर भूल जाते हैं।
ports: block को न बदलें। Upstream इसे 127.0.0.1:3000 पर bind करता है, जो केवल loopback है, इसलिए यह internet से पहुँच योग्य नहीं है और यह curl -I http://127.0.0.1:3000 के साथ सर्वर के भीतर से testing के लिए उपयोगी बना रहता है।
Agent dashboard live message delivery के लिए /cable पर एक websocket खुला रखता है। Traefik बिना किसी अतिरिक्त configuration के HTTP upgrade को forward कर देता है, इसलिए इसमें कुछ भी जोड़ने की आवश्यकता नहीं है। यदि आप बाद में Traefik के सामने कोई CDN या अन्य proxy लगाते हैं, तो वहाँ websockets की अनुमति दें, क्योंकि इसका लक्षण यह है कि dashboard सामान्य रूप से load होता है जबकि नए संदेश केवल manual refresh के बाद ही दिखाई देते हैं।
डेटाबेस को इनिशियलाइज़ करें और स्टैक शुरू करें
सबसे पहले डेटा सेवाओं को चालू करें और Postgres को अपना पहला रन पूरा करने दें।
docker compose up -d postgres redis
docker compose logs postgres | tail -n 5database system is ready to accept connections के लिए प्रतीक्षा करें। फिर स्कीमा बनाएँ।
docker compose run --rm rails bundle exec rails db:chatwoot_prepareयह डेटाबेस के न होने पर उसे बनाता है, फिर स्कीमा और डिफ़ॉल्ट सीड डेटा लोड करता है। यह माइग्रेशन लाइनें प्रिंट करता है और सफलतापूर्वक बंद हो जाता है। यदि यह postgres:5432 - no response प्रिंट करता रहता है, तो एंट्रीपॉइंट ऐसे डेटाबेस की प्रतीक्षा कर रहा है जो अभी कनेक्शन स्वीकार नहीं कर रहा है, जिसका अर्थ आमतौर पर यह है कि initdb अभी भी काम कर रहा है। प्रतीक्षा करें, Postgres लॉग पढ़ें, और फिर इसे दोबारा चलाएँ। यदि यह vector एक्सटेंशन पर रुक जाता है, तो आपने pgvector इमेज को स्टॉक Postgres से बदल दिया है।
docker compose up -d
docker compose ps
docker compose logs --tail 30 railsसभी चार कंटेनरों को Up पढ़ना चाहिए, और rails लॉग को http://0.0.0.0:3000 पर लिसन करने वाली Puma लाइन के साथ समाप्त होना चाहिए। फिर पब्लिक पाथ की जाँच करें:
curl -sI https://support.example.com | head -n 1HTTP/2 200 का मतलब है कि पूरी चेन काम कर रही है। Traefik से 404 का मतलब है कि राउटर नियम मेल नहीं खाया, आमतौर पर यह होस्टनेम में टाइपिंग की गलती होती है। 502 का मतलब है कि Traefik ने राउटर से मिलान तो किया लेकिन कंटेनर तक नहीं पहुँच सका, जो लगभग हमेशा गायब proxy नेटवर्क या loadbalancer.server.port के 3000 न होने के कारण होता है।
URL खोलें, /app/auth/signup पर अपना अकाउंट बनाएँ, फिर ENABLE_ACCOUNT_SIGNUP=false सेट करें और फॉर्म को बंद करने के लिए docker compose up -d चलाएँ।
SMTP के बिना पासवर्ड रीसेट और ईमेल वार्तालाप विफल क्यों होते हैं
SMTP (Simple Mail Transfer Protocol) सेटिंग्स के बिना Chatwoot एक ऐसा सपोर्ट डेस्क है जो मेल नहीं भेज सकता, और यह केवल नोटिफिकेशन से कहीं अधिक को प्रभावित करता है। पासवर्ड रीसेट काम करना बंद कर देते हैं, इसलिए यदि कोई एडमिन लॉक हो जाता है, तो वह लॉक ही रहता है। एजेंट आमंत्रण काम करना बंद कर देते हैं, क्योंकि आमंत्रण एक ईमेल होता है। ईमेल वार्तालाप में ग्राहक को जवाब देना बंद हो जाता है, जिससे वार्तालाप केवल एक तरफा रह जाता है। यह वह चरण है जिसे लोग छोड़ देते हैं और फिर अपने सबसे खराब सप्ताह के दौरान इसका पता चलता है।
इसकी प्रक्रिया स्पष्ट है। बिना SMTP सेटिंग्स के, ActionMailer पोर्ट 25 पर localhost पर डिलीवरी करने के अपने डिफ़ॉल्ट पर बना रहता है। Rails कंटेनर के अंदर कोई मेल सर्वर नहीं होता है, इसलिए डिलीवरी जॉब Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 उत्पन्न करती है। मेल एक बैकग्राउंड जॉब से बाहर जाता है, इसलिए वह लाइन Sidekiq लॉग में दर्ज होती है, न कि Rails लॉग में। इस बीच, "forgot password" पर क्लिक करने वाला व्यक्ति एक सकारात्मक पुष्टिकरण देखता है और उसे कुछ भी प्राप्त नहीं होता है।
MAILER_SENDER_EMAIL=Support <support@example.com>
SMTP_DOMAIN=example.com
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=support@example.com
SMTP_PASSWORD=<the relay password>
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=trueSTARTTLS के साथ पोर्ट 587 का उपयोग करें, जो कनेक्शन को प्लेन टेक्स्ट में खोलता है और प्रमाणीकरण से पहले इसे एन्क्रिप्टेड में अपग्रेड करता है। अधिकांश VPS प्रदाता स्पैम को सीमित करने के लिए आउटबाउंड पोर्ट 25 को ब्लॉक करते हैं, इसलिए 587 पर एक रिले आमतौर पर एकमात्र विकल्प है जो कनेक्ट हो पाएगा। SMTP_DOMAIN वह डोमेन है जिसे आपका सर्वर SMTP वार्तालाप के दौरान घोषित करता है, और कुछ रिले बेमेल होने पर इसे अस्वीकार कर देते हैं।
सेटिंग्स लागू करें और वर्कर को मॉनिटर करें:
docker compose up -d rails sidekiq
docker compose logs -f sidekiqलॉगिन पेज से पासवर्ड रीसेट ट्रिगर करें। एक सफल डिलीवरी Sidekiq लॉग में मेलर जॉब को सामान्य रूप से समाप्त होते हुए दिखाती है। विफलता होने पर एक्सेप्शन क्लास दिखाई देती है, और फिर Sidekiq बढ़ते बैकऑफ़ के साथ पुनः प्रयास करता है, यही कारण है कि एक खराब रिले घंटों तक हर कुछ मिनटों में वही त्रुटि उत्पन्न करता है।
दो प्रकार के अस्वीकरण सामान्य हैं, और इनमें से कोई भी Chatwoot का बग नहीं है। 535 Authentication failed का अर्थ है कि उस रिले के लिए उपयोगकर्ता नाम या पासवर्ड गलत है, और कई प्रदाता अकाउंट पासवर्ड के बजाय एप्लिकेशन पासवर्ड की मांग करते हैं। 550 Sender address rejected का अर्थ है कि MAILER_SENDER_EMAIL एक ऐसा पता है जिससे रिले मेल नहीं भेजेगा, इसलिए यह एक ऐसा मेलबॉक्स या डोमेन होना चाहिए जिसे आपने उनके साथ सत्यापित किया हो।
वार्तालाप में ईमेल प्राप्त करना एक अलग कार्य है। इसके लिए MAILER_INBOUND_EMAIL_DOMAIN और RAILS_INBOUND_EMAIL_SERVICE की आवश्यकता होती है, साथ ही एक मेल सर्वर जो आने वाले संदेशों को Chatwoot तक पहुँचाए। रिले किराए पर लेना सबसे तेज़ रास्ता है। यदि आप पूरे मेल पथ का स्वामित्व स्वयं रखना चाहते हैं, तो Mailcow के साथ अपना स्वयं का मेल सर्वर चलाना यह बताता है कि उस प्रतिबद्धता में वास्तव में क्या शामिल है।
क्या बैकअप लें, और यह कैसे सुनिश्चित करें कि रिस्टोर काम करता है
Chatwoot बैकअप के चार हिस्से होते हैं, और इनमें से किसी एक को भी छोड़ने का मतलब है कि रिस्टोर करने के बजाय आपको सब कुछ फिर से बनाना पड़ेगा।
- Postgres डेटाबेस, जिसमें बातचीत, संपर्क, एजेंट अकाउंट और हर सेटिंग सुरक्षित रहती है।
storage_dataवॉल्यूम, क्योंकिACTIVE_STORAGE_SERVICE=localअपलोड की गई फाइलों को डिस्क पर लिखता है और Postgres में केवल उनका संदर्भ (reference row) रखता है।.envफाइल, क्योंकि इसमेंSECRET_KEY_BASEऔरACTIVE_RECORD_ENCRYPTION_*कुंजियाँ (keys) होती हैं।- compose फाइलें, क्योंकि वे उस सटीक इमेज टैग को रिकॉर्ड करती हैं जिससे आपका डेटाबेस स्कीमा मेल खाता है।
यदि आप केवल डेटाबेस को रिस्टोर करते हैं, तो सभी बातचीत तो वापस आ जाएंगी लेकिन अटैचमेंट काम नहीं करेंगे, क्योंकि डेटाबेस की पंक्तियाँ उन फाइलों की ओर इशारा करती हैं जो अब डिस्क पर मौजूद नहीं हैं।
cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump-T महत्वपूर्ण है। इसके बिना Compose एक स्यूडो टर्मिनल आवंटित करता है, जो स्ट्रीम में न्यूलाइन बाइट्स को फिर से लिख देता है, जिससे आपको एक ऐसी डंप फाइल मिलती है जिसे pg_restore स्वीकार नहीं करता है। -Fc कस्टम फॉर्मेट है, जो डेटा को कंप्रेस करता है और pg_restore को चुनिंदा रूप से काम करने की अनुमति देता है।
docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/storage-$(date +%F).tgz -C /data .वॉल्यूम का नाम आपके प्रोजेक्ट डायरेक्टरी के नाम और _storage_data का संयोजन होता है। उस कमांड पर भरोसा करने से पहले docker volume ls | grep storage_data के साथ इसकी पुष्टि करें, क्योंकि यदि आप किसी ऐसे वॉल्यूम का नाम देते हैं जो मौजूद नहीं है, तो Docker त्रुटि देने के बजाय एक खाली वॉल्यूम बना देता है। आपको एक वैध लेकिन खाली आर्काइव मिल जाएगा और कोई त्रुटि भी नहीं दिखेगी। बाद में ls -lh storage-*.tgz के साथ आकार की जाँच करें।
ये दोनों फाइलें अब उसी डिस्क पर हैं जिसे वे सुरक्षित कर रही हैं, जो आपको किसी भी जोखिम से नहीं बचाती हैं। इन्हें सर्वर से बाहर भेजें और एन्क्रिप्ट करें, क्योंकि डेटाबेस डंप में हर ग्राहक का संदेश सादे टेक्स्ट (plain text) में होता है। restic के साथ एन्क्रिप्टेड ऑफ-साइट बैकअप शेड्यूलिंग और रिटेंशन के पहलुओं को कवर करता है।
रिस्टोर ड्रिल, इसे जरूरत पड़ने से पहले चलाकर देखें
रिस्टोर को लाइव सर्वर पर नहीं, बल्कि दूसरे VPS पर करें। .env, compose फाइलें और दोनों आर्काइव को कॉपी करें, फिर चलाएं:
docker compose up -d postgres
docker compose exec -T postgres pg_restore -U postgres -d chatwoot --clean --if-exists < db-2026-08-10.dump
docker run --rm -v chatwoot_storage_data:/data -v "$PWD":/backup alpine \
sh -c 'rm -rf /data/* && tar xzf /backup/storage-2026-08-10.tgz -C /data'
docker compose up -d--clean --if-exists लोड करने से पहले मौजूदा ऑब्जेक्ट्स को हटा देता है, इसलिए इसे केवल उसी डेटाबेस पर चलाएं जिसे आप खोने के लिए तैयार हैं। इसके बाद साइन इन करें और ऐसी बातचीत खोलें जिसमें अटैचमेंट हो। यदि संदेश सूची लोड हो जाती है और फाइल डाउनलोड हो जाती है, तो बैकअप सही है।
अलग SECRET_KEY_BASE के साथ रिस्टोर करने पर सभी सेशन कुकीज़ अमान्य हो जाती हैं, इसलिए सभी को फिर से साइन इन करना होगा। अलग ACTIVE_RECORD_ENCRYPTION_* कुंजियों के साथ रिस्टोर करना और भी बुरा है: Chatwoot चैनल क्रेडेंशियल्स रखने वाले कॉलम को डिक्रिप्ट नहीं कर पाएगा और ActiveRecord::Encryption::Errors::Decryption त्रुटि देगा। इसीलिए .env बैकअप सूची में शामिल है।
Chatwoot को नए tag पर अपग्रेड कैसे करें
कमांड्स से अधिक महत्वपूर्ण उनका क्रम है।
- अपने वर्तमान tag और target tag के बीच के release notes पढ़ें, ताकि किसी भी आवश्यक मैन्युअल चरण की जानकारी मिल सके।
- डेटाबेस का एक नया डंप और स्टोरेज का आर्काइव लें, और सुनिश्चित करें कि दोनों फाइलों का आकार सामान्य है।
docker-compose.yamlमेंbaseसर्विस पर image tag को एडिट करें।- नई इमेज को pull करें, स्टैक को रोकें, माइग्रेशन चलाएं, और फिर से शुरू करें।
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose imagesमाइग्रेशन से पहले इमेज को pull करें, क्योंकि माइग्रेशन नई इमेज से ही चलना चाहिए: पुरानी इमेज में नई माइग्रेशन फाइलें नहीं होती हैं। माइग्रेशन से पहले स्टैक को रोकें, क्योंकि पुराना कोड और नया स्कीमा एक-दूसरे के अनुकूल नहीं होते हैं, इसलिए चलता हुआ पुराना Rails प्रोसेस एरर दे सकता है या ऐसी पंक्तियाँ लिख सकता है जिन्हें नया स्कीमा स्वीकार नहीं करेगा। स्टैक को रोकने से वह मेमोरी भी खाली हो जाती है जिसकी माइग्रेशन को आवश्यकता होती है, और यही कारण है कि अपस्ट्रीम स्वैप (swap) का उपयोग करने का सुझाव देता है।
docker compose images यह प्रिंट करता है कि प्रत्येक कंटेनर वास्तव में कौन सा tag चला रहा है, जिससे यह पता चल जाता है कि कहीं आपने tag एडिट तो कर दिया लेकिन pull करना भूल तो नहीं गए।
एक साथ कई वर्ज़न आगे न बढ़ें। पुराने इंस्टॉलेशन के लिए अपस्ट्रीम की सलाह यह है कि बीच के वर्ज़न्स (intermediate tags) से होकर आगे बढ़ें, क्योंकि माइग्रेशन फाइल्स को बेस स्कीमा में शामिल करने के बाद हटा दिया जाता है, इसलिए बहुत पुराना डेटाबेस ऐसी स्थिति में पहुँच सकता है जहाँ से आगे बढ़ने का कोई रास्ता न हो। एक बार में एक माइनर वर्ज़न आगे बढ़ें और प्रत्येक के बाद prepare चरण चलाएं।
यदि माइग्रेशन चलने से पहले Rails शुरू हो जाता है, तो यह सर्विस देने से मना कर देता है और ActiveRecord::PendingMigrationError: Migrations are pending लॉग करता है। यदि restart: always सेट है, तो कंटेनर बार-बार रीस्टार्ट होता रहता है, जिससे docker compose ps में uptime हर कुछ सेकंड में रीसेट होता दिखता है। prepare चरण चलाएं और यह समस्या ठीक हो जाएगी।
रोलबैक करने का अर्थ है पुराने tag को वापस लाना और डंप को रिस्टोर करना। कोई ऐसा रिवर्स माइग्रेशन पाथ नहीं है जिस पर आप भरोसा कर सकें, इसीलिए चरण 2 का पालन करना आवश्यक है।
विफलता के प्रकार और दिखाई देने वाले संदेश
Traefik से 502 Bad Gateway. राउटर ने मैच ढूँढ लिया लेकिन backend ने कोई उत्तर नहीं दिया। जाँचें कि docker compose ps में rails को Up के रूप में दिखाया गया है, फिर docker network inspect proxy चलाएँ और सुनिश्चित करें कि rails container अपनी container सूची में दिखाई दे रहा है। जो container attached नहीं है, वह Traefik को दिखाई नहीं देता, इसलिए request राउटर से मैच तो हो जाती है लेकिन आगे कहीं नहीं पहुँचती।
डैशबोर्ड लोड होता है लेकिन नए संदेशों के लिए रिफ्रेश की आवश्यकता होती है. /cable के लिए websocket सफल नहीं हो पा रहा है, या FRONTEND_URL ब्राउज़र बार में दिए गए पते से मेल नहीं खाता है। मेल न खाने का मतलब है कि पेज किसी अलग origin पर websocket खोलने का प्रयास कर रहा है, जिसे ब्राउज़र ब्लॉक कर देता है।
FATAL: password authentication failed for user "postgres". .env में दिया गया पासवर्ड और Postgres डेटा वॉल्यूम में मौजूद पासवर्ड अलग-अलग हैं। इसे चलते हुए container के अंदर ALTER USER से ठीक करें, क्योंकि .env को दोबारा एडिट करने से पहले से initialised डेटाबेस में कोई बदलाव नहीं होगा।
NOAUTH Authentication required. Redis --requirepass के साथ चल रहा है लेकिन application बिना पासवर्ड के कनेक्ट हो गई है, जिसका अर्थ है कि REDIS_PASSWORD, .env में मौजूद नहीं है या उसे लागू नहीं किया गया है। इसे सीधे docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping के साथ टेस्ट करें, जिसे PONG का उत्तर देना चाहिए।
Containers का कोड 137 के साथ बंद होना. यह SIGKILL है, और छोटे सर्वर पर इसका मतलब kernel का out of memory killer है। Swap जोड़ें, प्रति-service मेमोरी सीमा निर्धारित करें, या किसी बड़े प्लान पर शिफ्ट हों।
FAQ
Chatwoot self-hosted VPS के लिए कितनी RAM की आवश्यकता है?
अगस्त 2026 तक, upstream कम से कम 4 GB RAM और 4 CPU cores की सिफारिश करता है, जो प्रतिदिन 10,000 conversations तक के लिए पर्याप्त है। 20,000 conversations के लिए 8 GB RAM और 8 cores की आवश्यकता होती है। कम से कम 1 GB swap जरूर जोड़ें, क्योंकि upgrade के दौरान migrations लागू करने के लिए एक दूसरा Rails process चलता है, जहाँ कम RAM वाले सर्वर memory की कमी के कारण crash हो जाते हैं। 2 GB का VPS कुछ agents के लिए boot हो सकता है और काम भी कर सकता है, लेकिन load बढ़ने पर केवल Sidekiq ही 1 GB से अधिक memory ले सकता है। इसलिए, व्यस्त समय और upgrades के दौरान containers के exit code 137 के साथ बंद होने की उम्मीद रखें।
Chatwoot password reset emails क्यों नहीं आते हैं?
ऐसा इसलिए होता है क्योंकि SMTP settings कॉन्फ़िगर नहीं हैं। ActionMailer डिफ़ॉल्ट रूप से port 25 पर localhost को mail भेजने का प्रयास करता है, जबकि container के अंदर कोई mail server नहीं होता है। यह job Sidekiq में Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 error के साथ विफल हो जाती है, जबकि browser में सफलता का संदेश दिखाई देता है। .env में SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD और MAILER_SENDER_EMAIL को सेट करें, rails और sidekiq services को restart करें, और फिर reset trigger करते समय docker compose logs -f sidekiq को monitor करें।
Chatwoot को restore करने के लिए मुझे क्या backup लेना चाहिए?
Postgres database, storage_data Docker volume, .env file और compose files का backup लें। केवल database का backup पर्याप्त नहीं है, क्योंकि upload की गई files volume में रहती हैं और Postgres में केवल उनके references होते हैं। इसलिए, केवल database restore करने पर आपको टूटे हुए attachments वाली conversations मिलेंगी। .env महत्वपूर्ण है क्योंकि एक अलग SECRET_KEY_BASE सभी users को logout कर देता है, और अलग ACTIVE_RECORD_ENCRYPTION_* keys encrypted columns को अपठनीय बना देती हैं।
Database को खराब किए बिना Chatwoot को upgrade कैसे करें?
Backup लें, अपनी compose file में image tag बदलें, और फिर docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare और docker compose up -d चलाएँ। पहले image pull करें क्योंकि migrations को नई image से चलना चाहिए, और stack को पहले stop करें क्योंकि नए schema के साथ पुराना code errors उत्पन्न करता है। पुराने install पर, एक बार में एक ही minor version upgrade करें, क्योंकि migrations को base schema में शामिल करने के बाद उन्हें हटा दिया जाता है।
क्या मैं pgvector के बजाय standard postgres image का उपयोग कर सकता हूँ?
नहीं। Chatwoot का schema vector extension को सक्षम करता है, इसलिए standard postgres image db:chatwoot_prepare के दौरान ERROR: extension "vector" is not available error के साथ विफल हो जाती है, क्योंकि उस image में extension की control file मौजूद नहीं होती है। upstream compose file से pgvector/pgvector:pg16 का उपयोग करें, या ऐसी कोई अन्य image उपयोग करें जिसमें आपके Postgres major version के लिए pgvector शामिल हो।