MAATRIX / Блог / FreeScout в Docker Compose: готовый файл

FreeScout в Docker Compose: готовый файл

MAATRIX

Help Scout и Zendesk удобны, но счёт за них растёт вместе с числом агентов — за 5-10 человек набегает $100-300 в месяц, и это только за тикет-систему. FreeScout решает ту же задачу — превращает почтовый ящик в нормальную helpdesk-систему с тикетами, статусами, заметками и распределением между агентами — но работает на вашем сервере и стоит только аренду VPS. Ниже — рабочий docker-compose.yml, который поднимает FreeScout с MySQL и правильными томами для данных, плюс нюансы, на которых спотыкаются при первом запуске.

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

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

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

Что такое FreeScout и когда он оправдан

FreeScout — открытый PHP-проект (форк идеи Help Scout, полностью независимая кодовая база), который берёт входящую почту и превращает переписку в тикеты с очередями, тегами, SLA-таймерами и внутренними заметками для команды. Из коробки есть:

  • несколько почтовых ящиков (Mailboxes) с разными адресами;
  • распределение тикетов между агентами вручную или автоматически;
  • модули (часть бесплатные, часть платные) — база знаний, чаты на сайте, интеграции с Slack и Telegram, автоматизация;
  • API и веб-хуки для связи с внешними системами.

Это имеет смысл, когда у вас есть support@ или info@, на который сыплются письма, и хотя бы 2-3 человека их разгребают — тикеты не теряются в общем ящике, видно, кто чем занят, есть история переписки с клиентом. Если писем 5-10 в день и обрабатывает их один человек — хватит и обычной почты, огород с сервером не окупится.

Из честных ограничений: интерфейс держится на Laravel + Vue и местами выглядит скромнее конкурентов, часть полезных модулей (SLA-политики, расширенные отчёты) платные — разово от $20 до $60 за модуль на сайте freescout.net, бесплатное ядро закрывает базовый workflow. Многоканальность (чаты, соцсети) слабее, чем у больших SaaS — FreeScout прежде всего про почту.

Схема развёртывания и что понадобится

FreeScout в контейнерах — это три сервиса: PHP-приложение (образ tiredofit/freescout, самый живой из поддерживаемых на Docker Hub), MySQL для данных и опционально отдельный контейнер с cron для запуска фоновых задач (получение почты по IMAP, отправка очереди писем). Понадобится:

  • VPS от 2 CPU / 4 GB RAM — на 1 GB FreeScout стартует, но с MySQL и несколькими агентами начинает тормозить под нагрузкой;
  • домен, указывающий на сервер (например, helpdesk.example.com);
  • рабочий SMTP для исходящей почты — свой Postfix, либо внешний сервис (Mailgun, SendGrid, Yandex 360). Если своей почты ещё нет, вариант поднять её на том же сервере разобран в статье про установку Postfix на VPS или полноценного почтового стека — в статье про iRedMail;
  • Docker и Docker Compose — если ещё не установлены, шаги есть в статье про установку Docker Compose на Ubuntu 24.04.

Для входящей почты у FreeScout два режима: либо он сам ходит по IMAP в существующий ящик (проще всего — подключить обычный support@ на Яндекс.Почте или Google Workspace через приложение-пароль), либо принимает письма напрямую по SMTP через собственный почтовый сервер. Для старта рекомендую первый вариант — меньше движущихся частей.

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

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

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

Готовый docker-compose.yml

Структура каталога:

freescout/
├── docker-compose.yml
├── .env
└── data/
    ├── mysql/
    └── app/

Файл .env:

# База данных
MYSQL_ROOT_PASSWORD=укажите_сложный_пароль
MYSQL_DATABASE=freescout
MYSQL_USER=freescout
MYSQL_PASSWORD=укажите_сложный_пароль_2

# FreeScout
APP_URL=https://helpdesk.example.com
TIMEZONE=Europe/Moscow
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=укажите_пароль_админа

# Исходящая почта (SMTP)
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=support@example.com
MAIL_PASSWORD=пароль_от_почты
MAIL_ENCRYPTION=tls

Файл docker-compose.yml:

version: "3.8"

services:
  db:
    image: mysql:8.0
    container_name: freescout_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - ./data/mysql:/var/lib/mysql
    networks:
      - freescout_net

  app:
    image: tiredofit/freescout:latest
    container_name: freescout_app
    restart: unless-stopped
    depends_on:
      - db
    environment:
      TIMEZONE: ${TIMEZONE}
      DB_HOST: db
      DB_NAME: ${MYSQL_DATABASE}
      DB_USER: ${MYSQL_USER}
      DB_PASS: ${MYSQL_PASSWORD}
      APPLICATION_URL: ${APP_URL}
      ADMIN_EMAIL: ${ADMIN_EMAIL}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      MAIL_HOST: ${MAIL_HOST}
      MAIL_PORT: ${MAIL_PORT}
      MAIL_USER: ${MAIL_USERNAME}
      MAIL_PASS: ${MAIL_PASSWORD}
      MAIL_ENCRYPTION: ${MAIL_ENCRYPTION}
      CRON: "TRUE"
    volumes:
      - ./data/app:/data
    ports:
      - "127.0.0.1:8080:80"
    networks:
      - freescout_net

networks:
  freescout_net:
    driver: bridge

Обратите внимание: порт приложения выведен только на 127.0.0.1:8080, наружу его не пускаем — перед контейнером стоит обратный прокси с SSL (см. ниже). Поднимаем:

mkdir -p freescout/data/{mysql,app} && cd freescout
# сюда кладём .env и docker-compose.yml
docker compose up -d
docker compose logs -f app

Первый запуск занимает 2-3 минуты — образ накатывает миграции базы и создаёт админ-пользователя из переменных ADMIN_EMAIL/ADMIN_PASSWORD. Дожидаться в логах строки вида Starting supervisord — это сигнал, что PHP-FPM и cron внутри контейнера поднялись.

SSL и обратный прокси

FreeScout работает по HTTP внутри контейнера, HTTPS снаружи обеспечивает прокси. Проще всего — Caddy с автоматическим Let's Encrypt, конфиг на весь домен:

helpdesk.example.com {
    reverse_proxy 127.0.0.1:8080
}

Подробно про установку и подводные камни Caddy с авто-SSL — в статье про Caddy на VPS. Если в инфраструктуре уже используется Traefik или Nginx Proxy Manager для нескольких сервисов на одном сервере, сравнение вариантов — в статье Traefik или Nginx Proxy Manager. Главное — не забыть проверить, что APP_URL в .env совпадает со схемой https://, иначе FreeScout будет генерировать ссылки на http и ловить предупреждения о смешанном контенте в браузере.

Подключение почтового ящика

После первого входа (https://helpdesk.example.com, логин — ADMIN_EMAIL/ADMIN_PASSWORD из .env) создаём Mailbox:

  1. Manage → Mailboxes → New Mailbox — указываем адрес, например support@example.com.
  2. Вкладка Incoming — тип IMAP, хост и порт почтового сервера (для большинства провайдеров — imap.example.com:993, шифрование SSL), логин и пароль. Если провайдер требует пароль приложения (Google Workspace, Яндекс с 2FA) — создаётся отдельно в настройках почты, обычный пароль аккаунта не подойдёт.
  3. Вкладка Outgoing — либо тот же SMTP, что и в .env глобально, либо свой для конкретного ящика (полезно, если у разных отделов разные адреса отправки).
  4. Сохраняем и жмём Fetch Emails — тестовое письмо должно появиться тикетом в течение минуты.

Забор почты по IMAP работает по cron внутри контейнера (переменная CRON: "TRUE" в compose-файле уже это включает) — по умолчанию раз в минуту. Если письма не подтягиваются, первым делом смотрим docker compose logs app | grep -i cron — там видны ошибки авторизации IMAP, самая частая причина — забытый пароль приложения вместо обычного.

Бэкапы

FreeScout хранит всё в двух местах: MySQL (тикеты, пользователи, настройки) и файловая система (вложения, логотипы, конфиги — том ./data/app). Бэкапить нужно оба:

#!/bin/bash
# backup-freescout.sh
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR=/opt/backups/freescout
mkdir -p $BACKUP_DIR

# дамп базы
docker exec freescout_db mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" freescout | gzip > $BACKUP_DIR/db_$DATE.sql.gz

# архив вложений и данных приложения
tar czf $BACKUP_DIR/app_$DATE.tar.gz -C ./data app

# чистим бэкапы старше 14 дней
find $BACKUP_DIR -type f -mtime +14 -delete

Ставим в cron хоста на ежедневный запуск в тихое время:

0 3 * * * /opt/scripts/backup-freescout.sh >> /var/log/freescout-backup.log 2>&1

Если нужен более системный подход с версионированием и хранением вне сервера — BorgBackup умеет это из коробки, инструкция — в статье про BorgBackup на VPS. Тестовое восстановление стоит хотя бы раз прогнать вручную (gunzip < db_ДАТА.sql.gz | docker exec -i freescout_db mysql -u root -p"$MYSQL_ROOT_PASSWORD" freescout) — бэкап, который никогда не разворачивали, не бэкап, а надежда.

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

Образ tiredofit/freescout обновляется вслед за релизами апстрима не сразу — перед апдейтом стоит свериться с changelog на GitHub и сделать бэкап базы (миграции необратимы). Сам процесс:

docker compose pull app
docker compose up -d app
docker compose logs -f app   # смотрим, что миграции прошли без ошибок

Автоматизировать обновления контейнеров можно через Watchtower, но для helpdesk-системы, где живут рабочие тикеты, безопаснее обновлять руками и по расписанию — если Watchtower уже используется для других сервисов на этом хосте, стоит явно исключить freescout_app из его области действия меткой com.centurylinklabs.watchtower.enable=false, чтобы не словить миграцию базы посреди рабочего дня без присмотра.

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

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

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

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

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

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

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

В 90% случаев — неверный пароль IMAP (нужен пароль приложения, а не основной) или блокировка со стороны почтового провайдера на "менее безопасные приложения". Проверяйте логи docker compose logs app | grep -i imap и тестовое подключение через обычный почтовый клиент теми же данными.

Можно ли обойтись без MySQL и использовать SQLite?

Официально FreeScout поддерживает MySQL/MariaDB как основную СУБД, SQLite не документирован для продакшена — не стоит рисковать тикетами команды ради экономии одного контейнера.

Нужен ли отдельный SMTP-сервер или подойдёт Gmail?

Для небольшой команды достаточно SMTP от обычного почтового провайдера (Яндекс, Google Workspace) с паролем приложения. Свой Postfix имеет смысл, когда объём писем растёт и упираетесь в лимиты отправки провайдера.

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

Чаще всего это несовместимая версия MySQL или незаполненные обязательные переменные в .env (особенно DB_PASS и APPLICATION_URL) — смотрите вывод docker compose logs app целиком, там всегда указана конкретная причина падения.

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

Переносятся том ./data/app (файлы) и дамп MySQL — та же схема, что описана в разделе про бэкапы, только вместо find … -delete на новом сервере разворачиваете архив и накатываете дамп в свежий контейнер db.

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

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

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