Cara Self-host Chatwoot di VPS Menggunakan Docker
Panduan lengkap memasang Chatwoot menggunakan Docker Compose dan Traefik. Pelajari cara mengurus Postgres, konfigurasi SMTP, sandaran data, serta proses naik taraf yang selamat.
Apa yang anda sedang bina
Untuk mengehos sendiri Chatwoot pada VPS, anda perlu menjalankan empat kontena: proses web Rails, pekerja latar belakang Sidekiq, PostgreSQL dengan sambungan pgvector, dan Redis. Chatwoot ialah meja bantuan sokongan pelanggan sumber terbuka, jadi anda mendapat peti masuk pasukan kongsi dan widget sembang laman web pada pelayan yang anda kawal. Pemasangan mengambil masa kira-kira dua puluh minit. Segala perkara selepas itu, seperti penghantaran e-mel, sandaran, naik taraf dan penentuan saiz, adalah perkara yang menentukan sama ada sistem tersebut masih berjalan dalam tempoh setahun.
Setiap kontena mempunyai satu tugas. Rails melayani papan pemuka ejen dan API (antara muka pengaturcaraan aplikasi) widget. Sidekiq menjalankan kerja yang perlahan: menghantar e-mel, meninjau saluran yang disambungkan, menjalankan peraturan automasi dan membina laporan. Postgres menyimpan perbualan, kenalan, akaun ejen dan setiap tetapan yang anda ubah dalam papan pemuka. Redis menyimpan baris gilir Sidekiq dan saluran pub/sub ActionCable yang menolak mesej baharu ke dalam papan pemuka yang terbuka tanpa memuat semula halaman. Redis di sini bukanlah cache sementara, kerana kehilangannya bermakna kehilangan kerja yang berada dalam baris gilir.
Imej Postgres dalam fail compose hulu ialah pgvector/pgvector:pg16 dan bukannya imej postgres standard, kerana skema Chatwoot mendayakan sambungan vector untuk ciri AI-nya. Jika anda menukar kepada Postgres standard, pangkalan data pertama yang dijalankan akan terhenti dengan ERROR: extension "vector" is not available, kerana fail kawalan sambungan tersebut tiada dalam imej itu. Gunakan imej yang dibekalkan oleh pihak hulu.
Panduan ini mengandaikan Docker dan reverse proxy sudah berfungsi pada pelayan anda. Jika belum, mulakan dengan Docker Compose pada VPS dan kembali semula ke sini.
Berapakah keperluan VPS untuk Chatwoot yang dihoskan sendiri?
Sehingga Ogos 2026, halaman keperluan rasmi menetapkan 4 GB RAM dan 4 teras CPU sebagai minimum, yang dinilai mampu mengendalikan sehingga 10,000 perbualan sehari. Spesifikasi 8 GB RAM dan 8 teras CPU pula dinilai untuk sehingga 20,000 perbualan sehari. Ia juga memerlukan sekurang-kurangnya 1 GB swap, dengan alasan yang jelas: supaya mesin tidak kehabisan memori semasa proses naik taraf. Sediakan 5 GB hingga 10 GB ruang cakera untuk Postgres sebelum mengambil kira muat naik fail.
Sekarang, realitinya. VPS 2 GB boleh memulakan Chatwoot, dan ia kelihatan stabil dengan dua ejen serta peti masuk yang tidak sibuk. Ia akan gagal dalam dua keadaan. Pertama ialah Sidekiq, yang menurut pembangun memerlukan lebih 1 GB pada pelayan yang sibuk, jadi lonjakan e-mel atau tugasan laporan akan menyebabkan penggunaan memori melebihi kapasiti sebelum Rails, Postgres dan Redis mengambil bahagian masing-masing. Kedua ialah proses naik taraf, kerana db:chatwoot_prepare memulakan proses Rails baharu untuk melaksanakan migrasi, dan proses but Rails pada imej ini memakan ratusan megabait sebelum ia melakukan sebarang kerja yang berguna.
Anda tidak akan menerima amaran awal. Fungsi out of memory killer pada kernel akan menghantar SIGKILL kepada proses yang paling besar, Docker melihat kontena tersebut mati, dan restart: always memulakannya semula. docker compose ps kemudian menunjukkan kontena yang terus kembali ke Exited (137), di mana 137 bermaksud ia dimatikan oleh signal 9. Sahkan perkara ini dengan sudo dmesg -T | grep -i "killed process", yang akan menamakan proses yang dipilih oleh kernel.
Jika 4 GB di luar bajet anda, jalankan mesin 2 GB dengan 2 GB swap dan terima hakikat bahawa masa tindak balas akan menjadi lebih perlahan di bawah beban berbanding servis yang mati terus. Menetapkan had memori yang ketat bagi setiap servis adalah langkah yang wajar dilakukan, supaya pekerja (worker) tidak menyebabkan pangkalan data terhenti. Lihat had memori dalam Docker Compose.
Muat naik fail adalah bahagian yang berkembang tanpa had yang anda tetapkan. Setiap tangkapan skrin yang dilampirkan oleh pelanggan akan disimpan dalam volum storan dan kekal di situ, jadi pantau docker system df -v dan jangan menganggap pangkalan data sebagai punca cakera penuh.
Dapatkan fail compose dan tetapkan tag versi
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 .envFail yang baru anda muat turun menyatakan image: chatwoot/chatwoot:latest. Tukar nilai tersebut sebelum melakukan sebarang tindakan lain.
services:
base: &base
image: chatwoot/chatwoot:v4.16.2
env_file: .env
volumes:
- storage_data:/app/storagelatest bermakna docker compose pull seterusnya memberikan anda apa sahaja yang diterbitkan pada pagi itu, yang mungkin merupakan versi utama dengan migrasi yang tidak pernah anda baca. Migrasi Chatwoot secara praktikalnya tidak boleh diterbalikkan, jadi lompatan yang tidak disengajakan bermakna anda perlu memulihkan daripada sandaran, bukan sekadar membatalkan tindakan. Tetapkan tag tersebut dan tukarkannya secara sengaja. v4.16.2 merupakan keluaran semasa setakat Ogos 2026; semak halaman keluaran untuk tag yang perlu anda tetapkan hari ini.
Servis base ialah anchor YAML yang digabungkan oleh rails dan sidekiq, jadi menukar tag di satu tempat akan mengubahnya untuk kedua-duanya. Semasa anda berada dalam fail tersebut, padamkan baris version: '3' di bahagian atas. Compose moden mengabaikannya dan mencetak the attribute 'version' is obsolete, it will be ignored pada setiap arahan.
Isi fail .env
Jana rahsia tersebut terlebih dahulu. Pihak upstream meminta nilai alfanumerik, kerana aksara khas akan rosak apabila nilai tersebut melalui shell atau parser YAML.
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''Kemudian, tetapkan kunci-kunci ini dalam .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 dan redis://redis:6379 ialah nama servis Compose, yang diselesaikan pada rangkaian lalai projek. FRONTEND_URL bukan sekadar hiasan. Chatwoot membina URL skrip widget dan setiap pautan di dalam e-mel keluar daripadanya, jadi nilai yang salah akan menyebabkan pautan tetapan semula kata laluan menghala ke hos yang tidak memberi respons.
Sekarang, perangkap dalam fail upstream. Servis postgres tidak membaca .env. Ia membawa blok environment sendiri dengan POSTGRES_PASSWORD= dibiarkan kosong, jadi menetapkan kata laluan dalam .env sahaja akan menyebabkan pangkalan data tidak mempunyai kata laluan manakala aplikasi pula mempunyainya. Halakan servis tersebut kepada pemboleh ubah yang sama:
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 membaca .env daripada direktori projek untuk penggantian ${...}, jadi kedua-dua pihak kini mendapat rentetan yang sama. Jika anda tersilap langkah ini, Rails akan berhenti dengan PG::ConnectionBad: FATAL: password authentication failed for user "postgres".
Satu kelakuan yang mengejutkan hampir semua orang: imej Postgres hanya menggunakan POSTGRES_PASSWORD apabila ia memulakan direktori data yang kosong. Menukar nilai tersebut kemudian tidak memberi kesan, kerana initdb tidak akan dijalankan buat kali kedua. Jika anda sudah memulakan stack sekali, tukarkannya di dalam pangkalan data itu sendiri.
docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"ENABLE_ACCOUNT_SIGNUP=true adalah bersifat sementara. Ia membuka borang pendaftaran awam supaya anda boleh mencipta akaun pertama. Tetapkannya kepada false dan jalankan docker compose up -d semula sebaik sahaja akaun anda wujud, atau sesiapa sahaja yang menemui URL tersebut boleh mendaftar di meja bantuan anda. Selepas itu, ejen akan masuk melalui jemputan dan kata laluan mereka hanya disimpan dalam aplikasi ini, yang memadai sehingga anda menjalankan setengah dozen servis dan berasa penat dengan senarai akaun berasingan bagi setiap satu, di mana pada tahap itu penyedia identiti layan diri seperti Authentik adalah komponen yang menggantikannya.
.env kini menyimpan setiap rahsia yang dimiliki oleh stack ini dalam teks biasa, jadi pastikan ia berada pada mod 600 dan jangan masukkan ke dalam git. Cara Compose membaca fail env, dan di mana rahsia boleh bocor merangkumi risiko-risiko tersebut, termasuk perbezaan antara env_file dan environment.
Letakkan Chatwoot di belakang Traefik sedia ada anda
Jangan bina proksi balikan (reverse proxy) kedua untuk satu aplikasi. Jika Traefik sudah menamatkan TLS (transport layer security) untuk kontena lain pada pelayan ini, Chatwoot boleh digabungkan menggunakan blok label. Jika anda belum memilikinya, sediakan dahulu dengan Traefik di hadapan beberapa aplikasi Docker Compose, kemudian kembali ke sini.
Pastikan docker-compose.yaml daripada hulu (upstream) kekal hampir kepada asal supaya anda boleh melakukan diff dengan salinan yang lebih baharu nanti, dan letakkan perubahan anda dalam fail ganti (override file). Compose akan menggabungkan docker-compose.override.yaml secara automatik, dan memecahkan Compose kepada berbilang fail menjelaskan peraturan penggabungan tersebut.
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: trueGunakan nama entrypoint dan certresolver anda sendiri. Kontena tersebut mesti berada pada rangkaian Docker yang sama dengan Traefik, iaitu fungsi entri proxy, dan ia juga mesti kekal pada default supaya tidak terputus hubungan dengan Postgres dan Redis. Baris kedua itu sering dilupakan oleh pengguna.
Biarkan blok ports: seperti asal. Hulu (upstream) mengikatnya kepada 127.0.0.1:3000, iaitu hanya untuk loopback, jadi ia tidak boleh dicapai dari internet dan kekal berguna untuk ujian dari dalam pelayan menggunakan curl -I http://127.0.0.1:3000.
Papan pemuka ejen mengekalkan sambungan websocket ke /cable untuk penghantaran mesej secara langsung. Traefik memajukan naik taraf HTTP tanpa konfigurasi tambahan, jadi tiada apa yang perlu ditambah. Jika anda kemudian meletakkan CDN atau proksi lain di hadapan Traefik, benarkan websocket di sana, kerana simptomnya ialah papan pemuka yang dimuatkan seperti biasa manakala mesej baharu hanya muncul selepas muat semula manual.
Mulakan pangkalan data dan jalankan stack
Jalankan servis data terlebih dahulu dan biarkan Postgres menyelesaikan proses permulaan pertamanya.
docker compose up -d postgres redis
docker compose logs postgres | tail -n 5Tunggu sehingga database system is ready to accept connections. Kemudian, cipta skema.
docker compose run --rm rails bundle exec rails db:chatwoot_prepareLangkah ini mencipta pangkalan data jika ia tiada, kemudian memuatkan skema dan data benih (seed data) lalai. Ia akan memaparkan baris migrasi dan keluar dengan sempurna. Jika ia terus memaparkan postgres:5432 - no response, bermakna entrypoint sedang menunggu pangkalan data yang belum menerima sambungan, yang pada permulaan pertama biasanya bermaksud initdb masih berfungsi. Tunggu, baca log Postgres, kemudian jalankannya semula. Jika ia terhenti pada sambungan vector, bermakna anda telah menggantikan imej pgvector dengan Postgres biasa.
docker compose up -d
docker compose ps
docker compose logs --tail 30 railsKeempat-empat kontena sepatutnya membaca Up, dan log rails sepatutnya berakhir dengan baris Puma yang mendengar pada http://0.0.0.0:3000. Kemudian, semak laluan awam:
curl -sI https://support.example.com | head -n 1HTTP/2 200 bermaksud keseluruhan rantaian berfungsi. Ralat 404 daripada Traefik bermaksud peraturan penghala (router rule) tidak sepadan, biasanya disebabkan kesilapan taip pada hostname. Ralat 502 bermaksud Traefik telah memadankan penghala tetapi tidak dapat mencapai kontena, yang hampir selalu disebabkan oleh rangkaian proxy yang tiada atau loadbalancer.server.port yang bukan 3000.
Buka URL tersebut, cipta akaun anda di /app/auth/signup, kemudian tetapkan ENABLE_ACCOUNT_SIGNUP=false dan jalankan docker compose up -d untuk menutup borang tersebut.
Mengapa tetapan semula kata laluan dan perbualan e-mel gagal tanpa SMTP
Chatwoot tanpa tetapan SMTP (Simple Mail Transfer Protocol) ialah meja bantuan yang tidak boleh menghantar e-mel, dan ini menjejaskan lebih daripada sekadar pemberitahuan. Tetapan semula kata laluan tidak berfungsi, jadi pentadbir yang terkunci keluar akan terus terkunci. Jemputan ejen tidak berfungsi kerana jemputan dihantar melalui e-mel. Membalas pelanggan dalam perbualan e-mel juga tidak berfungsi, menyebabkan perbualan hanya berjalan sehala. Ini adalah langkah yang sering dilangkau oleh pengguna dan hanya disedari semasa waktu kritikal.
Mekanismenya jelas. Tanpa tetapan SMTP, ActionMailer mengekalkan lalai untuk menghantar ke localhost pada port 25. Tiada pelayan e-mel di dalam kontena Rails, jadi tugasan penghantaran mencetuskan Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25. E-mel dihantar daripada tugasan latar belakang, jadi baris tersebut muncul dalam log Sidekiq dan bukannya log Rails. Sementara itu, individu yang menekan "forgot password" melihat pengesahan yang berjaya tetapi tidak menerima apa-apa.
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=trueGunakan port 587 dengan STARTTLS, yang membuka sambungan dalam teks biasa dan menaik tarafnya kepada disulitkan sebelum pengesahan. Kebanyakan penyedia VPS menyekat port 25 keluar untuk mengehadkan spam, jadi relay pada 587 biasanya satu-satunya cara untuk menyambung. SMTP_DOMAIN ialah domain yang diumumkan oleh pelayan anda semasa perbualan SMTP, dan sesetengah relay menolak jika terdapat ketidakpadanan.
Gunakan tetapan tersebut dan pantau pekerja:
docker compose up -d rails sidekiq
docker compose logs -f sidekiqCetuskan tetapan semula kata laluan daripada halaman log masuk. Penghantaran yang berjaya menunjukkan tugasan mailer selesai dengan normal dalam log Sidekiq. Kegagalan menunjukkan kelas pengecualian, kemudian Sidekiq membuat percubaan semula dengan backoff yang semakin meningkat, itulah sebabnya relay yang rosak menghasilkan ralat yang sama setiap beberapa minit selama berjam-jam.
Dua penolakan adalah perkara biasa, dan kedua-duanya bukan pepijat Chatwoot. 535 Authentication failed bermaksud nama pengguna atau kata laluan salah untuk relay tersebut, dan banyak penyedia memerlukan kata laluan aplikasi dan bukannya kata laluan akaun. 550 Sender address rejected bermaksud MAILER_SENDER_EMAIL ialah alamat yang tidak dibenarkan oleh relay untuk dihantar, jadi ia mestilah peti mel atau domain yang telah anda sahkan dengan mereka.
Menerima e-mel ke dalam perbualan adalah tugasan yang berasingan. Ia memerlukan MAILER_INBOUND_EMAIL_DOMAIN dan RAILS_INBOUND_EMAIL_SERVICE, serta pelayan e-mel yang menyerahkan mesej masuk kepada Chatwoot. Menyewa relay adalah jalan yang pantas. Jika anda lebih suka mengurus keseluruhan laluan e-mel, menjalankan pelayan e-mel anda sendiri dengan Mailcow merangkumi perkara yang sebenarnya terlibat dalam komitmen tersebut.
Perkara yang perlu disandarkan, dan cara membuktikan pemulihan berfungsi
Sandaran Chatwoot mempunyai empat bahagian, dan mengabaikan mana-mana bahagian akan menyebabkan pemulihan menjadi proses bina semula.
- Pangkalan data Postgres, yang menyimpan perbualan, kenalan, akaun ejen dan setiap tetapan.
- Volum
storage_data, keranaACTIVE_STORAGE_SERVICE=localmenulis fail yang dimuat naik ke cakera dan hanya menyimpan baris rujukan dalam Postgres. - Fail
.env, kerana ia menyimpanSECRET_KEY_BASEdan kunciACTIVE_RECORD_ENCRYPTION_*. - Fail compose, kerana ia merekodkan tag imej tepat yang sepadan dengan skema pangkalan data anda.
Pulihkan pangkalan data secara berasingan dan setiap perbualan akan kembali dengan lampiran yang rosak, kerana baris tersebut merujuk kepada fail yang tidak lagi berada pada cakera.
cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump-T adalah penting. Tanpanya, Compose memperuntukkan terminal pseudo, yang menulis semula bait baris baharu dalam aliran, jadi anda mendapat fail dump yang ditolak oleh pg_restore. -Fc ialah format tersuai, yang memampatkan dan membolehkan pg_restore berfungsi secara selektif.
docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/storage-$(date +%F).tgz -C /data .Nama volum ialah nama direktori projek anda ditambah _storage_data. Sahkan dengan docker volume ls | grep storage_data sebelum anda mempercayai arahan tersebut, kerana Docker mencipta volum kosong dan bukannya gagal apabila anda menamakan volum yang tidak wujud. Anda akan mendapat arkib kosong yang sah tanpa sebarang ralat. Semak saiz selepas itu dengan ls -lh storage-*.tgz.
Kedua-dua fail kini berada pada cakera yang sama dengan perkara yang dilindunginya, yang tidak melindungi anda daripada apa-apa. Pindahkan fail tersebut keluar dari pelayan dan enkripsikannya, kerana dump pangkalan data mengandungi setiap mesej pelanggan dalam teks biasa. Sandaran luar tapak yang disulitkan dengan restic merangkumi aspek penjadualan dan pengekalan.
Latihan pemulihan, jalankannya sebelum anda memerlukannya
Pulihkan ke VPS kedua, bukan pada VPS yang sedang berjalan. Salin .env, fail compose dan kedua-dua arkib, kemudian jalankan:
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 membuang objek sedia ada sebelum memuatkan, jadi hanya halakan arahan ini kepada pangkalan data yang anda sanggup hilang. Kemudian log masuk dan buka perbualan yang mempunyai lampiran. Jika senarai mesej dimuatkan dan fail boleh dimuat turun, sandaran tersebut adalah sah.
Pemulihan dengan SECRET_KEY_BASE yang berbeza akan membatalkan setiap kuki sesi, jadi semua orang akan dilog keluar. Pemulihan dengan kunci ACTIVE_RECORD_ENCRYPTION_* yang berbeza adalah lebih buruk: Chatwoot tidak dapat menyahsulit lajur yang menyimpan kelayakan saluran dan akan mengeluarkan ActiveRecord::Encryption::Errors::Decryption. Itulah sebabnya .env berada dalam senarai sandaran.
Cara menaik taraf Chatwoot ke tag baharu
Urutan langkah adalah lebih penting daripada arahan itu sendiri.
- Baca nota keluaran antara tag semasa anda dengan tag sasaran untuk mencari langkah manual yang diperlukan.
- Ambil dump pangkalan data dan arkib storan yang terkini, kemudian pastikan saiz kedua-dua fail kelihatan munasabah.
- Edit tag imej pada servis
basedalamdocker-compose.yaml. - Tarik imej baharu, hentikan stack, jalankan migrasi, kemudian mulakan semula.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose imagesTarik imej sebelum anda melakukan migrasi, kerana migrasi perlu dijalankan daripada imej baharu: imej lama tidak mengandungi fail migrasi yang baharu. Hentikan stack sebelum anda melakukan migrasi, kerana kod lama dan skema baharu tidak serasi; proses Rails lama yang sedang berjalan boleh mencetuskan ralat atau menulis baris data yang tidak diterima oleh skema baharu. Menghentikan stack juga membebaskan memori yang diperlukan oleh migrasi, yang merupakan sebab utama pihak pembangun meminta penggunaan swap.
docker compose images memaparkan tag yang sedang dijalankan oleh setiap kontena, yang membantu mengesan situasi di mana anda telah mengedit tag tetapi terlupa untuk menarik imej.
Jangan melangkau terlalu banyak versi sekaligus. Nasihat pihak pembangun untuk pemasangan lama adalah dengan melalui tag perantaraan, kerana migrasi akan dibuang sebaik sahaja ia diserap ke dalam skema asas. Oleh itu, pangkalan data yang terlalu lama boleh mencapai keadaan di mana tiada laluan untuk menaik taraf. Bergerak satu versi minor pada satu masa dan jalankan langkah penyediaan selepas setiap satu.
Jika Rails bermula sebelum migrasi dijalankan, ia akan menolak untuk beroperasi dan mencatat ActiveRecord::PendingMigrationError: Migrations are pending dalam log. Dengan restart: always ditetapkan, kontena tersebut akan berulang (cycle), menyebabkan docker compose ps menunjukkan uptime yang ditetapkan semula setiap beberapa saat. Jalankan langkah penyediaan dan masalah tersebut akan selesai.
Proses rollback bermaksud meletakkan semula tag lama dan memulihkan dump pangkalan data. Tiada laluan migrasi songsang yang boleh anda harapkan, itulah sebabnya langkah 2 disediakan.
Mod kegagalan dan rentetan yang akan anda lihat
502 Bad Gateway daripada Traefik. Penghala (router) telah dipadankan tetapi bahagian belakang (backend) tidak menjawab. Semak docker compose ps menunjukkan rails sebagai Up, kemudian jalankan docker network inspect proxy dan sahkan bekas (container) rails muncul dalam senarai bekasnya. Bekas yang tidak dilampirkan adalah tidak kelihatan kepada Traefik, jadi permintaan dipadankan dengan penghala tetapi tidak ke mana-mana.
Papan pemuka dimuatkan tetapi mesej baharu memerlukan muat semula. WebSocket ke /cable tidak berjaya ditembusi, atau FRONTEND_URL tidak sepadan dengan alamat dalam bar pelayar. Ketidakpadanan bermakna halaman cuba membuka WebSocket ke asal (origin) yang berbeza, yang disekat oleh pelayar.
FATAL: password authentication failed for user "postgres". Kata laluan dalam .env dan kata laluan yang dibina ke dalam volum data Postgres adalah berbeza. Betulkannya dengan ALTER USER di dalam bekas yang sedang berjalan, kerana menyunting .env sekali lagi tidak akan mengubah pangkalan data yang telah dimulakan.
NOAUTH Authentication required. Redis sedang berjalan dengan --requirepass tetapi aplikasi bersambung tanpa kata laluan, jadi REDIS_PASSWORD hilang daripada .env atau tidak diambil. Ujinya secara terus dengan docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping, yang sepatutnya menjawab PONG.
Bekas keluar dengan kod 137. Ini ialah SIGKILL, dan pada kotak kecil ia adalah pembunuh kehabisan memori (out of memory killer) kernel. Tambahkan swap, tetapkan had memori bagi setiap servis, atau beralih ke pelan yang lebih besar.
FAQ
Berapakah jumlah RAM yang diperlukan oleh VPS untuk Chatwoot yang dihoskan sendiri?
Sehingga Ogos 2026, pihak pembangun mengesyorkan sekurang-kurangnya 4 GB RAM dan 4 teras CPU untuk menampung sehingga 10,000 perbualan sehari, manakala 8 GB RAM dengan 8 teras CPU diperlukan untuk sehingga 20,000 perbualan. Tambahkan sekurang-kurangnya 1 GB swap, kerana proses naik taraf akan menjalankan proses Rails kedua untuk melaksanakan migrasi, yang sering menyebabkan pelayan berspesifikasi rendah kehabisan memori. VPS dengan 2 GB RAM boleh bermula dan berfungsi untuk beberapa ejen, namun Sidekiq sahaja boleh menggunakan lebih 1 GB RAM di bawah beban kerja. Oleh itu, jangkakan bekas (container) akan ditamatkan dengan exit code 137 semasa tempoh sibuk atau semasa proses naik taraf.
Mengapa e-mel tetapan semula kata laluan Chatwoot tidak pernah sampai?
Ini berlaku kerana tetapan SMTP tidak dikonfigurasikan, menyebabkan ActionMailer cuba menghantar e-mel ke localhost pada port 25, sedangkan tiada pelayan mel di dalam bekas tersebut. Tugasan tersebut gagal dalam Sidekiq dengan ralat Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25, walaupun pelayar masih memaparkan mesej kejayaan. Tetapkan SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD dan MAILER_SENDER_EMAIL dalam .env, mulakan semula servis rails dan sidekiq, kemudian pantau docker compose logs -f sidekiq semasa anda mencetuskan tetapan semula.
Apakah yang perlu saya sandarkan untuk memulihkan Chatwoot?
Pangkalan data Postgres, Docker volume storage_data, fail .env dan fail-fail compose. Pangkalan data sahaja tidak mencukupi kerana fail yang dimuat naik disimpan dalam volume, manakala Postgres hanya menyimpan rujukan kepada fail tersebut. Pemulihan pangkalan data sahaja akan menyebabkan perbualan mempunyai lampiran yang rosak. .env adalah penting kerana SECRET_KEY_BASE yang berbeza akan menyebabkan semua pengguna dilog keluar, dan kunci ACTIVE_RECORD_ENCRYPTION_* yang berbeza akan menyebabkan lajur yang disulitkan tidak dapat dibaca.
Bagaimanakah cara menaik taraf Chatwoot tanpa merosakkan pangkalan data?
Lakukan sandaran, tukar tag imej dalam fail compose anda, kemudian jalankan docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare dan docker compose up -d. Lakukan pull terlebih dahulu kerana migrasi mesti dijalankan daripada imej baharu, dan hentikan stack terlebih dahulu kerana kod lama yang dijalankan pada skema baharu akan mencetuskan ralat. Untuk pemasangan lama, lakukan naik taraf satu versi minor pada satu masa, kerana migrasi akan dibuang sebaik sahaja ia digabungkan ke dalam skema asas.
Bolehkah saya menggunakan imej postgres standard dan bukannya pgvector?
Tidak boleh. Skema Chatwoot mendayakan sambungan vector, jadi imej postgres standard akan gagal semasa db:chatwoot_prepare dengan ralat ERROR: extension "vector" is not available, kerana fail kawalan sambungan tersebut tidak tersedia dalam imej itu. Kekalkan pgvector/pgvector:pg16 daripada fail compose asal, atau gunakan imej lain yang menyertakan pgvector untuk versi utama Postgres anda.