Перейти до вмісту
EuroVPSEuroVPS

Оновлення self-hosted живого чату без втрати жодної розмови

Покроковий метод оновлення self-hosted Chatwoot у контейнерах: базові підрахунки, dump у стані спокою, записаний rollback і перевірки з боку відвідувача.

Автор EuroVPS Engineering

5 хв читання

Self-hosting живого чату вашого сайту є правильним рішенням, якщо вам не байдуже, хто зберігає розмови з вашими клієнтами. Воно також означає, що оновлення ваші. Chatwoot рухається швидко, і платформа чату, яка відстала далеко, стає проєктом з оновлення замість рутини. Ось метод, яким ми тримаємо self-hosted Chatwoot актуальним, не втрачаючи жодної розмови і без віджета, який виглядає нормально для вашого моніторингу, поки не працює для ваших відвідувачів.

Знайте, що ви оновлюєте

Типове контейнерне розгортання Chatwoot має п’ять рухомих частин:

  • контейнер web (застосунок Rails і API),
  • контейнер worker (Sidekiq, який надсилає сповіщення і виконує фонові завдання),
  • PostgreSQL (розмови, контакти, повідомлення, конфігурація),
  • Redis (черги і живий стан),
  • reverse proxy на кшталт nginx попереду, який термінує TLS і пропускає трафік WebSocket.

На наших платформах вони працюють як контейнери Podman, запущені через unit systemd, щоб стек повертався в правильному порядку після перезавантаження. Перш ніж почати, запишіть теги образів кожного контейнера, версію схеми бази даних і стан пакетів операційної системи. Вони знадобляться вам для rollback.

Крок перший: зніміть базовий рівень, з яким можна порівнювати

Перш ніж щось торкатися, запишіть, що містить база даних:

podman exec chatwoot-postgres psql -U chatwoot -d chatwoot_production -At -c "
  select 'conversations', count(*) from conversations union all
  select 'contacts', count(*) from contacts union all
  select 'users', count(*) from users union all
  select 'inboxes', count(*) from inboxes union all
  select 'messages', count(*) from messages;"

Збережіть вивід з позначкою часу. Після оновлення і ще раз після перезавантаження виконайте той самий запит. Розмови, користувачі, inboxes і повідомлення мають бути ідентичними; контакти можуть трохи зрости, бо живі відвідувачі продовжують приходити. Усе інше є причиною зупинитися.

Крок другий: заспокойте, потім зробіть dump

Dump, зроблений, поки worker пишуть, є dump рухомої цілі. Зупиніть контейнери web і worker, залиште базу даних працювати, потім зробіть dump:

podman stop chatwoot-web chatwoot-worker
podman exec chatwoot-postgres pg_dump -U chatwoot -Fc chatwoot_production > chatwoot_production.dump

Скопіюйте поруч файл середовища, файл compose, конфігурацію proxy і unit systemd у каталог з датою. Тримайте попередні образи контейнерів завантаженими; не дозволяйте завданню очищення видалити їх, доки нова версія не попрацює деякий час.

Крок третій: напишіть rollback до того, як він знадобиться

Напишіть точні команди для повернення до попередньої версії зараз, поки ви спокійні. Для Chatwoot rollback такий: зупинити стек, відновити попередні файли compose і середовища, запустити лише базу даних і Redis, видалити і створити заново базу даних, відновити dump, запустити стек і підтвердити, що API звітує стару версію.

podman exec chatwoot-postgres dropdb -U chatwoot chatwoot_production
podman exec chatwoot-postgres createdb -U chatwoot chatwoot_production
podman exec -i chatwoot-postgres pg_restore -U chatwoot -d chatwoot_production --no-owner --no-privileges < chatwoot_production.dump

Зауважте, що база даних має повертатися разом із застосунком. Chatwoot виконує міграції схеми під час оновлення, і старий застосунок проти мігрованої схеми не є підтримуваним станом.

Крок четвертий: оновлюйте одним свідомим рухом

Змініть тег образу для web і worker разом, завантажте і виконайте крок підготовки бази даних до того, як застосунок почне обслуговувати:

podman-compose pull
podman-compose run --rm web bundle exec rails db:chatwoot_prepare
podman-compose up -d

Якщо ви відстали на кілька випусків, прочитайте нотатки до кожного випуску, який перестрибуєте, а не лише до найновішого.

Це також добрий момент оновити пакети операційної системи хоста і перезавантажити його, щоб платформа та її основа йшли в ногу. Зробіть це в тому самому вікні, після того як застосунок перевірено один раз, щоб знати, яка зміна що спричинила.

Крок п’ятий: перевірте з боку відвідувача

Більшість моніторингу перевіряє, що URL повертає успішний статус. Віджет чату може пройти це і все одно бути зламаним для кожного відвідувача. Перевіряйте те, що насправді робить браузер:

  • API відповідає і звітує нову версію, з його чергою і сервісами даних у здоровому стані: curl -s https://chat.example.com/api.
  • Сторінка входу і вхід super admin повертаються успішно.
  • Скрипт віджета завантажується: curl -sI https://chat.example.com/packs/js/sdk.js.
  • Сторінка віджета завантажується зі справжнім user agent браузера. Недавні випуски Chatwoot пропускають запити, що виглядають як краулери, тож голий curl може отримати порожню відповідь, яка не є несправністю. Тестуйте браузером або надсилайте user agent браузера.
  • Живе з’єднання підвищується: запит WebSocket до /cable має відповісти 101 Switching Protocols. Якщо ваш proxy не пропускає заголовки upgrade, чат виглядає завантаженим, але повідомлення ніколи не приходять у реальному часі.
  • Вкладення і аватари завантажуються, що доводить, що файлове сховище змонтоване і читається.
  • Заголовки вбудовування досі правильні. Директива frame-ancestors у Content-Security-Policy має й далі перелічувати сайти, які вбудовують віджет.

Потім знову виконайте підрахунок записів, перезавантажте і проженіть усе ще раз. Стек, який працює лише до наступного перезавантаження, не був оновлений.

Одна деталь контейнерів, яка економить години

Спільні томи і SELinux. Якщо два контейнери ділять том сховища (контейнери web і worker зазвичай ділять файлове сховище для вкладень), монтуйте його зі спільною міткою :z, а не з приватною :Z. Приватна мітка застосовується для одного контейнера за раз, і іншому контейнеру тоді відмовляють у доступі до файлів, які йому потрібні, що проявляється як помилки сервера на зображеннях і вкладеннях, а не як очевидна проблема з правами. Тримайте SELinux у режимі enforcing; натомість правильно позначте том.

Після оновлення надішліть тестове сповіщення і підтвердьте, що воно надходить.

Що перевірити на вашій власній платформі чату

  • Чи знаєте ви, який випуск у вас працює, і наскільки він відстав?
  • Чи є у вас dump, зроблений до вашого останнього оновлення, і образи до нього?
  • Ваш rollback записаний чи лише в чиїйсь голові?
  • Чи завантажує ваш моніторинг віджет як браузер, включно з WebSocket?
  • Чи збігаються підрахунки записів до і після кожної зміни?

Пройдіть цей список один раз, і наступне оновлення стане рутинним вечірнім завданням замість ризику.

Якщо ви хочете, щоб ваш живий чат працював так, на вашому власному екземплярі, наші інженери можуть допомогти. Поговоріть з інженером

Related

  • /what-we-do/platforms/live-chat/
  • /what-we-do/operations/platform-currency/

Опубліковано 7 серпня 2026 р..

Усі нотатки з практики