bolt Valebyte VPS от $4/мес — NVMe, запуск за 60 секунд.

Получить VPS arrow_forward
eco Начальный Туториал

Установка Chatwoot на VPS: Docker, PostgreSQL, Redis, SSL и настройка email

calendar_month Oct 08, 2026 schedule 18 мин. чтения visibility 25 просмотров
Установка Chatwoot на VPS: Docker, PostgreSQL, Redis, SSL и настройка email
info

Нужен сервер для этого гайда? Мы предлагаем выделенные серверы и VPS в 50+ странах с мгновенной настройкой.

Нужен сервер для этого гайда?

Разверните VPS или выделенный сервер за минуты.

Установка Chatwoot на VPS: Docker, PostgreSQL, Redis, SSL и настройка email

TL;DR

Chatwoot — self-hosted платформа для поддержки клиентов через виджет сайта, email, Telegram, WhatsApp и другие каналы. В этом руководстве вы развернёте Chatwoot на Ubuntu VPS в Docker, подключите PostgreSQL и Redis, настроите HTTPS через Caddy, SMTP для исходящей почты, резервное копирование и безопасное обслуживание.

  • Для небольшой команды достаточно VPS с 2 vCPU, 4 ГБ RAM и 50–80 ГБ NVMe.
  • Chatwoot запускается в контейнерах: веб-приложение, фоновый worker, PostgreSQL, Redis и Caddy.
  • HTTPS-сертификат Let’s Encrypt выпускается и продлевается автоматически через Caddy.
  • Исходящая почта настраивается через SMTP-переменные в файле .env.
  • Перед запуском нужно создать базу данных командой db:chatwoot_prepare.
  • Критичные данные для бэкапа: PostgreSQL, .env, Caddy data и пользовательские загрузки.

Что мы настраиваем и зачем

Схема: Что мы настраиваем и зачем
Схема: Что мы настраиваем и зачем

Chatwoot — это open-source система customer support и omnichannel inbox. Она собирает обращения клиентов в одном интерфейсе: сообщения из веб-чата, email, Telegram, Facebook Messenger, Instagram, WhatsApp Business API и других интеграций. Операторы могут назначать диалоги друг другу, использовать метки, шаблоны ответов, автоматизацию, SLA и базу знаний.

В этой инструкции будет установлен self-hosted экземпляр Chatwoot на собственном VPS. Он будет доступен по вашему доменному имени, например chat.example.com, через защищённое HTTPS-подключение. Данные переписки, контакты, вложения и настройки будут храниться на вашем сервере, а не в чужом SaaS-аккаунте.

Что будет работать после установки

  • веб-интерфейс Chatwoot для администраторов и операторов;
  • виджет онлайн-чата, который можно добавить на сайт;
  • PostgreSQL 16 как основная база данных;
  • Redis 7 для очередей, кеша и фоновых задач;
  • Sidekiq worker для отправки email, обработки webhook и фоновых операций;
  • Caddy 2 как reverse proxy и менеджер TLS-сертификатов;
  • SMTP-отправка уведомлений, приглашений пользователей и ответов из email-канала;
  • автоматические бэкапы PostgreSQL в S3-совместимое хранилище.

Cloud-managed или self-hosted

Критерий Облачный сервис Self-hosted Chatwoot на VPS
Скорость старта Несколько минут, инфраструктура уже готова Нужно настроить сервер, DNS, SSL и бэкапы
Контроль данных Данные находятся у поставщика услуги Данные, логи и резервные копии контролируете вы
Кастомизация Ограничена тарифом и интерфейсом Можно менять конфиги, интеграции и версию приложения
Эксплуатация Обновления и бэкапы обычно выполняет сервис Обновления, безопасность и восстановление — ваша зона ответственности
Стоимость при росте команды Часто зависит от числа агентов и каналов Зависит в основном от ресурсов сервера и хранения

Self-hosted вариант подходит командам, которым важны контроль персональных данных, возможность интеграции с внутренними системами, фиксированные инфраструктурные расходы или размещение в нужной юрисдикции. Он также удобен для SaaS-проектов, агентств и внутренних служб поддержки.

Перед началом подготовьте домен или поддомен, например chat.example.com. Его A-запись должна указывать на публичный IPv4-адрес VPS. Для автоматического выпуска сертификата порты 80 и 443 должны быть доступны из интернета.

Какой VPS-конфиг нужен под эту задачу

Схема: Какой VPS-конфиг нужен под эту задачу
Схема: Какой VPS-конфиг нужен под эту задачу

Нагрузка Chatwoot зависит не только от числа операторов, но и от количества одновременных посетителей в веб-чате, размера вложений, числа подключённых каналов и активности автоматизации. PostgreSQL и Sidekiq чувствительны к нехватке памяти: сервер с 1 ГБ RAM для production-развёртывания использовать не стоит.

Сценарий vCPU RAM NVMe-диск Кому подходит
Тестовый стенд 2 2 ГБ 30 ГБ Тестирование, один администратор, без большого числа вложений
Минимальный production 2 4 ГБ 50–80 ГБ До 5–10 агентов и умеренный поток обращений
Рабочая команда 4 8 ГБ 100–160 ГБ 10–30 агентов, активные каналы и вложения
Высокая нагрузка 8+ 16+ ГБ 250+ ГБ Много диалогов, интеграций, API и длительное хранение медиа

Практичный стартовый конфиг — 2 vCPU, 4 ГБ RAM, 80 ГБ NVMe и канал от 100 Мбит/с. Этого достаточно, чтобы одновременно работали PostgreSQL, Redis, Caddy, веб-контейнер и worker. При выборе можно взять VPS с указанными характеристиками либо аналогичный сервер у другого провайдера.

Почему важен запас по диску

Диск расходуют не только Docker-образы. Пространство занимают база PostgreSQL, временные файлы, логи контейнеров, вложения из диалогов, резервные копии до отправки во внешнее хранилище и данные Caddy. Не планируйте диск «впритык»: держите минимум 25–30% свободного места. При заполнении раздела PostgreSQL может аварийно остановиться или повредить рабочий процесс транзакций.

Когда нужен dedicated, а не VPS

Выделенный сервер имеет смысл при стабильной высокой нагрузке, требованиях к изоляции ресурсов, хранении большого количества файлов или если Chatwoot работает вместе с другими тяжёлыми сервисами. Например, dedicated стоит рассмотреть при 50+ активных агентах, десятках тысяч разговоров в месяц, локальном хранении крупных медиафайлов и интенсивной аналитике.

Для обычной поддержки малого бизнеса VPS обычно лучше: его проще увеличить по CPU, RAM и диску, он дешевле на старте и не требует резервировать избыточные ресурсы. Не размещайте production Chatwoot на одном сервере с публичной базой данных, тестовыми CI-задачами или непроверенными контейнерами.

Как выбрать локацию

Локация влияет на задержку веб-чата, маршрутизацию email и требования к обработке персональных данных. Выбирайте регион ближе к операторам и основной аудитории. Если вы храните переписки клиентов из ЕС, заранее проверьте внутренние юридические требования к региону размещения и соглашениям обработки данных.

Подготовка сервера

Схема: Подготовка сервера
Схема: Подготовка сервера

Ниже используется Ubuntu Server 24.04 LTS. На 2026 год это подходящая LTS-база для Docker-развёртывания: в ней есть актуальное ядро, длительная поддержка и стабильный набор пакетов. Подключитесь к серверу под пользователем root, которого выдал провайдер.

Обновите операционную систему

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

apt update && apt upgrade -y
apt autoremove -y
reboot

После перезагрузки снова подключитесь по SSH и создайте отдельного пользователя для администрирования. Не работайте постоянно под root: это повышает риск случайно удалить данные или выполнить опасную команду без ограничений.

adduser deploy
usermod -aG sudo deploy
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chown -R deploy:deploy /home/deploy/.ssh

Скопируйте свой публичный SSH-ключ в файл авторизации. Выполняйте команду на локальном компьютере, заменив IP-адрес сервера.

ssh-copy-id deploy@SERVER_IP

Проверьте вход во втором терминале. Не закрывайте текущую root-сессию, пока не убедитесь, что ключ работает.

ssh deploy@SERVER_IP
sudo whoami

Ожидаемый вывод второй команды — root. После проверки запретите вход root-пользователя и парольную аутентификацию. Сначала сохраните резервную копию конфигурации SSH.

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo sed -i 's/^#\?PermitRootLogin./PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PasswordAuthentication./PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload ssh

Установите базовые утилиты и защиту от перебора паролей

Пакеты ниже понадобятся для диагностики, скачивания файлов, работы с репозиториями и защиты SSH. Даже при отключённой парольной аутентификации Fail2ban полезен как дополнительный уровень контроля.

sudo apt install -y ca-certificates curl gnupg git jq \
  ufw fail2ban unattended-upgrades apt-transport-https \
  software-properties-common

Настройте firewall. Открываются только SSH, HTTP и HTTPS. PostgreSQL на порту 5432 и Redis на порту 6379 наружу открывать нельзя: контейнеры будут взаимодействовать только во внутренней Docker-сети.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Создайте минимальную локальную конфигурацию Fail2ban для SSH. Значения означают: блокировать IP на один час, если он сделал пять неудачных попыток за десять минут.

sudo tee /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
EOF

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Создайте рабочий каталог

Все файлы стека будут находиться в /opt/chatwoot. Такой путь удобно резервировать, переносить и проверять. Не храните секреты в домашнем каталоге, если на сервере несколько администраторов.

sudo mkdir -p /opt/chatwoot
sudo chown -R deploy:deploy /opt/chatwoot
cd /opt/chatwoot

Установка ПО — пошагово

Схема: Установка ПО — пошагово
Схема: Установка ПО — пошагово

Для установки используется Docker Engine 27+ и Docker Compose Plugin v2. В production не устанавливайте PostgreSQL и Redis напрямую через apt, если планируете запускать их в Docker: смешивание двух способов усложняет сетевую диагностику, обновления и бэкапы.

Установите Docker Engine из официального репозитория

Сначала добавьте ключ и репозиторий Docker для Ubuntu.

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Следующая команда добавляет репозиторий, соответствующий архитектуре и версии Ubuntu.

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

sudo apt update

Установите Docker Engine, Compose Plugin и необходимые компоненты сети контейнеров.

sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

sudo systemctl enable --now docker
sudo usermod -aG docker deploy

Выйдите из SSH-сессии и подключитесь снова, чтобы группа docker применилась. Затем проверьте версии.

exit
ssh deploy@SERVER_IP
docker --version
docker compose version
docker run --rm hello-world

На 2026 год ориентируйтесь на Docker Engine 27 или новее и Docker Compose v2. Если команда docker run возвращает приветственное сообщение, демон работает корректно.

Создайте структуру постоянных данных

Docker named volumes переживают пересоздание контейнеров, но для Caddy и локальных вложений удобнее явно создать каталоги. Каталог storage будет использоваться Chatwoot при локальном хранении файлов.

cd /opt/chatwoot
mkdir -p caddy/data caddy/config storage backups
chmod 700 backups
find /opt/chatwoot -maxdepth 2 -type d -print

Сгенерируйте секреты

Chatwoot использует SECRET_KEY_BASE для подписания сессий и защиты криптографических данных приложения. Потеря этого ключа может разлогинить пользователей, а его публикация создаёт риск компрометации сессий. Сгенерируйте два случайных значения и не отправляйте их в мессенджеры или репозитории.

openssl rand -hex 64
openssl rand -hex 32

Первое значение будет использоваться как SECRET_KEY_BASE, второе — как пароль PostgreSQL. В следующем разделе они попадут в файл .env, права на который будут ограничены.

Проверьте DNS до запуска

До старта Caddy домен должен уже разрешаться в IP-адрес сервера. Замените имя на собственное. Если вывод показывает другой адрес или пустой результат, исправьте A-запись у DNS-провайдера и дождитесь обновления зоны.

getent ahostsv4 chat.example.com
curl -4 ifconfig.me
echo

Конфигурация Chatwoot, SSL и email

Схема: Конфигурация Chatwoot, SSL и email
Схема: Конфигурация Chatwoot, SSL и email

В этом варианте все сервисы описаны в одном файле compose.yaml. PostgreSQL и Redis не публикуют порты на хост, поэтому к ним нельзя подключиться напрямую из интернета. Caddy — единственный контейнер, который принимает внешние запросы на 80 и 443 портах.

Создайте файл с переменными окружения

Создайте /opt/chatwoot/.env. Замените домен, email администратора, пароли и SMTP-параметры. Значение FRONTEND_URL обязательно должно начинаться с https:// и не должно иметь слэш в конце.

cd /opt/chatwoot
nano .env
POSTGRES_DB=chatwoot_production
POSTGRES_USER=chatwoot
POSTGRES_PASSWORD=CHANGE_TO_A_LONG_RANDOM_DATABASE_PASSWORD
POSTGRES_HOST=postgres
POSTGRES_PORT=5432

REDIS_URL=redis://redis:6379
RAILS_ENV=production
NODE_ENV=production
INSTALLATION_ENV=docker
SECRET_KEY_BASE=CHANGE_TO_128_HEX_CHARACTERS_FROM_OPENSSL

FRONTEND_URL=https://chat.example.com
DEFAULT_LOCALE=ru
RAILS_LOG_TO_STDOUT=true
RAILS_SERVE_STATIC_FILES=true
ENABLE_ACCOUNT_SIGNUP=false

ACTIVE_STORAGE_SERVICE=local
LOCAL_STORAGE_PATH=/app/storage

[email protected]
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=smtp-login
SMTP_PASSWORD=CHANGE_TO_SMTP_PASSWORD
SMTP_DOMAIN=example.com
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true
SMTP_OPENSSL_VERIFY_MODE=peer

[email protected]

Для SMTP используйте отдельный почтовый ящик или SMTP-учётную запись. Почтовые сервисы часто требуют пароль приложения, а не основной пароль от ящика. Порт 587 используется с STARTTLS, порт 465 — с TLS сразу после подключения; для 465 обычно требуется дополнительная настройка адаптера, поэтому для первого запуска выбирайте 587.

Ограничьте доступ к файлу: читать его должны только root и пользователь deploy.

chmod 600 /opt/chatwoot/.env
ls -l /opt/chatwoot/.env

Создайте Docker Compose-конфигурацию

Ниже используется стабильный образ Chatwoot ветки 4.x. Перед крупным обновлением фиксируйте конкретный тег, например v4.x.y, после проверки релиз-нотов. Тег latest удобен для тестов, но для production ухудшает предсказуемость обновлений.

nano compose.yaml
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    env_file: .env
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - chatwoot_internal

  redis:
    image: redis:7.4-alpine
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - chatwoot_internal

  rails:
    image: chatwoot/chatwoot:v4.0.2
    restart: unless-stopped
    env_file: .env
    command: bundle exec rails server -p 3000 -b 0.0.0.0
    entrypoint: docker/entrypoints/docker-entrypoint.sh
    volumes:
      - ./storage:/app/storage
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - chatwoot_internal

  worker:
    image: chatwoot/chatwoot:v4.0.2
    restart: unless-stopped
    env_file: .env
    command: bundle exec sidekiq -C config/sidekiq.yml
    entrypoint: docker/entrypoints/docker-entrypoint.sh
    volumes:
      - ./storage:/app/storage
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - chatwoot_internal

  caddy:
    image: caddy:2.10-alpine
    restart: unless-stopped
    env_file: .env
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy/data:/data
      - ./caddy/config:/config
    depends_on:
      - rails
    networks:
      - chatwoot_internal

volumes:
  postgres_data:
  redis_data:

networks:
  chatwoot_internal:
    driver: bridge

Если к моменту установки актуальный стабильный релиз Chatwoot новее v4.0.2, замените тег у контейнеров rails и worker на одинаковый проверенный тег актуальной стабильной ветки. Никогда не обновляйте только один из этих двух контейнеров: веб-процесс и Sidekiq должны работать на одной версии приложения.

Настройте Caddy и TLS

Caddy сам запросит сертификат Let’s Encrypt, настроит HTTP-to-HTTPS редирект и будет продлевать сертификат. Сертификаты и аккаунт ACME сохраняются в ./caddy/data, поэтому они не исчезнут после пересоздания контейнера.

nano Caddyfile
CADDY_EMAIL {
  email {$CADDY_EMAIL}
}

chat.example.com {
  encode zstd gzip

  reverse_proxy rails:3000

  header {
    -Server
    Strict-Transport-Security "max-age=31536000; includeSubDomains"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "strict-origin-when-cross-origin"
  }

  log {
    output stdout
    format json
  }
}

Замените chat.example.com в Caddyfile на тот же домен, который указан в FRONTEND_URL. Переменная CADDY_EMAIL из файла .env применяется внутри Caddy через синтаксис {$CADDY_EMAIL}.

Запустите инфраструктурные контейнеры и подготовьте базу

Сначала скачайте образы и поднимите PostgreSQL с Redis. Затем выполните миграции и начальную подготовку базы. Команда db:chatwoot_prepare создаёт структуру таблиц и применяет миграции.

cd /opt/chatwoot
docker compose pull
docker compose up -d postgres redis
docker compose ps

Дождитесь статуса healthy у PostgreSQL и Redis. После этого запустите одноразовый контейнер с задачей подготовки базы.

docker compose run --rm rails \
  bundle exec rails db:chatwoot_prepare

Если команда завершилась без ошибки, запустите приложение, worker и reverse proxy. Параметр -d запускает сервисы в фоне.

docker compose up -d rails worker caddy
docker compose ps
docker compose logs --tail=100 caddy

Проверьте работоспособность

Проверьте ответ Caddy с самого VPS. Код 200, 301 или 302 означает, что маршрут отвечает. При первом запросе Caddy может несколько секунд получать сертификат.

curl -I http://chat.example.com
curl -I https://chat.example.com
docker compose logs --tail=100 rails
docker compose logs --tail=100 worker

Откройте https://chat.example.com в браузере. При первом запуске Chatwoot предложит создать аккаунт администратора и организацию. Поскольку ENABLE_ACCOUNT_SIGNUP=false, публичная регистрация будет отключена после создания первоначального аккаунта; новых агентов добавляйте из интерфейса администратора через приглашения.

Проверьте SMTP и настройте email-канал

После создания администратора перейдите в интерфейсе в раздел настроек организации и проверьте приглашение нового агента: это простой тест исходящей почты. Если письмо не приходит, сначала изучите логи worker, потому что отправка email выполняется фоновой задачей.

docker compose logs -f worker

Чтобы принимать обращения по email, создайте inbox типа Email Channel в панели Chatwoot. Сервис покажет адрес для пересылки или параметры интеграции. На стороне вашего почтового провайдера настройте forwarding с адреса поддержки на этот адрес либо используйте поддерживаемый почтовый канал по инструкции интерфейса.

Для хорошей доставляемости исходящей почты настройте DNS-записи SPF, DKIM и DMARC у домена отправителя. SMTP может технически работать и без них, но письма с приглашениями и ответами чаще будут попадать в спам. Адрес MAILER_SENDER_EMAIL должен принадлежать домену, для которого эти записи настроены.

Добавьте веб-виджет на сайт

После создания Website Inbox Chatwoot покажет готовый JavaScript-сниппет. Вставьте его перед закрывающим тегом </body> сайта. Не копируйте пример с чужим идентификатором сайта: используйте код, сформированный именно вашим экземпляром Chatwoot, иначе диалоги будут привязаны не к нужному inbox.

Бэкапы и обслуживание

Схема: Бэкапы и обслуживание
Схема: Бэкапы и обслуживание

Рабочий сервер без проверенного восстановления нельзя считать защищённым. Для Chatwoot нужно резервировать не только PostgreSQL: часть критичных данных находится в конфигурации и локальном хранилище вложений. Redis обычно не является основным источником данных, но его volume можно включить в полный аварийный бэкап.

Что обязательно сохранять

  • PostgreSQL: аккаунты, контакты, диалоги, сообщения, настройки inbox и интеграций.
  • Файл .env: секреты приложения, SMTP-параметры, пароль базы, публичный URL.
  • Каталог storage: вложения, если используется ACTIVE_STORAGE_SERVICE=local.
  • Каталог caddy/data: сертификаты и ACME-данные; их можно восстановить заново, но сохранять полезно.
  • compose.yaml и Caddyfile: инфраструктурная конфигурация.

Не полагайтесь только на Docker volume как на бэкап. Volume расположен на том же диске и не спасает при удалении VPS, ошибке администратора, повреждении файловой системы или блокировке аккаунта. Минимум одна копия должна уходить во внешнее S3-совместимое хранилище, на отдельный backup VPS или в объектное хранилище другого аккаунта.

Установите restic

Restic шифрует архивы на стороне сервера до загрузки в удалённое хранилище. Ниже показан вариант с S3-совместимым bucket. Создайте bucket заранее и выпустите отдельный access key с доступом только к этому bucket.

sudo apt install -y restic
sudo mkdir -p /etc/restic
sudo chmod 700 /etc/restic

Создайте файл окружения для restic. Значения endpoint, bucket и ключей получите у используемого S3-провайдера. Не добавляйте этот файл в Git.

sudo nano /etc/restic/chatwoot.env
RESTIC_REPOSITORY=s3:https://s3.example.net/chatwoot-backups
RESTIC_PASSWORD=CHANGE_TO_A_LONG_BACKUP_ENCRYPTION_PASSWORD
AWS_ACCESS_KEY_ID=CHANGE_TO_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=CHANGE_TO_SECRET_KEY
sudo chmod 600 /etc/restic/chatwoot.env
sudo chown root:root /etc/restic/chatwoot.env

Создайте скрипт резервного копирования

Скрипт создаёт консистентный дамп PostgreSQL через pg_dump, добавляет конфиги и файловое хранилище в зашифрованный архив restic, затем удаляет временный SQL-файл. Для крупных установок лучше вынести PostgreSQL в отдельный managed-сервис или настроить физические бэкапы, но логический дамп подходит большинству небольших команд.

sudo nano /usr/local/sbin/chatwoot-backup.sh
#!/usr/bin/env bash
set -euo pipefail

APP_DIR="/opt/chatwoot"
BACKUP_DIR="${APP_DIR}/backups"
STAMP="$(date +%F_%H-%M-%S)"
DUMP_FILE="${BACKUP_DIR}/chatwoot_${STAMP}.sql.gz"

set -a
source /etc/restic/chatwoot.env
set +a

mkdir -p "${BACKUP_DIR}"
cd "${APP_DIR}"

docker compose exec -T postgres \
  pg_dump -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" | gzip -9 > "${DUMP_FILE}"

restic backup \
  "${DUMP_FILE}" \
  "${APP_DIR}/.env" \
  "${APP_DIR}/compose.yaml" \
  "${APP_DIR}/Caddyfile" \
  "${APP_DIR}/storage" \
  "${APP_DIR}/caddy/data"

restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

rm -f "${DUMP_FILE}"

Скрипту нужны переменные PostgreSQL из /opt/chatwoot/.env. Добавьте загрузку этого файла перед выполнением pg_dump, иначе переменные не будут определены в окружении скрипта.

sudo sed -i '/cd "${APP_DIR}"/a set -a\nsource "${APP_DIR}/.env"\nset +a' \
  /usr/local/sbin/chatwoot-backup.sh

sudo chmod 700 /usr/local/sbin/chatwoot-backup.sh
sudo /usr/local/sbin/chatwoot-backup.sh

Первый запуск инициализирует репозиторий restic, если это требуется, либо запросит подтверждение. После успешного завершения проверьте список снимков.

sudo bash -c 'source /etc/restic/chatwoot.env && restic snapshots'

Запланируйте бэкап через cron

Запускайте бэкап ночью, например в 03:30. Вывод перенаправляется в лог, который пригодится при расследовании ошибок. Раз в неделю проверяйте, что новый snapshot действительно появился.

sudo crontab -e
30 3   * /usr/local/sbin/chatwoot-backup.sh >> /var/log/chatwoot-backup.log 2>&1

Проверка восстановления

Наличие backup-файлов не доказывает возможность восстановления. Не реже одного раза в квартал разворачивайте дамп на тестовом сервере. Для восстановления базы остановите приложение, создайте пустую базу и загрузите SQL-дамп. В production не выполняйте восстановление без подтверждённого плана отката.

gunzip -c chatwoot_YYYY-MM-DD_HH-MM-SS.sql.gz | \
  docker compose exec -T postgres \
  psql -U chatwoot -d chatwoot_production

Обновления Chatwoot и контейнеров

Для небольшого инстанса используйте maintenance window: предупредите операторов, сделайте бэкап, обновите образ, примените миграции и проверьте логи. Rolling update без простоя требует нескольких web-реплик, общего storage, отдельной базы и балансировщика; для одного VPS он обычно неоправданно сложен.

cd /opt/chatwoot
sudo /usr/local/sbin/chatwoot-backup.sh
docker compose pull
docker compose run --rm rails bundle exec rails db:migrate
docker compose up -d
docker image prune -f
docker compose ps

Перед обновлением прочитайте release notes целевой версии. Особое внимание уделяйте major-релизам, требованиям к PostgreSQL/Redis и изменениям переменных окружения. Если обновление вызывает ошибки, не удаляйте volumes и не запускайте произвольные команды миграции: сначала сохраните логи и вернитесь к предыдущему образу.

Также контролируйте дисковое пространство и состояние контейнеров.

df -h
docker system df
docker compose ps
docker stats --no-stream

Troubleshooting и FAQ

Почему Caddy не выпускает SSL-сертификат и в логах видна ACME error?

Сначала проверьте A-запись домена командой getent ahostsv4 chat.example.com: она должна возвращать IP вашего VPS. Затем убедитесь, что firewall разрешает 80 и 443, а другой процесс не занял эти порты: sudo ss -ltnp '( sport = :80 or sport = :443 )'. Также отключите проксирование DNS-записи через CDN на время первоначальной диагностики. Посмотрите docker compose logs caddy; там будет точная причина отказа ACME.

Почему страница Chatwoot возвращает 502 Bad Gateway?

Код 502 означает, что Caddy работает, но не может получить ответ от контейнера rails. Выполните docker compose ps и убедитесь, что rails имеет статус Up. Затем прочитайте последние логи: docker compose logs --tail=150 rails. Частые причины — не выполнены миграции базы, неверный SECRET_KEY_BASE, недоступный PostgreSQL или недостаток RAM. Проверьте память через free -h и kernel-логи OOM через dmesg -T | grep -i killed.

Почему worker постоянно перезапускается?

Контейнер worker зависит от Redis и PostgreSQL, поэтому сначала проверьте их healthcheck: docker compose ps. Далее откройте логи командой docker compose logs --tail=200 worker. Ошибка подключения к Redis обычно означает неверный REDIS_URL; внутри Docker-сети используйте имя сервиса redis, а не localhost. Ошибка базы указывает на неправильные POSTGRES_HOST, пароль или на то, что задача db:chatwoot_prepare не была выполнена.

Почему Chatwoot не отправляет email-приглашения и уведомления?

Почта отправляется Sidekiq worker, поэтому откройте его логи и найдите SMTP-ошибку. Проверьте адрес сервера, порт, логин, пароль приложения и тип шифрования. Для порта 587 обычно нужны SMTP_ENABLE_STARTTLS_AUTO=true и SMTP_AUTHENTICATION=plain. После изменения .env примените настройки командой docker compose up -d --force-recreate rails worker. Не забывайте, что почтовый провайдер может блокировать SMTP до подтверждения домена или включения SMTP-доступа.

Почему письма приходят в спам?

Проблема обычно не в Chatwoot, а в репутации домена или SMTP. Адрес MAILER_SENDER_EMAIL должен совпадать с проверенным доменом отправителя. Настройте SPF, DKIM и DMARC через DNS-панель почтового сервиса. Не используйте случайный адрес отправителя, если SMTP-провайдер разрешает отправку только от подтверждённого домена. Проверьте заголовки письма в почтовом клиенте: они покажут результаты SPF и DKIM. Для транзакционных писем лучше использовать специализированный SMTP-сервис.

Какой VPS-конфиг минимально подойдёт?

Для небольшого production-инстанса используйте минимум 2 vCPU, 4 ГБ RAM и 50 ГБ NVMe. Конфигурация с 2 ГБ памяти может работать в тестовом режиме, но при обновлениях, фоновой обработке вложений и одновременных диалогах возрастает риск OOM-ошибок. Если у вас включены несколько каналов, активно используется API или хранится много файлов, начните с 4 vCPU, 8 ГБ RAM и 100 ГБ диска. Диск выбирайте с запасом под бэкапы и вложения.

Что выбрать — VPS или dedicated для этой задачи?

VPS подходит большинству команд до нескольких десятков операторов: он проще в запуске, дешевле и легко масштабируется по тарифу. Dedicated выбирайте при постоянной высокой нагрузке, требовании к физической изоляции, большом объёме локальных вложений или если на одном хосте размещается несколько критичных сервисов. Сам по себе dedicated не решает проблемы с бэкапами, безопасностью и мониторингом. Для одного Chatwoot-инстанса рациональнее начать с VPS и перейти к выделенному серверу после измерения реальной нагрузки.

Как безопасно изменить домен Chatwoot?

Сначала создайте DNS-запись нового домена, затем измените FRONTEND_URL в .env и домен в Caddyfile. Перезапустите сервисы: docker compose up -d --force-recreate rails worker caddy. После этого проверьте curl -I https://new-chat.example.com. Старый домен желательно временно оставить в Caddy как отдельный сайт с редиректом, чтобы старые ссылки и уже загруженные виджеты не перестали работать мгновенно.

Выводы и следующие шаги

Схема: Выводы и следующие шаги
Схема: Выводы и следующие шаги

Теперь у вас есть self-hosted Chatwoot на VPS с Docker, PostgreSQL, Redis, HTTPS через Caddy и SMTP для системной почты. Конфигурация изолирует внутренние сервисы от интернета, а резервное копирование позволяет восстановить базу и файлы после сбоя.

  1. Создайте inbox для сайта и подключите виджет, затем добавьте операторов через приглашения.
  2. Настройте SPF, DKIM, DMARC и протестируйте доставку писем с реального клиентского адреса.
  3. Подключите мониторинг диска, памяти, доступности HTTPS и успешности ночных бэкапов.
  4. При росте нагрузки перенесите вложения в S3-совместимое хранилище, а PostgreSQL — на отдельный управляемый сервер или выделенный узел.

Был ли этот гайд полезен?

Ваш отзыв помогает нам улучшать гайды.

Поделиться записью:

Отправьте гайд тому, кому он может пригодиться.

Telegram VKVK WhatsApp Facebook LinkedIn XX

установка chatwoot на vps: docker, postgresql, redis, ssl и настройка email
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.