Runtime control в production нужен для ситуаций, когда проблема существует только в уже запущенном процессе. Подробный debug-log может быть необходим именно в момент инцидента, но держать его включенным постоянно нельзя: он создает шум, увеличивает объем файлов и иногда заметно нагружает горячие участки приложения.
Самый простой подход — изменить конфигурацию и перезапустить сервис. Но перезапуск часто уничтожает саму проблему. Состояние соединений, очередь запросов, конкретный пользовательский сценарий, нагрузка или редкая гонка могут исчезнуть вместе с процессом.
Поэтому в logme можно менять часть logging graph во время работы: включать и выключать channels, менять уровни, output flags, subsystem filtering, trace points и временные backend-ы. Это позволяет собрать нужную диагностику без перезапуска.
Но такая возможность автоматически создает management interface внутри процесса. Он способен менять поведение production-сервиса и, при определенной конфигурации, читать его лог-файлы. Поэтому runtime control нельзя относить к обычному “вспомогательному” API. Его нужно защищать так же внимательно, как административный endpoint.
Что именно меняет runtime control
В logme runtime control работает через встроенный control server. К нему подключаются logmectl и logmeweb.
Через этот интерфейс можно посмотреть текущую logging graph, список channels, состояние trace points и subsystem filters. При наличии соответствующей policy можно менять channel level, включать или выключать channel, менять output flags, создавать временный backend, включать trace point или ограничивать сообщения конкретного subsystem.
Например, во время инцидента можно включить подробности только для HTTP channel:
logmectl -p 9010 channel --enable http
logmectl -p 9010 level --channel http debug
А затем включить конкретные dormant trace points:
logmectl -p 9010 trace enable '*WorkerLoop*'
После воспроизведения проблемы настройки нужно вернуть обратно:
logmectl -p 9010 trace disable '*WorkerLoop*'
logmectl -p 9010 level --channel http info
Это важное отличие от постоянного debug logging. В коде могут существовать подробные диагностические точки, но они не обязаны создавать нагрузку и шум постоянно.
Runtime control не заменяет основную JSON-конфигурацию. Конфигурация остается описанием того, как logging должен быть построен при старте приложения: file paths, rotation, retention, buffer sizes и другие backend-specific параметры относятся именно к ней.
Runtime commands предназначены для оперативной диагностики. Они могут временно изменить уровень или добавить backend определенного типа, но не являются вторым полным языком конфигурации.
Control server — это management plane
Ошибка, которую легко допустить: увидеть control server как “порт для просмотра логов”.
На самом деле он сильнее. В полном режиме он может менять routing, создавать и удалять channels, добавлять backend-и, переключать trace points и при включенном logs command отдавать часть файлов из logger home directory.
Поэтому к нему нельзя относиться как к обычному status endpoint.
Если атакующий получает доступ к control server, он может не только увидеть диагностику. Он может включить слишком подробный лог, изменить output flags, создать дополнительный backend или получить доступ к лог-файлам в разрешенной директории. Даже временная смена logging policy может стать проблемой: она влияет на производительность, объем диска и иногда на состав диагностических данных.
Правильная модель: control server — административный интерфейс running process. Его нужно ограничивать по сети, защищать transport-ом, аутентифицировать клиентов и выдавать только минимально нужные права.
Начинайте с localhost
Самая безопасная базовая конфигурация — control server, привязанный только к loopback interface:
{
"control": {
"enable": true,
"interface": "127.0.0.1",
"port": 9010,
"discovery": {
"enable": false
}
}
}
В таком режиме внешний хост не может напрямую подключиться к control server. Оператор работает локально через logmectl, SSH port forwarding, VPN jump host или отдельный management agent.
Для большинства production-сервисов это предпочтительный вариант. Не нужно слушать 0.0.0.0 только потому, что иногда требуется диагностика с другого компьютера. Сначала стоит решить, можно ли оставить control server локальным и дать оператору безопасный способ попасть на host.
Если удаленный доступ действительно необходим, control server должен быть доступен только из выделенной management network или через VPN. Firewall должен пропускать соединения только от конкретных административных hosts или подсети. TLS не заменяет firewall: шифрование защищает трафик, но не делает публично доступный административный порт хорошей идеей.
TLS и пароль: два разных слоя
Control server поддерживает TLS и password authentication.
Если приложению переданы certificate и private key, сервер принимает только TLS connections. Если задан password, клиент должен выполнить auth до обычных control commands. logmectl делает это через --ssl и --pass:
logmectl \
--ip 127.0.0.1 \
--port 9010 \
--ssl \
--pass secret \
overview
Password здесь является gate для доступа к control surface. Но это не полноценная IAM-система. У control server нет user accounts, ролей, отдельных privileges для разных операторов или встроенной привязки команд к личности пользователя. Условно, пароль отвечает на вопрос “можно ли войти”, но не “кто именно выполнил изменение”.
Это особенно важно для production. TLS и пароль нужны, но их нельзя считать достаточной заменой network isolation, firewall rules и операционного контроля доступа.
Еще один важный нюанс: JSON block control может включить server, задать interface, port и discovery settings. Но password и TLS material не извлекаются из JSON configuration. Не стоит добавлять туда password, cert или key и ожидать, что control server автоматически станет защищенным.
Для password и TLS требуется явная настройка из application code или другого контролируемого startup path:
Logme::ControlConfig control{};
control.Enable = true;
control.Interface = 0x7F000001u; // 127.0.0.1
control.Port = 9010;
control.Password = controlPassword.c_str();
control.Cert = certificate;
control.Key = privateKey;
logger.StartControlServer(
control,
Logme::ControlPolicy::Safe()
);
Certificate и private key остаются объектами, которыми владеет приложение. Control server использует их для TLS, но не должен превращаться в место, где секреты хранятся в открытой конфигурации.
Также стоит помнить, что --pass удобен для примеров и локальной диагностики, но пароль в command line может оказаться в shell history или быть видимым другим процессам в том же trust domain. Для удаленного production-доступа стоит строить workflow так, чтобы сам host, операторский доступ и секреты уже были защищены отдельно.
Full, Safe и Diagnostic: права должны быть минимальными
В logme control commands ограничиваются через ControlPolicy.
ControlPolicy::Full() разрешает полный control surface. Это старое совместимое поведение, которое используется простым overload StartControlServer(control). Оно удобно для development, тестов и полностью доверенного management environment, но не должно быть production baseline.
ControlPolicy::Safe() предназначен для консервативной диагностики. Он разрешает изменить level, output flags, trace points и subsystem filtering. Также он разрешает безопасные информационные команды: help, version, overview, list и inspection channel state.
Но Safe() специально запрещает то, что заметно расширяет риск: создание и удаление channels, routing changes, error channel changes, backend changes, file backend changes, extensions и logs command.
ControlPolicy::Diagnostic() начинается с Safe(), но дополнительно разрешает backend changes. При этом file backend changes остаются запрещенными. Это удобно, когда во время расследования нужно временно подключить console, debugger, buffer или ring buffer, но не нужно позволять удаленному оператору писать произвольные новые файлы.
Именно так должна выглядеть обычная production-логика: чем меньше доверия к источнику команды, тем уже policy.
Что делать, если нужен только read-only доступ
Read-only access часто воспринимается как безопасный по умолчанию. Но это не всегда так.
Например, overview, channel inspection и trace statistics действительно полезны для наблюдения. Но logs viewer может раскрыть operational details, внутренние URL, request identifiers, stack-like diagnostics или пользовательские данные. Read-only доступ к логам — это все равно доступ к production diagnostics.
В logme нет одного универсального “read-only server mode”, потому что разные сценарии требуют разных разрешений. Safe() уже блокирует опасные structural changes, но все еще разрешает level, flags, trace points и subsystem filtering. Это не read-only policy.
Если нужен действительно read-only endpoint, лучше собрать custom policy:
Logme::ControlPolicy policy = Logme::ControlPolicy::Safe();
policy.AllowLevelChanges = false;
policy.AllowFlagChanges = false;
policy.AllowTraceChanges = false;
policy.AllowSubsystemChanges = false;
policy.AllowLogsCommand = true;
logger.StartControlServer(control, policy);
Такой вариант можно использовать для dashboard или внутреннего viewer, которому разрешено видеть runtime state и, при необходимости, лог-файлы, но нельзя менять поведение процесса.
При включении AllowLogsCommand нужно отдельно понимать границы. logs command работает только read-only, ограничен logger home directory и разрешенными file extensions. Он не должен принимать произвольные absolute paths или позволять выйти за пределы home directory.
Но “read-only” здесь означает только отсутствие изменения файлов. Это не означает отсутствие риска утечки данных.
logmectl и logmeweb решают разные задачи
logmectl — простой операторский CLI для control server. Он хорошо подходит для incident response, скриптов и точечных команд.
logmectl -p 9010 overview
logmectl -p 9010 channel http
logmectl -p 9010 trace stat '*WorkerLoop*'
Его сильная сторона — прозрачность. Команда явно видна, ее легко повторить в runbook, сохранить в incident notes и встроить в диагностический script.
logmeweb использует тот же control server, но дает браузерный интерфейс. Он удобен, когда нужно быстро просмотреть channels, subsystem filters, trace points, runtime overview или разрешенные log files.
При этом logmeweb добавляет второй security boundary.
Password, который задан у logmeweb, защищает сам browser UI. Password control server защищает connection от logmeweb до target process. Это два разных пароля и две разных точки доступа.
Если logmeweb слушает только 127.0.0.1, его можно использовать локально без отдельного UI password в доверенной среде. Но если UI доступен с другой машины, его нужно запускать с HTTPS и --password.
Практичная схема для production выглядит так:
browser
-> HTTPS reverse proxy
-> logmeweb on 127.0.0.1:8080
-> control server on 127.0.0.1:9010
-> target process
В таком варианте наружу смотрит только reverse proxy. Он может применять корпоративную authentication policy, network ACL, TLS certificate и audit access logs. logmeweb и control server остаются на loopback.
--trust-proxy-headers у logmeweb нужен только за доверенным reverse proxy, который сам очищает или переписывает forwarded headers. При прямом публичном доступе включать его нельзя: иначе клиент может подделать свой source identity через заголовки.
Audit: runtime control должен оставлять след
Runtime control особенно полезен потому, что позволяет менять работающий процесс. Но это же означает, что изменение должно быть объяснимым позже.
Текущий control server logme не является отдельной immutable audit system. Он не превращает каждую выполненную команду в защищенную audit record с идентичностью оператора, причиной изменения и проверяемой историей.
Поэтому не стоит подменять понятия. Internal diagnostics logme может помочь понять техническое состояние control server, а policy rejection из environment control может быть записан через CHINT. Но этого недостаточно для полноценного production audit.
Если remote runtime control используется регулярно, audit нужно строить снаружи. Обычно это означает, что доступ проходит через VPN, bastion host, reverse proxy, internal admin service или automation system, где уже фиксируются пользователь, target host, время, команда и результат.
В собственном management endpoint полезно сохранять хотя бы четыре вещи: кто запросил изменение, какой процесс был target, какая policy разрешила команду и какое состояние было до и после изменения. Пароли, токены и другие secrets в audit text попадать не должны.
Также стоит помнить, что control commands не транзакционные. Если оператор отправил несколько команд, а последняя была отклонена, предыдущие успешные команды не откатываются автоматически. Поэтому изменение логирования лучше делать короткими последовательностями: сначала inspection, затем одна scoped change, затем reproduction, затем явный rollback.
Runtime control должен быть временным
В production runtime control обычно нужен не для постоянного управления архитектурой логов, а для короткого диагностического окна.
Хорошая процедура выглядит так: сначала оператор фиксирует текущий level, flags и trace state. Затем включает только нужный channel или trace point. После сбора данных выгружает логи и возвращает исходные настройки. Если изменение оказалось действительно полезным постоянно, его нужно перенести в обычную configuration и пройти стандартный review.
Не стоит считать runtime changes постоянными. Конфигурация остается authoritative, а restart или config reload могут восстановить нормальную logging graph.
Это делает runtime control безопаснее организационно: он не превращается в скрытую вторую конфигурацию, которую никто не ревьюил и не понимает через месяц.
Итог
Runtime control в production нужен, чтобы включить точную диагностику без перезапуска и не держать дорогое подробное логирование активным постоянно.
Но control server — это не просто удобный порт для logmectl. Это management plane running process. Он может менять logging behavior и, при разрешенной policy, открывать доступ к диагностическим файлам.
Безопасная модель начинается с loopback binding. Для удаленного доступа нужен VPN или trusted management network, firewall rules, TLS и password authentication. В свою очередь, для обычной диагностики лучше использовать ControlPolicy::Safe(). Для временных backend-ов — Diagnostic(). Полный режим нужно оставлять только для полностью доверенной административной среды.
logmectl удобен для точных операторских команд. logmeweb удобен для интерактивной работы, но добавляет собственную web security boundary и должен быть защищен отдельно.
И самое важное: runtime control не должен существовать без операционной дисциплины. Ограниченные права, read-only policy там, где она нужна, явный rollback и внешний audit превращают мощную диагностику в безопасный инструмент, а не в новую дыру в production.

