SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-13

Установка Chatwoot на VPS через Docker и Docker Compose

Разверните Chatwoot на собственном сервере с использованием Docker Compose и Traefik. В руководстве описана настройка SMTP, резервное копирование Postgres и безопасное обновление.

Что вы создаете

Для самостоятельного размещения Chatwoot на VPS вы запустите четыре контейнера: веб-процесс Rails, фоновый обработчик Sidekiq, PostgreSQL с расширением pgvector и Redis. Chatwoot — это система поддержки клиентов с открытым исходным кодом, поэтому вы получаете общие командные почтовые ящики и виджет чата для сайта на сервере под вашим контролем. Установка занимает около 20 минут. Все последующие задачи — доставка почты, резервное копирование, обновления и масштабирование — определяют, будет ли система работать через год.

У каждого контейнера своя задача. Rails обслуживает панель управления агента и API (интерфейс прикладного программирования) виджета. Sidekiq выполняет ресурсоемкие задачи: отправку электронной почты, опрос подключенных каналов, выполнение правил автоматизации и построение отчетов. Postgres хранит переписки, контакты, учетные записи агентов и все настройки, которые вы меняете в панели управления. Redis хранит очереди Sidekiq и канал pub/sub для ActionCable, который передает новые сообщения в открытую панель управления без перезагрузки страницы. Redis здесь не является временным кэшем, так как его потеря означает потерю задач в очереди.

Образ Postgres в исходном файле compose — это pgvector/pgvector:pg16, а не стандартный образ postgres, так как схема Chatwoot активирует расширение vector для функций ИИ. Если заменить его на стандартный Postgres, первый запуск базы данных завершится с ошибкой ERROR: extension "vector" is not available, так как управляющий файл расширения отсутствует в этом образе. Используйте образ, который поставляют разработчики.

Это руководство предполагает, что Docker и reverse proxy уже настроены на сервере. Если это не так, начните с Docker Compose на VPS и вернитесь сюда.

Сколько ресурсов VPS требуется для self-hosted Chatwoot?

По состоянию на август 2026 года официальные требования к системе указывают 4 GB RAM и 4 ядра CPU как минимум, что рассчитано на нагрузку до 10 000 диалогов в день. Конфигурация с 8 GB RAM и 8 ядрами рассчитана на 20 000 диалогов. Также требуется не менее 1 GB swap, и причина указана прямо: чтобы система не исчерпала память во время обновления. Планируйте от 5 GB до 10 GB дискового пространства для Postgres, не учитывая объем загружаемых файлов.

Теперь о главном. VPS с 2 GB RAM запустит Chatwoot, и при наличии двух операторов и низкой активности в почтовом ящике всё будет работать нормально. Проблемы возникают в двух случаях. Во-первых, это Sidekiq, который, по данным разработчиков, потребляет более 1 GB на нагруженном сервере, поэтому всплеск входящих писем или запуск отчета переполняет память до того, как свою долю заберут Rails, Postgres и Redis. Во-вторых, это обновление, так как db:chatwoot_prepare запускает новый процесс Rails для применения миграций, а запуск Rails на этом образе требует сотни мегабайт еще до начала выполнения полезной работы.

Вы не получите вежливого предупреждения заранее. OOM-killer ядра отправляет SIGKILL самому «тяжелому» процессу, Docker видит, что контейнер завершился, и restart: always перезапускает его. docker compose ps затем показывает контейнер, который постоянно возвращается в состояние Exited (137), где код 137 означает завершение по сигналу 9. Подтвердите это с помощью sudo dmesg -T | grep -i "killed process", которая укажет процесс, выбранный ядром.

Если 4 GB не вписываются в бюджет, используйте VPS с 2 GB RAM и 2 GB swap, смирившись с тем, что время отклика под нагрузкой увеличится, вместо того чтобы сервис полностью падал. В любом случае стоит установить жесткие лимиты памяти для каждого сервиса, чтобы воркер не «утянул» за собой базу данных. См. лимиты памяти в Docker Compose.

Загружаемые файлы — это та часть, которая растет без установленных вами ограничений. Каждый скриншот, прикрепленный клиентом, попадает в том хранилища и остается там, поэтому следите за docker system df -v, а не предполагайте, что диск заполнила база данных.

Получение compose-файла и фиксация версии тега

mkdir -p ~/chatwoot && cd ~/chatwoot
wget -O .env https://raw.githubusercontent.com/chatwoot/chatwoot/develop/.env.example
wget -O docker-compose.yaml https://raw.githubusercontent.com/chatwoot/chatwoot/develop/docker-compose.production.yaml
chmod 600 .env

В только что загруженном файле указан тег image: chatwoot/chatwoot:latest. Измените его, прежде чем приступать к дальнейшим действиям.

services:
  base: &base
    image: chatwoot/chatwoot:v4.16.2
    env_file: .env
    volumes:
      - storage_data:/app/storage

Использование latest означает, что при каждом выполнении docker compose pull вы будете получать версию, опубликованную в этот день. Это может быть мажорный релиз с миграциями, о которых вы не читали. Миграции Chatwoot практически необратимы, поэтому случайное обновление потребует восстановления из резервной копии, а не просто отката. Зафиксируйте тег и меняйте его осознанно. Версия v4.16.2 была актуальным релизом на август 2026 года; проверьте страницу релизов, чтобы узнать, какой тег следует зафиксировать сегодня.

Сервис base является YAML-якорем, который используют rails и sidekiq, поэтому изменение тега в одном месте обновит его для обоих сервисов. Пока вы редактируете файл, удалите строку version: '3' в самом верху. Современный Compose игнорирует её и выводит предупреждение the attribute 'version' is obsolete, it will be ignored при каждой команде.

Заполнение файла .env

Сначала сгенерируйте секретный ключ. Разработчики требуют использовать буквенно-цифровое значение, так как специальные символы могут быть искажены при передаче через оболочку или YAML-парсер.

head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo ''

Затем установите следующие ключи в .env.

SECRET_KEY_BASE=<the 63 characters you just generated>
FRONTEND_URL=https://support.example.com
FORCE_SSL=true
DEFAULT_LOCALE=en
ENABLE_ACCOUNT_SIGNUP=true

POSTGRES_HOST=postgres
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=<long random string>
POSTGRES_DATABASE=chatwoot

REDIS_URL=redis://redis:6379
REDIS_PASSWORD=<a different long random string>

RAILS_ENV=production
INSTALLATION_ENV=docker
ACTIVE_STORAGE_SERVICE=local

POSTGRES_HOST=postgres и redis://redis:6379 — это имена сервисов в Compose, которые разрешаются внутри сети проекта по умолчанию. FRONTEND_URL — это не просто декорация. Chatwoot использует это значение для формирования URL виджета и всех ссылок в исходящих письмах, поэтому неверное значение приведет к тому, что ссылки на сброс пароля будут указывать на недоступный хост.

Теперь о ловушке в исходном файле. Сервис postgres не считывает .env. У него есть собственный блок environment, в котором POSTGRES_PASSWORD= оставлено пустым, поэтому установка пароля только в .env приведет к тому, что у базы данных не будет пароля, а у приложения он будет. Укажите сервису ту же переменную:

  postgres:
    image: pgvector/pgvector:pg16
    restart: always
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=chatwoot
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}

Compose считывает .env из директории проекта для подстановки ${...}, поэтому теперь обе стороны получают одну и ту же строку. Если допустить здесь ошибку, Rails завершит работу с ошибкой PG::ConnectionBad: FATAL: password authentication failed for user "postgres".

Одно поведение удивляет почти всех: образ Postgres применяет POSTGRES_PASSWORD только при инициализации пустой директории данных. Изменение значения позже не даст эффекта, так как initdb никогда не запускается повторно. Если вы уже запускали стек один раз, измените пароль непосредственно внутри базы данных.

docker compose exec postgres psql -U postgres -c "ALTER USER postgres WITH PASSWORD 'the-new-password';"

ENABLE_ACCOUNT_SIGNUP=true — временная настройка. Она открывает публичную форму регистрации, чтобы вы могли создать первую учетную запись. Установите значение false и снова выполните docker compose up -d сразу после того, как ваша учетная запись будет создана, иначе любой, кто найдет URL, сможет зарегистрироваться в вашей службе поддержки. С этого момента агенты добавляются по приглашению, а их пароли хранятся только в этом приложении. Это приемлемо, пока вы не запустите полдюжины сервисов и не устанете от отдельного списка учетных записей в каждом из них; в этот момент самохостируемый провайдер идентификации, такой как Authentik, станет тем компонентом, который заменит их.

.env теперь содержит все секреты этого стека в открытом виде, поэтому установите для него права доступа 600 и исключите из git. В статье Как Compose считывает env-файлы и где утекают секреты описаны все нюансы, включая разницу между env_file и environment.

Размещение Chatwoot за существующим Traefik

Не создавайте второй reverse proxy для одного приложения. Если Traefik уже выполняет TLS termination (transport layer security) для других контейнеров на этом сервере, Chatwoot подключается к нему через блок меток. Если у вас еще нет такой настройки, выполните её один раз согласно Traefik перед несколькими приложениями Docker Compose, а затем вернитесь сюда.

Старайтесь держать docker-compose.yaml от разработчика максимально близким к оригиналу, чтобы в будущем было проще сравнивать его с новыми версиями, а свои изменения вносите в файл переопределения. Compose автоматически объединяет docker-compose.override.yaml, а в статье разделение Compose на несколько файлов описаны правила этого объединения.

services:
  rails:
    networks:
      - default
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.chatwoot.rule=Host(`support.example.com`)"
      - "traefik.http.routers.chatwoot.entrypoints=websecure"
      - "traefik.http.routers.chatwoot.tls.certresolver=letsencrypt"
      - "traefik.http.services.chatwoot.loadbalancer.server.port=3000"

networks:
  proxy:
    external: true

Используйте свои собственные имена для entrypoint и certresolver. Контейнер должен находиться в той же сети Docker, что и Traefik, за что отвечает запись proxy, и он также должен оставаться в default, иначе он потеряет связь с Postgres и Redis. Эту вторую строку часто забывают.

Оставьте блок ports: без изменений. Разработчики привязывают его к 127.0.0.1:3000, что означает доступ только через loopback. Благодаря этому сервис недоступен из Интернета, но остается полезным для тестирования изнутри сервера с помощью curl -I http://127.0.0.1:3000.

Панель управления агента поддерживает открытое соединение websocket с /cable для доставки сообщений в реальном времени. Traefik пересылает HTTP upgrade без дополнительной настройки, поэтому ничего добавлять не нужно. Если позже вы установите CDN или другой прокси перед Traefik, разрешите там работу websockets. В противном случае панель управления будет загружаться нормально, но новые сообщения будут появляться только после ручного обновления страницы.

Инициализация базы данных и запуск стека

Сначала запустите сервисы данных и дождитесь завершения первого запуска Postgres.

docker compose up -d postgres redis
docker compose logs postgres | tail -n 5

Дождитесь database system is ready to accept connections. После этого создайте схему.

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

Эта команда создает базу данных, если она отсутствует, а затем загружает схему и начальные данные. Она выводит строки миграции и корректно завершает работу. Если процесс завис на выводе postgres:5432 - no response, значит, точка входа ожидает базу данных, которая еще не принимает соединения; при первом запуске это обычно означает, что процесс initdb еще выполняется. Подождите, изучите логи Postgres и запустите команду снова. Если процесс останавливается на расширении vector, значит, вы заменили образ pgvector на стандартный Postgres.

docker compose up -d
docker compose ps
docker compose logs --tail 30 rails

Все четыре контейнера должны иметь статус Up, а лог rails должен заканчиваться строкой Puma, сообщающей о прослушивании порта http://0.0.0.0:3000. Затем проверьте публичный путь:

curl -sI https://support.example.com | head -n 1

HTTP/2 200 означает, что вся цепочка работает. Ошибка 404 от Traefik означает, что правило маршрутизатора не совпало, обычно из-за опечатки в имени хоста. Ошибка 502 означает, что Traefik нашел маршрутизатор, но не смог связаться с контейнером; почти всегда это вызвано отсутствием сети proxy или тем, что порт loadbalancer.server.port не равен 3000.

Откройте URL, создайте учетную запись на /app/auth/signup, затем установите ENABLE_ACCOUNT_SIGNUP=false и выполните docker compose up -d, чтобы закрыть форму.

Почему сброс пароля и переписка по email не работают без SMTP

Chatwoot без настроек SMTP (simple mail transfer protocol) — это служба поддержки, которая не может отправлять почту, и это нарушает работу не только уведомлений. Сброс пароля перестает работать, поэтому администратор, потерявший доступ, не сможет его восстановить. Приглашения для агентов перестают работать, так как приглашение — это email. Ответы клиенту в рамках email-переписки также перестают работать, из-за чего диалог становится односторонним. Это тот шаг, который многие пропускают, а затем обнаруживают проблему в самый неподходящий момент.

Механизм прост. Без настроек SMTP ActionMailer использует значение по умолчанию для доставки на localhost через порт 25. Внутри контейнера Rails нет почтового сервера, поэтому задача доставки вызывает ошибку Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25. Почта отправляется фоновой задачей, поэтому эта строка попадает в лог Sidekiq, а не в лог Rails. В это же время пользователь, нажавший «забыли пароль», видит радостное подтверждение, но ничего не получает.

MAILER_SENDER_EMAIL=Support <support@example.com>
SMTP_DOMAIN=example.com
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=support@example.com
SMTP_PASSWORD=<the relay password>
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true

Используйте порт 587 с STARTTLS, который открывает соединение в открытом виде и переключает его на шифрованное перед аутентификацией. Большинство VPS-провайдеров блокируют исходящий порт 25 для борьбы со спамом, поэтому релей на порту 587 — это обычно единственный способ установить соединение. SMTP_DOMAIN — это домен, который ваш сервер объявляет во время SMTP-сессии, и некоторые релеи отклоняют запросы при несовпадении.

Примените настройки и наблюдайте за воркером:

docker compose up -d rails sidekiq
docker compose logs -f sidekiq

Инициируйте сброс пароля со страницы входа. Успешная доставка отображается в логе Sidekiq как завершенная задача mailer. Ошибка отображает класс исключения, после чего Sidekiq повторяет попытку с увеличивающейся задержкой, поэтому неисправный релей выдает одну и ту же ошибку каждые несколько минут в течение многих часов.

Часто встречаются два типа отклонений, и ни одно из них не является ошибкой Chatwoot. 535 Authentication failed означает, что имя пользователя или пароль неверны для данного релея, причем многие провайдеры требуют использовать пароль приложения, а не основной пароль от учетной записи. 550 Sender address rejected означает, что MAILER_SENDER_EMAIL — это адрес, от имени которого релей не разрешает отправку, поэтому это должен быть почтовый ящик или домен, который вы подтвердили у провайдера.

Получение входящих писем в переписку — это отдельная задача. Для нее требуются MAILER_INBOUND_EMAIL_DOMAIN и RAILS_INBOUND_EMAIL_SERVICE, а также почтовый сервер, который передает входящие сообщения в Chatwoot. Аренда релея — самый быстрый путь. Если вы предпочитаете полностью контролировать почтовый путь, запуск собственного почтового сервера с Mailcow описывает, что на самом деле подразумевает такая ответственность.

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

Резервная копия Chatwoot состоит из четырех частей. Пропуск любой из них превращает восстановление в пересборку системы с нуля.

  • База данных Postgres, где хранятся переписки, контакты, учетные записи агентов и все настройки.
  • Том storage_data, так как ACTIVE_STORAGE_SERVICE=local записывает загруженные файлы на диск, сохраняя в Postgres только ссылку на них.
  • Файл .env, так как в нем хранятся SECRET_KEY_BASE и ключи ACTIVE_RECORD_ENCRYPTION_*.
  • Файлы compose, так как они фиксируют точный тег образа, соответствующий схеме вашей базы данных.

Если восстановить только базу данных, все переписки будут содержать нерабочие вложения, так как записи в БД будут указывать на файлы, которых нет на диске.

cd ~/chatwoot
docker compose exec -T postgres pg_dump -U postgres -Fc chatwoot > db-$(date +%F).dump

Флаг -T важен. Без него Compose выделяет псевдотерминал, который переписывает символы переноса строки в потоке. В результате получается дамп, который pg_restore отклоняет при импорте. -Fc — это специальный формат, который обеспечивает сжатие и позволяет pg_restore выполнять выборочное восстановление.

docker run --rm -v chatwoot_storage_data:/data:ro -v "$PWD":/backup alpine \
  tar czf /backup/storage-$(date +%F).tgz -C /data .

Имя тома состоит из имени директории вашего проекта и суффикса _storage_data. Уточните его с помощью docker volume ls | grep storage_data, прежде чем доверять этой команде, так как Docker создает пустой том вместо ошибки, если указать несуществующее имя. Вы получите корректный, но пустой архив без каких-либо уведомлений об ошибке. Проверьте размер архива после выполнения с помощью ls -lh storage-*.tgz.

Сейчас оба файла находятся на том же диске, что и защищаемые данные, а значит, они не обеспечивают никакой защиты. Перенесите их на другой сервер и зашифруйте, так как дамп базы данных содержит все сообщения клиентов в открытом виде. В разделе Шифрованные удаленные резервные копии с помощью restic описаны вопросы планирования и хранения копий.

Учения по восстановлению: проведите их до того, как они понадобятся

Выполняйте восстановление на втором VPS, а не на рабочем сервере. Скопируйте .env, файлы compose и оба архива, затем выполните:

docker compose up -d postgres
docker compose exec -T postgres pg_restore -U postgres -d chatwoot --clean --if-exists < db-2026-08-10.dump
docker run --rm -v chatwoot_storage_data:/data -v "$PWD":/backup alpine \
  sh -c 'rm -rf /data/* && tar xzf /backup/storage-2026-08-10.tgz -C /data'
docker compose up -d

--clean --if-exists удаляет существующие объекты перед загрузкой, поэтому запускайте эту команду только для той базы данных, которую вы готовы потерять. После этого войдите в систему и откройте переписку с вложением. Если список сообщений загружается, а файл скачивается, значит, резервная копия корректна.

Восстановление с другим значением SECRET_KEY_BASE делает недействительными все сессионные cookie, поэтому все пользователи будут принудительно разлогинены. Восстановление с другими ключами ACTIVE_RECORD_ENCRYPTION_* еще опаснее: Chatwoot не сможет расшифровать столбцы с учетными данными каналов и выдаст ошибку ActiveRecord::Encryption::Errors::Decryption. Именно поэтому .env включен в список обязательных для резервного копирования элементов.

Как обновить Chatwoot до новой версии

Порядок действий важнее, чем сами команды.

  1. Изучите заметки к выпуску (release notes) для промежутка между вашей текущей версией и целевой, обращая внимание на необходимые ручные действия.
  2. Сделайте свежий дамп базы данных и архив хранилища, убедившись, что размеры файлов выглядят корректно.
  3. Измените тег образа для сервиса base в файле docker-compose.yaml.
  4. Загрузите новый образ, остановите стек, выполните миграции и запустите стек снова.
docker compose pull
docker compose down
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
docker compose up -d
docker compose images

Выполняйте загрузку образа перед миграцией, так как миграция должна запускаться из нового образа: старый образ не содержит новых файлов миграций. Остановите стек перед миграцией, так как старый код и новая схема базы данных несовместимы, и работающий процесс Rails может вызвать ошибки или записать строки, которые новая схема не примет. Остановка также освобождает память, необходимую для миграции, что является основной причиной, по которой разработчики рекомендуют использовать swap.

Команда docker compose images выводит тег, который фактически используется каждым контейнером; это позволяет выявить ситуацию, когда вы изменили тег в конфигурации, но забыли загрузить образ.

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

Если Rails запускается до завершения миграции, он отказывается обслуживать запросы и записывает в лог ActiveRecord::PendingMigrationError: Migrations are pending. Если установлена настройка restart: always, контейнер начинает перезапускаться, поэтому docker compose ps показывает время работы (uptime), которое сбрасывается каждые несколько секунд. Выполните этап подготовки, и ошибка исчезнет.

Откат к предыдущей версии означает возврат старого тега и восстановление дампа. Не существует надежного пути обратной миграции, именно поэтому необходим шаг 2.

Типичные сбои и сообщения об ошибках

502 Bad Gateway от Traefik. Маршрутизатор сработал, но backend не ответил. Проверьте, что docker compose ps показывает rails как Up, затем выполните docker network inspect proxy и убедитесь, что контейнер rails присутствует в списке контейнеров. Если контейнер не запущен, он невидим для Traefik, поэтому запрос проходит через маршрутизатор, но не находит адресата.

Панель управления загружается, но для получения новых сообщений требуется обновление страницы. WebSocket до /cable не проходит или FRONTEND_URL не совпадает с адресом в адресной строке браузера. Несоответствие означает, что страница пытается открыть WebSocket к другому источнику, что блокируется браузером.

FATAL: password authentication failed for user "postgres". Пароль в .env и пароль, сохраненный в томе данных Postgres, различаются. Исправьте это с помощью ALTER USER внутри запущенного контейнера, так как повторное редактирование .env не изменит уже инициализированную базу данных.

NOAUTH Authentication required. Redis запущен с --requirepass, но приложение подключилось без пароля. Это означает, что REDIS_PASSWORD отсутствует в .env или не было применено. Проверьте подключение напрямую с помощью docker compose exec redis redis-cli -a "$REDIS_PASSWORD" ping, команда должна вернуть PONG.

Контейнеры завершаются с кодом 137. Это сигнал SIGKILL. На сервере с малым объемом ресурсов это означает, что сработал механизм OOM Killer (out of memory) ядра Linux. Добавьте swap, установите лимиты памяти для каждого сервиса или перейдите на тарифный план с большим объемом ресурсов.

FAQ

Сколько оперативной памяти нужно VPS для самостоятельного размещения Chatwoot?

По состоянию на август 2026 года, разработчики требуют минимум 4 ГБ ОЗУ и 4 ядра CPU для обработки до 10 000 диалогов в день, и 8 ГБ с 8 ядрами для нагрузки до 20 000. Добавьте как минимум 1 ГБ swap, так как при обновлении запускается второй процесс Rails для применения миграций, и именно в этот момент на слабых серверах заканчивается память. VPS с 2 ГБ ОЗУ загрузится и будет работать для пары операторов, но под нагрузкой один только Sidekiq может потреблять более 1 ГБ. Ожидайте завершения контейнеров с кодом 137 в периоды высокой активности и во время обновлений.

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

Потому что не настроены параметры SMTP, поэтому ActionMailer пытается отправить почту на localhost через 25 порт, а почтового сервера внутри контейнера нет. Задача в Sidekiq завершается с ошибкой Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25, хотя в браузере отображается сообщение об успехе. Укажите SMTP_ADDRESS, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD и MAILER_SENDER_EMAIL в файле .env, перезапустите сервисы rails и sidekiq, а затем наблюдайте за docker compose logs -f sidekiq во время повторного запроса на сброс.

Что нужно резервировать для восстановления Chatwoot?

Базу данных Postgres, Docker-том storage_data, файл .env и compose-файлы. Одной базы данных недостаточно, так как загруженные файлы хранятся в томе, а в Postgres содержатся только ссылки на них; восстановление только базы данных приведет к появлению диалогов с неработающими вложениями. Файл .env важен, так как другой SECRET_KEY_BASE приведет к выходу всех пользователей из системы, а изменение ключей ACTIVE_RECORD_ENCRYPTION_* сделает зашифрованные столбцы нечитаемыми.

Как обновить Chatwoot, не повредив базу данных?

Сделайте резервную копию, измените тег образа в compose-файле, затем выполните docker compose pull, docker compose down, docker compose run --rm rails bundle exec rails db:chatwoot_prepare и docker compose up -d. Сначала выполните pull, так как миграции должны запускаться из нового образа, и сначала остановите стек, так как старый код при работе с новой схемой вызывает ошибки. При обновлении старой инсталляции переходите на одну минорную версию за раз, так как миграции удаляются после того, как они включаются в базовую схему.

Можно ли использовать стандартный образ postgres вместо pgvector?

Нет. Схема Chatwoot активирует расширение vector, поэтому стандартный образ postgres завершается ошибкой во время db:chatwoot_prepare с сообщением ERROR: extension "vector" is not available, так как файл управления расширением отсутствует в этом образе. Используйте pgvector/pgvector:pg16 из официального compose-файла или другой образ, который поставляется с pgvector для вашей мажорной версии Postgres.

#chatwoot#self-hosting#docker-compose#support-desk#smtp#backups