Задача
Что мы сделали
Мониторинг, который пришлось научить жить без root
Мы сделали панель, чтобы видеть свой сервер: нагрузку, диск, сеть, доступность сайтов, ошибки в логах и счета за облачные сервисы. Потом её попросили клиенты — и панель стала продуктом.
Сложность была не в графиках. Сложность в том, что половина клиентов сидит на шаред-хостинге, где нет ни root, ни доступа к системным счётчикам, ни SSH для обновления.
Верхний ряд отвечает на вопрос «всё в порядке?» за секунду. Остальная панель — на вопрос «а что именно».
Две половины одной панели
Сборщик и веб-панель разведены намеренно. Сборщик запускается раз в минуту от root — иначе он не увидит ни системных счётчиков, ни логов веб-сервера, ни конфигов доменов. Панель работает от обычного пользователя и не имеет доступа никуда, кроме одной базы.
Между ними SQLite. Метрики живут тридцать пять дней, ошибки — семь. Это не архив, это окно, в котором видно, что изменилось за последний месяц.
Нагрузка, которую видно целиком
Процессор, память, подкачка, диск, ввод-вывод, IOPS, сеть, количество процессов и PHP-воркеров — всё на одном экране, с выбором периода от тридцати минут до тридцати дней. Там, где есть жёсткий предел, пунктиром показан он: не «много или мало», а сколько осталось до потолка.
Сайты опрашиваются в обход DNS
Каждый домен панель проверяет раз в минуту — но обращается не по публичному DNS, а прямо на IP сервера. Это мелочь с большими последствиями: если сайт отвечает по IP, но не отвечает по имени, проблема не в сайте, а в записи DNS. Панель это различает и пишет об этом прямо.
Отдельно и реже проверяется то, что не меняется ежеминутно: DNS раз в четверть часа, сертификаты раз в шесть часов. В таблице видно код ответа, время отклика, доступность за сутки, срок сертификата и количество ошибок.
Ошибки без шума
Лог веб-сервера читается дописью: панель помнит, на каком месте остановилась, и при ротации не перечитывает файл заново. Но главное не в этом, а в фильтре.
Домены, закрытые намеренно, каждую минуту пишут в лог «доступ запрещён» — это работает защита, а не авария. Записи от нашего же мониторинга тоже не ошибки. Предупреждения и уведомления не считаются сбоями. Без этой чистки список ошибок превращается в ленту, в которую перестают смотреть.
Деньги рядом с метриками
Сервер падает не только от нагрузки — иногда от счёта. Поэтому в панели есть месячный трафик с долей от квоты, расходы на хранилище с прогнозом до конца месяца и расходы на API с разбивкой по моделям. Прогноз считается от реального темпа, а не от среднего за месяц.
Публичная страница отдельно от панели
То, что видит владелец, и то, что можно показать клиентам, — разные вещи. Панель под паролем, а рядом публичная страница статуса: полосы доступности за девяносто дней, среднее время ответа и одна фраза сверху — работает или нет.
Обновления без доступа к чужому серверу
У нас нет SSH на серверы клиентов и не должно быть. Поэтому связь устроена в обратную сторону: установка сама раз в сутки обращается к нашей панели, подтверждает лицензию и забирает обновление, если оно есть.
Лицензия подписана и проверяется офлайн на каждом запросе, а не запросом к нам — если наш сервер лежит, клиентские панели продолжают работать. На случай долгого простоя заложен двухнедельный запас: наша авария не должна гасить чужие установки.
Мелкие обновления ставятся сами, крупные — кнопкой. Из нашей панели можно раскатить версию принудительно, но только на те установки, в коде которых уже есть приёмник такого приказа. Это честное ограничение архитектуры, и оно видно в интерфейсе.
Как это делалось
Что под капотом
Сборщик
PHP по расписанию от root, чтение системных счётчиков, опрос доменов прямо на IP, дописное чтение логов с фиксацией позиции. Хранение — SQLite: метрики 35 дней, ошибки 7.
Панель
Никаких внешних библиотек: графики рисуются в SVG на сервере. Роли администратора и наблюдателя, публичная страница статуса отдельным слоем.
Продукт
Лицензии на подписи Ed25519, офлайн-проверка на каждом запросе, суточный checkin, двухнедельный запас. Обновление тянет сама установка — SSH к клиенту не нужен.
Что получилось
Панель, которую мы писали для себя, стоит на восьми установках, пять из них — на доменах клиентов. Она одинаково работает на VPS с полным доступом и на шаред-хостинге, где половина метрик недостижима: во втором случае она просто не показывает того, чего не может знать, вместо того чтобы рисовать нули.
И главное архитектурное решение оказалось верным: за всё время ни одно обновление не потребовало заходить на чужой сервер.



