Видите свой сетевой трафик чётко.
Мониторинг в реальном времени · Аудит трафика · Поддержка нескольких шлюзов
|
Важно
|
Отказ от ответственности Этот проект — инструмент анализа и визуализации трафика для локальных шлюзовых окружений. Он не предоставляет никаких сетевых служб доступа, прокси-подписок или межсетевого соединения. Все данные собираются из собственной сетевой среды пользователя. Проект выпущен под лицензией MIT. Авторы не несут ответственности за последствия использования данного программного обеспечения. Пожалуйста, используйте его в соответствии с действующим законодательством. |
|
|
|
|
О названии
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)
-
В панели управления перейдите в
Настройки → Бэкенды, добавьте бэкенд типаAgent, выберите тип шлюза -
Нажмите «Просмотреть скрипт агента» и скопируйте однострочную команду установки, затем выполните её на целевом хосте:
# Пример для шлюза 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), каждый указывает на свой шлюз.
Документация по агенту
-
Обзор: архитектура, сравнение Direct и Agent, модель безопасности
-
Быстрый старт: пошаговая настройка от UI до запущенного агента
-
Руководство по установке: методы установки, автозапуск через systemd / launchd
-
Конфигурация: полный справочник флагов и переменных окружения
-
Процесс релиза: версионирование и политика совместимости
-
Устранение неполадок: типичные ошибки и способы их исправления
📖 Первый запуск
Подключение к Clash / Mihomo
-
Откройте http://localhost:3000
-
При первом посещении появится диалог «Конфигурация шлюза»
-
Введите данные подключения к сетевому шлюзу (например, OpenClash):
-
Имя: произвольное (например, «Домашний шлюз»)
-
Тип: выберите
Clash / Mihomo -
Хост: адрес бэкенда шлюза (например,
192.168.101.1) -
Порт: порт бэкенда шлюза (например,
9090) -
Токен: заполните, если настроен Secret, иначе оставьте пустым
-
-
Нажмите «Добавить бэкенд» для сохранения
-
Система автоматически начнёт сбор и анализ данных трафика
💡 Узнать адрес шлюза: перейдите в панель управления шлюзом (например, OpenClash) → включите «Внешнее управление» → скопируйте адрес API
Подключение к Surge
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
-
Откройте диалог настроек Neko Master
-
Нажмите «Добавить бэкенд»
-
Заполните данные подключения:
-
Имя: произвольное (например, «Surge дома»)
-
Тип: выберите
Surge -
Хост: IP-адрес устройства с Surge (например,
192.168.1.1или127.0.0.1) -
Порт: порт HTTP API (по умолчанию
9091) -
Токен: пароль HTTP API (если настроен)
-
-
Нажмите «Проверить подключение» для проверки конфигурации
-
Сохраните конфигурацию
💡 Примечание: 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 |
Опционально |
Фронтенд по умолчанию использует одноимённый источник |
3002 |
WebSocket |
Опционально |
Конечная точка push в реальном времени; рекомендуется пробрасывать только через обратный прокси/туннель (в Compose по умолчанию пробрасывается) |
Переменные окружения (развёртывание)
| Переменная | По умолчанию | Назначение | Когда устанавливать |
|---|---|---|---|
|
|
Порт прослушивания веб (внутри контейнера) |
Обычно не меняется |
|
|
Порт прослушивания API (внутри контейнера) |
Обычно не меняется |
|
|
Порт прослушивания WS (внутри контейнера) |
Обычно не меняется |
|
|
Путь к данным SQLite |
При нестандартном пути к данным |
|
|
Внешний маппинг веб-порта в |
При изменении внешнего веб-порта |
|
|
Внешний маппинг порта API в |
При необходимости прямого внешнего доступа к API |
|
|
Внешний маппинг WS-порта в |
При прямом доступе к WS без прокси и изменении внешнего WS-порта |
|
пусто |
Переопределение базового URL API для фронтенда (например |
Когда API не на том же источнике |
|
пусто |
Переопределение WS URL для фронтенда (абсолютный URL или |
При нестандартном пути/домене WS |
|
|
Резервный порт прямого подключения WS (только на этапе сборки — установка при запуске Docker не даёт эффекта; используйте |
Только при сборке из исходного кода |
|
Цель перезаписи Next.js |
При изменении адреса прослушивания API |
|
|
автогенерация |
Секрет подписи cookie; если не зафиксирован, сессии могут инвалидироваться после перезапуска при отсутствии сохранённого каталога данных |
Настоятельно рекомендуется в production |
|
|
Источник геолокации IP ( |
При переключении на локальный поиск по MMDB |
|
Конечная точка онлайн-API геолокации IP (должна быть совместима со схемой ответа |
Только при развёртывании совместимой конечной точки |
|
|
|
Принудительно отключить управление доступом (аварийное восстановление) |
Только временно, при утере токена |
|
|
Режим демонстрации только для чтения (блокирует чувствительные операции записи) |
Только для публичных демо-сайтов |
Дополнительные переменные тонкой настройки (опционально)
| Переменная | По умолчанию | Описание |
|---|---|---|
|
|
Интервал сброса буфера записи коллектора |
|
|
Максимальный размер буфера перед досрочным сбросом |
|
|
Размер окна данных реального времени в памяти (в минутах) |
|
|
Допуск по времени окончания для диапазонных запросов |
|
|
Интервал синхронизации политик Surge |
|
|
TTL кэша диапазонных запросов |
|
|
TTL кэша исторических запросов |
|
|
Максимальное число записей кэша диапазонных запросов |
|
пусто |
Установите |
|
|
Включить отладочные логи коллектора Surge (значение |
Приоритет разрешения API / WS
-
Базовый URL API-клиента:
runtime-config.API_URL→NEXT_PUBLIC_API_URL→ одноимённый источник/api -
Цель серверной перезаписи
/api:API_URL(по умолчаниюhttp://localhost:3001, применяется в перезаписях Next.js) -
URL WebSocket:
runtime-config.WS_URL→NEXT_PUBLIC_WS_URL→ автоматические кандидаты (когда заданruntime-config.WS_PORT, предпочтительнее прямой порт; иначе сначала пробуется/_cm_ws) -
Порт WS:
runtime-config.WS_PORT(изWS_EXTERNAL_PORT) →NEXT_PUBLIC_WS_PORT→3002 -
В стандартных развёртываниях
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.
Дополнительные рекомендации:
-
Подключите постоянное хранилище (например
./data:/app/data), чтобы не потерять данные и секреты. -
Если вы используете прямой доступ к WS и внешний WS-порт отличается от
3002, установитеWS_EXTERNAL_PORT. -
При изменении порта/адреса API в сборке из исходного кода обновите также
API_URL. -
Для локального поиска по MMDB подключите
./geoip:/app/data/geoip:roи переключите источник вНастройки → Параметры → Источник поиска IP. -
Файлы 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
| Переменная | По умолчанию | Описание |
|---|---|---|
|
|
Включить подключение к ClickHouse (значение |
|
|
Включить двойную запись (требует |
|
|
При исправном CH пропускать запись статистики в SQLite (режим только CH) |
|
|
Адрес хоста ClickHouse |
|
|
HTTP-порт ClickHouse |
|
|
Имя базы данных |
|
|
Имя пользователя |
|
|
Пароль |
|
|
Использовать HTTPS-подключение |
|
|
Отказаться от запуска, если CH недоступен |
|
|
Автоматически создавать таблицы при первом запуске |
|
|
Максимальное число ожидающих пакетов записи |
|
|
Количество последовательных сбоев до пометки как нездорового (автоматический откат на SQLite) |
|
|
Источник чтения: |
|
|
Включить проверку согласованности SQLite ↔ ClickHouse |
|
|
Внешний HTTP-порт ClickHouse (маппинг в Compose) |
|
|
Внешний 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_ws → 3002.
Пример стандартной конфигурации 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* расположен выше /*.
Важные замечания
-
Не используйте
ws(без ведущего слэша) в качестве пути WS — это может вызвать чрезмерное совпадение и привести к ошибке/_next/static/… → 426 Upgrade Required -
Маршрут WS должен располагаться выше перехватывающего правила
/* -
NEXT_PUBLIC_WS_URLпо умолчанию не обязателен; при изменении — перезапустите фронтенд/контейнер -
Маппинг только
3000работает, но переключается на HTTP-поллинг (~5 с), что снижает оперативность -
Сбои
beacon.min.js(аналитический скрипт Cloudflare) обычно не связаны с потоком данных API/WS приложения -
В большинстве случаев правило обратного прокси для
/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
-
Установите фиксированный
COOKIE_SECRET(иначе сессии могут инвалидироваться после перезапуска). -
Не держите
FORCE_ACCESS_CONTROL_OFF=trueвключённым в обычной работе. -
Используйте
SHOWCASE_SITE_MODE=trueтолько для публичных демо-окружений (операции записи ограничены).
Пример:
COOKIE_SECRET=<случайная строка не менее 32 байт>
# FORCE_ACCESS_CONTROL_OFF=false
# SHOWCASE_SITE_MODE=false
Включение / отключение аутентификации
-
Откройте панель управления и нажмите «Настройки» в левой нижней части боковой панели.
-
Перейдите на вкладку «Безопасность».
-
Включите/отключите контроль доступа и установите токен.
Забыли токен (аварийный сброс)
Если вы забыли токен, временно установите FORCE_ACCESS_CONTROL_OFF=true для входа в аварийный режим.
Docker Compose
-
Добавьте в
docker-compose.yml:[source,yaml] ---- environment: - FORCE_ACCESS_CONTROL_OFF=true ----
-
Перезапустите:
[source,bash] ---- docker compose up -d ----
-
Откройте панель управления и сбросьте токен в «Настройки → Безопасность».
-
Немедленно после сброса удалите эту переменную окружения и снова перезапустите.
Docker CLI
-
Остановите и удалите контейнер:
[source,bash] ---- docker stop neko-master docker rm neko-master ----
-
Запустите повторно с аварийным флагом:
[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 ----
-
Сбросьте токен, затем уберите этот флаг и запустите в обычном режиме.
❓ Частые вопросы
В: Можно ли нормально работать, открыв только 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 или отсутствия сохранения каталога данных.
-
Установите фиксированный
COOKIE_SECRET -
Примонтируйте
./data:/app/data
В: Какие файлы нужны для локального поиска по MMDB?
О: Создайте директорию ./geoip в проекте (рекомендуется на том же уровне, что и docker-compose.yml), затем поместите в неё:
-
GeoLite2-City.mmdb(обязательно) -
GeoLite2-ASN.mmdb(обязательно) -
GeoLite2-Country.mmdb(опционально)
Рекомендуемый источник: https://github.com/P3TERX/GeoLite.mmdb.
Внутри контейнера фиксированный путь поиска — /app/data/geoip, поэтому сохраняйте маппинг:
./geoip:/app/data/geoip:ro. Для обновления впоследствии просто замените файлы в ./geoip на хосте.
В: Не удаётся подключиться к OpenClash / шлюзу?
О: Проверьте:
-
На стороне шлюза включено внешнее управление
-
Хост и порт указаны правильно
-
Токен/секрет указан правильно (если настроен)
-
Сетевая конфигурация контейнера позволяет достичь шлюза
В: Как создать резервную копию и восстановить данные?
О: Сначала создайте резервную копию:
cp -r ./data ./data-backup-$(date +%Y%m%d)
Восстановление:
docker compose down
cp -r ./data-backup-YYYYMMDD/. ./data/
docker compose up -d
🏗️ Руководство по архитектуре
Если вы хотите быстро понять глубину системного дизайна, читайте в следующем порядке:
-
Диаграмма системной архитектуры: сквозное разделение по уровням и ответственность модулей → docs/architecture.en.md
-
Поток данных: конвейеры сбора данных Clash / Surge и агрегация
-
Модель данных и хранилище: схема SQLite, буферные таблицы ClickHouse, политика хранения
-
Дизайн канала реального времени: стратегия слияния
RealtimeStoreи push через WS -
Модуль ClickHouse: архитектура двойной записи, аварийный откат, маршрутизация чтения
Полный индекс документации: docs/README.md
Документация охватывает основной дизайн сбора, агрегации, кэширования, push в реальном времени и управления несколькими бэкендами.
🤝 Обратная связь и сообщения об ошибках
Проект использует шаблоны GitHub Issues (Bug / Feature / Support).
Пожалуйста, укажите как минимум:
-
Метод развёртывания (Compose / Docker Run / исходный код)
-
Информацию о версии (тег образа или коммит)
-
Ключевые переменные окружения (замаскированные, например
COOKIE_SECRET=*) -
Шаги воспроизведения, ожидаемое и фактическое поведение
-
Ключевые логи (
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/ # Общие типы и утилиты
🛠️ Стек технологий
-
Фронтенд: Next.js 16 + React 19 + TypeScript
-
Стили: Tailwind CSS + shadcn/ui
-
Графики: Recharts
-
i18n: next-intl
-
База данных: SQLite (better-sqlite3) + ClickHouse (опционально)
🤝 Участие в разработке
Мы приветствуем вклад сообщества!
Перед открытием PR прочитайте CONTRIBUTING.md (рабочий процесс, проверки, требования по i18n и тёмной теме).
Разрабатываете с использованием AI-инструмента? (Claude Code, Copilot, Cursor, Codex, …) Направьте его на AGENTS.md — соглашения, ключевые контракты и карту проекта — а также на пошаговые руководства в .claude/skills/. Claude Code подхватывает оба файла автоматически.