Chatwoot
Overview
Chatwoot is an open source customer engagement and support platform. It is a self-hosted alternative to Intercom, Zendesk and Freshdesk. Your team gets a shared inbox for live chat, email and social channels, plus contact management, conversation routing and assignment, canned responses, reporting and an agent dashboard. You run customer support on your own infrastructure, without a per-seat SaaS subscription.
The SecureAnyCloud image installs Chatwoot 4.15.1 as the official production Docker Compose stack and runs it behind nginx as a systemd service. A complete support desk is online within minutes of launch.
What you get:
- Chatwoot 4.15.1 (MIT), deployed from the official production Docker Compose stack and pinned, so the image never silently upgrades at build time.
- Docker Engine (Docker CE) and the Docker Compose plugin, installed from the official Docker package repository.
- The Chatwoot Compose stack: the
railsweb application (Puma on container port 3000), thesidekiqbackground workers,postgres(PostgreSQL 16 with the pgvector extension) andredis(password protected). - A system
nginxreverse proxy on port 80, forwarding to the Rails app on127.0.0.1:3000. It sets the WebSocket upgrade headers that Chatwoot ActionCable realtime needs, and it serves an unauthenticated static/healthendpoint. - A dedicated data disk. All stateful data (the PostgreSQL database, the Redis data and every uploaded file) lives on a 40 GiB disk mounted at
/var/lib/chatwoot. Docker's data-root is relocated there. The disk is independently resizable and re-provisioned on every VM. - A per-VM super admin account (email and a generated password), created at first boot. Each instance gets a fresh Rails secret key base and fresh database and Redis passwords.
- Three systemd units:
nginx.service,chatwoot.service(a oneshot wrapper arounddocker compose up -d) andchatwoot-firstboot.service. - 24/7 SecureAnyCloud support
Prerequisites
Before you deploy this image, make sure you have an active Azure subscription, an SSH key, and a VNet with a subnet.
The recommended size is Standard_B4ms (4 vCPU / 16 GB RAM), because the Rails stack needs the memory. In the NSG, allow inbound 22/tcp from your management CIDR for SSH. Also allow 80/tcp from the CIDR that needs the Chatwoot web app. Add 443/tcp if you enable HTTPS.
Connect over SSH
Replace <vm-ip> with the public IP of your VM. The default login user is azureuser.
ssh azureuser@<vm-ip>Confirm the services are active
sudo systemctl is-active docker.service nginx.service chatwoot.service docker --version docker compose versionYou should see active printed three times, the Docker Engine version, and the Docker Compose v2 plugin version.
Confirm the Chatwoot containers are running
sudo docker ps --format "table {{.Names}}\t{{.Status}}"You should see all four containers in the Up state: chatwoot-rails-1, chatwoot-sidekiq-1, chatwoot-postgres-1 and chatwoot-redis-1.
Confirm the data disk is mounted
All stateful Chatwoot data lives on a dedicated data disk mounted at /var/lib/chatwoot.
findmnt /var/lib/chatwoot df -h /var/lib/chatwootfindmnt shows the device backing /var/lib/chatwoot, and df confirms the 40 GiB volume.
Check the health endpoint
The nginx reverse proxy serves an unauthenticated static /health endpoint on port 80. The Chatwoot API answers on /api.
curl -s http://localhost/health
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/api/health returns OK and /api returns 200. Together they confirm that nginx and the Rails app are both up.
Read the per-VM admin credentials
On its first boot, your instance generates a unique super admin email and password and writes them to a root-only file.
sudo cat /root/chatwoot-credentials.txtThis file lists CHATWOOT_URL (where to sign in), CHATWOOT_ADMIN_EMAIL and CHATWOOT_ADMIN_PASSWORD. Store the password somewhere safe.
Sign in to Chatwoot
Open http://<vm-ip>/ in your browser. You are redirected to the agent sign-in page. Enter the CHATWOOT_ADMIN_EMAIL and CHATWOOT_ADMIN_PASSWORD from Step 6, then sign in.
You can also verify the login from the command line with the Devise Token Auth endpoint. A correct password returns 200:
EMAIL=$(sudo grep '^CHATWOOT_ADMIN_EMAIL=' /root/chatwoot-credentials.txt | cut -d= -f2-)
PASS=$(sudo grep '^CHATWOOT_ADMIN_PASSWORD=' /root/chatwoot-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w "%{http_code}\n" -X POST http://localhost/auth/sign_in \
-H 'Content-Type: application/json' \
-d "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}"A 200 confirms that the per-VM super admin authenticates end to end.
Explore the dashboard
After you sign in, you land on the conversations dashboard. This is the shared team inbox where live chat, email and social conversations arrive and are assigned to agents.
From the dashboard, you can manage your contacts directory:
You can also review conversation analytics and configure your account from the reports and settings area:
Create your first inbox
Chatwoot organises incoming conversations into inboxes. From the agent dashboard, open Settings, then Inboxes, then Add Inbox. Choose a channel, for example a Website live-chat widget, an email channel or an API channel.
Follow the wizard to name the inbox. Then embed the generated widget script in your website, or connect your channel. New conversations from that channel appear in the dashboard for your agents.
Managing the stack
The Chatwoot stack is wrapped by the chatwoot.service systemd unit, which runs docker compose up -d from /opt/chatwoot.
sudo systemctl restart chatwoot.service
sudo systemctl status chatwoot.service --no-pagerTo inspect the application logs, tail the Rails container:
cd /opt/chatwoot
sudo docker compose logs --tail 50 railsEnabling HTTPS
The image serves plain HTTP on port 80. For any public deployment, put TLS in front with your own domain. Point a DNS A record at the VM public IP. Then install a certificate with the certbot nginx plugin, and update FRONTEND_URL in /opt/chatwoot/.env to your https:// domain. Finish with sudo systemctl restart chatwoot.service. In outline:
- Install certbot and the nginx plugin from the Ubuntu repositories.
- Run certbot against your domain to obtain and install a certificate into the nginx site.
- Set
FRONTEND_URL=https://your-domain/in/opt/chatwoot/.envand restartchatwoot.service.
Use your own registered domain throughout.
Maintenance
The OS receives unattended security updates.
To update Chatwoot itself, edit the pinned image tag in /opt/chatwoot/docker-compose.yml. Then, from /opt/chatwoot, run sudo docker compose pull, followed by sudo docker compose run --rm rails bundle exec rails db:chatwoot_prepare and sudo systemctl restart chatwoot.service. Always snapshot the /var/lib/chatwoot data disk before a major version upgrade.
Support
SecureAnyCloud provides 24/7 support for this image. Chatwoot is a trademark of Chatwoot Inc. This image is provided by SecureAnyCloud and is not affiliated with or endorsed by Chatwoot Inc.
Deploy on Azure
Launch Chatwoot 4.15.1 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
This guide covers how to deploy and configure Chatwoot on AWS using SecureAnyCloud AWS Marketplace AMIs. Chatwoot is an open source customer engagement and support platform. It is a shared team inbox that unifies website live chat, email and social messaging channels into one conversation view. Unified contacts, labels, teams, canned responses, automation rules and reporting are built in.
The SecureAnyCloud image ships the upstream Chatwoot release unmodified. It runs the officially supported way, as the production container stack, alongside PostgreSQL with the pgvector extension and Redis. All of it is 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. A single administrator account is seeded with a random password, which is written to a root-only file.
Chatwoot is a trademark of its respective owner. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by or sponsored by Chatwoot. It ships the upstream self-hosted software, unmodified.
What you get:
- 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 are published to the loopback interface only and are 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
80as the reverse proxy. It is preconfigured with the WebSocket upgrade headers that the real-time inbox and live chat need, and it serves an unauthenticated/healthreadiness endpoint. docker.service,nginx.service,chatwoot-firstboot.serviceandchatwoot.serviceas systemd units, enabled and active on boot.- A fresh application secret, database password and cache password for every instance, generated on first boot. A single administrator account is created 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. It holds the database, the cache, the uploaded attachments and the application images, and it is independently resizable and separate from the OS root. - An Ubuntu 24.04 LTS base with the latest security patches applied at build time.
- 24/7 SecureAnyCloud support with a guaranteed 24-hour response SLA
Prerequisites
Before you deploy this image, make sure you have:
- 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
The recommended instance type is m5.large (2 vCPU, 8 GB RAM). It 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.
In the security group, allow inbound 22/tcp from your management network and 80/tcp from the networks your agents and website visitors use. The listing's suggested group also opens port 443/tcp, so you can attach your own TLS certificate later, as shown near the end of this guide.
Connecting to your instance
SSH in with the private key of the EC2 key pair you selected at launch. On Ubuntu 24.04, the login user is 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.
Launch from the AWS Marketplace
Open the product page in AWS Marketplace and choose Continue to Subscribe. Accept the terms, then choose Continue to Configuration and Continue to Launch.
Pick your Region, the m5.large instance type, your VPC and public subnet, and your key pair. Choose a security group that allows inbound 22 and 80, as above. Then launch the instance.
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}]'Confirm the platform is up
Chatwoot serves an unauthenticated readiness endpoint at /health through nginx. Poll it until it returns 200. That signals that 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/healthGET /health -> HTTP 200Confirm that the four systemd units the appliance depends on are active:
systemctl is-active chatwoot.service nginx.service docker.serviceactive active activeThen confirm that 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 minutesRetrieve your per-instance administrator credentials
No login is baked into the image. First boot generates a random administrator password for this instance alone. It writes the password, together with the account email and the instance URL, to a root-only file:
sudo cat /root/chatwoot-credentials.txtThe 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.
Without leaving the shell, you can confirm that the credential is genuinely per instance and that a wrong password is rejected:
sudo grep -c '^CHATWOOT_ADMIN_PASSWORD=' /root/chatwoot-credentials.txt1Sign in to the agent inbox
Browse to http://<instance-public-ip>/ and sign in with the email and password from the credentials file.
After you sign in, you land on the agent dashboard. The conversation list is on the left, the shared inbox navigation runs down the side, and the getting-started cards are on the right.
Once you are in, change the administrator password from Profile Settings and store the new one in your password manager.
Create your first inbox
An inbox is a channel that Chatwoot receives conversations from. Go to Settings, then Inboxes, and choose Add Inbox to pick a channel.
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 you can select them.
Add agents and teams
Go to Settings, then Agents, and choose Add Agent to invite a colleague by email address. Each person can be given the Agent or Administrator role. Under Settings, then Teams, you can group agents so that conversations are routed to a team rather than an individual.
Account self-signup is disabled in this image, so people cannot create their own accounts on your instance. Add agents from this screen instead.
Outbound email is not configured out of the box. Agent invitation emails and notification emails are not delivered until you add SMTP settings (see Step 9).
Reporting
Reports gives live conversation and agent metrics. These include open, unattended, unassigned and pending conversation counts, agent availability, and conversation traffic and resolutions over time. It also provides per-agent, per-label, per-inbox, per-team, CSAT and SLA breakdowns.
Scope each report by date range and inbox. Download it as CSV using the download control on the panel.
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, because it contains your database and cache passwords:
sudo grep -Eo '^[A-Z_]+=' /opt/chatwoot/.env | tr -d '=' | sort | head -20ACTIVE_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_BASEAppend your SMTP configuration to /opt/chatwoot/.env with your editor of choice, then restart. For example, set SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD and MAILER_SENDER_EMAIL:
Task Command
Edit the environment file sudo nano /opt/chatwoot/.env
Restart Chatwoot after editing sudo systemctl restart chatwoot
The Chatwoot environment variable reference documents the exact variable names for your provider. Keep the file at mode 0600, because it holds your database and cache passwords as well.
Where your data lives
The database, the cache and every uploaded attachment live on a dedicated EBS volume mounted at /var/lib/chatwoot. It is 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/chatwootThe volume is mounted by filesystem UUID from /etc/fstab, so it survives reboots and instance-type changes:
grep chatwoot /etc/fstabTo grow it, expand the EBS volume in the AWS console or CLI. Then extend the filesystem on the instance with sudo resize2fs /dev/nvme1n1, substituting the device name reported by lsblk. No downtime is required.
Back up the database and attachments
Take an EBS snapshot of the data volume for a whole-appliance restore point. Also dump the database for a portable logical backup:
sudo docker exec chatwoot-postgres-1 pg_dump -U postgres chatwoot | gzip > ~/chatwoot-backup.sql.gzCheck that the dump was written with ls -lh ~/chatwoot-backup.sql.gz. Store the dump off the instance, for example in Amazon S3. Keep it alongside a snapshot of /var/lib/chatwoot, which holds the uploaded attachments.
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. 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 [::]:80Recommended hardening:
- Restrict
22/tcpin the security group to your management network only. - Restrict
80/tcpto the networks your agents use, if your live chat widget is used only 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.
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. There are 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 that 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 you issue the certificate.
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 with:
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/apiapp -> HTTP 200If it does not clear, read the application log with sudo docker logs --tail 100 chatwoot-rails-1.
The credentials file shows only its 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 it writes 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 the 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.
The 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
SecureAnyCloud provides 24/7 technical support for this image with a guaranteed 24-hour response SLA. Support covers deployment, first-boot configuration, DNS and TLS setup, SMTP setup, data volume resizing, container management and application updates. Contact sales@secureanycloud.com.
Deploy on AWS
Launch Chatwoot Customer Engagement Platform with 24/7 support from SecureAnyCloud.
View on Marketplace
Need help?
Our support team is available 24/7.
sales@secureanycloud.com