MAATRIX / Блог / Chatwoot на Ubuntu 24.04: пошаговая установка

Chatwoot на Ubuntu 24.04: пошаговая установка

MAATRIX

Клиенты пишут вам в чат на сайте, на почту, в Telegram и во «ВКонтакте» — и всё это в разных вкладках, которые вы или менеджер поддержки открываете по кругу. Рано или поздно кто-то теряется, кому-то отвечают через сутки, а разговор в одном канале не виден в другом. Chatwoot решает это одной инсталляцией: единый инбокс, куда стекаются все каналы, с назначением ответственных, метками и историей переписки по каждому клиенту. Дальше — как поднять его на собственном сервере с нуля, без магии и с реальными командами.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Chatwoot и зачем ставить его себе

Chatwoot — open-source платформа поддержки клиентов на Ruby on Rails: единый инбокс для веб-чата на сайте, email, Telegram, WhatsApp (через провайдера), Facebook и ВКонтакте (через интеграции). По функциям это self-hosted аналог Intercom или Zendesk Chat, но без ежемесячной платы за агента и без того, что переписка клиентов лежит на чужих серверах.

Причины ставить его самостоятельно, а не брать облачный тариф:

  • Данные клиентов остаются у вас. Для рынков с требованиями по хранению персональных данных это часто не опция, а обязанность.
  • Нет лимита на число агентов. Облачный Chatwoot берёт деньги за каждого агента, self-hosted — только ресурсы сервера.
  • Полный контроль над интеграциями — можно подключить свой SMTP, свой Redis для очередей, вписать в существующую инфраструктуру.

Обратная сторона: обновления, бэкапы и мониторинг — тоже ваша забота. Дальше разберём, как это организовать не героически, а рутинно.

Требования к серверу и подготовка

Chatwoot — не лёгкое приложение: Rails-монолит плюс Sidekiq-воркеры, PostgreSQL и Redis. На связке из пары агентов и десятков разговоров в день хватит скромной конфигурации, но с ростом трафика (особенно если подключаете email-канал с активной перепиской) память съедается быстро.

СценарийCPURAMДиск
Тест / 1-2 агента2 vCPU4 GB40 GB SSD
Рабочий инстанс, 5-10 агентов4 vCPU8 GB60 GB SSD
Активная поддержка, много каналов4-8 vCPU16 GB80+ GB SSD

Для старта достаточно 4 GB, но с запасом 8 GB вы не будете упираться в OOM при пиках Sidekiq. Если берёте VPS у maatrix.io — выбирайте конфигурацию с локацией ближе к вашей аудитории (RU, US или UK), это ощутимо сказывается на скорости загрузки виджета чата у посетителей сайта.

Перед установкой:

apt update && apt upgrade -y
apt install -y curl git ca-certificates gnupg ufw

Заведите непривилегированного пользователя — ставить прод-сервис под root не стоит:

adduser deploy
usermod -aG sudo deploy
su - deploy

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка Docker и Docker Compose

Chatwoot официально поддерживает установку через Docker Compose — это заметно проще, чем ручная сборка из исходников с Ruby, Node и системными зависимостями. Ставим Docker по официальному репозиторию:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Проверяем, что плагин compose встал:

docker compose version
usermod -aG docker deploy

После добавления в группу docker перелогиньтесь, чтобы не набирать sudo перед каждой командой.

Разворачиваем Chatwoot через Docker Compose

Клонируем официальный репозиторий с готовым compose-файлом:

git clone https://github.com/chatwoot/chatwoot.git
cd chatwoot
cp .env.example .env

Открываем .env и правим ключевые переменные. Обязательные для рабочего запуска:

# Секретный ключ — сгенерировать новый, не оставлять пример
SECRET_KEY_BASE=<результат openssl rand -hex 64>

# Домен, на котором будет доступен Chatwoot
FRONTEND_URL=https://support.example.com

# База данных (контейнер postgres из compose-файла)
POSTGRES_HOST=postgres
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=<сложный пароль>
POSTGRES_DATABASE=chatwoot_production

# Redis
REDIS_URL=redis://redis:6379

# SMTP для исходящей почты (регистрация, уведомления, email-канал)
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=support@example.com
SMTP_PASSWORD=<пароль от почтового ящика>
SMTP_AUTHENTICATION=login
SMTP_ENABLE_STARTTLS_AUTO=true

SECRET_KEY_BASE генерируется командой:

openssl rand -hex 64

Без SMTP письма-приглашения агентам и уведомления клиентам по email просто не уйдут — это частая причина, по которой «Chatwoot вроде работает, но никто не получает писем». Если поднимаете почтовый сервер на том же VPS — см. установку Postfix на VPS; для большинства проектов проще и надёжнее использовать внешний SMTP-релей (SendGrid, Mailgun, почта для домена у Yandex 360).

Поднимаем стек:

docker compose -f docker-compose.production.yaml up -d

Первый запуск создаёт контейнеры rails, sidekiq, postgres, redis. Проверяем, что всё поднялось:

docker compose -f docker-compose.production.yaml ps

Все сервисы должны быть в статусе running (или healthy, если healthcheck настроен). Инициализируем базу данных — это отдельный шаг, выполняется один раз при первом деплое:

docker compose -f docker-compose.production.yaml run --rm rails bundle exec rails db:chatwoot_prepare

Команда прогоняет миграции и создаёт дефолтные записи. Если контейнер rails падает сразу после старта — почти всегда причина в неверной строке подключения к Postgres или отсутствующем SECRET_KEY_BASE, проверьте логи:

docker compose -f docker-compose.production.yaml logs -f rails

Nginx как reverse proxy и SSL

Rails-приложение слушает порт 3000 внутри контейнера и наружу торчать напрямую не должно — перед ним нужен reverse proxy с TLS-терминацией. Ставим Nginx:

apt install -y nginx

Конфиг для домена (замените support.example.com на свой):

server {
    listen 80;
    server_name support.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;

        # для WebSocket (Action Cable, real-time обновления в инбоксе)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

WebSocket-заголовки здесь не для галочки: без них real-time обновления в интерфейсе агента (новое сообщение появляется без перезагрузки страницы) просто не будут работать, а Chatwoot начнёт казаться «подвисшим». Подробно о том, зачем нужен reverse proxy и какие ещё директивы полезны, — в статье как установить и настроить Nginx как reverse proxy на VPS.

Активируем конфиг и получаем сертификат через Certbot:

ln -s /etc/nginx/sites-available/chatwoot /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

apt install -y certbot python3-certbot-nginx
certbot --nginx -d support.example.com

Certbot сам пропишет listen 443 ssl и настроит редирект с 80 на 443. Автопродление сертификата проверяется командой certbot renew --dry-run — если интересует альтернатива с acme.sh и разница в подходах, есть отдельный разбор: certbot или acme.sh — что выбрать для сервера.

Firewall и базовая защита

Наружу должны смотреть только 80/443 (и 22 для SSH, желательно на нестандартном порту). Порт 3000 — только для localhost, снаружи он и не нужен, если Nginx настроен верно:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Проверьте, что порт 3000 не торчит наружу:

ss -tlnp | grep 3000

Если в выводе адрес 0.0.0.0:3000 — значит Rails слушает на всех интерфейсах и теоретически доступен напрямую в обход Nginx. В официальном compose-файле по умолчанию контейнер публикует порт как 127.0.0.1:3000:3000, но это стоит перепроверить после любого редактирования docker-compose.production.yaml.

Дополнительно есть смысл поставить fail2ban для защиты SSH и веб-логина от перебора паролей — стандартная мера для любого сервера, торчащего в интернет портами 80/443.

Первый запуск, каналы и подключение к сайту

Открываем https://support.example.com в браузере — Chatwoot покажет форму создания первого аккаунта администратора. После входа:

  1. Settings → Inboxes → Add Inbox — выбираете тип канала: Website, Email, API, или один из мессенджеров.
  2. Для веб-чата система выдаёт готовый JS-сниппет — вставляете его перед </body> на сайте:
<script>
  (function(d,t) {
    var BASE_URL = "https://support.example.com";
    var g = d.createElement(t), s = d.getElementsByTagName(t)[0];
    g.src = BASE_URL + "/packs/js/sdk.js";
    g.defer = true; g.async = true;
    s.parentNode.insertBefore(g, s);
    g.onload = function() {
      window.chatwootSDK.run({
        websiteToken: 'ВАШ_ТОКЕН',
        baseUrl: BASE_URL
      });
    };
  })(document, "script");
</script>
  1. Для email-канала Chatwoot либо принимает почту через собственный SMTP/IMAP-опрос, либо через forwarding — приходящие на выделенный адрес письма пересылаются в Chatwoot через вебхук.
  2. Приглашаете агентов через Settings → Agents — на их почту (через тот же SMTP из .env) уйдёт письмо с приглашением.

Разговоры из всех каналов падают в единый список слева, с фильтрами по статусу, назначенному агенту и метке — это и есть основная ценность единого инбокса.

Обновление и обслуживание

Chatwoot выпускает релизы регулярно, и накопленные несколько версий назад миграции иногда ломаются друг о друга — обновляться раз в квартал безопаснее, чем раз в год. Порядок действий:

cd chatwoot
git pull origin master
docker compose -f docker-compose.production.yaml build
docker compose -f docker-compose.production.yaml run --rm rails bundle exec rails db:migrate
docker compose -f docker-compose.production.yaml up -d

Перед обновлением обязательно сделайте дамп базы:

docker compose -f docker-compose.production.yaml exec postgres \
  pg_dump -U postgres chatwoot_production > chatwoot_backup_$(date +%F).sql

Держите такие дампы за пределами самого сервера — на отдельном хранилище или хотя бы копируйте на другую машину. Диски VPS не защищают от человеческой ошибки или сбоя провайдера, только от аппаратного отказа отдельного диска (и то не всегда). Если база разрастётся и начнутся сбои с подключением или производительностью — разбор типовых проблем есть в статье PostgreSQL на сервере: частые ошибки и решения.

Отдельно стоит следить за очередью Sidekiq — если контейнер sidekiq падает или зависает, письма и уведомления перестают уходить, а веб-чат может работать с задержками. Логи проверяются так же, как у rails:

docker compose -f docker-compose.production.yaml logs -f sidekiq

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Сколько агентов потянет минимальная конфигурация в 4 GB RAM?

Комфортно — 2-3 активных агента при умеренном потоке обращений. При росте нагрузки в первую очередь упирается Sidekiq и Postgres, увеличивайте RAM до 8 GB.

Можно ли подключить WhatsApp напрямую?

Нативно Chatwoot работает с WhatsApp Business API через сторонних провайдеров (Twilio, 360dialog и аналогичные) — прямого бесплатного подключения к личному WhatsApp Business App нет.

Что делать, если после docker compose up -d контейнер rails постоянно перезапускается?

В 90% случаев причина — неверный POSTGRES_PASSWORD/POSTGRES_HOST в .env или отсутствующий SECRET_KEY_BASE. Смотрите docker compose logs rails — там будет конкретная ошибка подключения.

Нужен ли отдельный сервер под Redis и Postgres при росте нагрузки?

На старте держать их в тех же контейнерах на одном сервере нормально. При заметном росте трафика имеет смысл вынести Postgres на отдельный инстанс — это снижает конкуренцию за память и диск с веб-процессом и Sidekiq.

Как перенести Chatwoot на другой сервер?

Дамп базы через pg_dump, копирование .env и содержимого volume с загруженными файлами (аватары, вложения), restore на новом сервере через psql, обновление DNS-записи домена.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →