Сервис для мониторинга и контроля целостности журналов событий на удалённых серверах.
Проект умеет:
- подключаться к удалённым серверам по SSH;
- автоматически искать журналы событий;
- собирать новые записи из найденных логов;
- сохранять метаданные, строки логов и контрольные значения в хранилище;
- проверять целостность логов и обнаруживать изменения;
- работать как HTTP-сервис и как отдельная CLI-утилита.
В текущей версии веб-интерфейс ещё не реализован. Для работы доступны HTTP API, Swagger UI и CLI.
- Как это работает
- Режимы запуска
- Требования
- Быстрый старт
- Конфигурация
- Переменные окружения
- CLI-утилита
- HTTP API
- Docker и Docker Compose
- Хранение данных и миграции
- Сборка бинарников
- Разработка
Сервис работает по следующей схеме:
- В конфиге задаются стартовые серверы, параметры SSH, база данных и поведение фоновых задач.
- При запуске приложение поднимает общее runtime-окружение: репозиторий, SSH-клиент, сервисный слой и runtime-state.
- В HTTP-режиме дополнительно поднимаются API, очередь job и scheduler.
- Для каждого сервера можно:
- обнаружить журналы;
- собрать новые строки;
- запустить проверку целостности.
- Результаты сохраняются в хранилище.
- Если сервер недоступен или работает нестабильно, приложение обновляет его health-состояние:
active,degraded,inactive,error.
Проект поддерживает два режима запуска.
| Режим | Значение LOGMONITOR_APP_MODE |
Точка входа | Назначение |
|---|---|---|---|
| HTTP | HTTP |
./cmd/server |
Долгоживущий сервис с REST API, Swagger, очередью задач и scheduler |
| CLI | CLI |
./cmd/cli |
Локальная консольная утилита для ручных операций |
Переменная LOGMONITOR_APP_MODE обязательна. Она читается до загрузки основного YAML-конфига. Если она не задана или содержит неверное значение, приложение завершится с ошибкой.
Допустимые значения:
HTTPCLI
- Go
1.26+ - PostgreSQL
13+для постоянного хранения данных - Docker и Docker Compose, если планируется запуск в контейнерах
- SSH-доступ к удалённым серверам
В проекте уже есть готовые примеры:
- config.local.yaml — локальный запуск;
- config.docker.yaml — запуск в Docker;
- config.yaml.example — общий пример.
Для первого запуска проще всего использовать config.local.yaml.
PowerShell:
$env:LOGMONITOR_APP_MODE = "HTTP"
go run ./cmd/server -config config.local.yamlBash:
LOGMONITOR_APP_MODE=HTTP go run ./cmd/server -config config.local.yamlПосле запуска будут доступны:
http://localhost:8080/healthzhttp://localhost:8080/readyzhttp://localhost:8080/swagger
PowerShell:
$env:LOGMONITOR_APP_MODE = "CLI"
go run ./cmd/cli --config config.local.yaml healthПримеры:
$env:LOGMONITOR_APP_MODE = "CLI"
go run ./cmd/cli --config config.local.yaml config validate
go run ./cmd/cli --config config.local.yaml server list
go run ./cmd/cli --config config.local.yaml dashboardФайл config.local.yaml по умолчанию не содержит настроек PostgreSQL, поэтому приложение использует in-memory storage.
Это удобно для разработки, но у такого режима есть ограничения:
- данные не сохраняются между перезапусками;
- история job и runtime-состояние тоже теряются;
- это не production-режим.
Если нужен постоянный storage, заполните секцию database и задайте ключ security.auth_value_encryption_key.
Основной конфиг хранится в YAML. Ниже кратко описано, что означает каждая секция.
| Секция | Назначение | Обязательна |
|---|---|---|
server |
Хост и порт HTTP-сервера | Только для HTTP |
api |
Токен авторизации для API | Только для HTTP |
security |
Ключи шифрования и HMAC | Да |
database |
Подключение к PostgreSQL | Нет, если устраивает in-memory |
ssh |
Таймауты и политика host key | Да |
scheduler |
Расписание discovery / collect / integrity | В основном для HTTP |
collector |
Batch/chunk-параметры сбора логов | Да |
health |
Политики degraded/error/backoff | Да |
jobs |
Размер очереди и история job | В основном для HTTP |
runtime |
Служебные режимы, например dry_run |
Да |
workers |
Параллелизм cron-задач | В основном для HTTP |
servers |
Стартовый список серверов из конфига | Нет |
serverиapiиспользуются только в режимеHTTP.- Если
database.host,database.userилиdatabase.dbnameне заданы, приложение переключается на in-memory storage. - Если
runtime.dry_run=true, scheduler отключается, а хранилище принудительно становится in-memory. - Серверы из секции
serversавтоматически загружаются при старте какconfig-managed. - Серверы, созданные через API, помечаются как
api-managed.
servers:
- name: "linux-demo"
host: "192.168.1.10"
port: 22
username: "root"
auth_type: "password"
auth_value: "secret"
os_type: "linux"
- name: "windows-demo"
host: "192.168.1.20"
port: 22
username: "administrator"
auth_type: "password"
auth_value: "secret"
os_type: "windows"| Переменная | Назначение | Обязательна | Пример |
|---|---|---|---|
LOGMONITOR_APP_MODE |
Режим запуска: HTTP или CLI |
Да | HTTP |
| Переменная | Назначение | Обязательна | Пример |
|---|---|---|---|
APP_HOST |
Хост HTTP-сервера | Нет | 0.0.0.0 |
APP_PORT |
Порт HTTP-сервера | Нет | 8080 |
API_AUTH_TOKEN |
API-токен для X-API-Key или Authorization: Bearer |
Нет, но рекомендуется | super-secret-token |
Если
API_AUTH_TOKENпустой, API будет доступен без авторизации. Для production так делать не стоит.
| Переменная | Назначение | Обязательна | Пример |
|---|---|---|---|
AUTH_VALUE_ENCRYPTION_KEY |
Ключ шифрования auth_value в PostgreSQL |
Обязательна при PostgreSQL | change-me-auth-value-encryption-key |
INTEGRITY_HMAC_KEY |
Ключ HMAC для контроля целостности | Да | change-me-integrity-hmac-key |
| Переменная | Назначение | Обязательна | Пример |
|---|---|---|---|
DB_HOST |
Хост PostgreSQL для приложения | Для постоянного storage | postgres |
DB_PORT |
Порт PostgreSQL для приложения | Нет | 5432 |
DB_USER |
Пользователь БД для приложения | Для постоянного storage | logmonitor |
DB_PASSWORD |
Пароль БД для приложения | Для постоянного storage | logmonitor |
DB_NAME |
Имя БД для приложения | Для постоянного storage | logmonitor |
DB_SSLMODE |
SSL mode | Нет | disable |
DB_MAX_CONNS |
Максимум соединений в пуле | Нет | 10 |
DB_MIN_CONNS |
Минимум соединений в пуле | Нет | 1 |
DB_MIGRATIONS_DIR |
Путь к миграциям goose | Нет | migrations |
Дополнительно в Docker Compose используются переменные контейнера PostgreSQL:
POSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_PORT
| Переменная | Назначение | Обязательна | Пример |
|---|---|---|---|
SSH_CONNECT_TIMEOUT_SECONDS |
Таймаут подключения | Нет | 10 |
SSH_COMMAND_TIMEOUT_SECONDS |
Таймаут выполнения команды | Нет | 30 |
SSH_KNOWN_HOSTS_PATH |
Путь к known_hosts |
Нет | C:/Users/user/.ssh/known_hosts |
SSH_INSECURE_IGNORE_HOST_KEY |
Игнорировать host key check | Нет | true |
| Переменная | Назначение | Пример |
|---|---|---|
DISCOVERY_CRON |
Расписание discovery | 0 */6 * * * |
COLLECTION_CRON |
Расписание collection | */5 * * * * |
INTEGRITY_CRON |
Расписание integrity check | 0 * * * * |
COLLECTOR_BATCH_SIZE |
Batch size при вставке логов | 5000 |
COLLECTOR_CHUNK_SIZE |
Размер чанка для групповых hash/HMAC-операций | 1000 |
COLLECTOR_STORE_RAW_CONTENT |
Сохранять текст строк лога | true |
COLLECTOR_CHUNK_HASH_ALGO |
Алгоритм hash для чанков | sha256 |
HEALTH_FAILURE_THRESHOLD |
Порог ошибок до реакции health-layer | 1 |
HEALTH_BACKOFF_BASE_SECONDS |
Базовый backoff | 60 |
HEALTH_BACKOFF_MAX_SECONDS |
Максимальный backoff | 900 |
HEALTH_LAST_ERROR_MAX_LENGTH |
Максимальная длина last_error |
2048 |
JOBS_WORKERS |
Число воркеров очереди job | 2 |
JOBS_QUEUE_SIZE |
Размер очереди job | 128 |
JOBS_HISTORY_LIMIT |
Максимум job в памяти | 1000 |
WORKERS_DISCOVERY_SERVERS |
Параллелизм discovery | 4 |
WORKERS_COLLECTION_SERVERS |
Параллелизм collection по серверам | 4 |
WORKERS_COLLECTION_LOG_FILES_PER_HOST |
Параллелизм collection по логам на сервер | 2 |
WORKERS_INTEGRITY_SERVERS |
Параллелизм integrity по серверам | 2 |
WORKERS_INTEGRITY_LOG_FILES_PER_HOST |
Параллелизм integrity по логам на сервер | 1 |
WORKERS_PER_SERVER_ISOLATION |
Изоляция конкурентных операций на один сервер | true |
RUNTIME_DRY_RUN |
Холостой запуск | false |
.env автоматически подхватывается:
docker compose;config.docker.yaml, потому что в нём используются шаблоны${VAR}.
Для локального запуска Go-процесса .env сам по себе не читается. В этом случае:
- либо задайте переменные в shell;
- либо используйте YAML с готовыми значениями;
- либо запускайте через Docker Compose.
CLI работает синхронно и использует тот же сервисный слой, что и HTTP-режим, но не поднимает API.
| Флаг | Назначение |
|---|---|
--config, -c |
Путь к YAML-конфигу |
--output, -o |
Формат вывода: table или json |
| Команда | Назначение |
|---|---|
logmonitor health |
Проверка, что CLI runtime может инициализироваться |
logmonitor ready |
Проверка readiness общего runtime |
logmonitor config validate |
Показ runtime validation и env resolution |
logmonitor server list |
Список серверов |
logmonitor server get <id> |
Просмотр сервера |
logmonitor server add ... |
Добавление сервера |
logmonitor server update <id> ... |
Обновление сервера |
logmonitor server delete <id> |
Удаление сервера |
logmonitor server retry <id> |
Сброс временного failure/backoff |
logmonitor discover [--server-id] |
Поиск логов |
logmonitor logfile list [--server-id] |
Список логов |
logmonitor collect --server-id ... |
Сбор строк |
logmonitor entry list --log-file-id ... |
Просмотр строк |
logmonitor check list --log-file-id ... |
История проверок |
logmonitor check run --server-id ... |
Запуск проверки целостности |
logmonitor problem list |
Агрегированный список проблем |
logmonitor dashboard |
Сводная статистика |
logmonitor runtime validation |
Снимок runtime-state |
$env:LOGMONITOR_APP_MODE = "CLI"
go run ./cmd/cli --config config.local.yaml server list
go run ./cmd/cli --config config.local.yaml server add --name web-1 --host 192.168.1.10 --username root --auth-type password --auth-value secret --os-type linux
go run ./cmd/cli --config config.local.yaml discover --server-id srv_123
go run ./cmd/cli --config config.local.yaml collect --server-id srv_123
go run ./cmd/cli --config config.local.yaml check run --server-id srv_123 --output json| URL | Назначение |
|---|---|
/healthz |
Liveness probe |
/readyz |
Readiness probe |
/swagger |
Swagger UI |
/swagger/openapi.json |
OpenAPI JSON |
Если api.auth_token не пустой, используйте один из вариантов:
X-API-Key: <token>или
Authorization: Bearer <token>HTTP API смешанного типа:
- синхронные: чтение списков, получение сущностей, health/readiness;
- асинхронные: discovery, collect, check run.
Асинхронные ручки:
- возвращают
202 Accepted; - выставляют
Location: /api/jobs/{id}; - сохраняют результат в in-memory истории job;
- поддерживают
X-Idempotency-Keyдля идемпотентных повторных вызовов.
| Статус | Значение |
|---|---|
queued |
Задача поставлена в очередь |
running |
Задача выполняется |
succeeded |
Задача завершилась успешно |
failed |
Задача завершилась с ошибкой |
canceled |
Задача отменена при shutdown |
Для list-ручек:
offset >= 0limit > 0limit <= 1000
| Метод | Путь | Описание |
|---|---|---|
GET |
/healthz |
Проверка жизни процесса |
GET |
/readyz |
Проверка готовности |
GET |
/swagger |
Swagger UI |
GET |
/swagger/openapi.json |
OpenAPI JSON |
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/runtime/validation |
Runtime warnings и env resolution |
GET |
/api/jobs |
Список job |
GET |
/api/jobs/{id} |
Получение job по ID |
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/dashboard |
Сводная статистика |
GET |
/api/problems |
Агрегированный список проблем |
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/servers |
Список серверов |
GET |
/api/servers/{id} |
Один сервер |
POST |
/api/servers |
Создание сервера |
PUT |
/api/servers/{id} |
Обновление API-managed сервера |
DELETE |
/api/servers/{id} |
Удаление API-managed сервера |
POST |
/api/servers/{id}/retry |
Сброс backoff/failure state |
POST |
/api/servers/discover |
Асинхронный discovery |
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/logfiles |
Список логов |
POST |
/api/logfiles/collect |
Асинхронный collection |
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/entries |
Список строк конкретного лога |
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/checks |
История проверок конкретного лога |
POST |
/api/checks/run |
Асинхронный integrity check |
curl -X POST http://localhost:8080/api/servers \
-H "Content-Type: application/json" \
-H "X-API-Key: your-token" \
-d '{
"name": "web-1",
"host": "192.168.1.10",
"port": 22,
"username": "root",
"auth_type": "password",
"auth_value": "secret",
"os_type": "linux"
}'curl -X POST http://localhost:8080/api/servers/discover \
-H "Content-Type: application/json" \
-H "X-API-Key: your-token" \
-H "X-Idempotency-Key: discover-web-1" \
-d '{
"server_id": "srv_123"
}'curl -X POST http://localhost:8080/api/logfiles/collect \
-H "Content-Type: application/json" \
-H "X-API-Key: your-token" \
-H "X-Idempotency-Key: collect-web-1" \
-d '{
"server_id": "srv_123"
}'curl -X POST http://localhost:8080/api/checks/run \
-H "Content-Type: application/json" \
-H "X-API-Key: your-token" \
-H "X-Idempotency-Key: integrity-web-1" \
-d '{
"server_id": "srv_123"
}'curl http://localhost:8080/api/jobs/<job-id> \
-H "X-API-Key: your-token"- Dockerfile — собирает HTTP-серверный бинарник;
- docker-compose.yaml — поднимает
appиpostgres; - config.docker.yaml — конфиг с
${ENV}-placeholder’ами; - .env.example — пример переменных.
- Скопируйте
.env.exampleв.env - При необходимости задайте реальные секреты
- Убедитесь, что
LOGMONITOR_APP_MODE=HTTP - Запустите:
docker compose up --build -d- Проверьте:
curl http://localhost:8080/healthzТекущий Dockerfile собирает только серверную часть ./cmd/server. CLI-утилита поставляется отдельно и обычно используется локально.
Если заполнена секция database, проект использует PostgreSQL через pgxpool.
При старте приложения автоматически выполняются миграции через goose.
Каталог миграций:
Если база не настроена или включён runtime.dry_run, используется in-memory storage.
Плюсы:
- быстро для разработки;
- не нужен PostgreSQL;
- удобно для пробных запусков.
Минусы:
- данные не переживают рестарт;
- история job тоже не сохраняется;
- не подходит для production.
- серверы;
- найденные лог-файлы;
- строки логов;
- чанки логов;
- результаты проверок.
auth_value в PostgreSQL хранится в зашифрованном виде. Для контроля целостности используется HMAC.
Сервер:
go build -o bin/logmonitor-server ./cmd/serverCLI:
go build -o bin/logmonitor-cli ./cmd/cliЗапуск после сборки:
PowerShell:
$env:LOGMONITOR_APP_MODE = "HTTP"
.\bin\logmonitor-server -config config.local.yaml$env:LOGMONITOR_APP_MODE = "CLI"
.\bin\logmonitor-cli --config config.local.yaml server listgo generate ./cmd/serverСгенерированные файлы:
go test ./...
go build ./...
go vet ./...
golangci-lint run- HTTP async job history хранится в памяти процесса и очищается после рестарта.
- CLI выполняет операции синхронно и не использует HTTP API.
api.auth_tokenлучше всегда задавать явно.- Для production лучше использовать PostgreSQL, а не in-memory storage.
- Если
os_typeпустой, система пытается определить ОС удалённого сервера автоматически.