SSD Nodes Learn 🎉 VPS vanaf $5.50/mnd
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-13

Chatwoot zelf hosten op een VPS met Docker

Installeer Chatwoot op uw eigen VPS met Docker Compose en Traefik. Leer hoe u SMTP configureert, Postgres back-ups maakt en veilig upgrades uitvoert voor een stabiele omgeving.

Wat u bouwt

Om Chatwoot zelf te hosten op een VPS draait u vier containers: een Rails webproces, een Sidekiq achtergrondworker, PostgreSQL met de pgvector extensie, en Redis. Chatwoot is een open source klantenserviceplatform, waardoor u beschikt over een gedeelde team-inbox en een chatwidget voor uw website op een server die u zelf beheert. De installatie duurt ongeveer twintig minuten. Alles wat daarna komt, zoals e-mailbezorging, back-ups, upgrades en schaling, bepaalt of de applicatie over een jaar nog steeds operationeel is.

Elke container heeft één taak. Rails bedient het dashboard voor medewerkers en de widget API (application programming interface). Sidekiq voert het trage werk uit: e-mails versturen, verbonden kanalen pollen, automatiseringsregels uitvoeren en rapporten genereren. Postgres bevat gesprekken, contacten, accounts van medewerkers en elke instelling die u in het dashboard wijzigt. Redis bevat de Sidekiq-wachtrijen en het ActionCable pub/sub-kanaal dat een nieuw bericht naar een geopend dashboard pusht zonder dat de pagina opnieuw geladen hoeft te worden. Redis is hier geen tijdelijke cache, want verlies hiervan betekent verlies van wachtrijtaken.

De Postgres-image in het upstream compose-bestand is pgvector/pgvector:pg16 in plaats van de standaard postgres-image, omdat het schema van Chatwoot de vector-extensie voor zijn AI-functies inschakelt. Gebruikt u de standaard Postgres, dan stopt de eerste database-run met ERROR: extension "vector" is not available, omdat het controlebestand van de extensie niet in die image aanwezig is. Gebruik de image die upstream wordt geleverd.

Deze handleiding gaat ervan uit dat Docker en een reverse proxy al werken op de server. Als dat niet het geval is, begin dan bij Docker Compose op een VPS en keer daarna terug.

Hoeveel VPS-capaciteit heeft een zelfgehoste Chatwoot nodig?

Sinds augustus 2026 adviseert de officiële documentatie minimaal 4 GB RAM en 4 CPU-cores, wat voldoende is voor maximaal 10.000 gesprekken per dag. Voor maximaal 20.000 gesprekken per dag wordt 8 GB RAM en 8 CPU-cores aanbevolen. Er wordt tevens gevraagd om minimaal 1 GB swapruimte, met de directe reden dat het systeem tijdens een upgrade anders zonder geheugen komt te zitten. Reken op 5 GB tot 10 GB schijfruimte voor Postgres, nog voordat u rekening houdt met bestandsuploads.

Nu de harde realiteit. Een VPS met 2 GB RAM zal Chatwoot opstarten en het lijkt prima te werken met twee medewerkers en een rustige inbox. Het systeem loopt echter op twee punten vast. Het eerste punt is Sidekiq, dat volgens de ontwikkelaars op een drukke server meer dan 1 GB verbruikt. Een piek in e-mailverkeer of een rapportage-taak duwt het systeem over de geheugenlimiet heen, nog voordat Rails, Postgres en Redis hun deel hebben opgeëist. Het tweede punt is de upgrade, omdat db:chatwoot_prepare een nieuw Rails-proces opstart om migraties toe te passen. Het opstarten van Rails op deze image kost honderden megabytes voordat er enig nuttig werk wordt verricht.

U krijgt vooraf geen beleefde waarschuwing. De out-of-memory killer van de kernel stuurt een SIGKILL naar het grootste proces, Docker ziet dat de container stopt en restart: always start deze opnieuw. docker compose ps toont vervolgens een container die blijft terugkeren naar Exited (137), waarbij 137 betekent dat het proces is beëindigd door signaal 9. Bevestig dit met sudo dmesg -T | grep -i "killed process", waarin het proces wordt genoemd dat door de kernel is geselecteerd.

Als 4 GB buiten uw budget valt, gebruik dan een server met 2 GB RAM en 2 GB swap. Accepteer dat de responstijden onder belasting trager worden in plaats van dat de service volledig uitvalt. Het instellen van een harde geheugenlimiet per service is in beide gevallen aan te raden, zodat de worker niet de database mee de afgrond in trekt. Zie geheugenlimieten in Docker Compose.

Bestandsuploads zijn het onderdeel dat onbeperkt groeit. Elke schermafbeelding die een klant toevoegt, belandt in het opslagvolume en blijft daar staan. Monitor daarom docker system df -v in plaats van ervan uit te gaan dat de database de schijf heeft gevuld.

Het compose-bestand ophalen en een versie-tag vastzetten

mkdir -p ~/chatwoot && cd ~/chatwoot
wget -O .env https://raw.githubusercontent.com/chatwoot/chatwoot/develop/.env.example
wget -O docker-compose.yaml https://raw.githubusercontent.com/chatwoot/chatwoot/develop/docker-compose.production.yaml
chmod 600 .env

Het bestand dat u zojuist heeft gedownload, bevat image: chatwoot/chatwoot:latest. Wijzig dit voordat u verdere acties onderneemt.

services:
  base: &base
    image: chatwoot/chatwoot:v4.16.2
    env_file: .env
    volumes:
      - storage_data:/app/storage

latest betekent dat de volgende docker compose pull u voorziet van de versie die die ochtend is gepubliceerd. Dit kan een grote versie zijn met migraties waarover u niets heeft gelezen. Migraties van Chatwoot zijn in de praktijk niet omkeerbaar; een onbedoelde update betekent dus een herstel vanaf een back-up in plaats van een simpele undo. Zet de tag vast en wijzig deze alleen bewust. v4.16.2 was de huidige release in augustus 2026; controleer de releases-pagina voor de tag die u vandaag moet vastzetten.

De base-service is een YAML-anker dat zowel rails als sidekiq samenvoegt, waardoor het wijzigen van de tag op één plek deze voor beide aanpast. Terwijl u in het bestand bent, verwijdert u de regel version: '3' bovenaan. Moderne Compose-versies negeren deze regel en tonen anders bij elk commando de melding the attribute 'version' is obsolete, it will be ignored.

Het .env-bestand invullen

Genereer eerst het geheim. De upstream-documentatie vraagt om een alfanumerieke waarde, omdat speciale tekens corrupt kunnen raken wanneer de waarde door een shell of een YAML-parser wordt verwerkt.

head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''

Stel vervolgens deze sleutels in in .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=local

POSTGRES_HOST=postgres en redis://redis:6379 zijn de Compose-servicenamen, die worden omgezet op het standaardnetwerk van het project. FRONTEND_URL is geen decoratie. Chatwoot bouwt hiermee de URL van het widget-script en elke link in een uitgaande e-mail; een onjuiste waarde zorgt ervoor dat links voor het opnieuw instellen van wachtwoorden verwijzen naar een host die niet reageert.

Let nu op de valkuil in het upstream-bestand. De postgres-service leest .env niet. Deze bevat een eigen environment-blok waarbij POSTGRES_PASSWORD= leeg is gelaten. Het instellen van het wachtwoord in .env alleen zorgt er dus voor dat de database geen wachtwoord heeft en de applicatie wel. Wijs de service naar dezelfde variabele:

  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 leest .env uit de projectmap voor ${...}-substitutie, waardoor beide zijden nu dezelfde tekenreeks ontvangen. Als u dit fout doet, stopt Rails met PG::ConnectionBad: FATAL: password authentication failed for user "postgres".

Eén gedrag verrast bijna iedereen: de Postgres-image past POSTGRES_PASSWORD alleen toe wanneer deze een lege datamap initialiseert. Het later wijzigen van de waarde heeft geen effect, omdat initdb nooit een tweede keer wordt uitgevoerd. Als u de stack al een keer heeft gestart, wijzig het wachtwoord dan in de database zelf.

docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"

ENABLE_ACCOUNT_SIGNUP=true is tijdelijk. Deze opent het openbare registratieformulier zodat u het eerste account kunt aanmaken. Zet deze op false en voer docker compose up -d opnieuw uit zodra uw account bestaat; anders kan iedereen die de URL vindt zich registreren op uw supportdesk. Vanaf dat moment komen agenten binnen via uitnodigingen en staan hun wachtwoorden alleen in deze applicatie. Dit is prima totdat u een half dozijn services draait en genoeg heeft van een aparte accountlijst in elke applicatie; op dat moment is een zelfgehoste identity provider zoals Authentik de oplossing die deze vervangt.

.env bevat nu elk geheim van deze stack in platte tekst. Houd het bestand daarom op modus 600 en houd het buiten git. Hoe Compose env-bestanden leest en waar geheimen lekken behandelt de risico's, inclusief het verschil tussen env_file en environment.

Plaats Chatwoot achter uw bestaande Traefik

Bouw geen tweede reverse proxy voor één applicatie. Als Traefik al TLS (transport layer security) afhandelt voor andere containers op deze server, voegt u Chatwoot toe met een label-blok. Als u dit nog niet heeft, stel dit dan eenmalig in via Traefik voor meerdere Docker Compose-applicaties, en keer daarna hier terug.

Houd de docker-compose.yaml van de upstream-bron zo dicht mogelijk bij de standaardversie, zodat u deze later eenvoudig kunt vergelijken met een nieuwere kopie. Plaats uw wijzigingen in een override-bestand. Compose voegt docker-compose.override.yaml automatisch samen, en het splitsen van Compose over meerdere bestanden legt de samenvoegregels uit.

services:
  rails:
    networks:
      - default
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.chatwoot.rule=Host(`support.example.com`)"
      - "traefik.http.routers.chatwoot.entrypoints=websecure"
      - "traefik.http.routers.chatwoot.tls.certresolver=letsencrypt"
      - "traefik.http.services.chatwoot.loadbalancer.server.port=3000"

networks:
  proxy:
    external: true

Gebruik uw eigen namen voor entrypoints en certresolvers. De container moet zich op hetzelfde Docker-netwerk bevinden als Traefik; dit is wat de proxy-regel doet. De container moet ook op default blijven staan, anders verliest deze de verbinding met Postgres en Redis. Die tweede regel wordt vaak vergeten.

Laat het ports:-blok ongewijzigd. De upstream-bron bindt dit aan 127.0.0.1:3000, wat alleen loopback is. Hierdoor is het niet bereikbaar vanaf het internet, terwijl het bruikbaar blijft voor tests vanaf de server zelf met curl -I http://127.0.0.1:3000.

Het dashboard voor medewerkers houdt een websocket open naar /cable voor het live afleveren van berichten. Traefik stuurt de HTTP-upgrade zonder extra configuratie door, dus er hoeft niets te worden toegevoegd. Als u later een CDN of een andere proxy voor Traefik plaatst, sta dan websockets daar toe. Het symptoom van een geblokkeerde websocket is een dashboard dat normaal laadt, terwijl nieuwe berichten pas verschijnen na een handmatige verversing.

De database initialiseren en de stack starten

Start eerst de dataservices en laat Postgres de eerste run voltooien.

docker compose up -d postgres redis
docker compose logs postgres | tail -n 5

Wacht op database system is ready to accept connections. Maak daarna het schema aan.

docker compose run --rm rails bundle exec rails db:chatwoot_prepare

Dit creëert de database als deze ontbreekt en laadt vervolgens het schema en de standaard seed-data. Het script toont migratieregels en sluit correct af. Als het script blijft hangen bij het tonen van postgres:5432 - no response, wacht het entrypoint op een database die nog geen verbindingen accepteert; bij een eerste run betekent dit meestal dat initdb nog bezig is. Wacht af, lees de Postgres-logs en voer het commando opnieuw uit. Als het stopt bij de vector-extensie, heeft u de pgvector-image vervangen door standaard Postgres.

docker compose up -d
docker compose ps
docker compose logs --tail 30 rails

Alle vier de containers zouden Up moeten aangeven en het rails-logboek zou moeten eindigen met een Puma-regel die luistert op http://0.0.0.0:3000. Controleer vervolgens het publieke pad:

curl -sI https://support.example.com | head -n 1

HTTP/2 200 betekent dat de gehele keten werkt. Een 404 van Traefik betekent dat de routerregel niet overeenkwam, meestal door een typefout in de hostnaam. Een 502 betekent dat Traefik de router wel vond, maar de container niet kon bereiken; dit komt bijna altijd door een ontbrekend proxy-netwerk of een loadbalancer.server.port die niet op 3000 staat.

Open de URL, maak uw account aan op /app/auth/signup, stel vervolgens ENABLE_ACCOUNT_SIGNUP=false in en voer docker compose up -d uit om het formulier te sluiten.

Waarom wachtwoordresets en e-mailconversaties falen zonder SMTP

Chatwoot zonder SMTP-instellingen (Simple Mail Transfer Protocol) is een supportdesk die geen e-mail kan verzenden, en dat heeft meer gevolgen dan alleen het uitblijven van notificaties. Wachtwoordresets werken niet meer, waardoor een beheerder die buitengesloten is, ook buitengesloten blijft. Uitnodigingen voor agents werken niet, omdat een uitnodiging een e-mail is. Reageren op een klant in een e-mailconversatie werkt niet, waardoor de conversatie slechts in één richting verloopt. Dit is de stap die mensen overslaan en waar ze pas achter komen tijdens hun slechtste week.

Het mechanisme is eenvoudig. Zonder SMTP-instellingen behoudt ActionMailer de standaardinstelling om af te leveren bij localhost op poort 25. Er is geen mailserver aanwezig in de Rails-container, dus de aflevertaak genereert Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25. E-mail wordt verzonden vanuit een achtergrondtaak, dus die regel verschijnt in het Sidekiq-logboek en nooit in het Rails-logboek. Ondertussen ziet de persoon die op "wachtwoord vergeten" klikt een vrolijke bevestiging, maar ontvangt niets.

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=true

Gebruik poort 587 met STARTTLS, wat de verbinding opent in platte tekst en deze opwaardeert naar versleuteld vóór de authenticatie. De meeste VPS-providers blokkeren uitgaand verkeer op poort 25 om spam te beperken, dus een relay op 587 is meestal de enige optie die überhaupt verbinding maakt. SMTP_DOMAIN is het domein dat uw server aankondigt tijdens de SMTP-conversatie, en sommige relays weigeren een mismatch.

Pas de instellingen toe en monitor de worker:

docker compose up -d rails sidekiq
docker compose logs -f sidekiq

Activeer een wachtwoordreset vanaf de inlogpagina. Een succesvolle aflevering toont in het Sidekiq-logboek dat de mailer-taak normaal wordt afgerond. Een fout toont de exception-klasse, waarna Sidekiq het opnieuw probeert met een toenemende backoff; dit is de reden waarom een defecte relay urenlang elke paar minuten dezelfde fout genereert.

Twee weigeringen komen vaak voor, en geen van beide is een bug in Chatwoot. 535 Authentication failed betekent dat de gebruikersnaam of het wachtwoord onjuist is voor die relay; veel providers vereisen een applicatiewachtwoord in plaats van het accountwachtwoord. 550 Sender address rejected betekent dat MAILER_SENDER_EMAIL een adres is waarvandaan de relay niet wil verzenden; het moet dus een mailbox of domein zijn dat u bij hen heeft geverifieerd.

Het ontvangen van e-mail in een conversatie is een afzonderlijke taak. Hiervoor zijn MAILER_INBOUND_EMAIL_DOMAIN en RAILS_INBOUND_EMAIL_SERVICE nodig, plus een mailserver die inkomende berichten doorgeeft aan Chatwoot. Een relay huren is de snelste weg. Als u liever het volledige e-mailpad in eigen beheer heeft, behandelt uw eigen mailserver draaien met Mailcow wat die verplichting daadwerkelijk inhoudt.

Wat u moet back-uppen en hoe u controleert of een herstel werkt

Een Chatwoot-back-up bestaat uit vier onderdelen. Als u er een overslaat, verandert een herstel in een volledige herbouw.

  • De Postgres-database, die gesprekken, contacten, agent-accounts en alle instellingen bevat.
  • Het storage_data-volume, omdat ACTIVE_STORAGE_SERVICE=local geüploade bestanden naar de schijf schrijft en alleen een referentie in Postgres bewaart.
  • Het .env-bestand, omdat dit de SECRET_KEY_BASE en de ACTIVE_RECORD_ENCRYPTION_*-sleutels bevat.
  • De compose-bestanden, omdat deze de exacte image-tag vastleggen die overeenkomt met uw databaseschema.

Als u alleen de database herstelt, komen alle gesprekken terug met defecte bijlagen, omdat de rijen verwijzen naar bestanden die niet meer op de schijf staan.

cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump

-T is van belang. Zonder deze vlag wijst Compose een pseudo-terminal toe, die newline-bytes in de stream herschrijft. Hierdoor krijgt u een dumpbestand dat pg_restore weigert. -Fc is het aangepaste formaat dat comprimeert en ervoor zorgt dat pg_restore selectief kan werken.

docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
  tar czf /backup/storage-$(date +%F).tgz -C /data .

De volumenaam is uw projectmapnaam plus _storage_data. Bevestig de naam met docker volume ls | grep storage_data voordat u het commando vertrouwt, omdat Docker een leeg volume aanmaakt in plaats van een foutmelding te geven wanneer u een naam opgeeft die niet bestaat. U zou dan een geldig, maar leeg archief krijgen zonder enige foutmelding. Controleer de grootte achteraf met ls -lh storage-*.tgz.

Beide bestanden staan nu op dezelfde schijf als de data die ze moeten beschermen, wat u tegen niets beveiligt. Verplaats ze naar een andere locatie en versleutel ze, aangezien een database-dump elk klantbericht in platte tekst bevat. Versleutelde off-site back-ups met restic behandelt de planning en retentie.

De hersteltest: voer deze uit voordat u hem nodig heeft

Herstel naar een tweede VPS, niet naar de actieve server. Kopieer .env, de compose-bestanden en beide archieven, en voer vervolgens het volgende uit:

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 verwijdert de bestaande objecten vóór het laden, dus wijs dit alleen toe aan een database die u mag verliezen. Meld u daarna aan en open een gesprek met een bijlage. Als de berichtenlijst laadt en het bestand kan worden gedownload, is de back-up in orde.

Een herstel met een andere SECRET_KEY_BASE maakt alle sessie-cookies ongeldig, waardoor iedereen wordt afgemeld. Een herstel met andere ACTIVE_RECORD_ENCRYPTION_*-sleutels is erger: Chatwoot kan de kolommen met kanaalreferenties niet ontsleutelen en geeft ActiveRecord::Encryption::Errors::Decryption. Daarom staat .env op de back-uplijst.

Chatwoot upgraden naar een nieuwe tag

De volgorde is belangrijker dan de commando's zelf.

  1. Lees de release notes tussen uw huidige tag en de doelversie en let op vereiste handmatige stappen.
  2. Maak een verse database-dump en een archief van de opslag, en controleer of beide bestandsgroottes logisch lijken.
  3. Wijzig de image-tag van de base service in docker-compose.yaml.
  4. Haal de nieuwe image op, stop de stack, voer migraties uit en start vervolgens opnieuw.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose images

Haal de image op voordat u migreert, omdat de migratie moet worden uitgevoerd vanuit de nieuwe image: de oude image bevat de nieuwe migratiebestanden niet. Stop de stack voordat u migreert, omdat de oude code en het nieuwe schema niet overeenkomen; een draaiend oud Rails-proces kan fouten genereren of rijen schrijven die het nieuwe schema niet accepteert. Het stoppen van de stack maakt ook het geheugen vrij dat de migratie nodig heeft, wat de reden is waarom de ontwikkelaars om swap vragen.

docker compose images toont de tag waarop elke container daadwerkelijk draait; dit detecteert situaties waarin u de tag heeft gewijzigd maar bent vergeten de image op te halen.

Sla niet meerdere versies tegelijk over. Het advies voor een oude installatie is om stapsgewijs door tussenliggende tags te gaan, omdat migraties worden verwijderd zodra ze zijn opgenomen in het basisschema. Een zeer oude database kan daardoor in een staat raken waarvoor geen migratiepad meer bestaat. Upgrade één minor-versie per keer en voer na elke stap de voorbereidende acties uit.

Als Rails start voordat de migratie is uitgevoerd, weigert de applicatie te draaien en logt deze ActiveRecord::PendingMigrationError: Migrations are pending. Met restart: always ingeschakeld, blijft de container herstarten, waardoor docker compose ps een uptime toont die elke paar seconden reset. Voer de voorbereidende stap uit om dit op te lossen.

Rollback betekent het terugzetten van de oude tag en het herstellen van de dump. Er is geen betrouwbaar pad voor terugwaartse migraties, en daarom is stap 2 essentieel.

Foutmodi en de meldingen die u zult zien

502 Bad Gateway van Traefik. De router heeft een match gevonden, maar de backend antwoordde niet. Controleer of docker compose ps de rails-service toont als Up, voer vervolgens docker network inspect proxy uit en bevestig dat de rails-container in de containerlijst verschijnt. Een container die niet is gekoppeld, is onzichtbaar voor Traefik; het verzoek komt dus wel bij de router aan, maar loopt daarna dood.

Het dashboard laadt, maar nieuwe berichten vereisen een verversing. De websocket naar /cable komt niet door, of FRONTEND_URL komt niet overeen met het adres in de browserbalk. Een mismatch betekent dat de pagina probeert een websocket te openen naar een andere origin, wat door de browser wordt geblokkeerd.

FATAL: password authentication failed for user "postgres". Het wachtwoord in .env en het wachtwoord dat in het Postgres-datavolume is opgeslagen, verschillen van elkaar. Herstel dit met ALTER USER in de draaiende container, aangezien het opnieuw bewerken van .env een reeds geïnitialiseerde database niet zal wijzigen.

NOAUTH Authentication required. Redis draait met --requirepass, maar de applicatie maakte verbinding zonder wachtwoord. Dit betekent dat REDIS_PASSWORD ontbreekt in .env of niet correct is ingelezen. Test dit direct met docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping, wat zou moeten antwoorden met PONG.

Containers die afsluiten met code 137. Dit is SIGKILL; op een kleine server is dit de 'out of memory'-killer van de kernel. Voeg swap toe, stel geheugenlimieten per service in of stap over naar een groter abonnement.

FAQ

Hoeveel RAM heeft een zelfgehoste Chatwoot VPS nodig?

Sinds augustus 2026 adviseert de upstream-leverancier minimaal 4 GB RAM en 4 CPU-cores voor maximaal 10.000 gesprekken per dag, en 8 GB met 8 cores voor maximaal 20.000. Voeg ten minste 1 GB swap toe, omdat een upgrade een tweede Rails-proces start om migraties toe te passen; hierdoor komen kleine systemen geheugen tekort. Een VPS met 2 GB start op en werkt voor een paar medewerkers, maar Sidekiq alleen kan onder belasting meer dan 1 GB verbruiken. Verwacht daarom dat containers worden beëindigd met exitcode 137 tijdens drukke periodes en upgrades.

Waarom komen wachtwoordherstel-e-mails van Chatwoot nooit aan?

Omdat er geen SMTP-instellingen zijn geconfigureerd, probeert ActionMailer af te leveren bij localhost op poort 25, terwijl er geen mailserver in de container aanwezig is. De taak faalt in Sidekiq met Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25, terwijl de browser nog steeds een succesmelding toont. Stel SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD en MAILER_SENDER_EMAIL in via .env, herstart de rails- en sidekiq-services en monitor vervolgens docker compose logs -f sidekiq terwijl u een herstelactie activeert.

Wat moet ik back-uppen om Chatwoot te herstellen?

De Postgres-database, het storage_data Docker-volume, het .env-bestand en de compose-bestanden. De database alleen is onvoldoende, omdat geüploade bestanden in het volume staan terwijl Postgres alleen verwijzingen daarnaar bevat; een herstel van alleen de database resulteert in gesprekken met defecte bijlagen. .env is van belang omdat een andere SECRET_KEY_BASE alle gebruikers uitlogt en verschillende ACTIVE_RECORD_ENCRYPTION_*-sleutels de versleutelde kolommen onleesbaar maken.

Hoe upgrade ik Chatwoot zonder de database te beschadigen?

Maak een back-up, wijzig de image-tag in uw compose-bestand en voer vervolgens docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare en docker compose up -d uit. Voer eerst een pull uit omdat migraties vanuit de nieuwe image moeten draaien, en stop eerst de stack omdat oude code tegen een nieuw schema fouten veroorzaakt. Bij een oudere installatie voert u de upgrade stapsgewijs uit per minor-versie, aangezien migraties worden verwijderd zodra ze zijn opgenomen in het basisschema.

Kan ik de standaard postgres-image gebruiken in plaats van pgvector?

Nee. Het schema van Chatwoot activeert de vector-extensie, waardoor de standaard postgres-image faalt tijdens db:chatwoot_prepare met ERROR: extension "vector" is not available, omdat het controlebestand van de extensie niet aanwezig is in die image. Behoud pgvector/pgvector:pg16 uit het upstream compose-bestand of gebruik een andere image die pgvector voor uw Postgres-hoofdversie bevat.

#chatwoot#self-hosting#docker-compose#support-desk#smtp#backups