Paano Mag-self-host ng Chatwoot sa VPS gamit ang Docker
I-deploy ang Chatwoot sa VPS gamit ang Docker Compose at Traefik, pinned tags, SMTP na talagang nagpapadala, Postgres at uploads backups, at ligtas na upgrades.
Mga binubuo mo
Para mag-self-host ng Chatwoot sa isang VPS, magpapatakbo ka ng apat na container: isang Rails web process, isang Sidekiq background worker, PostgreSQL na may pgvector extension, at Redis. Ang Chatwoot ay isang open source customer support desk, kaya magkakaroon ka ng shared team inbox at website chat widget sa server na kontrolado mo. Tumatagal nang humigit-kumulang dalawampung minuto ang installation. Ang lahat pagkatapos nito—mail delivery, backups, upgrades, at sizing—ang magpapasya kung tumatakbo pa rin ito makalipas ang isang taon.
May isang trabaho ang bawat container. Ibinibigay ng Rails ang agent dashboard at widget API (application programming interface). Isinasagawa ng Sidekiq ang mabibigat na background task: pagpapadala ng email, pag-poll sa mga nakakonektang channel, pagpapatakbo ng automation rules, at pagbuo ng reports. Nag-iimbak ang Postgres ng mga conversation, contact, agent account, at bawat setting na binabago mo sa dashboard. Nag-iimbak ang Redis ng mga Sidekiq queue at ng ActionCable pub/sub channel na nagtutulak ng bagong mensahe sa bukas na dashboard nang hindi nire-reload ang page. Hindi lang pansamantalang cache ang Redis dito, dahil kapag nawala ito, mawawala rin ang mga naka-queue na job.
Ang Postgres image sa upstream compose file ay pgvector/pgvector:pg16 sa halip na stock na postgres image, dahil ine-enable ng Chatwoot schema ang vector extension para sa AI features nito. Kapag pinalitan mo ito ng stock Postgres, hihinto ang unang database run na may ERROR: extension "vector" is not available, dahil wala sa image na iyon ang control file ng extension. Gamitin ang image na nire-release ng upstream.
Ipinapalagay ng guide na ito na gumagana na ang Docker at reverse proxy sa server. Kung hindi pa, magsimula sa Docker Compose sa isang VPS at bumalik dito.
Gaano kalaking VPS ang kailangan ng self-hosted Chatwoot?
Noong August 2026, hinihingi ng upstream requirements page ang 4 GB RAM at 4 CPU cores bilang minimum, at tinatantiyang sapat ito para sa hanggang 10,000 conversation bawat araw. Tinatantiyang sapat naman ang 8 GB at 8 cores para sa hanggang 20,000 bawat araw. Kailangan din nito ng hindi bababa sa 1 GB swap. Direktang ibinibigay ang dahilan: upang hindi maubusan ng memory ang machine habang nag-a-upgrade. Maglaan ng 5 GB hanggang 10 GB disk space para sa Postgres bago isama ang file uploads.
Ito ang malinaw na bahagi. Magbo-boot ang Chatwoot sa isang 2 GB VPS, at mukhang maayos ito kapag dalawang agent lang at kaunti ang laman ng inbox. Ngunit bumibigay ito sa dalawang sitwasyon. Una ang Sidekiq. Ayon sa upstream measurements, umaabot ito sa mahigit 1 GB sa busy na server. Kaya kapag sabay-sabay ang email o may report job, lalampas sa available memory ang machine bago pa makuha ng Rails, Postgres, at Redis ang kani-kanilang bahagi. Ikalawa ang upgrade, dahil db:chatwoot_prepare ay nagbo-boot ng bagong Rails process para ilapat ang migrations. Sa image na ito, kumokonsumo ang pag-boot ng Rails ng daan-daang megabytes bago pa ito makagawa ng kapaki-pakinabang na trabaho.
Hindi muna magpapakita ng maayos na warning ang system. Magpapadala ang kernel's out of memory killer ng SIGKILL sa pinakamalaking process. Makikita ito ng Docker bilang paghinto ng container, at restart: always ay sisimulang muli ito. Ipinapakita naman ng docker compose ps ang container na patuloy na bumabalik sa Exited (137), kung saan ang 137 ay nangangahulugang pinatay ito ng signal 9. Kumpirmahin ito gamit ang sudo dmesg -T | grep -i "killed process", na nagpapakita kung aling process ang pinili ng kernel.
Kung lampas sa budget ang 4 GB, maaaring gumamit ng 2 GB machine na may 2 GB swap. Tanggapin lamang na babagal ang response times kapag mataas ang load, sa halip na tuluyang mamatay ang service. Mainam pa ring magtakda ng hard memory ceiling para sa bawat service upang hindi madamay ng worker ang database kapag naubusan ito ng memory. Tingnan ang mga memory limit sa Docker Compose.
Ang file uploads ang bahaging lumalaki nang walang limit na awtomatikong itinakda. Napupunta sa storage volume ang bawat screenshot na ina-attach ng customer at nananatili roon. Kaya monitorin ang docker system df -v sa halip na ipagpalagay na database ang pumuno sa disk.
Kunin ang compose file at mag-pin ng 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 .envNakasulat sa file na kaka-download mo lang ang image: chatwoot/chatwoot:latest. Palitan ito bago ka gumawa ng iba.
services:
base: &base
image: chatwoot/chatwoot:v4.16.2
env_file: .env
volumes:
- storage_data:/app/storageIbig sabihin ng latest, ibibigay sa iyo ng susunod na docker compose pull ang anumang na-publish noong umagang iyon. Maaaring major version ito na may migrations na hindi mo pa nababasa. Sa aktuwal na paggamit, hindi reversible ang Chatwoot migrations. Kaya kapag aksidenteng nag-jump ang version, kailangan mong mag-restore mula sa backup sa halip na mag-undo. I-pin ang tag at baguhin ito nang sadya. Ang v4.16.2 ang kasalukuyang release noong August 2026. Tingnan ang releases page para malaman ang tag na dapat mong i-pin ngayon.
Ang base service ay isang YAML anchor na mina-merge ng rails at sidekiq. Kaya kapag binago mo ang tag sa isang lugar, mababago ito para sa dalawa. Habang nasa file ka na, burahin ang version: '3' line sa itaas. Hindi na ito pinapansin ng modern Compose at nagpi-print ito ng the attribute 'version' is obsolete, it will be ignored sa bawat command.
Punan ang .env file
Bumuo muna ng secret. Humihingi ang upstream ng alphanumeric na value dahil maaaring ma-modify ang special characters kapag dumaan ang value sa shell o YAML parser.
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''Pagkatapos, itakda ang mga key na ito sa .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=localAng POSTGRES_HOST=postgres at redis://redis:6379 ang mga pangalan ng Compose service na nareresolba sa default network ng project. Hindi dekorasyon ang FRONTEND_URL. Ginagamit ito ng Chatwoot para buuin ang widget script URL at lahat ng link sa mga outgoing email. Kaya kapag mali ang value, maglalaman ang password reset link ng host na hindi sumasagot.
Narito ang karaniwang bitag sa upstream file. Hindi binabasa ng postgres service ang .env. May sarili itong environment block, at walang laman ang POSTGRES_PASSWORD=. Kaya kung itatakda mo lamang ang password sa .env, walang password ang database pero may password ang application. Ituro ang service sa parehong 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}Binabasa ng Compose ang .env mula sa project directory para sa ${...} substitution. Dahil dito, pareho na ang string na matatanggap ng dalawang panig. Kapag mali ito, hihinto ang Rails at magpapakita ng PG::ConnectionBad: FATAL: password authentication failed for user "postgres".
May isang behavior na kadalasang ikinagugulat ng halos lahat: inilalapat ng Postgres image ang POSTGRES_PASSWORD kapag nag-initialize lamang ito ng walang lamang data directory. Walang epekto ang pagpapalit ng value pagkatapos nito dahil hindi na muling tumatakbo ang initdb. Kung nasimulan mo na ang stack, palitan ang value sa loob mismo ng database.
docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"Temporary ang ENABLE_ACCOUNT_SIGNUP=true. Binubuksan nito ang public registration form para makagawa ka ng unang account. Itakda ito sa false at patakbuhin muli ang docker compose up -d pagkalikha ng account. Kung hindi, maaaring mag-register sa support desk mo ang sinumang makahanap ng URL. Pagkatapos nito, sa pamamagitan ng invitation pumapasok ang mga agent, at sa iisang app lamang nakalagay ang kanilang mga password. Ayos ito hanggang sa magpatakbo ka ng kalahating dosenang service at magsawa sa magkakahiwalay na account list sa bawat isa. Sa puntong iyon, isang self-hosted identity provider gaya ng Authentik ang pumapalit sa mga ito.
Nasa .env na ngayon ang lahat ng secret ng stack na ito bilang plain text. Panatilihin itong nasa mode 600 at huwag isama sa git. Sinasaklaw ng Paano nagbabasa ang Compose ng env file at kung saan nalalantad ang mga secret ang mahahalagang panganib, kabilang ang pagkakaiba ng env_file at environment.
Ilagay ang Chatwoot sa likod ng iyong kasalukuyang Traefik
Huwag gumawa ng pangalawang reverse proxy para sa isang application. Kung nagte-terminate na ang Traefik ng TLS (transport layer security) para sa iba pang container sa server na ito, isama ang Chatwoot gamit ang isang label block. Kung wala ka pa nito, i-set up muna ito nang isang beses gamit ang Traefik sa harap ng ilang Docker Compose app, pagkatapos ay bumalik dito.
Panatilihing malapit sa stock ang upstream na docker-compose.yaml para maikumpara mo ito sa mas bagong kopya sa hinaharap, at ilagay ang iyong mga pagbabago sa isang override file. Awtomatikong mina-merge ng Compose ang docker-compose.override.yaml, at ipinapaliwanag ng paghahati ng Compose sa maraming file ang mga panuntunan sa pag-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: trueGamitin ang sarili mong mga pangalan para sa entrypoint at certresolver. Dapat nasa parehong Docker network ng Traefik ang container. Ito ang ginagawa ng proxy entry. Dapat manatili rin ito sa default, kung hindi mawawalan ito ng access sa Postgres at Redis. Ang ikalawang linyang ito ang madalas nakalilimutan.
Huwag baguhin ang ports: block. Naka-bind ito ng upstream sa 127.0.0.1:3000, na loopback lamang. Kaya hindi ito naaabot mula sa internet, at nananatili itong kapaki-pakinabang para sa testing mula sa loob ng server gamit ang curl -I http://127.0.0.1:3000.
Nananatiling bukas ang websocket ng agent dashboard sa /cable para sa live na paghahatid ng mensahe. Ipinapasa ng Traefik ang HTTP upgrade nang walang karagdagang configuration, kaya wala kang kailangang idagdag. Kung maglalagay ka sa hinaharap ng CDN o iba pang proxy sa harap ng Traefik, payagan doon ang websockets. Ang sintomas ay dashboard na normal na naglo-load, pero lumalabas lamang ang mga bagong mensahe matapos ang manual refresh.
Inisyalisa ang database at simulan ang stack
I-start muna ang mga data service at hintaying matapos ng Postgres ang first run nito.
docker compose up -d postgres redis
docker compose logs postgres | tail -n 5Hintayin ang database system is ready to accept connections. Pagkatapos, gawin ang schema.
docker compose run --rm rails bundle exec rails db:chatwoot_prepareGinagawa nito ang database kung wala pa ito, pagkatapos ay nilo-load ang schema at ang default seed data. Nagpi-print ito ng mga migration line at malinis na nag-e-exit. Kung patuloy itong nagpi-print ng postgres:5432 - no response, naghihintay ang entrypoint sa database na hindi pa tumatanggap ng connections. Sa first run, karaniwang ibig sabihin nito ay gumagana pa ang initdb. Maghintay, basahin ang Postgres logs, pagkatapos ay patakbuhin itong muli. Kung huminto ito sa vector extension, pinalitan mo ang pgvector image ng stock Postgres.
docker compose up -d
docker compose ps
docker compose logs --tail 30 railsDapat magpakita ang lahat ng apat na container ng Up, at dapat magtapos ang rails log sa isang Puma line na nakikinig sa http://0.0.0.0:3000. Pagkatapos, suriin ang public path:
curl -sI https://support.example.com | head -n 1Ibig sabihin ng HTTP/2 200 ay gumagana ang buong chain. Ang 404 mula sa Traefik ay nangangahulugang hindi tumugma ang router rule, karaniwan dahil may typo sa hostname. Ang 502 ay nangangahulugang tumugma ang Traefik sa router ngunit hindi nito maabot ang container. Halos palaging nawawala ang proxy network, o may loadbalancer.server.port na hindi 3000.
Buksan ang URL, gawin ang iyong account sa /app/auth/signup, pagkatapos ay itakda ang ENABLE_ACCOUNT_SIGNUP=false at patakbuhin ang docker compose up -d upang isara ang form.
Bakit pumapalya ang pag-reset ng password at mga usapan sa email kapag walang SMTP
Ang Chatwoot na walang SMTP (simple mail transfer protocol) settings ay isang support desk na hindi makapagpadala ng email, at hindi lang notifications ang naaapektuhan nito. Hindi gumagana ang pag-reset ng password, kaya mananatiling naka-lock out ang admin na nawalan ng access. Hindi rin gumagana ang mga invitation para sa agent dahil email ang isang invitation. Hindi gumagana ang pagsagot sa customer sa isang usapan sa email, kaya one-way lamang ang usapan. Ito ang hakbang na madalas nilalaktawan at saka lamang natutuklasan sa pinakamasamang pagkakataon.
Simple ang mekanismo. Kapag walang SMTP settings, nananatili ang default ng ActionMailer na mag-deliver sa localhost sa port 25. Walang mail server sa loob ng Rails container, kaya nagkakaroon ng Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 ang delivery job. Mula sa background job ipinapadala ang mail, kaya napupunta ang linyang iyon sa Sidekiq log at hindi sa Rails log. Samantala, makakakita ang taong nag-click sa "forgot password" ng maayos na confirmation pero walang matatanggap.
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=trueGamitin ang port 587 na may STARTTLS. Binubuksan nito ang connection bilang plain text at ina-upgrade ito sa encrypted connection bago ang authentication. Hinaharangan ng karamihan ng VPS provider ang outbound port 25 upang limitahan ang spam, kaya relay sa 587 ang karaniwang tanging makakakonekta. Ang SMTP_DOMAIN ang domain na ipinapakilala ng server mo habang nagaganap ang SMTP conversation, at may ilang relay na nagre-reject kapag hindi tugma ito.
Ilapat ang settings at i-monitor ang worker:
docker compose up -d rails sidekiq
docker compose logs -f sidekiqMag-trigger ng password reset mula sa login page. Kapag gumagana ang delivery, makikitang normal na natatapos ang mailer job sa Sidekiq log. Kapag may failure, makikita muna ang exception class, saka muling susubukan ng Sidekiq ang job na may palaki nang palaking backoff. Dahil dito, ang sirang relay ay naglalabas ng parehong error kada ilang minuto sa loob ng ilang oras.
Dalawa ang karaniwang rejection, at hindi Chatwoot bug ang alinman sa mga ito. Ibig sabihin ng 535 Authentication failed ay mali ang username o password para sa relay na iyon, at maraming provider ang nangangailangan ng application password sa halip na password ng account. Ibig sabihin ng 550 Sender address rejected na ang MAILER_SENDER_EMAIL ay address na hindi papayagang pagpadalhan ng relay, kaya dapat itong mailbox o domain na na-verify mo sa provider.
Hiwalay na trabaho ang pagtanggap ng email sa isang conversation. Kailangan nito ng MAILER_INBOUND_EMAIL_DOMAIN at RAILS_INBOUND_EMAIL_SERVICE, pati ng mail server na nagpapasa ng mga papasok na message sa Chatwoot. Ang pag-renta ng relay ang pinakamabilis na paraan. Kung mas gusto mong ikaw ang magmay-ari ng buong mail path, ipinapaliwanag sa pagpapatakbo ng sarili mong mail server gamit ang Mailcow kung ano talaga ang kinakailangan sa commitment na iyon.
Ano ang dapat i-back up, at paano patutunayang gumagana ang restore
May apat na bahagi ang backup ng Chatwoot. Kapag may isang nilaktawan, magiging rebuild ang restore sa halip na tunay na recovery.
- Ang Postgres database, na naglalaman ng mga conversation, contact, agent account, at lahat ng setting.
- Ang
storage_datavolume, dahil nagsusulat angACTIVE_STORAGE_SERVICE=localng mga uploaded file sa disk at reference row lamang ang itinatago nito sa Postgres. - Ang
.envfile, dahil naglalaman ito ngSECRET_KEY_BASEat mgaACTIVE_RECORD_ENCRYPTION_*key. - Ang compose files, dahil itinatala ng mga ito ang eksaktong image tag na katugma ng schema ng database.
Kung database lamang ang ire-restore, babalik ang bawat conversation na sira ang mga attachment dahil tumuturo ang mga row sa mga file na wala na sa disk.
cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dumpMahalaga ang -T. Kung wala ito, naglalaan ang Compose ng pseudo terminal na nagre-rewrite ng newline bytes sa stream. Dahil dito, makakakuha ka ng dump file na tinatanggihan ng pg_restore. Ang -Fc ang custom format na nagko-compress at nagbibigay-daan sa pg_restore na gumana nang pili lamang.
docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/storage-$(date +%F).tgz -C /data .Ang pangalan ng volume ay pangalan ng iyong project directory na sinusundan ng _storage_data. Kumpirmahin ito gamit ang docker volume ls | grep storage_data bago pagkatiwalaan ang command na iyon, dahil gumagawa ang Docker ng walang laman na volume sa halip na mag-fail kapag nagbigay ka ng pangalang hindi umiiral. Makakakuha ka ng valid ngunit walang laman na archive at walang error. Suriin ang laki nito pagkatapos gamit ang ls -lh storage-*.tgz.
Nasa parehong disk na ngayon ang dalawang file at ang pinoprotektahan ng mga ito. Wala itong naitutulong sa iyo kapag nasira o nawala ang disk. Ipadala ang mga ito sa labas ng server at i-encrypt, dahil naglalaman ang database dump ng bawat mensahe ng customer bilang plain text. Sinasaklaw ng Mga naka-encrypt na off-site backup gamit ang restic ang pag-schedule at retention.
Ang restore drill; patakbuhin ito bago mo ito kailanganin
Mag-restore sa pangalawang VPS, hindi sa live na server. I-copy ang .env, ang compose files, at ang dalawang archive, pagkatapos ay patakbuhin:
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 -dBinabagsak ng --clean --if-exists ang mga umiiral na object bago mag-load. Ituro lamang ito sa database na handa mong mawala. Pagkatapos, mag-sign in at magbukas ng conversation na may attachment. Kung naglo-load ang listahan ng mga mensahe at nada-download ang file, tunay na gumagana ang backup.
Ang restore gamit ang ibang SECRET_KEY_BASE ay nagpapawalang-bisa sa bawat session cookie, kaya masa-sign out ang lahat. Mas malala ang restore gamit ang ibang ACTIVE_RECORD_ENCRYPTION_* key: hindi ma-decrypt ng Chatwoot ang mga column na naglalaman ng channel credentials at maglalabas ito ng ActiveRecord::Encryption::Errors::Decryption. Kaya kasama sa backup list ang .env.
Paano i-upgrade ang Chatwoot sa bagong tag
Mas mahalaga ang pagkakasunod-sunod kaysa sa mismong mga command.
- Basahin ang release notes mula sa kasalukuyan mong tag hanggang sa target na tag. Hanapin ang mga kinakailangang manual na hakbang.
- Gumawa ng bagong database dump at storage archive. Tiyaking makatwiran ang laki ng parehong file.
- I-edit ang image tag sa
baseservice sadocker-compose.yaml. - I-pull ang bagong image, ihinto ang stack, patakbuhin ang migrations, at pagkatapos ay simulan itong muli.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose imagesI-pull muna ang image bago mag-migrate dahil kailangang mula sa bagong image patakbuhin ang migration. Wala sa lumang image ang mga bagong migration file. Ihinto ang stack bago mag-migrate dahil hindi tugma ang lumang code at bagong schema. Maaaring magtaas ng error ang tumatakbong lumang Rails process o magsulat ng mga row na hindi tatanggapin ng bagong schema. Napapalaya rin ng paghinto ang memory na kailangan ng migration. Ito ang dahilan kung bakit humihingi ang upstream ng swap.
Ipinapakita ng docker compose images ang tag na aktuwal na pinapatakbo ng bawat container. Nahuhuli nito ang sitwasyong na-edit mo ang tag pero nakalimutan mong mag-pull.
Huwag lumaktaw sa maraming version nang sabay-sabay. Para sa lumang install, ipinapayo ng upstream na dumaan sa mga intermediate tag. Inaalis ang mga migration kapag naisama na ang mga ito sa base schema. Dahil dito, maaaring mapunta ang napakalumang database sa state na wala nang susunod na migration path. Lumipat ng isang minor version sa bawat hakbang at patakbuhin ang prepare step pagkatapos ng bawat isa.
Kung magsisimula ang Rails bago mapatakbo ang migration, tatanggi itong mag-serve at magla-log ng ActiveRecord::PendingMigrationError: Migrations are pending. Kapag naka-set ang restart: always, paulit-ulit na magre-restart ang container. Dahil dito, ipapakita ng docker compose ps ang uptime na nagre-reset bawat ilang segundo. Patakbuhin ang prepare step upang ma-clear ito.
Ang rollback ay nangangahulugang ibalik ang dating tag at i-restore ang dump. Walang reverse migration path na maaasahan. Ito ang dahilan kung bakit kailangan ang hakbang 2.
Mga failure mode at mga string na makikita mo
502 Bad Gateway mula sa Traefik. Na-match ang router ngunit hindi sumagot ang backend. Suriin kung ipinapakita ng docker compose ps ang rails bilang Up, pagkatapos ay patakbuhin ang docker network inspect proxy at tiyaking lumilitaw ang rails container sa listahan ng mga container nito. Hindi nakikita ng Traefik ang container na hindi naka-attach, kaya nagma-match ang request sa isang router ngunit hindi ito napupunta kahit saan.
Naglo-load ang dashboard ngunit kailangang mag-refresh para makita ang mga bagong mensahe. Hindi nakakalusot ang websocket papunta sa /cable, o hindi tumutugma ang FRONTEND_URL sa address sa browser bar. Ibig sabihin ng mismatch, sinusubukan ng page na magbukas ng websocket sa ibang origin, na bina-block ng browser.
FATAL: password authentication failed for user "postgres". Magkaiba ang password sa .env at ang password na naka-embed sa Postgres data volume. Ayusin ito gamit ang ALTER USER sa loob ng tumatakbong container, dahil hindi mababago ng muling pag-edit sa .env ang database na na-initialize na.
NOAUTH Authentication required. Tumatakbo ang Redis gamit ang --requirepass ngunit kumonekta ang application nang walang password, kaya nawawala ang REDIS_PASSWORD sa .env o hindi ito nabasa ng application. Direktang subukan ito gamit ang docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping, na dapat sumagot ng PONG.
Mga container na nag-e-exit na may code 137. Iyon ay SIGKILL, at sa maliit na server, karaniwang sanhi ito ng out-of-memory killer ng kernel. Magdagdag ng swap, magtakda ng memory limits bawat service, o lumipat sa mas malaking plan.
FAQ
Gaano karaming RAM ang kailangan ng isang self-hosted Chatwoot VPS?
Noong August 2026, ang minimum na hinihingi ng upstream ay 4 GB ng RAM at 4 na CPU core, na may rating na hanggang 10,000 conversation kada araw, at 8 GB na may 8 core para sa hanggang 20,000. Maglaan ng hindi bababa sa 1 GB ng swap dahil nagpapatakbo ang upgrade ng pangalawang Rails process para ilapat ang migrations, at dito nauubusan ng memory ang maliliit na server. Nagbo-boot at gumagana ang 2 GB VPS para sa ilang agent, pero maaaring lumampas sa 1 GB ang konsumo ng Sidekiq kapag mataas ang load. Asahan ang pagpatay sa mga container na may exit code 137 sa mga abalang oras at habang nag-a-upgrade.
Bakit hindi dumarating ang mga email para sa Chatwoot password reset?
Dahil walang naka-configure na SMTP settings, kaya sinusubukan ng ActionMailer na mag-deliver sa localhost sa port 25 at walang mail server sa loob ng container. Nabibigo ang job sa Sidekiq na may Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 habang success message pa rin ang ipinapakita ng browser. Itakda ang SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD at MAILER_SENDER_EMAIL sa .env, i-restart ang rails at sidekiq services, pagkatapos ay i-monitor ang docker compose logs -f sidekiq habang nagti-trigger ka ng reset.
Ano ang kailangan kong i-back up para ma-restore ang Chatwoot?
Ang Postgres database, ang storage_data Docker volume, ang .env file, at ang compose files. Hindi sapat ang database lamang dahil nasa volume ang mga in-upload na file, samantalang mga reference lamang sa mga ito ang nasa Postgres. Kaya kapag database-only ang restore, magkakaroon ka ng mga conversation na sira ang mga attachment. Mahalaga ang .env dahil awtomatikong nagla-logout sa lahat ng user ang ibang SECRET_KEY_BASE, at hindi mababasa ang mga encrypted column kapag ibang ACTIVE_RECORD_ENCRYPTION_* ang ginamit.
Paano ko ia-upgrade ang Chatwoot nang hindi nasisira ang database?
Gumawa ng backup, palitan ang image tag sa compose file, pagkatapos ay patakbuhin ang docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare at docker compose up -d. Mag-pull muna dahil kailangang patakbuhin ang migrations mula sa bagong image, at ihinto muna ang stack dahil nagdudulot ng error ang lumang code kapag gumagana ito sa bagong schema. Sa lumang install, isang minor version lang ang ilipat sa bawat upgrade dahil inaalis ang migrations kapag naisama na ang mga ito sa base schema.
Maaari ko bang gamitin ang standard postgres image sa halip na pgvector?
Hindi. Ine-enable ng schema ng Chatwoot ang vector extension, kaya nabibigo ang stock postgres image habang isinasagawa ang db:chatwoot_prepare at lumalabas ang ERROR: extension "vector" is not available dahil wala sa image na iyon ang control file ng extension. Panatilihin ang pgvector/pgvector:pg16 mula sa upstream compose file, o gumamit ng ibang image na may kasamang pgvector para sa iyong Postgres major version.