This guide installs Chatwoot natively with Ruby on Rails, PostgreSQL, Redis, and Nginx on Debian 10 to latest stable, Ubuntu LTS, and RHEL 9+ compatible hosts.
- name: Install Chatwoot
hosts: chatwoot
become: true
vars:
chatwoot_root: /opt/chatwoot
chatwoot_user: chatwoot
chatwoot_port: 3000
chatwoot_url: https://chatwoot.example.com
postgres_password: "change-me-now"
secret_key_base: "generate-with-rails-secret-keygen"
redis_bind: 127.0.0.1
ruby_version: "3.2"
node_version: "24.x"
tasks:
- name: Install dependencies on Debian/Ubuntu
apt:
name:
- nginx
- postgresql
- postgresql-contrib
- libpq-dev
- redis-server
- curl
- git
- build-essential
- libssl-dev
- libreadline-dev
- zlib1g-dev
- libxml2-dev
- libxslt1-dev
- libffi-dev
- imagemagick
- libmagickwand-dev
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install Node.js repository
apt_repository:
repo: "deb https://deb.nodesource.com/node_{{ node_version }} {{ ansible_distribution_release }} main"
state: present
when: ansible_os_family == "Debian"
- name: Install Node.js
apt:
name: nodejs
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install rbenv and Ruby
block:
- name: Install rbenv dependencies
apt:
name:
- rbenv
- ruby-build
state: present
- name: Install Ruby {{ ruby_version }}
command: rbenv install {{ ruby_version }}
args:
creates: /home/{{ ansible_user }}/.rbenv/versions/{{ ruby_version }}
- name: Set global Ruby version
command: rbenv global {{ ruby_version }}
when: ansible_os_family == "Debian"
- name: Enable and start required services
service:
name: "{{ item }}"
state: started
enabled: true
loop:
- postgresql
- redis-server
- nginx
- name: Create Chatwoot user
user:
name: "{{ chatwoot_user }}"
shell: /bin/bash
create_home: yes
- name: Create Chatwoot directory
file:
path: "{{ chatwoot_root }}"
state: directory
owner: "{{ chatwoot_user }}"
group: "{{ chatwoot_user }}"
mode: "0755"
- name: Clone Chatwoot repository
git:
repo: https://github.com/chatwoot/chatwoot.git
dest: "{{ chatwoot_root }}"
version: master
become: yes
become_user: "{{ chatwoot_user }}"
- name: Create PostgreSQL database and user
become: yes
become_user: postgres
postgresql_db:
name: chatwoot
encoding: UTF-8
owner: chatwoot
state: present
- name: Create PostgreSQL user
become: yes
become_user: postgres
postgresql_user:
name: chatwoot
password: "{{ postgres_password }}"
db: chatwoot
priv: ALL
state: present
- name: Write Chatwoot .env file
copy:
dest: "{{ chatwoot_root }}/.env"
owner: "{{ chatwoot_user }}"
group: "{{ chatwoot_user }}"
mode: "0600"
content: |
FRONTEND_URL={{ chatwoot_url }}
SECRET_KEY_BASE={{ secret_key_base }}
REDIS_URL=redis://{{ redis_bind }}:6379
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USERNAME=chatwoot
DB_PASSWORD={{ postgres_password }}
DB_NAME=chatwoot
RAILS_ENV=production
NODE_ENV=production
- name: Install Ruby dependencies
command: bundle install --without development test
args:
chdir: "{{ chatwoot_root }}"
become: yes
become_user: "{{ chatwoot_user }}"
environment:
RBENV_ROOT: /home/{{ ansible_user }}/.rbenv
PATH: /home/{{ ansible_user }}/.rbenv/bin:/home/{{ ansible_user }}/.rbenv/shims:{{ ansible_env.PATH }}
- name: Install Node.js dependencies
command: pnpm install
args:
chdir: "{{ chatwoot_root }}"
become: yes
become_user: "{{ chatwoot_user }}"
- name: Compile assets
command: pnpm build
args:
chdir: "{{ chatwoot_root }}"
become: yes
become_user: "{{ chatwoot_user }}"
environment:
RAILS_ENV: production
- name: Prepare Chatwoot database
command: bundle exec rails db:chatwoot_prepare
args:
chdir: "{{ chatwoot_root }}"
become: yes
become_user: "{{ chatwoot_user }}"
environment:
RBENV_ROOT: /home/{{ ansible_user }}/.rbenv
PATH: /home/{{ ansible_user }}/.rbenv/bin:/home/{{ ansible_user }}/.rbenv/shims:{{ ansible_env.PATH }}
RAILS_ENV: production
run_once: true
- name: Create Nginx virtual host
copy:
dest: /etc/nginx/sites-available/chatwoot
mode: "0644"
content: |
upstream chatwoot_backend {
server 127.0.0.1:{{ chatwoot_port }};
keepalive 64;
}
server {
listen 80;
server_name {{ inventory_hostname }};
location / {
proxy_pass http://chatwoot_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
notify: restart nginx
- name: Enable Chatwoot site
command: ln -s /etc/nginx/sites-available/chatwoot /etc/nginx/sites-enabled/chatwoot
args:
creates: /etc/nginx/sites-enabled/chatwoot
notify: restart nginx
- name: Create systemd service for Chatwoot Rails server
copy:
dest: /etc/systemd/system/chatwoot-rails.service
mode: "0644"
content: |
[Unit]
Description=Chatwoot Rails Server
After=network.target postgresql.service redis-server.service
[Service]
Type=simple
User={{ chatwoot_user }}
WorkingDirectory={{ chatwoot_root }}
Environment=RAILS_ENV=production
Environment=RBENV_ROOT=/home/{{ ansible_user }}/.rbenv
Environment=PATH=/home/{{ ansible_user }}/.rbenv/bin:/home/{{ ansible_user }}/.rbenv/shims:/usr/bin:/bin
ExecStart=/home/{{ ansible_user }}/.rbenv/shims/bundle exec rails server -b 127.0.0.1 -p {{ chatwoot_port }}
Restart=always
[Install]
WantedBy=multi-user.target
notify: restart systemd
- name: Create systemd service for Chatwoot Sidekiq
copy:
dest: /etc/systemd/system/chatwoot-sidekiq.service
mode: "0644"
content: |
[Unit]
Description=Chatwoot Sidekiq Worker
After=network.target postgresql.service redis-server.service
[Service]
Type=simple
User={{ chatwoot_user }}
WorkingDirectory={{ chatwoot_root }}
Environment=RAILS_ENV=production
Environment=RBENV_ROOT=/home/{{ ansible_user }}/.rbenv
Environment=PATH=/home/{{ ansible_user }}/.rbenv/bin:/home/{{ ansible_user }}/.rbenv/shims:/usr/bin:/bin
ExecStart=/home/{{ ansible_user }}/.rbenv/shims/bundle exec sidekiq -C config/sidekiq.yml
Restart=always
[Install]
WantedBy=multi-user.target
notify: restart systemd
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
- name: restart systemd
systemd:
daemon_reload: yes
rails db:encryption:init.Start the Chatwoot services:
systemctl start chatwoot-rails
systemctl start chatwoot-sidekiq
systemctl enable chatwoot-rails
systemctl enable chatwoot-sidekiq
Configure reverse proxy with Let’s Encrypt SSL
Access Chatwoot at https://chatwoot.example.com
Create the first admin account
Enable MFA for all agents
Configure email channels and integrations
Any questions?
Feel free to contact us. Find all contact information on our contact page.