FAQ

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

Ответы на самые популярные вопросы

Начало работы

1. Что такое OpenKassa?

OpenKassa — универсальный фреймворк для быстрого запуска SaaS-проектов на PHP.

Что включено:
• Аутентификация — телефон + пароль, восстановление через MAX
• Платежи — ЮKassa, подписки, разовые платежи, промокоды
• Уведомления — Email, MAX, Telegram, in-app + очереди на БД
• Модули — онбординг, FAQ-помощник, аудит, cookie-баннер
• Инфраструктура — миграции, CLI, feature-флаги, тёмная тема

Каждый модуль включается флагом FEATURE_* в .env. Можно оставить только то, что нужно проекту.

2. Как развернуть OpenKassa на новом сервере?

1. Скопируйте папку проекта на сервер (вне DocumentRoot для private/).
2. Создайте домен в панели управления (Hestia/DirectAdmin), DocumentRoot — public_html.
3. Настройте private/.env: БД, ключи ЮKassa, токены ботов.
4. Примените миграции: ./bin/cli migrate.
5. Заполните тарифы в private/Config/tariffs.php под ваш проект.
6. Включите нужные модули флагами FEATURE_* в .env.
7. Соберите CSS: ./bin/tailwindcss -i public_html/css/input.css -o public_html/css/app.css --minify.

Готово — проект развёрнут.

3. Какой технологический стек используется?

Backend:
• PHP 8.5+
• MySQL 5.7+ (PDO, prepared statements)
• Без фреймворков и Composer-зависимостей

Frontend:
• HTML + Vanilla JS (без сборки)
• Tailwind CSS v4 (standalone CLI)
• Lucide-иконки (CDN)

Интеграции:
• ЮKassa API v3 (платежи)
• MAX API v3 (боты)
• Telegram Bot API
• DaData (опционально)

Особенности:
• Структура Hestia — private/ вне DocumentRoot
• Никаких node_modules, никакой сборки на проде

4. Какие требования к серверу?

Минимум:
• PHP 8.5+ с расширениями: PDO, pdo_mysql, curl, mbstring, json, zip, xml, dom
• MySQL 5.7+ / MariaDB 10.3+
• Apache с mod_rewrite или nginx с proxy_pass на PHP-FPM
• 256 MB RAM
• 500 MB места

Особенности:
• SSL-сертификат (Let's Encrypt — оптимально)
• Доступ к внешним API (ЮKassa, MAX, Telegram) по HTTPS
• Russian Trusted Root CA для работы с MAX (по желанию)
• cron для воркера очередей

5. Как устроена структура проекта?

Корневая папка проекта:
• private/ — код, конфиги, логи, хранилище (вне DocumentRoot)
• public_html/ — DocumentRoot, только публичные файлы
• bin/ — CLI и Tailwind

Внутри private/:
• Core/ — ядро (Database, Auth, Response, Validator)
• Services/ — бизнес-логика
• Config/ — конфиги (features, tariffs, onboarding)
• migrations/ — SQL-миграции
• logs/ — логи
• storage/ — приватные файлы
• data/ — статические данные (например, faq.json)

Внутри public_html/:
• api/ — все API endpoints
• js/, css/, images/ — статика
• index.php — front controller
• template.html — SPA-шаблон
• faq.php, privacy.php — SEO-страницы

Аутентификация

6. Какой формат телефона для входа?

Поддерживаются все распространённые форматы:

• +79117001288
• 89117001288
• +7 (911) 700-12-88
• 8 911 700-12-88
• 9117001288

Все они нормализуются к 79117001288 при входе. Если номер не распознан — увидите ошибку «Неверный формат телефона».

7. Какие требования к паролю?

Минимум 8 символов. Обязательно наличие:

• Заглавной буквы (A-Z)
• Строчной буквы (a-z)
• Цифры (0-9)
• Спецсимвола: !@#$%^&*()_+-=[]{};:'"|,.<>/?

Проверка происходит при регистрации (визуальный чек-лист под полями) и при смене пароля через MAX-бота.

Пароли хранятся в виде Bcrypt-хеша — восстановить оригинал невозможно.

8. Я забыл пароль — что делать?

Восстановление через MAX-бота:

1. На странице /login нажмите «Забыли пароль?».
2. Откроется чат с ботом в MAX (веб или приложение).
3. Нажмите «Отправить номер телефона» — отправьте свой контакт.
4. Бот проверит номер и попросит ввести новый пароль.
5. Придумайте пароль по требованиям выше.
6. После смены все активные сессии завершаются — войдите заново.

Если номер не подходит — проверьте, тем ли телефоном вы регистрировались.

9. Сколько живёт сессия?

Сессия действует 30 дней с момента последнего входа.

Автопродление: если до истечения остаётся менее 5 дней, срок автоматически продлевается при следующем заходе. То есть при активном использовании вы никогда не разлогинитесь.

При смене пароля все сессии завершаются — это требование безопасности.

10. Можно ли быть залогиненным на нескольких устройствах?

Да, количество сессий не ограничено.

Каждое устройство (браузер) имеет свой токен. Список активных сессий не показывается в UI, но все они инвалидируются при смене пароля.

Если подозреваете взлом — смените пароль через MAX-бота, это завершит все сессии на всех устройствах.

11. Что происходит при множественных неудачных входах?

Защита от брутфорса:

• 5 попыток неудачного входа за 15 минут — блокировка
• Учёт по IP-адресу и по телефону
• Ответ 429 Too Many Requests при превышении
• Автосброс после успешного входа

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

Подписка и платежи

12. Как оплатить подписку?

1. Откройте «Настройки → Подписка».
2. Выберите подходящий тариф.
3. Нажмите «Выбрать».
4. В модалке подтверждения вы увидите сумму. Если есть промокод — нажмите «Промокод» и введите его.
5. Нажмите «Перейти к оплате» — откроется ЮKassa.
6. Оплатите картой, СБП или кошельком.
7. Вернётесь на сайт — подписка активируется автоматически.

Фискальный чек придёт на email из профиля.

13. Как применить промокод?

Промокод вводится в модалке подтверждения тарифа:

1. Выбрали тариф → «Промокод».
2. Ввели код → «Применить».
3. Система покажет скидку и итоговую цену.
4. Продолжили оплату.

Особенности:
• Один промокод — один раз на аккаунт
• Промокоды могут быть с лимитом использований и сроком действия
• Промокод может применяться только к определённым тарифам/периодам

Если промокод не применился — увидите причину: «Лимит исчерпан», «Срок истёк», «Уже использован».

14. Как перейти на более дорогой тариф?

На вкладке «Настройки → Подписка» выберите новый тариф.

Бонус за остаток: если у вас активна базовая подписка, остаток дней пересчитывается в бонусные дни нового тарифа.

Пример: осталось 30 дней базовой (490 ₽ / 90 дней). Стоимость остатка ≈ 163 ₽. При апгрейде на Продвинутую (1500 ₽ / 90 дней, daily rate ≈ 16.67 ₽) — бонус ≈ 10 дней.

Итог: новая дата окончания = сегодня + 90 дней + 10 бонусных = 100 дней.

15. Почему нельзя перейти на более дешёвый тариф?

Пока активна Продвинутая подписка, кнопка «Базовая» заблокирована.

Причина: понижение может привести к потере доступа к функциям/данным, доступным только на Pro.

Что делать:
• Дождитесь окончания текущего периода
• Затем оформите Базовую

Если случайно оплатили Базовую при активной Pro — деньги вернутся автоматически в течение 1-3 дней.

16. Можно ли вернуть деньги за подписку?

Да, в течение 14 дней с момента оплаты, если вы не пользовались платными функциями.

Что делать:
1. Напишите на support@openkassa.com
2. Укажите:
• Дату и сумму оплаты
• ID платежа (из раздела «История платежей»)
• Причину возврата
3. Возврат придёт на ту же карту в течение 10 рабочих дней.

Если функции использовались — возврат возможен только в исключительных случаях.

17. Где взять фискальный чек?

Фискальный чек формируется автоматически в момент оплаты и приходит на email из вашего профиля.

Если email не указан — чек передаётся в ЮKassa и доступен по ссылке от платёжной системы.

Где посмотреть:
• В профиле — поле Email
• В ЮKassa — в личном кабинете пользователя
• В истории платежей OpenKassa — ссылка на платёж в ЮKassa

Если чек не пришёл — проверьте спам или напишите в поддержку.

18. Оплата не проходит — что делать?

Возможные причины:

• Недостаточно средств на карте
• 3D-Secure не подтверждён — попробуйте заново
• Банк блокирует операцию — позвоните в банк
• Технический сбой ЮKassa — подождите 5-10 минут

Что делать:
1. Откройте «История платежей» в настройках
2. Если платёж в статусе «Ожидает» — нажмите «Оплатить» для повторного перехода
3. Или создайте новый платёж (старый будет отменён автоматически)

Если проблема повторяется — напишите в поддержку с номером платежа.

Уведомления

19. По каким каналам приходят уведомления?

4 канала:

• Email — на адрес из профиля
• MAX — если подключили бота
• Telegram — если подключили Telegram-бота
• В приложении — колокольчик в шапке

Управление: «Настройки → Уведомления».

Каналы, для которых не заполнены данные (email/chat_id) — подсвечены серым с подсказкой.

20. Где посмотреть уведомления в интерфейсе?

В шапке страницы есть колокольчик с красным счётчиком.

Клик открывает модалку со списком:
• Непрочитанные — на синем фоне с точкой слева
• Прочитанные — на белом фоне

Кнопки внизу:
• «Прочитать все» — обнуляет счётчик
• «Настройки» — переход к управлению каналами

Клик по уведомлению помечает его прочитанным и, если есть ссылка — переходит по ней.

21. Как отключить уведомления?

«Настройки → Уведомления» → снимите галочку с ненужного канала.

Изменения применяются мгновенно. Toast «Настройки сохранены» подтвердит.

Если канал недоступен (нет email/chat_id) — чекбокс задизейблен, рядом подсказка что делать.

22. Как подключить MAX-бота для уведомлений?

Проще всего — через сценарий восстановления пароля:

1. Откройте /login → «Забыли пароль?»
2. В боте нажмите «Отправить контакт»
3. Отправьте свой номер
4. Бот сохранит ваш chat_id и впредь сможет вам писать

Проверить: «Настройки → Уведомления» → канал MAX должен быть доступен (не серый).

Если хотите уведомления без сброса пароля — напишите боту любой текст, он подскажет что делать.

23. Как подключить Telegram-бота?

Найти бота:
• Имя бота — в .env проекта (TELEGRAM_BOT_USERNAME)
• Откройте Telegram → поиск по username

Подключить:
1. Отправьте боту /start
2. Следуйте инструкции (если она настроена)
3. После привязки ваш telegram_chat_id сохранится

Проверка: «Настройки → Уведомления» → канал Telegram не серый.

Если бот не отвечает — напишите в поддержку, может быть проблема с токеном.

24. Почему уведомление приходит с задержкой?

Уведомления отправляются через очередь (фоновые задачи), а не мгновенно.

Как работает:
• Мгновенно ставится задача в таблицу jobs
• Воркер раз в минуту (cron) обрабатывает накопленные задачи
• Средняя задержка — до 60 секунд

Почему так: если email-сервер тормозит или MAX недоступен, пользователь не должен ждать. Отправка идёт в фоне, а интерфейс отвечает мгновенно.

Критичные уведомления (подтверждение оплаты) идут синхронно — без задержки.

Онбординг

25. Что такое онбординг?

Это чат-визард, который помогает новому пользователю пройти первые шаги: заполнить профиль, настроить проект, подключить интеграции.

Как выглядит: модальная панель в правом нижнем углу с пошаговыми вопросами бота. Пользователь отвечает — бот ведёт дальше.

По умолчанию выключен. Включается флагом FEATURE_ONBOARDING=true в .env.

Зачем: снижает % пользователей, которые заходят и не понимают что делать.

26. Как настроить шаги онбординга?

Все шаги описываются в private/Config/onboarding.php.

Формат шага:
``
[
'id' => 'full_name',
'type' => 'input',
'bot' => 'Как вас зовут?',
'placeholder' => 'Иванов Иван',
'validate' => 'required|min:2|max:255',
'save_to' => 'users.full_name',
]
`

Типы шагов:
•
input — однострочный ввод
•
textarea — многострочный
•
choices — кнопки выбора
•
final — финальный шаг

Поля:
•
save_to — куда сохранить: users.field или null
•
validate — правила валидатора
•
bot` — сообщение бота (может быть функцией)

Пример с 3-4 шагами — в самом файле, раскомментируйте.

27. Как отключить онбординг?

В .env установите:
``
FEATURE_ONBOARDING=false
`

И рестартните PHP-FPM:
`
sudo systemctl restart php8.5-fpm
``

Что произойдёт:
• Панель онбординга не будет показываться
• Кнопка «Пройти настройку заново» в помощнике исчезнет
• Существующие данные онбординга сохранятся (на случай включения обратно)

По умолчанию флаг выключен — включайте только когда действительно нужен.

28. Как сбросить онбординг и пройти заново?

Способ 1 — через UI:
1. Откройте помощника (пузырь внизу справа)
2. Если онбординг был пройден — в начале FAQ кнопка «Пройти настройку заново»
3. Нажмите — данные сбросятся, откроется панель

Способ 2 — через API:
``
POST /api/onboarding/reset.php
`

Способ 3 — вручную в БД:
`sql
UPDATE users SET onboarding_completed = 0 WHERE id = X;
DELETE FROM onboarding_state WHERE user_id = X;
``

После сброса при следующем заходе появится панель онбординга.

Помощник и FAQ

29. Что такое помощник?

Плавающий виджет в правом нижнем углу страницы:

• Кнопка-пузырь с иконкой bot
• При клике — панель с FAQ (эта страница)
• Поиск по вопросам с подсветкой
• Оценки вопросов 👍/👎
• Доступен авторизованным и гостям

Где виден: на лендинге, dashboard, settings, faq. Скрыт: на /login, /register.

Настройка: флаг FEATURE_FAQ=true в .env (по умолчанию включён).

30. Как редактировать вопросы FAQ?

Все вопросы лежат в private/data/faq.json.

Структура:
``
{
"categories": [
{
"id": "start",
"title": "Начало работы",
"icon": "rocket",
"questions": [
{ "id": "what-is", "q": "...", "a": "..." }
]
}
]
}
`

Разметка в ответах:
•
жирный → жирный
•
код → код
•
[текст](url) → ссылка

Иконки: используются из библиотеки Lucide. Любая иконка: rocket, bell, shield-check, credit-card` и т.д.

После правки — рестарт FPM (opcache) не нужен, JSON читается каждый раз.

31. Как работает поиск в помощнике?

Поиск по всем вопросам и ответам:

• Нормализация: lowercase, ё→е, без пунктуации
• Токенизация: каждое слово запроса должно найтись в вопросе ИЛИ в ответе
• Скоринг: слово в вопросе = +3, слово в ответе = +1
• Максимум: 5 слов в запросе, каждое длиннее 3 символов
• Совпадения: по началу слова (префикс)

Результаты группируются по категориям. Совпадения подсвечиваются жёлтым.

Если ничего не найдено — показывается форма для связи с поддержкой.

32. Как работает оценка вопросов?

Под каждым ответом две кнопки: 👍 (полезно) и 👎 (не помогло).

Правила:
• Один голос на вопрос от пользователя
• Авторизованные — по user_id
• Гости — по хешу IP, действует 24 часа
• После голосования кнопки блокируются

Голоса сохраняются в таблице faq_feedback. Повторное голосование от того же пользователя игнорируется.

Цель: видеть какие вопросы сложные, дополнять ответы, находить проблемные темы.

Разработка

33. Как добавить новый модуль?

7 шагов:

1. Сервис в private/Services/ — бизнес-логика
2. Миграции в private/migrations/ (нумерация по порядку: 015_xxx.sql)
3. API endpoints в public_html/api/
4. Флаг в private/Config/features.php
5. Проверка флага в эндпоинтах и в UI
6. UI — блок в template.html + метод в app.js
7. FAQ — добавить пункт в private/data/faq.json

Регистрация в роутере не нужна — index.php автоматически роутит /api/xxx/yyy → public_html/api/xxx/yyy.php.

Миграции: ./bin/cli migrate.

34. Какие есть CLI-команды?

Запуск: ./bin/cli <команда> (от имени владельца проекта, обычно host1)

Доступные команды:
``
help — список команд
migrate — применить миграции
migrate:status — статус миграций
make:migration <name> — создать файл миграции
seed — залить тестовые данные
queue:work — воркер очередей
queue:stats — статистика очереди
`

Примеры:
`
./bin/cli make:migration add_orders_table
./bin/cli migrate
./bin/cli queue:work --max-seconds=55
``

Все команды запускаются от имени владельца проекта, а не от вашего юзера.

35. Как работают миграции?

Миграции — файлы private/migrations/NNN_name.sql, применяются по порядку.

Как это работает:
1. Таблица migrations хранит список применённых файлов
2. ./bin/cli migrate находит новые файлы и применяет
3. Файл разбивается по ;, комментарии -- ... вырезаются
4. Каждый SQL-запрос выполняется отдельно

Особенности:
• Идемпотентно — повторный запуск не сломает
• SQL должен быть самодостаточным (без внешних зависимостей)
• Для существующих таблиц — ALTER TABLE
• Для новых — CREATE TABLE IF NOT EXISTS

Создать новую:
``
./bin/cli make:migration add_new_field
``

36. Как работают очереди?

Очереди на БД (таблица jobs), без Redis/RabbitMQ.

Постановка задачи:
``
QueueService::push(
'App\\Services\\MailService::handleSend',
['to' => '...', 'subject' => '...'],
'notifications'
);
`

Воркер запускается в кроне раз в минуту:
`
* * * * * cd /path && php bin/cli queue:work --max-seconds=55
`

Каждую минуту воркер работает 55 секунд, обрабатывает задачи, умирает — и следующий крон запускает заново.

Особенности:
•
FOR UPDATE SKIP LOCKED — безопасно для нескольких воркеров
• Retry с экспоненциальной задержкой (15s → 30s → 60s...)
•
max_attempts` = 3 по умолчанию
• Автоочистка done/failed старше 7 дней

37. Как работают feature-флаги?

Флаги описаны в private/Config/features.php и читают значения из .env.

Список флагов:
``
FEATURE_ONBOARDING=true/false
FEATURE_MAX_BOT=true/false
FEATURE_TELEGRAM_BOT=true/false
FEATURE_EMAIL_NOTIFY=true/false
FEATURE_INAPP_NOTIFY=true/false
FEATURE_FAQ=true/false
FEATURE_BILLING=true/false
FEATURE_PROMO=true/false
FEATURE_QUEUE=true/false
FEATURE_AUDIT=true/false
FEATURE_ADMIN=true/false
FEATURE_COOKIE_BANNER=true/false
FEATURE_DARK_THEME=true/false
`

Использование в PHP:
`
$features = require SRC_PATH . '/Config/features.php';
if ($features['billing']) {
// модуль платежей включён
}
`

Использование в JS:
`
document.body.dataset.featureBilling === 'true'
``

После изменения флага — рестарт FPM (opcache).

38. Как работает аудит-лог?

Таблица audit_log + трейт Auditable для логирования CRUD-операций.

Использование:
``
use App\\Core\\Traits\\Auditable;

Auditable::log(
'update', // действие
'users', // сущность
$userId, // ID сущности
$oldData, // старое состояние
$newData, // новое состояние
$actorId // кто сделал
);
`

Что сохраняется:
• Действие (create/update/delete)
• Тип и ID сущности
• Old/New JSON-данные
• IP, User-Agent
• Автор изменения

Особенности:
• Автоматически маскирует поля:
password, token, secret`
• Ошибки аудита не ломают основной поток (catch + log)
• Логи хранятся бессрочно

39. Как деплоить обновления?

Минимальный деплой:
1. Загрузить изменённые файлы через SFTP/rsync
2. Если есть новые миграции — ./bin/cli migrate
3. Если менялись JS/CSS — bump APP_VERSION в bootstrap.php
4. Если менялись PHP-файлы — рестарт FPM (opcache)
5. Пересобрать CSS: ./bin/tailwindcss -i ... --minify

Важное правило:
Всегда рестартите PHP-FPM после правки PHP-файлов. Opcache держит старую версию в памяти, и вы можете долго не понимать почему изменения не работают.

Опасные зоны:
• Не редактируйте файлы с эмодзи/кириллицей через nano без UTF-8 локали
• Не забудьте .htaccess для новых директорий вне DocumentRoot
• Проверьте права (chown host1:host1)

Безопасность

40. Как работает CSRF-защита?

Токен в БД, время жизни 2 часа, многоразовый.

Как работает:
1. При логине фронт запрашивает токен через /api/auth/csrf.php
2. Токен сохраняется в localStorage.ok_csrf
3. Каждый POST/PUT/DELETE отправляет токен в X-CSRF-Token или _csrf
4. Бэкенд вызывает Auth::requireCsrf() для проверки

Почему многоразовый:
Одноразовость ломала цепочки запросов (проверка промокода → создание платежа). Токен с TTL — стандарт для SPA.

Автообновление:
При 403 с ошибкой «Недействительный CSRF токен» api.js запрашивает новый токен и повторяет запрос.

41. Как хранятся токены авторизации?

Двойное хранение:
• auth_token — HttpOnly cookie (для защиты от XSS)
• ok_token — localStorage (для API-запросов)

В БД: хранится только hash('sha256', $token), не сам токен.

Срок жизни: 30 дней, автопродление при < 5 дней.

Fingerprint:
Дополнительно сохраняется hash('sha256', User-Agent). При запросе с другим UA — токен отвергается.

Инвалидация:
• При logout — конкретный токен удаляется
• При смене пароля — все токены пользователя удаляются
• Soft-delete: поле is_deleted = 1

42. Как защищаетесь от SQL-инъекций и XSS?

SQL-инъекции:
• Только PDO prepared statements
• Никогда — конкатенация пользовательских данных в SQL
• Для LIKE-запросов — Database::escapeLikeString()

XSS:
• Сервер — htmlspecialchars() для вывода
• Клиент — textContent для вставки текста
• escapeHtml() для вставки в innerHTML
• renderBotText() для markdown-подобной разметки — экранирует всё кроме разрешённых тегов

HTTP-заголовки:
``
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
``

43. Как защищены файлы конфигурации?

Физическое размещение:
• .env — в private/, вне DocumentRoot
• logs/ — в private/logs/
• storage/ — в private/storage/
• schema.sql — в private/

Все эти файлы недоступны через HTTP — Apache/Nginx не отдаёт ничего вне DocumentRoot.

Дополнительно:
• .htaccess в private/storage/ — Deny from all
• Глобальный .htaccess — блокирует .env, .log, .sql, .md, .lock
• Права .env — 600 (только владелец)

Правило: если файл не должен отдаваться браузеру — он вне public_html/.

44. Какие есть защиты от атак?

Bruteforce логина:
• 5 неудачных попыток / 15 минут
• Блокировка по IP + телефону
• Ответ 429

CSRF:
• Токен с TTL 2 часа
• Проверка на всех модифицирующих запросах

Rate limiting вебхуков:
• Проверка секрета через hash_equals() (защита от timing-атак)
• Логирование всех входящих

SQL-инъекции:
• Prepared statements везде

XSS:
• Экранирование на сервере и клиенте

Файлы:
• Загрузки — только .xlsx, до 10 МБ
• Проверка MIME + расширения
• Сохранение вне DocumentRoot

Администрирование

45. Какие переменные должны быть в .env?

Обязательные:
``
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS
APP_URL, APP_NAME
APP_DEBUG=false
`

Для платежей:
`
YOOKASSA_SHOP_ID, YOOKASSA_SECRET_KEY
YOOKASSA_RETURN_URL
`

Для MAX-бота:
`
MAX_BOT_TOKEN, MAX_BOT_USERNAME
MAX_WEBHOOK_SECRET
`

Для Telegram:
`
TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_USERNAME
`

Для email:
`
MAIL_DRIVER=mail или smtp
MAIL_FROM_EMAIL, MAIL_FROM_NAME
`

Для Метрики (опционально):
`
YANDEX_METRIKA_ID=
`

Feature-флаги:
Все
FEATURE_* — по желанию, дефолты в features.php`.

46. Где смотреть логи?

Все логи — в private/logs/.

Файлы:
• error.log — ошибки PHP, исключения, медленные запросы
• yookassa.log — вебхуки ЮKassa + активации подписок
• max_webhook.log — входящие от MAX-бота
• queue.log — воркер очередей (OK/RETRY/FAIL)

Просмотр:
``
sudo -u host1 tail -50 private/logs/error.log
sudo -u host1 tail -30 private/logs/yookassa.log
`

Особенности:
• Логи не ротируются автоматически — следите за размером
• Если файл вырос до гигабайт — обнулите (
truncate -s 0)
•
error.log пишется глобальным handler'ом и Database::logError()`

47. Как делать бэкапы?

Что бэкапить:
• Базу данных (обязательно)
• Папку private/storage/ — если там пользовательские файлы
• Папку private/.env — отдельно, она содержит ключи

MySQL:
``
mysqldump -u USER -p DB_NAME > backup_$(date +%Y%m%d).sql
`

Cron для ежедневного бэкапа:
`
0 3 * * * cd /backup && mysqldump -u USER -pPASS DB_NAME | gzip > db_$(date +\%Y\%m\%d).sql.gz
`

Что НЕ надо бэкапить:
• Папку
private/logs/ — там просто логи
• Папку
public_html/css/app.css — собирается из input.css`
• Статику — она в git

Ротация:
Храните последние 7-30 дней. Старые удаляйте автоматически.

48. Как мониторить работоспособность?

Что проверять:

1. Healthcheck вебхуков:
``
curl https://your-domain.com/api/max/webhook.php
# Ожидаемо: Webhook is active

curl https://your-domain.com/api/payments/callback.php
# Ожидаемо: {"ok":true}
`

2. Размер очереди:
`
./bin/cli queue:stats
`
Если
pending растёт — воркер не работает или падает.

3. Логи на ошибки:
`
tail -20 private/logs/error.log
`

4. Срок подписки:
`
SELECT COUNT(*) FROM subscriptions WHERE is_active = 1 AND expires_at < CURDATE();
``

5. Мониторинг извне (бесплатно):
• UptimeRobot — пингует URL каждые 5 минут
• Healthchecks.io — для cron-задач

Настройте уведомления в MAX/Telegram — узнаете о проблемах первыми.

Не нашли ответ?

Напишите нам — ответим в течение рабочего дня.

Написать в поддержку