Overview
Chatwoot is an open-source customer engagement platform — an embeddable live-chat widget, a shared email inbox, and an omni-channel agent desk in one application. This template deploys the Community Edition (-ce, MIT core): a Rails web tier serving the dashboard, REST API, widget, and WebSockets on port 3000, a Sidekiq worker for background jobs and migrations, a bundled single-node Redis, and a highly available pgvector-capable PostgreSQL cluster. Attachments go to a persistent volume or to object storage.
Architecture
- Chatwoot web — A stateful workload running the official image, serving the agent dashboard, the REST and public APIs, the chat widget, and the ActionCable WebSocket endpoint on port
3000. Scale it withchatwoot.replicas. - Chatwoot worker — A standard workload running Sidekiq from the same image. It also runs the database migrations and the first-run bootstrap on boot, so it is a fixed single replica; background throughput scales through
worker.concurrencyinstead. - PostgreSQL (HA, default) — The postgres-highly-available template as a subchart: 3× Patroni PostgreSQL 17.5, 3× etcd, and a HAProxy leader endpoint Chatwoot connects through. Its image ships pgvector, which Chatwoot’s schema requires.
- PostgreSQL (dev/lightweight, optional) — The single-instance postgres template instead, on a pgvector image.
- Redis — A bundled single-node stateful workload with AOF persistence and password authentication, carrying the Sidekiq queues, the ActionCable pub/sub channel that drives every live update, the cache, and the one-time install-onboarding flag.
What Gets Created
- Stateful Chatwoot Web Workload —
{release}-chatwooton port3000, atchatwoot.replicasreplicas, with/apias its readiness probe and/healthas its liveness probe. - Standard Chatwoot Worker Workload —
{release}-chatwoot-worker, a fixed single replica running Sidekiq, migrations, and the first-run bootstrap. It has no inbound access and no ports. - Stateful Redis Workload —
{release}-chatwoot-redison port6379, pinned to one node, reachable only from inside the GVC. - Database Workloads — HA mode: a stateful Patroni PostgreSQL workload, a stateful etcd workload, and a HAProxy leader-routing workload. Single-instance mode: one stateful PostgreSQL workload.
- Volume Sets —
{release}-chatwoot-redis-vsfor the Redis AOF file at/data,{release}-chatwoot-storagefor local attachments at/app/storage(only whenstorage.typeislocal), plus the database subchart’s volumes. - Secrets — A template-created dictionary secret (
{release}-chatwoot-creds) holding the bundled Redis password, two opaque start-script secrets for the web and worker containers, and the database credentials from the subchart. Your prerequisite keys secret is not created by the template — see Prerequisites. - Identity & Policy — One identity shared by the web and worker workloads, and a policy granting it
revealon exactly the secrets those workloads read: the database credentials, the two start scripts, the Redis credentials secret, your prerequisite secret, and — when configured — the S3 key and SMTP secrets. In keyless S3 mode the identity also carries the cloud account link and your bucket-scoped IAM policy.
This template does not create a GVC. You must deploy it into an existing GVC.
Prerequisites
Chatwoot signs its sessions and encrypts sensitive columns with four keys that you supply through a dictionary secret created before installing. The values are never passed through Helm values.1
Create the keys secret
All four keys are required. Generate them with Set
openssl:secrets.name to the secret’s name (default my-chatwoot-secrets). Secrets are org-level, so no GVC flag is involved.2
Back the values up
Store a copy somewhere safe, outside Control Plane. All four keys are write-once for the life of the installation.
3
Change the bundled credentials
Change the database password (
postgresHA.postgres.password or postgres.config.password) and the Redis password (redis.auth.password) from their placeholder defaults before installing. Both seed their component on first boot and are not updated by later value edits.- Object-storage attachments — an existing bucket plus either a Control Plane cloud account (AWS S3) or a static-key secret (S3-compatible servers). See Attachment Storage. Required if you plan to run more than one web replica.
- Authenticated SMTP — a dictionary secret holding
SMTP_USERNAMEandSMTP_PASSWORD. See Email. - Database backups — a bucket and access setup for one of the supported providers. See Backing Up.
UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
First Run
Chatwoot ships no default account. The first browser session to reach the endpoint runs the onboarding wizard and creates the super admin.1
Wait for the web workload to report ready
On the default HA database path a first install takes roughly eight minutes end to end: the Patroni cluster elects a leader, the worker then loads the schema and runs 158 migrations, and only then does the web tier pass its readiness probe. The single-instance database path is closer to three and a half minutes.
2
Complete the onboarding wizard
Browse to the canonical
*.cpln.app endpoint of the {release}-chatwoot workload. It redirects to /installation/onboarding, where the form creates your account and the super admin user. Do this as soon as the workload is ready — the wizard is unauthenticated until it is completed.3
Create an inbox
In the dashboard, add an inbox — a website widget for live chat, or an API channel for a custom integration. The widget snippet and the API channel identifier are issued there.
4
Configure email before inviting agents
Agent invitations, password resets, and email-channel replies are all delivered by mail. Set up SMTP before you invite your team.
Configuration
The defaultvalues.yaml for this template:
Chatwoot Web
chatwoot.image— The Community Edition image, used by both the web and worker workloads. Pin a released-cetag.chatwoot.replicas— Web-tier replica count. Anything above1requires object storage; see Scaling.chatwoot.frontendUrl— The public base URL Chatwoot puts in the widget snippet, email links, and callbacks, including thehttps://scheme. Leave it empty to derive it from the web workload’s canonical endpoint; set it when you serve Chatwoot on a custom domain. The worker advertises the same URL, so mailer links always point at the web tier.chatwoot.resources— CPU and memory bounds for the web container. The memory ceiling leaves headroom for the Rails boot path.
Sidekiq Worker
worker.concurrency— Number of background jobs Sidekiq processes in parallel. It also sets this process’s PostgreSQL connection-pool size.worker.resources— CPU and memory bounds for the worker container.
worker.concurrency instead.
The worker workload has no probes — Sidekiq exposes no port, and its failure mode is process exit, which restarts the container. It therefore reports
ready as soon as it is scheduled, even while it is still migrating. Worker readiness is not a health signal; read its logs instead.Attachment Storage
storage.type decides where uploaded files and images are kept.
- Local volume (default)
- AWS S3 (keyless)
- S3-compatible (MinIO and others)
Attachments are written to a persistent volume set mounted at The volume is attached to the web workload only, so the Sidekiq worker cannot read attachments in this mode — attachment emails and ActiveStorage analyze and purge jobs cannot succeed. Local storage also works only with a single replica. Use object storage for production.
/app/storage on the web workload, and survive restarts, redeploys, and upgrades under the same release name.Scaling
chatwoot.replicas sets how many web replicas run. Replicas share the database and the bundled Redis, so a message received by one replica reaches a WebSocket client connected to another.
smtp.address— The relay hostname. Chatwoot readsSMTP_ADDRESS, notSMTP_HOST.smtp.domain— The HELO domain. Empty omits it.smtp.authentication—plain,login, orcram_md5. Leave it empty for an unauthenticated relay.smtp.enableStarttlsAuto— Setfalseonly for a plaintext relay such as a local mail catcher.smtp.fromEmail— TheFromaddress on outbound mail.smtp.auth.secretName— Optional dictionary secret with the relay credentials, created before installing:
reveal on exactly that secret.
Access
publicAccess.enabled— Serve the dashboard, API, widget, and WebSockets on the auto-assigned*.cpln.appHTTPS endpoint (default). Because the widget and visitors live outside the GVC, public access is on by default. Set tofalsefor an internal-only instance: external requests are refused at the edge, and in-GVC callers still reach it perinternalAccess.internalAccess.type— Controls which workloads can reach the Chatwoot web tier over the internal network:
The worker and the bundled Redis are never publicly reachable: the worker accepts no inbound traffic at all, and Redis accepts only same-GVC traffic.
Database
Enable exactly one ofpostgresHA (default) or postgres — the chart refuses to render with both or neither enabled. Chatwoot is wired to the active database automatically: the HAProxy leader endpoint in HA mode, or the single instance directly.
postgresHA(default) — 3× Patroni PostgreSQL 17.5 with etcd and a HAProxy leader endpoint. Its image ships pgvector natively, which is why it is the default. A first install on this path takes roughly eight minutes.postgres— One PostgreSQL instance for lighter, non-production deployments. It reaches ready in a few minutes but has no failover.
postgresHA.postgres.password / postgres.config.password) — it seeds the database on first boot and is not updated by later value edits.
On the HA path the worker crash-loops a handful of times during the first install, logging
PG::ConnectionBad … server closed the connection unexpectedly while Patroni elects a leader. This is expected and self-heals as soon as the leader accepts writes.Redis
redis.image— The bundled Redis image.redis.auth.password— Password for the bundled Redis, embedded in Chatwoot’sREDIS_URL. Change it before installing. Only letters, digits,-, and_are accepted; other characters would corrupt the connection URL, and the chart rejects them.redis.resources— CPU and memory bounds for the Redis container.redis.volumeset.capacity— Volume size in GiB for the append-only file at/data. Persistence is on and eviction is disabled, so a queued job is never silently dropped.
Connecting
Managing the Installation
Chatwoot keeps instance-wide settings in its database rather than in environment variables, so they are managed in the application after install, not through Helm values. Sign in as the super admin and openhttps://<canonical>.cpln.app/super_admin. Under Settings you can change instance configuration, including ENABLE_ACCOUNT_SIGNUP, which controls whether visitors can create their own accounts. Self-serve signup is off on a fresh install — accounts are created by the onboarding wizard and by agent invitations until you turn it on.
Backing Up
Database backups are optional and disabled by default. They cover the PostgreSQL database — the conversations, contacts, inboxes, and users that make up your Chatwoot instance. Attachments are not included; in object-storage mode they live in your bucket, and in local mode on the attachment volume set. Enable backups withpostgresHA.backup.enabled or postgres.backup.enabled (matching your database mode), and complete the storage setup for your provider before installing. The values below are shown under backup.* — set them within the enabled database block.
- AWS S3
- Google Cloud Storage
- S3-compatible (MinIO and others)
1
Create a bucket
Create an S3 bucket. Set
backup.aws.bucket and backup.aws.region to match.2
Set up a Cloud Account
If you do not have one, create a Cloud Account for your AWS account. Set
backup.aws.cloudAccountName to its name.3
Create a bucket-scoped IAM policy
Create an AWS IAM policy with the JSON below (replace
YOUR_BUCKET), then set backup.aws.policyName to the policy’s name:backup.mode selects logical (a scheduled pg_dump run by a cron workload) or wal-g (continuous WAL archiving). The single-instance mode takes scheduled logical dumps. backup.prefix is the key prefix within the bucket, and backup.*.schedule is a standard cron expression in UTC.
Important Notes
- Create the keys secret before installing —
secrets.namemust point at an existing dictionary secret holdingSECRET_KEY_BASEand the threeACTIVE_RECORD_ENCRYPTION_*keys. A missing secret pauses the deployment and the install looks broken until it exists. - All four keys are write-once — rotating
SECRET_KEY_BASElogs out every user, and rotating anACTIVE_RECORD_ENCRYPTION_*key makes stored two-factor secrets undecryptable. Back the values up outside Control Plane. - Complete the onboarding wizard right after install — the first browser session to reach the endpoint creates the super admin account, with no email confirmation.
- Restart the web workload after any Redis restart — queues and cache recover on their own, but live updates stay dead, silently, until the web tier restarts.
- A Helm upgrade restarts the bundled Redis and costs a few minutes of
503s — the web readiness probe fails while Redis is down, so replicas leave the load balancer. Upgrade during a quiet period. - Choose the database mode before installing — switching
postgresHAandpostgreson a live release points Chatwoot at a different, empty database. - In single-instance mode the database image must carry pgvector — keep
postgres.imageon a pgvector build; the chart refuses to render against a stockpostgres:image. chatwoot.replicasabove1requires object storage — local attachments are per-replica and would404across replicas.- In
localstorage mode the worker cannot read attachments — the volume is attached to the web workload only, so attachment emails and ActiveStorage analyze and purge jobs fail. Use object storage for production. - AWS S3 is keyless only — a cloud account plus a bucket-scoped IAM policy. Static keys are accepted only for S3-compatible endpoints.
- With SMTP off, no mail is delivered — agent invites, password resets, and email-channel replies all fail. Configure
smtp.*before inviting agents. - Do not scale the worker — it is a fixed singleton that also runs migrations and the first-run bootstrap. Scale background throughput with
worker.concurrency. - Self-serve signup is managed in the app, not in values — turn it on at
/super_admin→ Settings; it is off on a fresh install. - Enterprise features are not included — the
-ceimage omits SSO/SAML and SCIM, audit logs, agent capacity management, custom branding, SLA policies, and Captain AI. The core is MIT-licensed. - Data survives restarts and upgrades — conversations live in the database volume sets and local attachments in the storage volume set. Uninstalling deletes those volume sets and everything in them; your keys secret is yours and survives an uninstall.
External References
Chatwoot Self-Hosted Docs
Official self-hosting documentation
Environment Variables
Every setting the Chatwoot application reads from its environment
Community vs Enterprise
What the Community Edition image includes and excludes
Product Guides
Inboxes, channels, agents, and day-to-day usage
Chatwoot on GitHub
Source code and release notes
Chatwoot Template
View the source files, default values, and chart definition