Applications AWS

Chatwoot Customer Engagement Platform on AWS User Guide

| Product: Chatwoot Customer Engagement Platform

Overview

This guide covers the deployment and configuration of Chatwoot on AWS using cloudimg AWS Marketplace AMIs. Chatwoot is an open source customer engagement and support platform: a shared team inbox that unifies website live chat, email and social messaging channels into one conversation view, with unified contacts, labels, teams, canned responses, automation rules and reporting built in.

The cloudimg image ships the upstream Chatwoot release unmodified, run the officially supported way as the production container stack, alongside PostgreSQL with the pgvector extension and Redis, all captured into the AMI so your instance starts without pulling anything. Chatwoot's own LICENSE puts everything outside the repository's enterprise/ directory under the MIT Expat licence; the enterprise/ directory carries Chatwoot's separate enterprise licence and those features require a licence key obtained from Chatwoot directly. Nothing ships with a known secret: a fresh application secret, a fresh database password and a fresh cache password are generated for each instance on first boot, the database is initialised empty under those rotated secrets, and a single administrator account is seeded with a random password written to a root-only file. Backed by 24/7 cloudimg support.

Chatwoot is a trademark of its respective owner. This image is produced by cloudimg and is not affiliated with, endorsed by, or sponsored by Chatwoot. It ships the upstream self-hosted software, unmodified.

What is included:

  • Chatwoot v4.16.1 (the open source customer engagement and support platform), pinned to the upstream release image
  • The Rails web application and the Sidekiq background worker, both from the same pinned image
  • PostgreSQL 16 with the pgvector extension, and Redis 8.8.0, both published to the loopback interface only and never reachable from outside the instance
  • Docker Engine and the Compose plugin from the official Docker APT repository, with the Rails application on loopback 127.0.0.1:3000
  • nginx on port 80 as the reverse proxy, preconfigured with the WebSocket upgrade headers the real-time inbox and live chat need, plus an unauthenticated /health readiness endpoint
  • docker.service, nginx.service, chatwoot-firstboot.service and chatwoot.service as systemd units, enabled and active on boot
  • A fresh application secret, database password and cache password generated per instance on first boot, plus a single administrator account with a random password in a root-only credentials file
  • Account self-signup disabled, so a freshly launched instance is never open to the public
  • A dedicated 40 GiB EBS data volume mounted at /var/lib/chatwoot holding the database, the cache, the uploaded attachments and the application images, independently resizable and separate from the OS root
  • Ubuntu 24.04 LTS base with latest security patches applied at build time
  • 24/7 cloudimg support with guaranteed 24 hour response SLA

Prerequisites

  • An active AWS account and an EC2 key pair in your target region
  • A subscription to the Chatwoot listing on AWS Marketplace
  • A VPC with a public subnet, and a security group as described below

Recommended instance type: m5.large (2 vCPU, 8 GB RAM) is a sensible starting point for a small support team. Chatwoot runs four containers including a Rails application, so do not go below 8 GB of memory. For larger agent counts or heavy conversation volume choose a larger instance. Security group inbound: allow 22/tcp from your management network and 80/tcp from the networks your agents and website visitors use. Port 443/tcp is also opened by the listing's suggested group so you can attach your own TLS certificate later, as shown near the end of this guide.

Connecting to your instance

SSH in as the default login user for the AMI variant you launched, using the private key of the EC2 key pair you selected at launch:

AMI variant SSH login user
Ubuntu 24.04 ubuntu
Task Command
SSH to the instance ssh -i /path/to/your-key.pem ubuntu@<instance-public-ip>
Read the generated administrator credentials sudo cat /root/chatwoot-credentials.txt

The first boot rotates every secret, initialises an empty database and seeds your administrator account. On an m5.large this typically completes within two to four minutes of the instance first reaching the running state; the readiness endpoint below is the reliable signal.

Step 1: Launch from the AWS Marketplace

Open the product page in AWS Marketplace, choose Continue to Subscribe, accept the terms, then Continue to Configuration and Continue to Launch. Pick your region, the m5.large instance type, your VPC and public subnet, your key pair, and a security group that allows inbound 22 and 80 as above. Launch the instance.

Step 2: Launch from the AWS CLI

aws ec2 run-instances \
  --image-id <ami-id-from-the-listing> \
  --instance-type m5.large \
  --key-name your-key \
  --security-group-ids sg-xxxxxxxx \
  --subnet-id subnet-xxxxxxxx \
  --associate-public-ip-address \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=chatwoot-01}]'

Step 3: Confirm the platform is up

Chatwoot serves an unauthenticated readiness endpoint at /health through nginx. Poll it until it returns 200; that is the signal first boot has finished and the agent inbox is reachable.

curl -s -o /dev/null -w "GET /health -> HTTP %{http_code}\n" http://127.0.0.1/health
GET /health -> HTTP 200

Confirm the four systemd units the appliance depends on are active:

systemctl is-active chatwoot.service nginx.service docker.service
active
active
active

And confirm the four containers of the stack are running on the pinned release:

sudo docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
NAMES                 IMAGE                       STATUS
chatwoot-rails-1      chatwoot/chatwoot:v4.16.1   Up 2 minutes
chatwoot-sidekiq-1    chatwoot/chatwoot:v4.16.1   Up 2 minutes
chatwoot-redis-1      redis:alpine                Up 2 minutes
chatwoot-postgres-1   pgvector/pgvector:pg16      Up 2 minutes

Step 4: Retrieve your per-instance administrator credentials

No login is baked into the image. First boot generates a random administrator password for this instance alone and writes it, together with the account email and the instance URL, to a root-only file:

sudo cat /root/chatwoot-credentials.txt

The file contains a CHATWOOT_URL, a CHATWOOT_ADMIN_EMAIL and a CHATWOOT_ADMIN_PASSWORD. Copy the password into your password manager and treat the file as a secret; it is mode 0600 and owned by root.

You can confirm the credential is genuinely per instance, and that a wrong password is rejected, without leaving the shell:

sudo grep -c '^CHATWOOT_ADMIN_PASSWORD=' /root/chatwoot-credentials.txt
1

Step 5: Sign in to the agent inbox

Browse to http://<instance-public-ip>/ and sign in with the email and password from the credentials file.

Chatwoot login screen

After signing in you land on the agent dashboard: the conversation list on the left, the shared inbox navigation down the side, and the getting-started cards on the right.

Chatwoot agent dashboard

Change the administrator password from Profile Settings once you are in, and store the new one in your password manager.

Step 6: Create your first inbox

An inbox is a channel Chatwoot receives conversations from. Go to Settings then Inboxes and choose Add Inbox to pick a channel.

Chatwoot inbox channel picker

For a website live chat widget, choose Website, give the inbox a name and your site's domain, then finish the wizard. Chatwoot generates a small JavaScript snippet; paste it before the closing </body> tag of your site and the widget appears for your visitors. Conversations started in the widget arrive in the inbox you just created.

Other channels available in this image include Email (connect a mailbox over IMAP/SMTP), WhatsApp, SMS via Twilio, Telegram, Line, and a generic API channel for building your own integration. Channels that require a third-party developer application, such as Facebook and Instagram, need those credentials configured before they can be selected.

Step 7: Add agents and teams

Go to Settings then Agents and choose Add Agent to invite a colleague by email address. Agents can be given the Agent or Administrator role. Under Settings then Teams you can group agents so conversations can be routed to a team rather than an individual.

Note that account self-signup is disabled in this image, so people cannot create their own accounts on your instance. Adding agents from this screen is the intended path.

Outbound email is not configured out of the box, so agent invitation emails and notification emails will not be delivered until you add SMTP settings; see Step 9.

Step 8: Reporting

Reports gives live conversation and agent metrics: open, unattended, unassigned and pending conversation counts, agent availability, conversation traffic and resolutions over time, plus per-agent, per-label, per-inbox, per-team, CSAT and SLA breakdowns.

Chatwoot reports overview

Each report can be scoped by date range and inbox, and downloaded as CSV using the download control on the panel.

Step 9: Configure outbound email (SMTP)

Chatwoot needs an SMTP relay to send agent invitations, password resets, notifications and email-channel replies. Add your provider's settings to the environment file and restart the stack.

The environment file at /opt/chatwoot/.env holds the application configuration. List the setting names it currently defines (never print the file itself, it contains your database and cache passwords):

sudo grep -Eo '^[A-Z_]+=' /opt/chatwoot/.env | tr -d '=' | sort | head -20
ACTIVE_STORAGE_SERVICE
ENABLE_ACCOUNT_SIGNUP
FORCE_SSL
FRONTEND_URL
INSTALLATION_ENV
LOG_LEVEL
NODE_ENV
POSTGRES_DATABASE
POSTGRES_HOST
POSTGRES_PASSWORD
POSTGRES_PORT
POSTGRES_USERNAME
RAILS_ENV
RAILS_LOG_TO_STDOUT
REDIS_PASSWORD
REDIS_URL
SECRET_KEY_BASE

Append your SMTP configuration (for example SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, MAILER_SENDER_EMAIL) to /opt/chatwoot/.env with your editor of choice, then restart:

Task Command
Edit the environment file sudo nano /opt/chatwoot/.env
Restart Chatwoot after editing sudo systemctl restart chatwoot

The exact variable names for your provider are documented in the Chatwoot environment variable reference. Keep the file at mode 0600; it holds your database and cache passwords as well.

Step 10: Where your data lives

The database, the cache and every uploaded attachment live on a dedicated EBS volume mounted at /var/lib/chatwoot, separate from the OS root volume so you can resize or snapshot it independently:

df -h /var/lib/chatwoot | tail -1
/dev/nvme1n1     40G   75M   37G   1% /var/lib/chatwoot

The volume is mounted by filesystem UUID from /etc/fstab, so it survives reboots and instance-type changes:

grep chatwoot /etc/fstab

To grow it, expand the EBS volume in the AWS console or CLI, then extend the filesystem on the instance with sudo resize2fs /dev/nvme1n1 (substitute the device name reported by lsblk). No downtime is required.

Step 11: Back up the database and attachments

Take an EBS snapshot of the data volume for a whole-appliance restore point, and additionally dump the database for a portable logical backup:

sudo docker exec chatwoot-postgres-1 pg_dump -U postgres chatwoot | gzip > ~/chatwoot-backup.sql.gz

Check the dump was written with ls -lh ~/chatwoot-backup.sql.gz. Store the dump off the instance (Amazon S3 is the obvious destination) and keep it alongside a snapshot of /var/lib/chatwoot, which holds the uploaded attachments.

Step 12: Security model

The only service published on the instance's network interface is nginx on port 80. The Rails application, PostgreSQL and Redis are all bound to the loopback interface, so they cannot be reached from outside the instance even if your security group is wide open:

sudo ss -tlnp | grep -E ':80 |:3000 |:5432 |:6379 ' | awk '{print $1, $4}'
LISTEN 127.0.0.1:5432
LISTEN 127.0.0.1:6379
LISTEN 0.0.0.0:80
LISTEN 127.0.0.1:3000
LISTEN [::]:80

Recommended hardening:

  • Restrict 22/tcp in the security group to your management network only
  • Restrict 80/tcp to the networks your agents use, if your live chat widget is only used internally
  • Terminate TLS in front of Chatwoot (see Step 13) so agent credentials and customer conversations are encrypted in transit
  • Enable EBS encryption on the data volume for encryption at rest
  • Change the seeded administrator password after first sign-in, and add named agent accounts rather than sharing it

Step 13: Add your own domain and HTTPS

Chatwoot is served over plain HTTP on port 80 out of the box so the appliance is reachable immediately after launch. For production use, put it behind TLS. Two supported approaches:

Terminate TLS on an AWS Application Load Balancer. Point an ALB at the instance on port 80, attach an AWS Certificate Manager certificate, and put your DNS record on the ALB. Then set the public URL Chatwoot advertises:

Task Command
Set the public URL sudo sed -i 's#^FRONTEND_URL=.*#FRONTEND_URL=https://chat.example.com/#' /opt/chatwoot/.env
Apply the change sudo systemctl restart chatwoot

Or terminate TLS on the instance with Let's Encrypt. Point a DNS A record at the instance's public address, then install certbot and let it configure the existing nginx site:

Task Command
Install certbot sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
Issue and install the certificate sudo certbot --nginx -d chat.example.com
Set the public URL sudo sed -i 's#^FRONTEND_URL=.*#FRONTEND_URL=https://chat.example.com/#' /opt/chatwoot/.env
Apply the change sudo systemctl restart chatwoot

Certbot installs a renewal timer automatically. Make sure 443/tcp is open in the security group before issuing the certificate.

Step 14: Operating the appliance

Task Command
Start Chatwoot sudo systemctl start chatwoot
Stop Chatwoot sudo systemctl stop chatwoot
Restart Chatwoot sudo systemctl restart chatwoot
Application logs sudo docker logs -f chatwoot-rails-1
Background worker logs sudo docker logs -f chatwoot-sidekiq-1
Reverse proxy status systemctl status nginx
First-boot log sudo journalctl -u chatwoot-firstboot -n 100

Check the running container set at any time:

sudo docker compose -f /opt/chatwoot/docker-compose.yml ps --format '{{.Name}} {{.State}}'

Troubleshooting

The site returns 502 Bad Gateway. nginx is up but the Rails application has not finished booting. This is normal for the first minute or two after launch or after a restart. Poll /health and then the application:

curl -s -o /dev/null -w "app -> HTTP %{http_code}\n" http://127.0.0.1/api
app -> HTTP 200

If it does not clear, read the application log with sudo docker logs --tail 100 chatwoot-rails-1.

The credentials file only shows the placeholder header. First boot has not completed. Watch it with sudo journalctl -u chatwoot-firstboot -f; it rotates the secrets, initialises the database and seeds the administrator account before writing the file.

Real-time updates do not arrive in the inbox. Chatwoot uses WebSockets for its real-time inbox. The bundled nginx site already sets the upgrade headers; if you have put your own proxy or load balancer in front, make sure it also forwards Upgrade and Connection headers and does not buffer the connection.

Agent invitations never arrive. Outbound email is not configured by default. Add your SMTP settings as in Step 9.

Disk is filling up. Attachments and the database both live on /var/lib/chatwoot. Check usage with df -h /var/lib/chatwoot, then grow the EBS volume and run resize2fs.

Support

cloudimg provides 24/7 technical support for this image with a guaranteed 24 hour response SLA, covering deployment, first-boot configuration, DNS and TLS setup, SMTP wiring, data volume resizing, container management and application updates. Contact support@cloudimg.co.uk.