MAATRIX / Блог / OpenProject на сервере: частые ошибки и решения

OpenProject на сервере: частые ошибки и решения

MAATRIX

OpenProject — один из немногих open-source инструментов, который реально закрывает потребности крупной команды: диаграммы Ганта с зависимостями задач, канбан-доски, бэклог, тайм-трекинг, роли и права на уровне проекта. Именно поэтому его чаще ставят не под личный пет-проект, а под десятки и сотни пользователей — а значит, ошибки конфигурации, которые для маленького сервиса прошли бы незамеченными, здесь сразу становятся жалобами всей команды. Официальный путь установки — Docker (all-in-one образ или docker-compose с отдельными Postgres, Memcached, worker и cron), и большинство проблем растут именно из связки этих сервисов с внешним reverse-proxy. Разбираем конкретные ошибки и способы их починить.

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

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

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

Контейнер openproject не стартует или падает после первого запуска

Первое, с чем сталкиваются при установке — контейнер поднимается, крутит миграции несколько минут и падает, либо просто не отвечает на порту. Смотрите логи сразу, не гадайте: docker compose logs web --tail=150.

Частые причины:

  • Не хватает памяти на этапе assets:precompile или миграций. Сборка ассетов при первом запуске съедает заметно больше RAM, чем последующая работа сервиса. На сервере с 2 ГБ RAM без swap процесс Ruby часто убивает OOM-killer прямо посреди миграции — проверьте dmesg | grep -i oom.
  • База данных не готова к моменту старта web. Сервис web должен ждать здоровья db, но на медленном диске Postgres иногда не успевает уложиться в отведённый healthcheck-интервал. Увеличьте interval/retries в healthcheck db, а не перезапускайте web вручную.
  • Старый volume от предыдущей неудачной попытки. Если пароль Postgres в .env менялся после первого docker compose up, а volume уже создан со старым паролем, web не подключится (FATAL: password authentication failed). Верните старый пароль либо удалите volume docker volume rm <project>_pgdata и поднимите стек заново.

Официальный минимум для тестового запуска — 2 vCPU и 4 ГБ RAM. Под живую нагрузку от 15-20 активных пользователей практический ориентир — 4 vCPU и 8 ГБ RAM отдельно от других сервисов на сервере; это оценка по опыту эксплуатации похожих Rails-стеков, реальное потребление зависит от числа пользователей и размера проектов.

502 Bad Gateway и бесконечный редирект на HTTPS

Если OpenProject развёрнут за внешним Nginx или Traefik (когда SSL терминируется снаружи, а не в контейнере Traefik из штатного compose-файла), самая частая ошибка — либо 502, либо бесконечный редирект между http:// и https://.

Причина почти всегда в переменной OPENPROJECT_HTTPS:

OPENPROJECT_HTTPS=true
OPENPROJECT_HOST__NAME=project.ваш-домен.ru

Если внешний прокси терминирует SSL и проксирует на контейнер по обычному http, а OPENPROJECT_HTTPS не выставлен в true, приложение не понимает, что соединение снаружи уже защищено, и принудительно редиректит на https://, который для него самого выглядит как ещё один незащищённый запрос — получается петля. Прокидывайте заголовок X-Forwarded-Proto:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Без него приложение не доверяет прокси и продолжает считать соединение небезопасным, даже если заголовки Host выставлены верно. Второй частый источник 502 — несовпадение OPENPROJECT_HOST__NAME с реальным доменом в браузере: лишний www. или порт в этой переменной ломает часть внутренних редиректов и ссылок в письмах.

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

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

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

Диаграмма Ганта тормозит или не открывается на больших проектах

Это болезненная тема именно для крупных команд, ради которых OpenProject обычно и выбирают. Модуль диаграммы Ганта — самый тяжёлый по фронтенду: он рендерит таблицу задач и timeline одновременно, пересчитывая зависимости и критический путь на клиенте. На проекте в несколько сотен задач вкладка грузится заметно дольше остальных, а прокрутка и перетаскивание подлагивают.

Что реально помогает:

  • Фильтруйте представление. Открывать Ганта сразу по всему проекту без фильтров — плохая практика при 300+ задачах. Сохранённые представления по спринту, статусу или ответственному снимают нагрузку и с браузера, и с backend-запроса.
  • Проверьте бэкенд, а не только браузер. Если тормозит именно загрузка (крутится спиннер, а не отрисовка), узкое место обычно в Postgres — запрос диаграммы джойнит work_packages с зависимостями и кастомными полями. Включите pg_stat_statements в postgresql.conf и посмотрите медленные запросы через SELECT query, mean_exec_time FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 10.
  • Не экономьте на ресурсах worker-процесса. Формирование данных для больших диаграмм частично идёт через фоновые задачи контейнера worker — если ему выделен 1 CPU на весь стек, задержка растёт пропорционально числу активных проектов, а не только размеру одного.
  • Ограничьте глубину иерархии. Глубоко вложенные подзадачи (5+ уровней) рендерятся заметно дольше плоской структуры — разносите крупные эпики по отдельным родительским задачам.

Ресурсы самой БД, а не только web-контейнера — общий фактор, который часто упускают. Настройки shared_buffers и work_mem под нагрузку от Rails-приложений разбираются в статье про частые ошибки PostgreSQL на сервере — многие «тормоза» Гантта лечатся именно там.

Email-уведомления и приглашения не доходят

OpenProject отправляет письма при регистрации, назначении задачи, изменении статуса и по дайджестам активности. Ошибка отправки чаще всего просто логируется, а не показывается пользователю — проблему замечают, когда новый сотрудник жалуется, что не может принять приглашение в проект.

Блок SMTP-переменных (задаётся в .env или через админку, раздел Email Settings):

OPENPROJECT_EMAIL__DELIVERY__METHOD=smtp
OPENPROJECT_SMTP_ADDRESS=smtp.yandex.ru
OPENPROJECT_SMTP_PORT=587
OPENPROJECT_SMTP_AUTHENTICATION=plain
OPENPROJECT_SMTP_USER__NAME=noreply@ваш-домен.ru
OPENPROJECT_SMTP_PASSWORD=пароль_приложения
OPENPROJECT_SMTP_ENABLE__STARTTLS__AUTO=true

Частые ошибки:

  • Потеряно двойное подчёркивание в именах переменных. OpenProject использует __ там, где в названии настройки составное слово — HOST__NAME, USER__NAME. Одно подчёркивание вместо двух — переменная не подхватывается, без явной ошибки при старте.
  • Обычный пароль вместо пароля приложения. Яндекс, Mail.ru и Gmail требуют отдельный пароль приложения для SMTP — обычный пароль от почты не пройдёт авторизацию.
  • Исходящий SMTP-порт заблокирован у провайдера. Часть бюджетных VPS блокирует 25/587 порт по умолчанию — если письма не уходят вообще без ошибок в логах worker, проверьте это первым у хостинга.

Проверить конфигурацию можно из консоли контейнера, не дожидаясь события в интерфейсе: docker compose exec web bundle exec rails runner "ActionMailer::Base.mail(to: 'test@example.com', from: 'noreply@ваш-домен.ru', subject: 'Test', body: 'ok').deliver_now". Если команда падает — в трейсбеке будет точная причина (auth failed, connection refused, timeout), это быстрее, чем перебирать настройки вслепую.

Экспорт в PDF не работает или обрывается по таймауту

Экспорт work package'ов, диаграммы Ганта и отчётов в PDF — частая функция для крупных команд, которым нужно показать статус проекта заказчику отдельным файлом. Генерация PDF для больших наборов задач — тяжёлая операция: на слабом сервере она либо падает по таймауту прокси, либо контейнер web временно использует всю доступную память на рендер одного файла.

Если экспорт обрывается без явного сообщения — смотрите логи web и убедитесь, что таймаут внешнего прокси достаточен: proxy_read_timeout 300s; вместо дефолтных 60 секунд у Nginx, которых хватает только на небольшой список задач — на отчёте в несколько сотен строк с кастомными полями время генерации растёт нелинейно.

Если после увеличения таймаута экспорт всё равно падает, а не просто долго идёт — проверьте память контейнера web (docker stats): рендер PDF временно поднимает потребление RAM заметно выше фонового уровня, и на перегруженном сервере без swap процесс убивает тот же OOM-killer, что и при первом запуске. Практика настройки swap под такие всплески разобрана в статье про правильный размер swap для VPS — для Rails-приложений с периодическими тяжёлыми операциями это не опция, а необходимость.

Вложения и файлы: ошибки загрузки, права доступа, хранилище

По умолчанию OpenProject хранит вложения на локальном диске в volume (обычно монтируется в /var/openproject/assets). Проблемы с загрузкой чаще всего сводятся к трём вещам:

СимптомВероятная причинаЧто проверить
Ошибка при загрузке, без деталей в интерфейсеПрава на volume не совпадают с пользователем процессаdocker compose exec web ls -la /var/openproject/assets
Файл загрузился, но не скачивается (404)Диск переполнен или не тот volumedf -h, путь volume в docker-compose.yml
Крупные файлы (100+ МБ) обрываютсяclient_max_body_size в прокси меньше лимита приложенияПоднять лимит в конфиге Nginx/Traefik: client_max_body_size 512M;

Лимит нужно синхронизировать на двух уровнях сразу — в самом OpenProject и во внешнем прокси. Если он выставлен только в одном месте, файл до определённого размера загружается, а следующий по размеру обрывается с невнятной ошибкой: кажется, что проблема плавающая, хотя на деле это просто два разных потолка.

Для команд, уже использующих внешнее хранилище (Nextcloud, S3-совместимое), в OpenProject есть модуль Managed Storages — он подключает его к проектам вместо локального volume, но добавляет отдельный слой OAuth-авторизации, который стоит протестировать отдельно перед боевым использованием.

Обновление OpenProject ломает стек

Обновление через docker compose pull && docker compose up -d выглядит безопасным, но между минорными версиями иногда меняется схема переменных .env или появляются обязательные миграции БД, требующие больше времени и ресурсов, чем обычный перезапуск.

Безопасный порядок:

docker compose down
docker compose exec -T db pg_dump -U openproject openproject > backup_$(date +%F).sql
tar czf assets_backup_$(date +%F).tar.gz /var/lib/docker/volumes/<project>_opdata
docker compose pull && docker compose up -d
docker compose logs -f web

Дождитесь в логах строки о завершении миграций, прежде чем считать обновление успешным. Если миграция падает на середине — не откатывайте образ вслепую поверх уже частично изменённой схемы БД: восстановите дамп и только потом разбирайтесь, что пошло не так. Подход к бэкапу Docker-volume, если данные хранятся не во внешней управляемой БД, разобран в статье про бэкап Docker volume на сервере.

Если worker и cron настроены отдельными контейнерами, обновляйте их синхронно с web — рассинхрон версий приводит к тому, что фоновые задачи (напоминания, дайджесты, экспорт) падают с ошибками сериализации, даже когда сам интерфейс работает нормально.

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

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

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

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

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

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

Сколько реально нужно RAM для команды из 30-50 человек?

Официальный минимум — 2 vCPU / 4 ГБ RAM, но под живую нагрузку такой командой практический ориентир — 4-8 ГБ RAM и 4 vCPU отдельно от других сервисов; реальное потребление зависит от числа активных пользователей и размера проектов.

После установки не могу войти под admin.

При первом запуске сервис-сидер (seeder) выводит сгенерированный пароль администратора один раз в лог — проверьте docker compose logs seeder сразу после установки. Если лог потерян, пароль сбрасывается через консоль Rails внутри контейнера web.

Cron не выполняет напоминания и дайджесты.

Убедитесь, что контейнер cron (в старых compose-файлах эта роль объединена с worker) реально запущен — docker compose ps должен показывать Up, а не Restarting.

Стоит ли OpenProject вместо связки Gitea/GitLab с отдельным таск-трекером?

Это разные задачи: OpenProject закрывает управление проектами, а не хранение кода — держите их отдельно и связывайте через интеграции. Сравнение git-платформ есть в статье Gitea против GitLab: что выгоднее и когда.

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

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

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