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.
Berapa kapasiti VPS yang diperlukan untuk Chatwoot yang dihoskan sendiri?
Setakat October 2026, halaman keperluan upstream menetapkan 4 GB RAM dan 4 teras CPU sebagai minimum, dengan kapasiti sehingga 10,000 perbualan sehari. Halaman itu menetapkan 8 GB RAM dan 8 teras CPU untuk sehingga 20,000 perbualan sehari. Ia juga memerlukan sekurang-kurangnya 1 GB swap, dengan alasan yang dinyatakan dengan jelas: supaya mesin tidak kehabisan memori semasa naik taraf. Sediakan 5 GB hingga 10 GB ruang cakera untuk Postgres sebelum mengambil kira muat naik fail.
Bahagian pentingnya adalah seperti berikut. VPS 2 GB boleh memulakan Chatwoot, dan kelihatan mencukupi dengan dua ejen serta peti masuk yang tidak sibuk. Namun, ia gagal dalam dua keadaan. Yang pertama ialah Sidekiq, yang menurut upstream menggunakan lebih daripada 1 GB pada pelayan yang sibuk. Oleh itu, lonjakan e-mel atau tugas laporan boleh menyebabkan pelayan melebihi kapasiti memorinya sebelum Rails, Postgres dan Redis mendapat bahagian masing-masing. Yang kedua ialah proses naik taraf, kerana db:chatwoot_prepare memulakan proses Rails baharu untuk menggunakan migrasi. Proses permulaan Rails pada imej ini menggunakan ratusan megabait sebelum menjalankan kerja yang berguna.
Anda tidak semestinya menerima amaran yang jelas terlebih dahulu. Out of memory killer kernel menghantar SIGKILL kepada proses yang dipilih, biasanya proses terbesar. Docker mengesan bahawa container itu telah berhenti, lalu restart: always memulakannya semula. docker compose ps --all kemudian menunjukkan container yang terus dimulakan semula atau kekal pada Exited (137). Nilai 137 bermaksud proses itu dihentikan oleh signal 9. Jika --all ditinggalkan, container yang telah berhenti tidak disenaraikan langsung. Exit code 137 sahaja tidak membuktikan bahawa memori ialah puncanya, kerana docker kill menghantar signal yang sama. Oleh itu, sahkan puncanya dengan sudo dmesg -T | grep -i "killed process", yang menyatakan proses yang dipilih oleh kernel.
Jika 4 GB melebihi bajet, gunakan pelayan 2 GB dengan 2 GB swap dan terima bahawa masa tindak balas akan menjadi lebih lama apabila beban meningkat. Swap ialah penimbal untuk mengelakkan kehabisan memori, bukan jaminan. Lonjakan yang cukup besar masih boleh menyebabkan container dihentikan. Menetapkan had memori yang tegas bagi setiap servis tetap wajar dilakukan, supaya worker tidak menyebabkan pangkalan data turut terhenti. Lihat had memori dalam Docker Compose.
Muat naik fail ialah bahagian yang boleh terus bertambah tanpa had yang anda tetapkan. Setiap tangkapan skrin yang dilampirkan oleh pelanggan disimpan dalam volume storan dan kekal di situ. Oleh itu, pantau docker system df -v dan jangan menganggap bahawa pangkalan data yang memenuhi ruang cakera.
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 mengandungi image: chatwoot/chatwoot:latest. Ubahnya sebelum melakukan perkara lain.
services:
base: &base
image: chatwoot/chatwoot:v4.18.0
env_file: .env
volumes:
- storage_data:/app/storagelatest bermaksud docker compose pull seterusnya akan mengambil apa sahaja yang diterbitkan pada pagi itu. Versi tersebut mungkin versi utama yang mengandungi migrasi yang tidak pernah anda semak. Secara praktikal, migrasi Chatwoot tidak boleh dibuat asal. Oleh itu, lonjakan versi secara tidak sengaja memerlukan pemulihan daripada sandaran, bukan pembatalan perubahan. Tetapkan tag dan ubahnya dengan sengaja. v4.18.0 ialah keluaran semasa pada Oktober 2026, dan nota keluarannya mengesyorkan versi tersebut untuk pembaikan keselamatan. Semak halaman releases untuk mengetahui tag yang perlu anda tetapkan hari ini. Sebarang perisian yang mengurus pangkalan data memerlukan langkah berjaga-jaga yang sama. Atas sebab itu, self-hosting penjejak senaman openGym bermula dengan menetapkan tag git walaupun aplikasi itu jauh lebih kecil daripada aplikasi ini.
Servis base ialah anchor YAML yang digabungkan oleh rails dan sidekiq. Oleh itu, menukar tag di satu tempat akan mengubahnya untuk kedua-duanya. Semasa fail itu dibuka, padamkan baris version: '3' di bahagian atas. Compose moden mengabaikannya dan memaparkan 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.
Sebab tetapan semula kata laluan dan perbualan e-mel gagal tanpa SMTP
Chatwoot tanpa tetapan SMTP (simple mail transfer protocol) ialah meja sokongan yang tidak boleh menghantar e-mel, dan keadaan ini menjejaskan lebih daripada sekadar pemberitahuan. Tetapan semula kata laluan tidak lagi berfungsi, jadi pentadbir yang terkunci daripada akaun akan terus terkunci. Jemputan ejen tidak lagi berfungsi kerana jemputan dihantar melalui e-mel. Membalas pelanggan dalam perbualan e-mel juga tidak lagi berfungsi, jadi perbualan hanya berjalan sehala. Langkah ini sering dilangkau, kemudian masalahnya hanya disedari pada minggu yang paling sukar.
Mekanismenya mudah. Jika SMTP_ADDRESS tidak ditetapkan, Chatwoot menukar ActionMailer kepada penghantaran melalui sendmail. Dokumentasi huluan menerangkan kaedah ini sebagai persediaan Postfix, yang menjadi lalai sejak v2.12.0, dan arahannya memasang Postfix pada pelayan dengan sudo apt install -y postfix. Persediaan Docker ini tidak melakukannya, jadi tiada pelayan mel yang dikonfigurasikan untuk menerima e-mel daripada penghantaran tersebut. E-mel dihantar daripada tugas latar belakang, jadi apa-apa ralat yang dihasilkan oleh penghantaran akan masuk ke log Sidekiq dan bukannya log Rails. Sementara itu, orang yang mengklik "forgot password" melihat pengesahan yang meyakinkan 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. Sambungan dibuka dalam teks biasa dan dinaik taraf kepada sambungan yang disulitkan sebelum pengesahan. Kebanyakan pembekal VPS menyekat port keluar 25 untuk mengehadkan spam, jadi relay pada port 587 biasanya satu-satunya pilihan yang boleh disambungkan. SMTP_DOMAIN ialah domain yang diumumkan oleh pelayan anda semasa perbualan SMTP, dan sesetengah relay akan menolak ketidakpadanan.
Gunakan tetapan tersebut dan pantau worker:
docker compose up -d rails sidekiq
docker compose logs -f sidekiqCetuskankan tetapan semula kata laluan daripada halaman log masuk. Penghantaran yang berfungsi akan menunjukkan tugas mailer selesai seperti biasa dalam log Sidekiq. Kegagalan akan menunjukkan kelas pengecualian, kemudian Sidekiq akan mencuba semula dengan tempoh backoff yang semakin panjang. Oleh itu, relay yang rosak menghasilkan ralat yang sama setiap beberapa minit selama berjam-jam.
Dua penolakan berikut adalah lazim, dan kedua-duanya bukan pepijat Chatwoot. 535 Authentication failed bermaksud nama pengguna atau kata laluan untuk relay tersebut salah, dan banyak pembekal memerlukan kata laluan aplikasi berbanding kata laluan akaun. 550 Sender address rejected bermaksud MAILER_SENDER_EMAIL ialah alamat yang tidak dibenarkan oleh relay untuk digunakan sebagai alamat penghantar. Alamat itu mestilah peti mel atau domain yang telah anda sahkan dengan pembekal tersebut.
Menerima e-mel ke dalam perbualan ialah tugas yang berasingan. Tugas ini memerlukan MAILER_INBOUND_EMAIL_DOMAIN dan RAILS_INBOUND_EMAIL_SERVICE, serta pelayan mel yang menyerahkan mesej masuk kepada Chatwoot. Menyewa relay ialah cara yang paling cepat. Jika anda lebih suka mengurus keseluruhan laluan mel sendiri, menjalankan pelayan mel sendiri dengan Mailcow menerangkan perkara yang sebenarnya diperlukan oleh 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 dipaparkan
502 Bad Gateway daripada Traefik. Router sepadan, tetapi backend tidak memberikan respons. Semak docker compose ps untuk memastikan rails dipaparkan sebagai Up, kemudian jalankan docker network inspect proxy dan sahkan bahawa container rails muncul dalam senarai containernya. Container yang tidak dilampirkan tidak dapat dilihat oleh Traefik. Oleh itu, permintaan sepadan dengan router tetapi tidak diteruskan ke mana-mana.
Papan pemuka dimuatkan tetapi mesej baharu memerlukan refresh. WebSocket ke /cable tidak berjaya diteruskan, atau FRONTEND_URL tidak sepadan dengan alamat dalam bar pelayar. Ketidakpadanan ini bermaksud halaman cuba membuka WebSocket ke origin yang berbeza, lalu pelayar menyekatnya.
FATAL: password authentication failed for user "postgres". Kata laluan dalam .env berbeza daripada kata laluan yang telah disimpan dalam volume data Postgres. Betulkan dengan ALTER USER di dalam container yang sedang berjalan kerana mengedit .env sekali lagi tidak akan mengubah pangkalan data yang telah dimulakan.
NOAUTH Authentication required. Redis berjalan dengan --requirepass, tetapi aplikasi bersambung tanpa kata laluan. Ini bermaksud REDIS_PASSWORD tiada dalam .env atau tidak digunakan. Uji kata laluan yang diperlukan oleh Redis secara terus dengan docker compose exec redis sh -c 'redis-cli -a "$REDIS_PASSWORD" ping'. Perintah itu sepatutnya memberikan respons PONG. Petikan tunggal penting kerana petikan tersebut menyebabkan pemboleh ubah dikembangkan di dalam container, yang membaca .env, bukannya dalam shell anda sendiri, yang biasanya kosong.
Container keluar dengan kod 137. Itu ialah SIGKILL. Pada pelayan kecil, penghantar yang lazim ialah pembunuh kernel kerana kehabisan memori, tetapi docker kill menghantar isyarat yang sama. Oleh itu, semak sudo dmesg -T | grep -i "killed process" sebelum menyalahkan memori. Jika masalahnya ialah memori, tambah swap, tetapkan had memori bagi setiap servis atau gunakan pelan yang lebih besar.
FAQ
Berapa banyak RAM yang diperlukan oleh VPS Chatwoot yang dihoskan sendiri?
Setakat Oktober 2026, upstream memerlukan sekurang-kurangnya 4 GB RAM dan 4 teras CPU, dengan penarafan sehingga 10,000 perbualan sehari, serta 8 GB dan 8 teras untuk sehingga 20,000 perbualan. Tambahkan sekurang-kurangnya 1 GB swap kerana proses naik taraf menjalankan proses Rails kedua untuk menggunakan migrasi, dan pada ketika itulah mesin kecil kehabisan memori. VPS 2 GB boleh but dan berfungsi untuk beberapa ejen, tetapi Sidekiq sahaja boleh menggunakan lebih daripada 1 GB apabila dimuatkan. Oleh itu, jangkakan container dihentikan dengan exit code 137 ketika tempoh sibuk dan semasa naik taraf.
Mengapakah e-mel tetapan semula kata laluan Chatwoot tidak pernah diterima?
Kerana tiada SMTP_ADDRESS ditetapkan. Oleh itu, Chatwoot kembali menggunakan penghantaran sendmail, yang menurut upstream bertujuan untuk pelayan Postfix yang dipasang pada host, sedangkan persediaan Docker ini tidak mempunyai pelayan tersebut. Tugas itu berjalan dalam Sidekiq. Oleh itu, sebarang ralat penghantaran masuk ke log Sidekiq, manakala pelayar masih memaparkan mesej berjaya. 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 disandarkan untuk memulihkan Chatwoot?
Pangkalan data Postgres, volume Docker storage_data, fail .env dan fail compose. Pangkalan data sahaja tidak mencukupi kerana fail yang dimuat naik disimpan dalam volume, manakala Postgres hanya menyimpan rujukan kepadanya. Oleh itu, pemulihan pangkalan data sahaja menghasilkan perbualan dengan lampiran yang rosak. .env penting kerana SECRET_KEY_BASE yang berbeza akan menyebabkan semua pengguna dilog keluar, manakala ACTIVE_RECORD_ENCRYPTION_* yang berbeza menjadikan lajur yang disulitkan tidak dapat dibaca.
Bagaimanakah cara menaik taraf Chatwoot tanpa merosakkan pangkalan data?
Buat sandaran, ubah tag image 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. Jalankan pull terlebih dahulu kerana migrasi mesti dijalankan daripada image baharu. Hentikan stack terlebih dahulu kerana kod lama yang beroperasi pada skema baharu akan menghasilkan ralat. Pada pemasangan lama, naik taraf satu versi minor pada satu masa kerana migrasi akan dibuang selepas digabungkan ke dalam skema asas.
Bolehkah saya menggunakan image postgres standard dan bukannya pgvector?
Tidak. Skema Chatwoot mengaktifkan extension vector. Oleh itu, image postgres stok gagal semasa db:chatwoot_prepare dengan ERROR: extension "vector" is not available kerana fail kawalan extension tersebut tiada dalam image itu. Kekalkan pgvector/pgvector:pg16 daripada fail compose upstream, atau gunakan image lain yang menyertakan pgvector untuk versi major Postgres anda.