Частые вопросы
Ответы на самые популярные вопросы
Начало работы
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 или nullvalidate
• — правила валидатора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 — безопасно для нескольких воркеровmax_attempts` = 3 по умолчанию
• Retry с экспоненциальной задержкой (15s → 30s → 60s...)
•
• Автоочистка 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 — узнаете о проблемах первыми.