Docker ile VPS uzerinde Chatwoot kurulumu rehberi
Docker Compose ve Traefik kullanarak Chatwoot kurulumu yapin. SMTP ayarlarini yapilandirma, Postgres yedekleme stratejileri ve guvenli surum yukseltme adimlarini ogrenin.
Ne inşa ediyorsunuz
Chatwoot'u bir VPS üzerinde self-host etmek için dört container çalıştırırsınız: bir Rails web süreci, bir Sidekiq arka plan işçisi, pgvector eklentisine sahip PostgreSQL ve Redis. Chatwoot açık kaynaklı bir müşteri destek masasıdır; bu sayede kontrolünüz altındaki bir sunucuda paylaşımlı bir ekip gelen kutusuna ve web sitesi sohbet widget'ına sahip olursunuz. Kurulum yaklaşık yirmi dakika sürer. Kurulumdan sonraki her şey; posta gönderimi, yedeklemeler, yükseltmeler ve boyutlandırma, sistemin bir yıl sonra hala çalışıp çalışmayacağını belirleyen unsurlardır.
Her container'ın tek bir görevi vardır. Rails, temsilci panelini ve widget API'sini (uygulama programlama arayüzü) sunar. Sidekiq yavaş işleri yürütür: e-posta gönderme, bağlı kanalları sorgulama, otomasyon kurallarını çalıştırma ve rapor oluşturma. Postgres; konuşmaları, kişileri, temsilci hesaplarını ve panelde değiştirdiğiniz her ayarı tutar. Redis, Sidekiq kuyruklarını ve yeni bir mesajı sayfa yenilemeye gerek kalmadan açık bir panele ileten ActionCable pub/sub kanalını tutar. Redis burada geçici bir önbellek değildir; çünkü onu kaybetmek, kuyruktaki işlerin kaybedilmesi anlamına gelir.
Upstream compose dosyasındaki Postgres imajı, standart postgres imajı yerine pgvector/pgvector:pg16 imajıdır; çünkü Chatwoot şeması, yapay zeka özellikleri için vector eklentisini etkinleştirir. Standart Postgres ile değiştirirseniz, eklentinin kontrol dosyası o imajda bulunmadığı için ilk veritabanı çalıştırma işlemi ERROR: extension "vector" is not available hatasıyla durur. Upstream'in sunduğu imajı kullanın.
Bu kılavuz, Docker ve bir reverse proxy'nin sunucuda halihazırda çalıştığını varsayar. Eğer çalışmıyorlarsa, Docker Compose on a VPS ile başlayın ve ardından geri dönün.
Kendi kendine barındırılan Chatwoot için ne kadar VPS gerekir?
Ağustos 2026 itibarıyla, yukarı akış gereksinimleri sayfası minimum 4 GB RAM ve 4 CPU çekirdeği talep etmekte ve bunu günde 10.000 görüşmeye kadar derecelendirmektedir. 8 GB RAM ve 8 çekirdek için ise günde 20.000 görüşmeye kadar destek belirtilmektedir. Ayrıca en az 1 GB swap alanı istenmekte ve bunun nedeni doğrudan açıklanmaktadır: yükseltme sırasında makinenin bellek yetersizliği yaşamaması için. Dosya yüklemelerini hesaba katmadan önce Postgres için 5 GB ile 10 GB arası disk alanı planlayın.
Şimdi işin net kısmına gelelim. 2 GB bir VPS, Chatwoot'u başlatabilir ve iki temsilci ile sakin bir gelen kutusuyla sorunsuz görünebilir. Ancak iki noktada sistem çöker. Birincisi, yukarı akışın yoğun bir sunucuda 1 GB'ın üzerinde ölçtüğü Sidekiq'tir; bu nedenle bir e-posta yoğunluğu veya raporlama işi, Rails, Postgres ve Redis kendi paylarını almadan önce sunucuyu bellek sınırının ötesine iter. İkincisi ise yükseltme işlemidir; çünkü db:chatwoot_prepare, veritabanı migrasyonlarını uygulamak için yeni bir Rails süreci başlatır ve bu imaj üzerinde bir Rails başlatma işlemi, herhangi bir faydalı iş yapmadan önce yüzlerce megabayt bellek tüketir.
Önceden nazik bir uyarı almazsınız. Çekirdeğin bellek yetersizliği öldürücüsü (OOM killer), en büyük sürece SIGKILL sinyali gönderir, Docker konteynerin öldüğünü görür ve restart: always onu yeniden başlatır. docker compose ps daha sonra sürekli Exited (137) durumuna dönen bir konteyner gösterir; burada 137 kodu, sürecin 9 numaralı sinyal ile öldürüldüğü anlamına gelir. Bunu, çekirdeğin seçtiği süreci adlandıran sudo dmesg -T | grep -i "killed process" ile doğrulayabilirsiniz.
Eğer 4 GB bütçenizi aşıyorsa, 2 GB swap alanı ile 2 GB'lık bir sunucu çalıştırın ve servis tamamen ölmek yerine yük altında yanıt sürelerinin uzamasını kabul edin. Her iki durumda da servis başına katı bir bellek sınırı belirlemek faydalıdır; böylece çalışan süreç veritabanını da beraberinde çökertemez. Bkz: Docker Compose içinde bellek sınırları.
Dosya yüklemeleri, sizin belirlediğiniz bir sınır olmaksızın büyüyen kısımdır. Bir müşterinin eklediği her ekran görüntüsü depolama birimine iner ve orada kalır; bu nedenle diski dolduranın veritabanı olduğunu varsaymak yerine docker system df -v komutunu izleyin.
Compose dosyasını edinin ve bir sürüm etiketi sabitleyin
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 .envAz önce indirdiğiniz dosya image: chatwoot/chatwoot:latest değerini içeriyor. Başka bir işlem yapmadan önce bunu değiştirin.
services:
base: &base
image: chatwoot/chatwoot:v4.16.2
env_file: .env
volumes:
- storage_data:/app/storagelatest ifadesi, bir sonraki docker compose pull komutunun o sabah yayınlanan her neyse onu çekmesi anlamına gelir; bu, hakkında hiçbir şey okumadığınız büyük bir sürüm değişikliği veya veritabanı migrasyonu içerebilir. Chatwoot migrasyonları pratikte geri alınamaz; bu nedenle yanlışlıkla yapılan bir sürüm yükseltmesi, geri alma işlemi değil, yedekten geri yükleme gerektirir. Etiketi sabitleyin ve değişikliği bilinçli bir şekilde yapın. Ağustos 2026 itibarıyla güncel sürüm v4.16.2 idi; bugün sabitlemeniz gereken etiket için sürümler sayfasına göz atın.
base servisi, rails ve sidekiq servislerinin her ikisinin de birleştirdiği bir YAML çapasıdır (anchor); bu nedenle etiketi tek bir yerde değiştirmek her ikisi için de geçerli olur. Dosya içerisindeyken, en üstteki version: '3' satırını silin. Modern Compose bu satırı dikkate almaz ve her komutta the attribute 'version' is obsolete, it will be ignored uyarısı verir.
.env dosyasını doldurun
Önce gizli anahtarı oluşturun. Upstream, alfanümerik bir değer talep eder; çünkü özel karakterler, değer bir shell veya YAML ayrıştırıcısından geçerken bozulabilir.
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''Ardından bu anahtarları .env içinde ayarlayın.
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 ve redis://redis:6379, projenin varsayılan ağı üzerinde çözümlenen Compose servis isimleridir. FRONTEND_URL bir süsleme değildir. Chatwoot, widget betiği URL'sini ve giden her e-postanın içindeki bağlantıları bu değerle oluşturur; bu nedenle yanlış bir değer, parola sıfırlama bağlantılarının yanıt vermeyen bir ana bilgisayara yönlenmesine neden olur.
Şimdi upstream dosyasındaki tuzağa gelelim. postgres servisi .env dosyasını okumaz. Kendi environment bloğunu taşır ve bu blokta POSTGRES_PASSWORD= boş bırakılmıştır; bu yüzden parolayı sadece .env içinde ayarlamak, veritabanını parolasız, uygulamayı ise parolalı bırakır. Servisi aynı değişkene yönlendirin:
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, ${...} ikamesi için proje dizinindeki .env dosyasını okur, böylece her iki taraf da aynı dizgiyi alır. Bunu yanlış yaparsanız Rails, PG::ConnectionBad: FATAL: password authentication failed for user "postgres" hatasıyla durur.
Bir davranış neredeyse herkesi şaşırtır: Postgres imajı, POSTGRES_PASSWORD değerini yalnızca boş bir veri dizinini başlatırken uygular. Değeri daha sonra değiştirmek bir etki yaratmaz, çünkü initdb asla ikinci kez çalışmaz. Yığını zaten bir kez başlattıysanız, değişikliği veritabanının içinden yapın.
docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"ENABLE_ACCOUNT_SIGNUP=true geçicidir. İlk hesabı oluşturabilmeniz için herkese açık kayıt formunu açar. Hesabınız oluşur oluşmaz değeri false olarak ayarlayın ve docker compose up -d komutunu tekrar çalıştırın; aksi takdirde URL'yi bulan herkes destek masanıza kayıt olabilir. O andan itibaren temsilciler davetiye ile gelir ve parolaları yalnızca bu uygulamada saklanır. Bu durum, yarım düzine servis çalıştırıp her birinde ayrı bir hesap listesi tutmaktan yorulduğunuz ana kadar sorunsuzdur; o noktada Authentik gibi self-hosted bir kimlik sağlayıcı bunların yerini alan parçadır.
.env artık bu yığındaki tüm gizli bilgileri düz metin olarak tutar, bu yüzden dosya modunu 600 olarak ayarlayın ve git dışında tutun. Compose'un env dosyalarını nasıl okuduğu ve gizli bilgilerin nerede sızdığı, env_file ve environment arasındaki fark da dahil olmak üzere kritik noktaları kapsar.
Chatwoot'u mevcut Traefik'inizin arkasına konumlandırma
Tek bir uygulama için ikinci bir reverse proxy kurmayın. Eğer Traefik bu sunucudaki diğer container'lar için halihazırda TLS (transport layer security) termination yapıyorsa, Chatwoot'u bir label bloğu ile buna dahil edin. Eğer henüz böyle bir yapınız yoksa, birden fazla Docker Compose uygulamasının önünde Traefik kurulumunu bir kez yapın ve ardından buraya geri dönün.
Upstream'e ait docker-compose.yaml dosyasını orijinal haline yakın tutun; böylece daha sonra yeni bir kopyasıyla karşılaştırma (diff) yapabilir ve değişikliklerinizi bir override dosyasında toplayabilirsiniz. Compose, docker-compose.override.yaml dosyalarını otomatik olarak birleştirir; Compose dosyasını birden fazla dosyaya bölme rehberi birleştirme kurallarını açıklar.
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: trueKendi entrypoint ve certresolver isimlerinizi kullanın. Container, Traefik ile aynı Docker ağı üzerinde bulunmalıdır; proxy girdisi bunu sağlar. Ayrıca container, default ağında da kalmalıdır, aksi takdirde Postgres ve Redis bağlantısını kaybeder. İkinci satır, genellikle unutulan kısımdır.
ports: bloğuna dokunmayın. Upstream bunu yalnızca loopback olan 127.0.0.1:3000 adresine bağlar; bu sayede internetten erişilemez kalır ve sunucu içinden curl -I http://127.0.0.1:3000 ile test yapmak için kullanılabilir durumda olur.
Temsilci paneli, canlı mesaj iletimi için /cable adresine bir websocket bağlantısı açık tutar. Traefik, HTTP upgrade işlemini ek bir yapılandırma gerektirmeden iletir. Eğer daha sonra Traefik'in önüne bir CDN veya başka bir proxy koyarsanız, websocket trafiğine izin verin; aksi takdirde panel normal şekilde yüklenir ancak yeni mesajlar yalnızca manuel yenileme yapıldığında görünür.
Veritabanını başlatın ve yığını çalıştırın
Önce veri servislerini ayağa kaldırın ve Postgres'in ilk çalıştırma işlemini tamamlamasına izin verin.
docker compose up -d postgres redis
docker compose logs postgres | tail -n 5database system is ready to accept connections işleminin tamamlanmasını bekleyin. Ardından şemayı oluşturun.
docker compose run --rm rails bundle exec rails db:chatwoot_prepareBu komut, veritabanı mevcut değilse oluşturur, ardından şemayı ve varsayılan başlangıç verilerini yükler. İşlem, migrasyon satırlarını yazdırır ve sorunsuz bir şekilde sonlanır. Eğer postgres:5432 - no response çıktısını yazdırmaya devam ediyorsa, giriş noktası (entrypoint) henüz bağlantı kabul etmeyen bir veritabanını bekliyordur; bu durum ilk çalıştırmada genellikle initdb işleminin hala devam ettiği anlamına gelir. Bekleyin, Postgres günlüklerini okuyun ve ardından komutu tekrar çalıştırın. Eğer vector eklentisinde duruyorsa, pgvector imajını standart Postgres imajı ile değiştirmişsiniz demektir.
docker compose up -d
docker compose ps
docker compose logs --tail 30 railsDört container'ın tamamı Up durumunu göstermeli ve rails günlüğü, http://0.0.0.0:3000 üzerinde dinleme yapan bir Puma satırı ile bitmelidir. Ardından genel yolu kontrol edin:
curl -sI https://support.example.com | head -n 1HTTP/2 200 yanıtı, tüm zincirin çalıştığı anlamına gelir. Traefik'ten gelen 404 hatası, yönlendirici kuralının eşleşmediğini gösterir; bu genellikle bir alan adı yazım hatasıdır. 502 hatası ise Traefik'in yönlendirici ile eşleştiğini ancak container'a ulaşamadığını gösterir; bu durum neredeyse her zaman eksik proxy ağından veya 3000 olmayan bir loadbalancer.server.port değerinden kaynaklanır.
URL'yi açın, /app/auth/signup adresinden hesabınızı oluşturun, ardından ENABLE_ACCOUNT_SIGNUP=false ayarını yapın ve formu kapatmak için docker compose up -d komutunu çalıştırın.
SMTP olmadan parola sıfırlama ve e-posta görüşmeleri neden başarısız olur
SMTP (Simple Mail Transfer Protocol) ayarları yapılmamış bir Chatwoot, e-posta gönderemeyen bir destek masasıdır ve bu durum sadece bildirimlerden fazlasını bozar. Parola sıfırlama işlemleri çalışmaz; bu nedenle kilitlenen bir yönetici sistem dışında kalır. Temsilci davetleri çalışmaz, çünkü davet bir e-postadır. Bir e-posta görüşmesinde müşteriye yanıt vermek çalışmaz, bu yüzden görüşme yalnızca tek taraflı ilerler. Bu, insanların atladığı ve en kötü haftalarında fark ettikleri adımdır.
Mekanizma basittir. SMTP ayarları olmadığında ActionMailer, localhost adresine 25 numaralı port üzerinden teslimat yapma varsayılanını korur. Rails container içerisinde bir posta sunucusu yoktur, bu yüzden teslimat işi Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 hatasını tetikler. Posta bir arka plan işinden gönderildiği için bu satır Rails günlüğüne değil, Sidekiq günlüğüne düşer. Bu sırada "parolamı unuttum" butonuna tıklayan kişi neşeli bir onay mesajı görür ancak eline hiçbir şey ulaşmaz.
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=trueBağlantıyı düz metin olarak başlatan ve kimlik doğrulamadan önce şifreli hale getiren STARTTLS ile 587 numaralı portu kullanın. Çoğu VPS sağlayıcısı, spam'i sınırlamak için 25 numaralı porttan giden trafiği engeller; bu nedenle 587 üzerinden bir aktarıcı (relay), genellikle bağlantı kurabilen tek seçenektir. SMTP_DOMAIN, sunucunuzun SMTP görüşmesi sırasında duyurduğu alan adıdır ve bazı aktarıcılar uyumsuzluk durumunda bağlantıyı reddeder.
Ayarları uygulayın ve çalışanı izleyin:
docker compose up -d rails sidekiq
docker compose logs -f sidekiqGiriş sayfasından bir parola sıfırlama işlemini tetikleyin. Başarılı bir teslimat, Sidekiq günlüğünde posta gönderim işinin normal şekilde tamamlandığını gösterir. Bir hata durumunda ise istisna sınıfı görünür ve Sidekiq artan bir bekleme süresiyle yeniden deneme yapar; bozuk bir aktarıcının saatlerce her birkaç dakikada bir aynı hatayı üretmesinin nedeni budur.
İki tür reddedilme yaygındır ve bunların hiçbiri Chatwoot hatası değildir. 535 Authentication failed, söz konusu aktarıcı için kullanıcı adı veya parolanın yanlış olduğu anlamına gelir; birçok sağlayıcı hesap parolası yerine uygulama parolası kullanılmasını ister. 550 Sender address rejected, MAILER_SENDER_EMAIL adresinin aktarıcının gönderim yapmayacağı bir adres olduğu anlamına gelir; bu nedenle adresin, sağlayıcı üzerinde doğrulanmış bir posta kutusu veya alan adı olması gerekir.
Bir görüşmeye e-posta almak ayrı bir iştir. Bu işlem MAILER_INBOUND_EMAIL_DOMAIN ve RAILS_INBOUND_EMAIL_SERVICE ayarlarının yanı sıra, gelen iletileri Chatwoot'a iletecek bir posta sunucusu gerektirir. Bir aktarıcı kiralamak en hızlı yoldur. Tüm posta yolunun sorumluluğunu üstlenmek isterseniz, Mailcow ile kendi posta sunucunuzu çalıştırmak rehberi, bu taahhüdün gerçekte neleri içerdiğini açıklar.
Nelerin yedekleneceği ve geri yüklemenin çalıştığının nasıl doğrulanacağı
Bir Chatwoot yedeği dört parçadan oluşur; bunlardan herhangi birini atlamak, geri yükleme işlemini bir yeniden inşa sürecine dönüştürür.
- Konuşmaları, kişileri, temsilci hesaplarını ve tüm ayarları barındıran Postgres veritabanı.
storage_databirimi; çünküACTIVE_STORAGE_SERVICE=local, yüklenen dosyaları diske yazar ve Postgres içinde yalnızca bir referans satırı tutar..envdosyası; çünküSECRET_KEY_BASEveACTIVE_RECORD_ENCRYPTION_*anahtarlarını içerir.- Compose dosyaları; çünkü veritabanı şemanızın uyumlu olduğu tam imaj etiketini bunlar kaydeder.
Veritabanını tek başına geri yüklerseniz, tüm konuşmalar bozuk eklerle geri gelir; çünkü satırlar artık diskte bulunmayan dosyaları işaret etmektedir.
cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump-T önemlidir. Bu bayrak olmadan Compose, akış içindeki satır başı baytlarını yeniden yazan bir sözde terminal (pseudo terminal) ayırır; bu da pg_restore tarafından reddedilen bir döküm dosyasıyla sonuçlanır. -Fc, sıkıştırma sağlayan ve pg_restore aracının seçici çalışmasına olanak tanıyan özel formattır.
docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
tar czf /backup/storage-$(date +%F).tgz -C /data .Birim adı, proje dizininizin adıyla birlikte _storage_data ifadesinden oluşur. Bu komuta güvenmeden önce docker volume ls | grep storage_data ile birim adını doğrulayın; çünkü Docker, var olmayan bir isim verdiğinizde hata vermek yerine boş bir birim oluşturur. Bu durumda hiçbir hata almadan geçerli ancak boş bir arşiv elde edersiniz. İşlem sonrasında boyutu ls -lh storage-*.tgz ile kontrol edin.
Her iki dosya da şu an korudukları şeyle aynı diskte durmaktadır, bu da sizi hiçbir şeye karşı korumaz. Veritabanı dökümü tüm müşteri mesajlarını düz metin olarak içerdiğinden, bu dosyaları sunucudan dışarı aktarın ve şifreleyin. restic ile şifreli sunucu dışı yedeklemeler bölümü, zamanlama ve saklama tarafını ele almaktadır.
Geri yükleme tatbikatı: İhtiyaç duymadan önce deneyin
Geri yüklemeyi canlı sunucuya değil, ikinci bir VPS üzerine yapın. .env dosyasını, compose dosyalarını ve her iki arşivi kopyaladıktan sonra şu komutu çalıştırın:
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, yükleme yapmadan önce mevcut nesneleri siler, bu nedenle bu komutu yalnızca kaybetmeyi göze aldığınız bir veritabanı üzerinde kullanın. Ardından giriş yapın ve bir eki olan bir konuşmayı açın. Mesaj listesi yükleniyor ve dosya indirilebiliyorsa, yedekleme gerçektir.
Farklı bir SECRET_KEY_BASE ile yapılan geri yükleme, tüm oturum çerezlerini geçersiz kılar ve herkesin oturumu kapatılır. Farklı ACTIVE_RECORD_ENCRYPTION_* anahtarlarıyla yapılan bir geri yükleme ise daha kötüdür: Chatwoot, kanal kimlik bilgilerini tutan sütunların şifresini çözemez ve ActiveRecord::Encryption::Errors::Decryption hatası verir. .env dosyasının yedekleme listesinde yer almasının nedeni budur.
Chatwoot sürümünü yeni bir etikete yükseltme
Sıralama, kullanılan komutlardan daha önemlidir.
- Mevcut etiketiniz ile hedef etiket arasındaki sürüm notlarını okuyun ve gerekli manuel adımları kontrol edin.
- Veritabanının güncel bir yedeğini ve depolama arşivini alın; her iki dosya boyutunun da makul olduğunu doğrulayın.
basedosyasındakidocker-compose.yamlservisine ait imaj etiketini düzenleyin.- Yeni imajı çekin, stack'i durdurun, migrasyonları çalıştırın ve ardından tekrar başlatın.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose imagesMigrasyon işleminden önce imajı çekin; çünkü migrasyonun yeni imaj üzerinden çalışması gerekir. Eski imaj yeni migrasyon dosyalarını içermez. Migrasyon öncesinde stack'i durdurun; çünkü eski kod ile yeni şema uyumsuzdur. Çalışan eski bir Rails süreci hatalara neden olabilir veya yeni şemanın kabul etmeyeceği satırlar yazabilir. Durdurma işlemi ayrıca migrasyonun ihtiyaç duyduğu belleği serbest bırakır; upstream tarafının swap istemesinin temel nedeni budur.
docker compose images komutu, her container'ın halihazırda çalıştırdığı etiketi yazdırır. Bu, etiketi düzenleyip imajı çekmeyi unuttuğunuz durumları tespit etmenizi sağlar.
Birden fazla sürümü aynı anda atlamayın. Eski bir kurulum için upstream tavsiyesi, ara etiketler üzerinden ilerlemektir. Migrasyonlar temel şemaya dahil edildikten sonra kaldırıldığı için, çok eski bir veritabanı ilerleme yolu olmayan bir duruma gelebilir. Her seferinde bir alt sürüm yükseltmesi yapın ve her adımdan sonra hazırlık aşamasını çalıştırın.
Rails, migrasyon çalışmadan önce başlarsa servis vermeyi reddeder ve ActiveRecord::PendingMigrationError: Migrations are pending hatasını günlüğe kaydeder. restart: always ayarı yapılmışsa container döngüye girer ve docker compose ps çıktısında çalışma süresi her birkaç saniyede bir sıfırlanır. Hazırlık aşamasını çalıştırdığınızda bu durum düzelir.
Geri alma işlemi, eski etikete dönmeyi ve veritabanı yedeğini geri yüklemeyi gerektirir. Güvenebileceğiniz bir tersine migrasyon yolu yoktur; 2. adımın amacı da budur.
Hata modları ve karşılaşacağınız dizeler
Traefik üzerinden 502 Bad Gateway. Yönlendirici eşleşti ancak arka uç yanıt vermedi. docker compose ps komutunu çalıştırarak rails servisinin Up durumunda olduğunu doğrulayın, ardından docker network inspect proxy komutunu çalıştırarak rails container'ının container listesinde göründüğünden emin olun. Çalışmayan bir container Traefik için görünmezdir; bu durumda istek yönlendirici ile eşleşir ancak gidecek bir yer bulamaz.
Dashboard yükleniyor ancak yeni mesajlar için yenileme gerekiyor. /cable adresine giden websocket bağlantısı engelleniyor veya FRONTEND_URL tarayıcı çubuğundaki adresle eşleşmiyor. Uyumsuzluk, sayfanın farklı bir kaynağa websocket açmaya çalışması anlamına gelir ve tarayıcı bunu engeller.
FATAL: password authentication failed for user "postgres". .env içindeki parola ile Postgres veri birimine işlenmiş parola birbirinden farklıdır. Bu sorunu çalışan container içerisinde ALTER USER komutunu kullanarak çözün; çünkü .env dosyasını tekrar düzenlemek, halihazırda başlatılmış bir veritabanını değiştirmeyecektir.
NOAUTH Authentication required. Redis --requirepass ile çalışıyor ancak uygulama parolasız bağlandı; bu durum REDIS_PASSWORD değerinin .env dosyasında eksik olduğunu veya yapılandırmanın algılanmadığını gösterir. Durumu doğrudan docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping ile test edin; bu komut PONG yanıtını döndürmelidir.
Container'lar 137 koduyla kapanıyor. Bu kod SIGKILL sinyalini ifade eder ve küçük bir sunucuda çekirdeğin bellek yetersizliği nedeniyle süreci sonlandırdığı (OOM killer) anlamına gelir. Swap alanı ekleyin, servis bazlı bellek limitleri belirleyin veya daha yüksek kaynaklı bir plana geçiş yapın.
FAQ
Kendi kendine barındırılan bir Chatwoot VPS'i ne kadar RAM'e ihtiyaç duyar?
Ağustos 2026 itibarıyla, upstream minimum 4 GB RAM ve 4 CPU çekirdeği önermektedir; bu yapılandırma günde 10.000 görüşmeye kadar destek sağlar. 20.000 görüşmeye kadar olan yükler için 8 GB RAM ve 8 çekirdek gereklidir. En az 1 GB swap alanı eklenmelidir; çünkü yükseltme işlemleri sırasında migrasyonları uygulamak için ikinci bir Rails süreci çalıştırılır ve düşük bellekli sunucular bu noktada bellek yetersizliği yaşar. 2 GB RAM'e sahip bir VPS, birkaç temsilci için çalışabilir ancak Sidekiq tek başına yük altında 1 GB belleği aşabilir. Bu nedenle yoğun dönemlerde ve yükseltme süreçlerinde container'ların 137 çıkış kodu ile sonlandırılmasını beklemelisiniz.
Chatwoot şifre sıfırlama e-postaları neden ulaşmıyor?
SMTP ayarları yapılandırılmadığı için ActionMailer, e-postaları 25 numaralı port üzerinden localhost adresine teslim etmeye çalışır ancak container içerisinde bir posta sunucusu bulunmaz. İşlem Sidekiq içerisinde Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25 hatası ile başarısız olurken, tarayıcı hala başarılı mesajı gösterir. .env dosyasında SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD ve MAILER_SENDER_EMAIL değişkenlerini ayarlayın, rails ve sidekiq servislerini yeniden başlatın ve ardından sıfırlama işlemini tetiklerken docker compose logs -f sidekiq dosyasını izleyin.
Chatwoot'u geri yüklemek için neleri yedeklemem gerekir?
Postgres veritabanı, storage_data Docker volume alanı, .env dosyası ve compose dosyaları. Yalnızca veritabanı yedeği yeterli değildir; yüklenen dosyalar volume içerisinde tutulurken Postgres sadece bunlara ait referansları saklar. Bu nedenle sadece veritabanı geri yüklemesi, bozuk ekli görüşmelerle sonuçlanır. .env önemlidir çünkü farklı bir SECRET_KEY_BASE tüm kullanıcıların oturumunu kapatır ve farklı ACTIVE_RECORD_ENCRYPTION_* anahtarları şifrelenmiş sütunların okunamaz hale gelmesine neden olur.
Veritabanını bozmadan Chatwoot'u nasıl yükseltebilirim?
Yedek alın, compose dosyanızdaki image etiketini değiştirin ve ardından docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare ve docker compose up -d komutlarını çalıştırın. Önce pull işlemini yapın çünkü migrasyonlar yeni image üzerinden çalışmalıdır. Ayrıca stack'i önceden durdurun; çünkü eski kodun yeni şema üzerinde çalışması hatalara yol açar. Eski bir kurulumda, migrasyonlar temel şemaya dahil edildikten sonra kaldırıldığı için her seferinde bir alt sürüm yükseltmesi yapın.
pgvector yerine standart postgres image kullanabilir miyim?
Hayır. Chatwoot şeması vector eklentisini etkinleştirir, bu nedenle standart postgres image dosyası db:chatwoot_prepare sırasında ERROR: extension "vector" is not available hatası verir; çünkü eklentinin kontrol dosyası bu image içerisinde mevcut değildir. Upstream compose dosyasındaki pgvector/pgvector:pg16 değerini koruyun veya Postgres ana sürümünüz için pgvector içeren başka bir image kullanın.