Neko Master: мониторинг сетевого трафика в реальном времени

Логотип Neko Master

Видите свой сетевой трафик чётко.
Мониторинг в реальном времени · Аудит трафика · Поддержка нескольких шлюзов

Важно

Отказ от ответственности

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

Он не предоставляет никаких сетевых служб доступа, прокси-подписок или межсетевого соединения. Все данные собираются из собственной сетевой среды пользователя.

Проект выпущен под лицензией MIT. Авторы не несут ответственности за последствия использования данного программного обеспечения. Пожалуйста, используйте его в соответствии с действующим законодательством.

Предпросмотр Neko Master — светлая тема, вариант 1
Предпросмотр Neko Master — светлая тема, вариант 2
Предпросмотр Neko Master — тёмная тема, вариант 1
Предпросмотр Neko Master — тёмная тема, вариант 2

О названии

Neko (ねこ) по-японски означает кот. Произносится /ˈneɪkoʊ/ (НЭ-ко).

Подобно кошке, Neko Master тихо и точно наблюдает за сетевым трафиком. Это лёгкая аналитическая панель управления, разработанная для современных шлюзовых окружений.

✨ Возможности

Возможность Описание

📊 Мониторинг в реальном времени

Сбор данных через WebSocket с задержкой в миллисекунды

📈 Анализ тенденций

Многомерные тренды трафика: 30 мин / 1 ч / 24 ч

🌐 Анализ доменов

Просмотр трафика, связанных IP-адресов и количества подключений для каждого домена

🗺️ Анализ IP-адресов

Отображение ASN, геолокации и связанных доменов

🚀 Статистика прокси

Распределение трафика и количество подключений по узлам прокси

📱 Поддержка PWA

Установка в виде настольного приложения для нативного опыта

🌙 Тёмный режим

Поддержка светлой, тёмной и системной темы оформления

🌍 Поддержка i18n

Бесшовное переключение между английским и китайским языками

🔄 Несколько бэкендов

Одновременный мониторинг нескольких экземпляров OpenClash

🚀 Быстрый старт

Вариант 1: Docker Compose (рекомендуется)

Встроенный в репозиторий файл docker-compose.yml по умолчанию пробрасывает порты 3000/3001/3002. Сценарии A и B ниже — минимальные шаблоны для типовых развёртываний.

Сценарий A: Минимальное развёртывание (только порт 3000)

services:
  neko-master:
    image: foru17/neko-master:latest
    container_name: neko-master
    restart: unless-stopped
    ports:
      - "3000:3000" # Web UI
    volumes:
      - ./data:/app/data
      # Локальный MMDB (опционально, файлы нужно загрузить в ./geoip)
      - ./geoip:/app/data/geoip:ro
    environment:
      - NODE_ENV=production
      - DB_PATH=/app/data/stats.db
      - COOKIE_SECRET=${COOKIE_SECRET}

Рекомендуется добавить в .env (в той же директории, что и docker-compose.yml): COOKIE_SECRET=<случайная строка не менее 32 байт> (сгенерируйте командой openssl rand -hex 32)

Этот режим полностью совместим при обновлениях и работает «из коробки». Если WS не маршрутизируется, приложение автоматически переключается на HTTP-поллинг.

Сценарий B: WebSocket в реальном времени (рекомендуется при использовании обратного прокси)

services:
  neko-master:
    image: foru17/neko-master:latest
    container_name: neko-master
    restart: unless-stopped
    ports:
      - "3000:3000" # Web UI
      - "3002:3002" # WebSocket (для проброса через Nginx / туннель)
    volumes:
      - ./data:/app/data
      # Локальный MMDB (опционально, файлы нужно загрузить в ./geoip)
      - ./geoip:/app/data/geoip:ro
    environment:
      - NODE_ENV=production
      - DB_PATH=/app/data/stats.db
      - COOKIE_SECRET=${COOKIE_SECRET}

Затем выполните:

docker compose up -d

Откройте http://localhost:3000 для начала работы.

Если вы используете встроенный в репозиторий файл Compose (по умолчанию 3000/3001/3002), команда та же.

Вариант 2: Docker Run

# Сначала сгенерируйте фиксированный секрет для cookie (для сохранения сессий)
export COOKIE_SECRET="$(openssl rand -hex 32)"
# Минимальный вариант (только 3000)
docker run -d \
  --name neko-master \
  -p 3000:3000 \
  -v $(pwd)/data:/app/data \
  -e COOKIE_SECRET="$COOKIE_SECRET" \
  --restart unless-stopped \
  foru17/neko-master:latest

# Реальное время через WS (с обратным прокси)
docker run -d \
  --name neko-master \
  -p 3000:3000 \
  -p 3002:3002 \
  -v $(pwd)/data:/app/data \
  -e COOKIE_SECRET="$COOKIE_SECRET" \
  --restart unless-stopped \
  foru17/neko-master:latest

Откройте http://localhost:3000 для начала работы.

Фронтенд по умолчанию использует одноимённый источник /api, поэтому порт 3001 снаружи обычно не нужен. Для WS в реальном времени обратный прокси или туннель должен иметь доступ к порту 3002. Если это недоступно, приложение переключится на HTTP-поллинг с интервалом ~5 секунд.

При использовании docker run меняйте внешние порты через параметры -p. Только если вы используете прямой доступ к WS (без обратного прокси) и внешний WS-порт отличается от 3002, также передайте -e WS_EXTERNAL_PORT=<внешний-ws-порт>.

Режим локального поиска MMDB (опционально): подключите -v $(pwd)/geoip:/app/data/geoip:ro, затем переключите источник на «Local» в Настройки → Параметры → Источник поиска IP.

Вариант 3: Скрипт одной командой

Автоматически обнаруживает конфликты портов и настраивает всё:

# С использованием curl
curl -fsSL https://raw.githubusercontent.com/foru17/neko-master/main/setup.sh | bash

# Или с использованием wget
wget -qO- https://raw.githubusercontent.com/foru17/neko-master/main/setup.sh | bash

Скрипт автоматически выполнит:

  • ✅ Загрузку docker-compose.yml

  • ✅ Проверку занятости портов по умолчанию (3000/3001/3002)

  • ✅ Предложение доступных альтернативных портов

  • ✅ Создание файла конфигурации и запуск сервиса

Вариант 4: Из исходного кода

# 1. Клонируйте репозиторий
git clone https://github.com/foru17/neko-master.git
cd neko-master

# 2. Установите зависимости
pnpm install

# 3. Подготовьте окружение для коллектора (в режиме исходного кода читается apps/collector/.env)
cp apps/collector/.env.example apps/collector/.env

# 4. Запустите сервисы разработки
pnpm dev

Откройте http://localhost:3000 для настройки.

В режиме исходного кода: коллектор слушает на 3001/3002, веб — на 3000 по умолчанию. Если вы изменили API_PORT (не 3001), соответственно установите API_URL (например API_URL=http://localhost:4001), чтобы перезапись /api указывала на правильный API. apps/collector/.env.local имеет приоритет над apps/collector/.env.

🤖 Развёртывание агента

Режим агента (Agent) подходит, когда нужен один централизованный сервис Neko Master, а несколько удалённых устройств (OpenWrt, Linux, macOS) собирают локальные данные шлюза. Агент работает рядом со шлюзом, забирает данные и отправляет их на панель управления — панель никогда не подключается к шлюзу напрямую.

Поддерживаемые типы шлюзов: Clash / Mihomo (WebSocket в реальном времени) и Surge v5+ (HTTP-поллинг).

Быстрая установка (команда, сгенерированная в UI)

  1. В панели управления перейдите в Настройки → Бэкенды, добавьте бэкенд типа Agent, выберите тип шлюза

  2. Нажмите «Просмотреть скрипт агента» и скопируйте однострочную команду установки, затем выполните её на целевом хосте:

# Пример для шлюза Clash / Mihomo
curl -fsSL https://raw.githubusercontent.com/foru17/neko-master/main/apps/agent/install.sh \
  | env NEKO_SERVER='http://your-panel:3000' \
        NEKO_BACKEND_ID='1' \
        NEKO_BACKEND_TOKEN='ag_xxx' \
        NEKO_GATEWAY_TYPE='clash' \
        NEKO_GATEWAY_URL='http://127.0.0.1:9090' \
        sh

# Пример для шлюза Surge
curl -fsSL https://raw.githubusercontent.com/foru17/neko-master/main/apps/agent/install.sh \
  | env NEKO_SERVER='http://your-panel:3000' \
        NEKO_BACKEND_ID='2' \
        NEKO_BACKEND_TOKEN='ag_yyy' \
        NEKO_GATEWAY_TYPE='surge' \
        NEKO_GATEWAY_URL='http://127.0.0.1:9091' \
        sh

После установки управляйте экземплярами с помощью nekoagent:

nekoagent list               # список всех экземпляров
nekoagent status <instance>  # проверить состояние
nekoagent logs <instance>    # просмотр логов в реальном времени
nekoagent restart <instance> # перезапуск
nekoagent upgrade            # глобальное обновление (CLI + бинарный файл)

Скрипт автоматически обнаруживает существующую установку — если neko-agent уже присутствует, он только добавит новый экземпляр без повторной загрузки. На одном хосте может работать несколько экземпляров (с разными NEKO_INSTANCE_NAME), каждый указывает на свой шлюз.

Документация по агенту

📖 Первый запуск

Экран первого запуска Neko Master

Подключение к Clash / Mihomo

  1. Откройте http://localhost:3000

  2. При первом посещении появится диалог «Конфигурация шлюза»

  3. Введите данные подключения к сетевому шлюзу (например, OpenClash):

    • Имя: произвольное (например, «Домашний шлюз»)

    • Тип: выберите Clash / Mihomo

    • Хост: адрес бэкенда шлюза (например, 192.168.101.1)

    • Порт: порт бэкенда шлюза (например, 9090)

    • Токен: заполните, если настроен Secret, иначе оставьте пустым

  4. Нажмите «Добавить бэкенд» для сохранения

  5. Система автоматически начнёт сбор и анализ данных трафика

💡 Узнать адрес шлюза: перейдите в панель управления шлюзом (например, OpenClash) → включите «Внешнее управление» → скопируйте адрес API

Подключение к Surge

Настройка Surge HTTP API

Neko Master поддерживает подключение к шлюзам Surge для полной визуализации цепочки правил и анализа трафика.

1. Включение Surge HTTP API

Включите HTTP-API удалённого доступа в конфигурации Surge:

[General]
http-api = 127.0.0.1:9091
http-api-tls = false
http-api-web-dashboard = true

Или настройте через графический интерфейс Surge:

  • HTTP Remote API: НастройкиОсновныеHTTP Remote API

  • Порт: по умолчанию 9091

  • Аутентификация: рекомендуется установить пароль для повышения безопасности

2. Добавление бэкенда Surge в Neko Master

  1. Откройте диалог настроек Neko Master

  2. Нажмите «Добавить бэкенд»

  3. Заполните данные подключения:

    • Имя: произвольное (например, «Surge дома»)

    • Тип: выберите Surge

    • Хост: IP-адрес устройства с Surge (например, 192.168.1.1 или 127.0.0.1)

    • Порт: порт HTTP API (по умолчанию 9091)

    • Токен: пароль HTTP API (если настроен)

  4. Нажмите «Проверить подключение» для проверки конфигурации

  5. Сохраните конфигурацию

💡 Примечание: Surge использует HTTP-поллинг для получения данных (в отличие от WebSocket-потока Clash в реальном времени), задержка обновления данных составляет около 2 секунд.

🔧 Устранение конфликтов портов

Если вы видите ошибку «порт уже используется», воспользуйтесь одним из способов:

Способ 1: Файл .env

Создайте файл .env в той же директории, что и docker-compose.yml:

WEB_EXTERNAL_PORT=8080    # Изменить порт Web UI
API_EXTERNAL_PORT=8081    # Изменить порт API
WS_EXTERNAL_PORT=8082     # Изменить внешний порт WebSocket (только для прямого доступа)
COOKIE_SECRET=your-long-random-secret   # Настоятельно рекомендуется зафиксировать

Затем перезапустите:

docker compose down
docker compose up -d

Теперь откройте http://localhost:8080

Способ 2: Прямое редактирование docker-compose.yml

ports:
  - "8080:3000" # Внешний 8080 → Внутренний 3000
  - "8082:3002" # Внешний 8082 → Внутренний 3002 (для проброса WS через прокси/туннель)

Примечание: если вы используете прямой доступ к WS (без обратного прокси) и внешний WS-порт отличается от 3002, установите WS_EXTERNAL_PORT=<внешний-ws-порт>.

Способ 3: Скрипт одной командой

curl -fsSL https://raw.githubusercontent.com/foru17/neko-master/main/setup.sh | bash

Скрипт автоматически обнаружит и предложит доступные порты.

🐳 Конфигурация Docker

Порты

Порт Назначение Нужен снаружи Описание

3000

Web UI

Точка входа для фронтенда

3001

API

Опционально

Фронтенд по умолчанию использует одноимённый источник /api; публичное открытие обычно не требуется (в Compose по умолчанию пробрасывается)

3002

WebSocket

Опционально

Конечная точка push в реальном времени; рекомендуется пробрасывать только через обратный прокси/туннель (в Compose по умолчанию пробрасывается)

Переменные окружения (развёртывание)

Переменная По умолчанию Назначение Когда устанавливать

WEB_PORT

3000

Порт прослушивания веб (внутри контейнера)

Обычно не меняется

API_PORT

3001

Порт прослушивания API (внутри контейнера)

Обычно не меняется

COLLECTOR_WS_PORT

3002

Порт прослушивания WS (внутри контейнера)

Обычно не меняется

DB_PATH

/app/data/stats.db

Путь к данным SQLite

При нестандартном пути к данным

WEB_EXTERNAL_PORT

3000

Внешний маппинг веб-порта в docker-compose.yml

При изменении внешнего веб-порта

API_EXTERNAL_PORT

3001

Внешний маппинг порта API в docker-compose.yml

При необходимости прямого внешнего доступа к API

WS_EXTERNAL_PORT

3002

Внешний маппинг WS-порта в docker-compose.yml; также используется для определения порта прямого подключения WS

При прямом доступе к WS без прокси и изменении внешнего WS-порта

NEXT_PUBLIC_API_URL

пусто

Переопределение базового URL API для фронтенда (например https://api.example.com)

Когда API не на том же источнике /api

NEXT_PUBLIC_WS_URL

пусто

Переопределение WS URL для фронтенда (абсолютный URL или /custom_ws)

При нестандартном пути/домене WS

NEXT_PUBLIC_WS_PORT

3002

Резервный порт прямого подключения WS (только на этапе сборки — установка при запуске Docker не даёт эффекта; используйте WS_EXTERNAL_PORT)

Только при сборке из исходного кода

API_URL

http://localhost:3001

Цель перезаписи Next.js /api (в основном для сборок из исходного кода)

При изменении адреса прослушивания API

COOKIE_SECRET

автогенерация

Секрет подписи cookie; если не зафиксирован, сессии могут инвалидироваться после перезапуска при отсутствии сохранённого каталога данных

Настоятельно рекомендуется в production

GEOIP_LOOKUP_PROVIDER

online

Источник геолокации IP (online / local)

При переключении на локальный поиск по MMDB

GEOIP_ONLINE_API_URL

https://api.ipinfo.es/ipinfo

Конечная точка онлайн-API геолокации IP (должна быть совместима со схемой ответа ipinfo.my)

Только при развёртывании совместимой конечной точки

FORCE_ACCESS_CONTROL_OFF

false

Принудительно отключить управление доступом (аварийное восстановление)

Только временно, при утере токена

SHOWCASE_SITE_MODE

false

Режим демонстрации только для чтения (блокирует чувствительные операции записи)

Только для публичных демо-сайтов

Дополнительные переменные тонкой настройки (опционально)

Переменная По умолчанию Описание

FLUSH_INTERVAL_MS

30000

Интервал сброса буфера записи коллектора

FLUSH_MAX_BUFFER_SIZE

5000

Максимальный размер буфера перед досрочным сбросом

REALTIME_MAX_MINUTES

180

Размер окна данных реального времени в памяти (в минутах)

REALTIME_RANGE_END_TOLERANCE_MS

120000

Допуск по времени окончания для диапазонных запросов

SURGE_POLICY_SYNC_INTERVAL_MS

600000

Интервал синхронизации политик Surge

DB_RANGE_QUERY_CACHE_TTL_MS

8000

TTL кэша диапазонных запросов

DB_HISTORICAL_QUERY_CACHE_TTL_MS

300000

TTL кэша исторических запросов

DB_RANGE_QUERY_CACHE_MAX_ENTRIES

1024

Максимальное число записей кэша диапазонных запросов

DB_RANGE_QUERY_CACHE_DISABLED

пусто

Установите 1 для отключения кэша диапазонных запросов

DEBUG_SURGE

false

Включить отладочные логи коллектора Surge (значение true)

Приоритет разрешения API / WS

  1. Базовый URL API-клиента: runtime-config.API_URLNEXT_PUBLIC_API_URL → одноимённый источник /api

  2. Цель серверной перезаписи /api: API_URL (по умолчанию http://localhost:3001, применяется в перезаписях Next.js)

  3. URL WebSocket: runtime-config.WS_URLNEXT_PUBLIC_WS_URL → автоматические кандидаты (когда задан runtime-config.WS_PORT, предпочтительнее прямой порт; иначе сначала пробуется /_cm_ws)

  4. Порт WS: runtime-config.WS_PORT (из WS_EXTERNAL_PORT) → NEXT_PUBLIC_WS_PORT3002

  5. В стандартных развёртываниях NEXT_PUBLIC_WS_URL обычно не нужен, если только вы не используете нестандартный путь/домен WS

Базовая конфигурация production-среды (рекомендуется)

NODE_ENV=production
DB_PATH=/app/data/stats.db
COOKIE_SECRET=<случайная строка не менее 32 байт>
# Опционально: использовать локальный поиск по MMDB по умолчанию
# GEOIP_LOOKUP_PROVIDER=local
# В обычной работе оставьте false
# FORCE_ACCESS_CONTROL_OFF=false

Для генерации COOKIE_SECRET используйте openssl rand -hex 32.

Дополнительные рекомендации:

  1. Подключите постоянное хранилище (например ./data:/app/data), чтобы не потерять данные и секреты.

  2. Если вы используете прямой доступ к WS и внешний WS-порт отличается от 3002, установите WS_EXTERNAL_PORT.

  3. При изменении порта/адреса API в сборке из исходного кода обновите также API_URL.

  4. Для локального поиска по MMDB подключите ./geoip:/app/data/geoip:ro и переключите источник в Настройки → Параметры → Источник поиска IP.

  5. Файлы MMDB имеют большой размер и не включены в образ. Загрузите их и поместите в ./geoip с фиксированными именами: GeoLite2-City.mmdb, GeoLite2-ASN.mmdb (обязательно) и GeoLite2-Country.mmdb (опционально). Рекомендуемый источник: https://github.com/P3TERX/GeoLite.mmdb.

Подробная документация по агенту (установка, конфигурация, релизы, совместимость) находится в docs/agent/*.

🗄️ ClickHouse (опционально)

SQLite — стандартное хранилище Neko Master, которое отлично подходит для большинства пользователей. Рассмотрите включение ClickHouse, если вам нужно:

  • Очень большие наборы данных (сотни тысяч записей доменов/IP)

  • Быстрые агрегирующие запросы за длинные временные диапазоны (≥ 7 дней)

  • Разделение исторической статистики и хранилища конфигурации/метаданных

ClickHouse полностью опционален. SQLite остаётся хранилищем конфигурации и метаданных независимо от того, включён ли ClickHouse.

Обзор архитектуры

При включении ClickHouse система переходит в режим двойной записи (dual-write):

BatchBuffer.flush()
    │
    ├──→ SQLite (конфигурация / метаданные, записывается всегда)
    └──→ ClickHouse (статистика трафика, двойная запись)
           └── Buffer tables → SummingMergeTree асинхронное слияние

Источник чтения контролируется через STATS_QUERY_SOURCE (по умолчанию: sqlite).

Включение ClickHouse (Docker)

Шаг 1: Запуск контейнера ClickHouse

Встроенный в репозиторий файл docker-compose.yml уже включает сервис ClickHouse, защищённый profiles: [clickhouse], поэтому по умолчанию он не запускается. Из корневой директории репозитория выполните:

docker compose --profile clickhouse up -d

Данные ClickHouse сохраняются в ./data/clickhouse, отдельно от основного каталога данных приложения.

Если вы используете собственный docker-compose.yml (например, сценарии A или B выше), добавьте блок сервиса ClickHouse вручную:

services:
  neko-master:
    # ... ваша существующая конфигурация ...
    environment:
      # добавьте к существующему разделу environment:
      - CH_ENABLED=${CH_ENABLED:-0}
      - CH_HOST=${CH_HOST:-clickhouse}
      - CH_PORT=${CH_PORT:-8123}
      - CH_DATABASE=${CH_DATABASE:-neko_master}
      - CH_USER=${CH_USER:-neko}
      - CH_PASSWORD=${CH_PASSWORD:-neko_master}
      - CH_WRITE_ENABLED=${CH_WRITE_ENABLED:-0}
      - STATS_QUERY_SOURCE=${STATS_QUERY_SOURCE:-sqlite}
    networks:
      - neko-master-network

  clickhouse:
    image: clickhouse/clickhouse-server:24.8
    container_name: neko-master-clickhouse
    restart: unless-stopped
    profiles: ["clickhouse"]
    ports:
      - "${CH_EXTERNAL_HTTP_PORT:-8123}:8123"
      - "${CH_EXTERNAL_NATIVE_PORT:-9000}:9000"
    volumes:
      - ./data/clickhouse:/var/lib/clickhouse
    environment:
      - CLICKHOUSE_DB=${CH_DATABASE:-neko_master}
      - CLICKHOUSE_USER=${CH_USER:-neko}
      - CLICKHOUSE_PASSWORD=${CH_PASSWORD:-neko_master}
      - CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1
    networks:
      - neko-master-network
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:8123/ping || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

networks:
  neko-master-network:
    driver: bridge

Шаг 2: Настройка переменных окружения

Добавьте в .env (в той же директории, что и docker-compose.yml):

# Включить подключение к ClickHouse
CH_ENABLED=1

# Включить двойную запись
CH_WRITE_ENABLED=1

# Источник чтения: sqlite (по умолчанию) / auto (умная маршрутизация) / clickhouse (принудительно)
STATS_QUERY_SOURCE=auto

# Подключение к ClickHouse (значения по умолчанию совпадают с docker-compose.yml, менять не нужно)
CH_HOST=clickhouse
CH_PORT=8123
CH_DATABASE=neko_master
CH_USER=neko
CH_PASSWORD=neko_master

Перезапустите:

docker compose --profile clickhouse up -d

Переменные окружения ClickHouse

Переменная По умолчанию Описание

CH_ENABLED

0

Включить подключение к ClickHouse (значение 1)

CH_WRITE_ENABLED

0

Включить двойную запись (требует CH_ENABLED=1)

CH_ONLY_MODE

0

При исправном CH пропускать запись статистики в SQLite (режим только CH)

CH_HOST

clickhouse

Адрес хоста ClickHouse

CH_PORT

8123

HTTP-порт ClickHouse

CH_DATABASE

neko_master

Имя базы данных

CH_USER

neko

Имя пользователя

CH_PASSWORD

neko_master

Пароль

CH_SECURE

0

Использовать HTTPS-подключение

CH_REQUIRED

0

Отказаться от запуска, если CH недоступен

CH_AUTO_CREATE_TABLES

1

Автоматически создавать таблицы при первом запуске

CH_WRITE_MAX_PENDING_BATCHES

200

Максимальное число ожидающих пакетов записи

CH_UNHEALTHY_THRESHOLD

5

Количество последовательных сбоев до пометки как нездорового (автоматический откат на SQLite)

STATS_QUERY_SOURCE

sqlite

Источник чтения: sqlite / auto / clickhouse

CH_COMPARE_ENABLED

0

Включить проверку согласованности SQLite ↔ ClickHouse

CH_EXTERNAL_HTTP_PORT

8123

Внешний HTTP-порт ClickHouse (маппинг в Compose)

CH_EXTERNAL_NATIVE_PORT

9000

Внешний Native-порт ClickHouse (маппинг в Compose)

Здоровье и откат: после CH_UNHEALTHY_THRESHOLD последовательных сбоев записи система автоматически помечает ClickHouse как нездоровый и возобновляет запись в SQLite — даже при CH_ONLY_MODE=1. После восстановления ClickHouse он снова помечается здоровым и это фиксируется в логах.

Руководство по миграции для существующих пользователей

Обновляетесь с версии только с SQLite? Ваши данные в безопасности. Файл SQLite (./data/stats.db) полностью сохраняется. Рекомендуемый поэтапный путь миграции:

Фаза 1: Двойная запись (период наблюдения, рекомендуемая отправная точка)

CH_ENABLED=1
CH_WRITE_ENABLED=1
STATS_QUERY_SOURCE=sqlite   # Продолжаем читать из SQLite, пока CH накапливает данные

Запустите и следите за логами [ClickHouse Writer] для подтверждения успешных записей.

Фаза 2: Переключение источника чтения

STATS_QUERY_SOURCE=auto        # Умная маршрутизация: свежие данные из CH, исторические — из SQLite
# или
STATS_QUERY_SOURCE=clickhouse  # Принудительно все чтения из ClickHouse

Фаза 3 (опционально): Миграция исторических данных

Для перемещения исторической статистики SQLite в ClickHouse:

# Стандартная миграция (усечение CH и повторный импорт с проверкой согласованности)
./scripts/ch-migrate-docker.sh

# Режим добавления (сохранить существующие данные CH, инкрементальный импорт)
./scripts/ch-migrate-docker.sh --append

# Конкретное временное окно
./scripts/ch-migrate-docker.sh --from 2026-02-01T00:00:00Z --to 2026-02-20T00:00:00Z

Фаза 4 (опционально): Режим только CH

После стабильной работы ClickHouse остановите запись статистики в SQLite:

CH_ONLY_MODE=1

Даже при CH_ONLY_MODE=1, если ClickHouse становится нездоровым, система автоматически переключается на запись в SQLite — без потери данных.

Возврат к только SQLite

Вы всегда можете полностью откатиться:

CH_ENABLED=0
CH_WRITE_ENABLED=0
CH_ONLY_MODE=0
STATS_QUERY_SOURCE=sqlite

После перезапуска всё вернётся в режим чистого SQLite. Исторические данные сохранятся.


🌐 Обратный прокси и туннели

Рекомендуемый подход: держать Web и WS под одним доменом с маршрутизацией по пути: /3000, /_cm_ws3002.

Пример стандартной конфигурации Nginx

server {
  listen 443 ssl http2;
  server_name neko.example.com;

  location / {
    proxy_pass http://<neko-master-host>:3000;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }

  location ^~ /_cm_ws {
    proxy_pass http://<neko-master-host>:3002;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_read_timeout 86400;
    proxy_send_timeout 86400;
    proxy_buffering off;
  }
}

Опциональное переопределение через env:

# По умолчанию не требуется (уже /_cm_ws)
# NEXT_PUBLIC_WS_URL=/custom_ws

Пример стандартной конфигурации Cloudflare Tunnel

~/.cloudflared/config.yml:

tunnel: <имя-или-id-туннеля>
credentials-file: /path/to/<credentials>.json

ingress:
  - hostname: neko.example.com
    path: /_cm_ws*
    service: http://localhost:3002
  - hostname: neko.example.com
    path: /*
    service: http://localhost:3000
  - service: http_status:404

Запуск:

cloudflared tunnel --config ~/.cloudflared/config.yml run <имя-или-id-туннеля>

Для маршрутов, управляемых через панель Zero Trust (режим токена), настройте те же два маршрута и убедитесь, что /_cm_ws* расположен выше /*.

Важные замечания

  1. Не используйте ws (без ведущего слэша) в качестве пути WS — это может вызвать чрезмерное совпадение и привести к ошибке /_next/static/…​ → 426 Upgrade Required

  2. Маршрут WS должен располагаться выше перехватывающего правила /*

  3. NEXT_PUBLIC_WS_URL по умолчанию не обязателен; при изменении — перезапустите фронтенд/контейнер

  4. Маппинг только 3000 работает, но переключается на HTTP-поллинг (~5 с), что снижает оперативность

  5. Сбои beacon.min.js (аналитический скрипт Cloudflare) обычно не связаны с потоком данных API/WS приложения

  6. В большинстве случаев правило обратного прокси для /api не требуется; фронтенд использует одноимённый источник /api, а приложение самостоятельно обрабатывает внутреннее перенаправление на 3001

Примечание: ошибка /_next/static/…​ 426 Upgrade Required характерна для некорректно настроенного обратного прокси / туннеля и редко встречается при прямом локальном доступе без прокси.

Поддержка нескольких архитектур

Образы Docker поддерживают как linux/amd64, так и linux/arm64.

Сохранение данных

Данные хранятся в /app/data внутри контейнера. Примонтируйте этот каталог на хост, чтобы предотвратить потерю данных:

volumes:
  - ./data:/app/data

Обновление до последней версии

# Загрузить последний образ и перезапустить
docker compose pull
docker compose up -d

🔐 Аутентификация и безопасность

Neko Master поддерживает аутентификацию доступа для защиты данных панели управления.

Базовая конфигурация безопасности для production

  1. Установите фиксированный COOKIE_SECRET (иначе сессии могут инвалидироваться после перезапуска).

  2. Не держите FORCE_ACCESS_CONTROL_OFF=true включённым в обычной работе.

  3. Используйте SHOWCASE_SITE_MODE=true только для публичных демо-окружений (операции записи ограничены).

Пример:

COOKIE_SECRET=<случайная строка не менее 32 байт>
# FORCE_ACCESS_CONTROL_OFF=false
# SHOWCASE_SITE_MODE=false

Включение / отключение аутентификации

  1. Откройте панель управления и нажмите «Настройки» в левой нижней части боковой панели.

  2. Перейдите на вкладку «Безопасность».

  3. Включите/отключите контроль доступа и установите токен.

Забыли токен (аварийный сброс)

Если вы забыли токен, временно установите FORCE_ACCESS_CONTROL_OFF=true для входа в аварийный режим.

Docker Compose

  1. Добавьте в docker-compose.yml:

    [source,yaml]
    ----
    environment:
      - FORCE_ACCESS_CONTROL_OFF=true
    ----
  2. Перезапустите:

    [source,bash]
    ----
    docker compose up -d
    ----
  3. Откройте панель управления и сбросьте токен в «Настройки → Безопасность».

  4. Немедленно после сброса удалите эту переменную окружения и снова перезапустите.

Docker CLI

  1. Остановите и удалите контейнер:

    [source,bash]
    ----
    docker stop neko-master
    docker rm neko-master
    ----
  2. Запустите повторно с аварийным флагом:

    [source,bash]
    ----
    docker run -d \
      --name neko-master \
      -p 3000:3000 \
      -v $(pwd)/data:/app/data \
      -e FORCE_ACCESS_CONTROL_OFF=true \
      foru17/neko-master:latest
    ----
  3. Сбросьте токен, затем уберите этот флаг и запустите в обычном режиме.

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

В: Можно ли нормально работать, открыв только 3000:3000?

О: Да. Основные функции по-прежнему будут работать. Если WS не маршрутизируется, приложение автоматически переключается на HTTP-поллинг. Для полного опыта в реальном времени направьте /_cm_ws на порт 3002.

В: Конфликт портов или недоступность после изменения портов?

О: Создайте или обновите .env (в той же директории, что и docker-compose.yml):

WEB_EXTERNAL_PORT=8080
API_EXTERNAL_PORT=8081
WS_EXTERNAL_PORT=8082

Затем перезапустите:

docker compose down
docker compose up -d

В: Почему логин/сессия пропадает после перезапуска?

О: Обычно это происходит из-за нефиксированного COOKIE_SECRET или отсутствия сохранения каталога данных.

  1. Установите фиксированный COOKIE_SECRET

  2. Примонтируйте ./data:/app/data

В: Какие файлы нужны для локального поиска по MMDB?

О: Создайте директорию ./geoip в проекте (рекомендуется на том же уровне, что и docker-compose.yml), затем поместите в неё:

  1. GeoLite2-City.mmdb (обязательно)

  2. GeoLite2-ASN.mmdb (обязательно)

  3. GeoLite2-Country.mmdb (опционально)

Рекомендуемый источник: https://github.com/P3TERX/GeoLite.mmdb. Внутри контейнера фиксированный путь поиска — /app/data/geoip, поэтому сохраняйте маппинг: ./geoip:/app/data/geoip:ro. Для обновления впоследствии просто замените файлы в ./geoip на хосте.

В: Не удаётся подключиться к OpenClash / шлюзу?

О: Проверьте:

  1. На стороне шлюза включено внешнее управление

  2. Хост и порт указаны правильно

  3. Токен/секрет указан правильно (если настроен)

  4. Сетевая конфигурация контейнера позволяет достичь шлюза

В: Как создать резервную копию и восстановить данные?

О: Сначала создайте резервную копию:

cp -r ./data ./data-backup-$(date +%Y%m%d)

Восстановление:

docker compose down
cp -r ./data-backup-YYYYMMDD/. ./data/
docker compose up -d

🏗️ Руководство по архитектуре

Если вы хотите быстро понять глубину системного дизайна, читайте в следующем порядке:

  1. Диаграмма системной архитектуры: сквозное разделение по уровням и ответственность модулей → docs/architecture.en.md

  2. Поток данных: конвейеры сбора данных Clash / Surge и агрегация

  3. Модель данных и хранилище: схема SQLite, буферные таблицы ClickHouse, политика хранения

  4. Дизайн канала реального времени: стратегия слияния RealtimeStore и push через WS

  5. Модуль ClickHouse: архитектура двойной записи, аварийный откат, маршрутизация чтения

Полный индекс документации: docs/README.md

Документация охватывает основной дизайн сбора, агрегации, кэширования, push в реальном времени и управления несколькими бэкендами.

🤝 Обратная связь и сообщения об ошибках

Проект использует шаблоны GitHub Issues (Bug / Feature / Support).

Пожалуйста, укажите как минимум:

  1. Метод развёртывания (Compose / Docker Run / исходный код)

  2. Информацию о версии (тег образа или коммит)

  3. Ключевые переменные окружения (замаскированные, например COOKIE_SECRET=*)

  4. Шаги воспроизведения, ожидаемое и фактическое поведение

  5. Ключевые логи (docker logs, консоль браузера, сетевые ошибки)

📁 Структура проекта

neko-master/
├── docker-compose.yml      # Конфигурация Docker Compose
├── Dockerfile              # Сборка Docker-образа
├── setup.sh                # Скрипт автоматической установки
├── docker-start.sh         # Скрипт запуска контейнера Docker
├── start.sh                # Скрипт запуска для разработки из исходного кода
├── docs/                   # Документация (см. docs/README.md)
│   ├── README.md           # Индекс документации (английский по умолчанию)
│   ├── README.zh.md        # Индекс документации (китайский)
│   ├── README.en.md        # Индекс документации (зеркало на английском)
│   ├── architecture.md     # Системная архитектура (китайский)
│   ├── architecture.en.md  # Системная архитектура (английский)
│   ├── release-checklist.md
│   ├── agent/              # Документация по агенту (двуязычная)
│   │   ├── overview.md / overview.en.md
│   │   ├── quick-start.md / quick-start.en.md
│   │   ├── install.md / install.en.md
│   │   ├── config.md / config.en.md
│   │   ├── release.md / release.en.md
│   │   └── troubleshooting.md / troubleshooting.en.md
│   ├── research/           # Исследовательские отчёты
│   └── dev/                # Внутренняя документация для разработчиков
├── assets/                 # Скриншоты и иконки
├── apps/
│   ├── collector/          # Сервис сбора данных (Node.js + WebSocket)
│   ├── agent/              # Демон агента (Go)
│   └── web/                # Фронтенд-приложение Next.js
└── packages/
    └── shared/             # Общие типы и утилиты

🛠️ Стек технологий

🤝 Участие в разработке

Мы приветствуем вклад сообщества!

Перед открытием PR прочитайте CONTRIBUTING.md (рабочий процесс, проверки, требования по i18n и тёмной теме).

Разрабатываете с использованием AI-инструмента? (Claude Code, Copilot, Cursor, Codex, …​) Направьте его на AGENTS.md — соглашения, ключевые контракты и карту проекта — а также на пошаговые руководства в .claude/skills/. Claude Code подхватывает оба файла автоматически.

📄 Лицензия

MIT © foru17

© 2026 meganuke