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

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

MAATRIX

Crater — self-hosted инструмент для выставления счетов и оценок на Laravel + Vue.js, который многие ставят как более лёгкую альтернативу тяжёлым системам вроде Invoice Ninja. На бумаге всё просто: composer install, .env, миграции — и готово. На практике же почти каждая установка спотыкается об одну из пяти-шести типовых проблем: белый экран вместо интерфейса, ошибка 500 после первого запуска, PDF-счета не скачиваются, письма клиентам не уходят. Ниже — разбор этих ошибок с конкретными командами, без воды.

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

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

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

Что такое Crater и на что обратить внимание перед установкой

Crater — открытый проект на Laravel (бэкенд, PHP) и Vue.js (фронтенд, собирается через npm/webpack). Хранит данные в MySQL или MariaDB, настройки почты и часть конфигурации — не только в .env, но и в таблицах БД, что важно помнить при отладке (об этом ниже).

Важный нюанс: оригинальный репозиторий crater-invoice/crater в какой-то момент разделился — часть сообщества и активная разработка ушли в форк InvoiceShelf. Перед клонированием проверьте дату последнего коммита и открытые issues — для вашей задачи может оказаться актуальнее форк с более свежими патчами. На установку это не влияет (кодовая база почти идентична), но влияет на то, какие баги уже исправлены.

Минимальные требования, с которыми Crater реально работает без сюрпризов:

КомпонентВерсияКомментарий
PHP8.1–8.2нужны extensions: mbstring, xml, curl, gd, zip, bcmath, intl
MySQL/MariaDBMySQL 5.7+/MariaDB 10.3+обязательна поддержка JSON-колонок
Node.js16–18 LTSтолько для сборки фронтенда, в проде не нужен
Composer2.x
RAMот 1 ГБна 512 МБ сборка npm падает, см. ниже

На VPS заложите отдельного пользователя для деплоя, а не root: часть проблем ниже связана как раз с тем, что установку запускали разными пользователями и права разъехались.

Белый экран или ошибка 500 после установки

Самая частая жалоба: страница логина не открывается, вместо неё либо белый экран, либо Laravel-страница "500 Server Error" без деталей. В 90% случаев причина — не сгенерированный APP_KEY:

cp .env.example .env
php artisan key:generate

Если .env уже существует, но APP_KEY пустой — та же команда исправит. Проверить, что ключ реально попал в файл:

grep APP_KEY .env
# APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=

Если ключ на месте, а 500 всё равно есть — временно включите вывод ошибок, чтобы увидеть реальную причину вместо общей заглушки:

# в .env
APP_DEBUG=true
APP_ENV=local

После этого обновите страницу — Laravel покажет трассировку. Часто это:

  • отсутствующее расширение PHP (intl, bcmath — без них падают модули пересчёта валют и локализации);
  • недоступная БД (неверные DB_HOST/DB_DATABASE/DB_PASSWORD в .env);
  • не выполненные миграции.

Обязательно верните APP_DEBUG=false в проде — с включённой отладкой Laravel показывает пути на сервере, переменные окружения и куски кода любому, кто попадёт на страницу ошибки. Это чувствительная утечка, если сервер смотрит наружу.

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

php artisan config:clear
php artisan cache:clear
php artisan view:clear

Если ранее кто-то выполнил php artisan config:cache, Laravel использует закэшированный bootstrap/cache/config.php, игнорируя актуальный .env — и вы будете чинить не то.

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

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

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

Permission denied: storage, bootstrap/cache и загрузка логотипов

Вторая по частоте проблема — file_put_contents(): failed to open stream: Permission denied в логе или молчаливо не сохраняющиеся логотипы компаний/аватары. Laravel активно пишет во время работы в storage/ и bootstrap/cache/, и если веб-сервер запущен от www-data, а файлы после git clone/composer install принадлежат вашему деплой-пользователю — начинаются отказы.

Решение — выставить владельца на пользователя веб-сервера и дать группе права на запись:

sudo chown -R www-data:www-data storage bootstrap/cache
sudo find storage bootstrap/cache -type d -exec chmod 775 {} \;
sudo find storage bootstrap/cache -type f -exec chmod 664 {} \;

Если сервер работает не под www-data (например, у вас nginx + php-fpm с отдельным пулом под другим пользователем), подставьте нужное имя — посмотреть его можно в конфиге пула:

grep -E '^user|^group' /etc/php/8.2/fpm/pool.d/www.conf

Отдельная грабля — символическая ссылка на публичное хранилище. Если после установки логотипы и вложения не открываются (404 на /storage/...), значит не выполнена команда:

php artisan storage:link

Она создаёт симлинк public/storage -> storage/app/public. На хостингах с ограничением на symlink() (актуально для части shared-хостингов, но не для VPS с рутом) команда тихо ничего не делает — тогда придётся вручную создать директорию и настроить nginx на раздачу файлов напрямую из storage/app/public.

Похожие проблемы с правами при выкладке кода на сервер разобраны подробнее в статье про permission denied при деплое — там же есть чек-лист, что проверять по порядку, а не гадать.

Composer install падает или тянет не те версии

composer install на Crater нередко упирается в одну из трёх вещей:

Несовпадение версии PHP. В composer.json жёстко прописан диапазон поддерживаемых версий PHP. Если на сервере стоит PHP 8.3, а проект рассчитан на 8.1–8.2, Composer откажется ставить зависимости с ошибкой вида requires php ^8.1|^8.2 -> your php version does not satisfy that requirement. Проверить текущую версию и переключиться, если на сервере установлено несколько версий через update-alternatives:

php -v
sudo update-alternatives --config php

Нехватка памяти у Composer. На VPS с 512 МБ–1 ГБ RAM без свопа composer install может падать с Allowed memory size exhausted. Временное решение:

php -d memory_limit=-1 /usr/local/bin/composer install --no-dev --optimize-autoloader

Это лечит симптом, но не причину — лучше добавить своп-файл на 1–2 ГБ, иначе на сборке фронтенда (npm run build) столкнётесь с тем же самым.

Конфликт версий из-за composer.lock. Если вы обновляли форк или переключались между Crater и InvoiceShelf, composer.lock может ссылаться на несуществующие теги пакетов. В этом случае безопаснее удалить lock-файл и кэш и пересобрать заново:

rm composer.lock
composer clear-cache
composer install --no-dev --optimize-autoloader

PDF-счета не скачиваются или ломается кириллица

Crater генерирует PDF через dompdf (рендерит HTML-шаблон счёта в PDF на стороне PHP, без headless-браузера). Отсюда два характерных сбоя:

  1. Кнопка "Скачать PDF" не отвечает или отдаёт 500. Чаще всего не хватает PHP-расширения gd или mbstring, которые dompdf использует для обработки изображений и текста. Проверьте:
php -m | grep -E 'gd|mbstring'

Если пусто — доустановите и перезапустите php-fpm:

sudo apt install php8.2-gd php8.2-mbstring
sudo systemctl restart php8.2-fpm
  1. В PDF кириллица превращается в кракозябры или квадраты. dompdf по умолчанию использует встроенные шрифты без полного набора кириллических глифов. Решение — прописать в шаблоне счёта (или в настройках темы Crater) шрифт с поддержкой кириллицы, например DejaVu Sans, который обычно уже идёт в комплекте dompdf, но иногда не подключён на уровне CSS шаблона:
body { font-family: 'DejaVu Sans', sans-serif; }

После правки шаблона обязательно очистите кэш конфигурации и вьюх (php artisan view:clear), иначе увидите старую версию.

Если генерация PDF стабильно упирается в память (актуально для счетов с большим числом позиций), поднимите memory_limit в php.ini для php-fpm пула — 128M по умолчанию хватает не всегда, безопасно поднять до 256M.

Письма не уходят, повторяющиеся счета не создаются

Важная особенность Crater: почтовые настройки (SMTP-хост, логин, пароль, отправитель) обычно задаются не в .env, а через интерфейс — Settings → Mail Configuration, и хранятся в таблице настроек в БД. Если вы правите MAIL_* переменные в .env, ожидая, что это повлияет на отправку — письма всё равно не уйдут, потому что приложение читает конфиг из БД. Правильный путь — зайти в админку и указать SMTP там; после сохранения выполните php artisan config:clear, чтобы сброс кэша не мешал подхватить новые значения.

Второй источник тишины — очереди и cron. Повторяющиеся счета, напоминания об оплате и отложенная отправка писем у Crater реализованы через Laravel Scheduler, а он должен вызываться cron-задачей на сервере:

crontab -e
# добавить строку
* * * * * cd /var/www/crater && php artisan schedule:run >> /dev/null 2>&1

Без этой строки в crontab внутренний планировщик Laravel просто не запускается — визуально ничего не ломается, но повторяющиеся счета не создаются вовремя, а очередь писем копится и не разбирается. Если письма используют драйвер очереди database (проверить в .envQUEUE_CONNECTION=database), дополнительно нужен воркер:

php artisan queue:work --daemon --tries=3

В проде его стоит держать не голой командой в терминале, а через supervisor, чтобы воркер перезапускался при падении. Как правильно настраивать cron-задачи на сервере и что делать, если они не срабатывают в ожидаемое время (частая проблема с часовым поясом на VPS), — отдельно разобрано в статье про частые ошибки cron-задач на сервере.

Если же письма не уходят даже при верном SMTP и рабочем cron — проверьте сам SMTP-провайдер: многие бесплатные впн/relay-сервисы блокируют исходящий 587/465 порт по умолчанию, и это выглядит как проблема Crater, хотя на деле сервер просто не может достучаться наружу.

Ошибки БД и падения при миграциях

php artisan migrate — второй по частоте источник проблем при первой установке. Типичные сообщения и что за ними стоит:

  • SQLSTATE[42000]: ... max_key_length — старая версия MySQL/MariaDB с движком MyISAM или устаревшей кодировкой. Убедитесь, что база создана с utf8mb4, а не utf8:
CREATE DATABASE crater CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • SQLSTATE[HY000] [2002] Connection refused — MySQL не слушает на адресе из .env (частая ситуация, если в DB_HOST стоит 127.0.0.1, а MySQL сконфигурирован только на unix-сокет, или наоборот). Проверьте, что сервис запущен и слушает нужный порт:
sudo systemctl status mysql
sudo ss -tlnp | grep 3306
  • Миграции обрываются на середине — обычно нехватка max_allowed_packet при большом объёме сидируемых демо-данных. Временно поднимите значение в конфиге MySQL и перезапустите сервис.

Если ошибки БД у вас системные, а не разовые — стоит заглянуть в общий разбор частых ошибок MySQL на сервере, там собраны причины, которые повторяются не только в Crater, но и в любом Laravel-проекте. И на всякий случай — на своём же сервере сразу настройте резервное копирование MySQL: счета и клиентская база — не те данные, которые хочется терять из-за неудачного migrate:fresh, введённого по невнимательности в проде вместо тестового стенда.

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

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

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

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

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

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

Crater и InvoiceShelf — это одно и то же?

Исторически да, InvoiceShelf — форк, продолживший разработку после того, как Crater замедлился. Кодовая база на момент разделения почти идентична. Если проблема не находится в issues Crater — поищите в трекере InvoiceShelf, часто патчи совпадают.

Нужен ли Node.js на проде после установки?

Нет. npm нужен только на этапе npm run build, который собирает статические JS/CSS файлы. После сборки Node.js на сервере можно не держать.

Почему npm run build падает с out of memory на 1 ГБ RAM?

Webpack-сборка Vue-фронтенда требовательна к памяти, а вместе с работающими MySQL и php-fpm её может не хватать. Помогает временный своп-файл или сборка на более мощной машине с выгрузкой готовых public/js, public/css на прод.

Как перенести Crater на другой сервер без потери данных?

Дамп базы (mysqldump), копия директории storage/app целиком (логотипы, вложения, сгенерированные PDF) и файл .env. После разворачивания повторите php artisan storage:link и проверьте права на storage/.

Можно ли обойтись без Composer и Node.js на сервере?

Да, если использовать Docker-образ или готовый архив с уже собранным фронтендом и vendor/ — тогда локально ничего собирать не нужно, только настроить .env, БД и веб-сервер.

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

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

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