
Современная и элегантная панель управления для визуализации и анализа сетевого трафика.
Neko Master
Ясно видьте свой сетевой трафик.
Мониторинг в реальном времени · Аудит трафика · Поддержка нескольких шлюзов
English | 中文
[!IMPORTANT] Отказ от ответственности
Этот проект представляет собой инструмент анализа и визуализации трафика для локальных шлюзовых сред.
Он не предоставляет никаких услуг сетевого доступа, прокси-подписок или межсетевого подключения. Все данные собираются из собственной сетевой среды пользователя.
Этот проект распространяется с открытым исходным кодом под лицензией MIT. Мы не несём ответственности за любые последствия, возникшие в результате использования данного программного обеспечения. Пожалуйста, используйте его в соответствии с применимыми законами и нормативными актами.
Neko (ねこ) означает кошка по-японски. Произносится /ˈneɪkoʊ/ (НЭ-ко).
Как кошка, Neko Master наблюдает за сетевым трафиком тихо и точно. Это лёгкая аналитическая панель, разработанная для современных шлюзовых сред.
Встроенный в репозиторий
docker-compose.ymlпо умолчанию пробрасывает порты3000/3001/3002. Сценарии A/B ниже — это минимальные шаблоны для типовых развёртываний.
services: neko-master: image: foru17/neko-master:latest container_name: neko-master restart: unless-stopped ports: - "3000:3000" # Web UI volumes: - ./data:/app/data # Local MMDB (optional, files should be downloaded into ./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 в реальном времени (рекомендуется с обратным прокси)```yaml
services:
neko-master:
image: foru17/neko-master:latest
container_name: neko-master
restart: unless-stopped
ports:
- "3000:3000" # Web UI
- "3002:3002" # WebSocket (for Nginx / Tunnel forwarding)
volumes:
- ./data:/app/data
# Local MMDB (optional, files should be downloaded into ./geoip)
- ./geoip:/app/data/geoip:ro
environment:
- NODE_ENV=production
- DB_PATH=/app/data/stats.db
- COOKIE_SECRET=${COOKIE_SECRET}
Затем выполните:```bash docker compose up -d
Откройте <http://localhost:3000>, чтобы начать работу.
Если вы используете встроенный Compose-файл репозитория (по умолчанию `3000/3001/3002`), выполните ту же команду.
### Вариант 2: Docker Run```bash
# Generate a fixed cookie secret first (for session persistence)
export COOKIE_SECRET="$(openssl rand -hex 32)"
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |```bash
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
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=<external-ws-port>`.
>
> Режим локального поиска по MMDB (опционально): смонтируйте `-v $(pwd)/geoip:/app/data/geoip:ro`,
> затем переключите источник на Local в `Settings -> Preferences -> IP Lookup Source`.
### Вариант 3: Скрипт в один клик
Автоматически обнаруживает конфликты портов и настраивает всё:```bash
# Using curl
curl -fsSL https://raw.githubusercontent.com/foru17/neko-master/main/setup.sh | bash
# Or using wget
wget -qO- https://raw.githubusercontent.com/foru17/neko-master/main/setup.sh | bash
Скрипт автоматически:
docker-compose.ymlgit clone https://github.com/foru17/neko-master.git cd neko-master
pnpm install
cp apps/collector/.env.example apps/collector/.env
pnpm dev
Откройте <http://localhost:3000> для настройки.
> В режиме source: collector слушает на `3001/3002`, web по умолчанию слушает на `3000`.
> Если вы изменили `API_PORT` (не 3001), задайте `API_URL` соответствующим образом (например `API_URL=http://localhost:4001`), чтобы rewrite `/api` в web указывал на правильный API.
> `apps/collector/.env.local` имеет приоритет над `apps/collector/.env`.
## 🤖 Развёртывание агента
Используйте режим Agent, когда вам нужен один централизованный сервис Neko Master и несколько удалённых устройств (OpenWrt, Linux, macOS), собирающих данные локального шлюза. Агент работает рядом со шлюзом, забирает данные и отправляет их на панель — панель никогда не подключается к шлюзу напрямую.
Поддерживаемые типы шлюзов: **Clash / Mihomo** (WebSocket в реальном времени) и **Surge v5+** (HTTP-опрос).
### Быстрая установка (команда, сгенерированная в UI)
1. В панели управления перейдите в `Settings → Backends`, добавьте backend `Agent`, выберите тип шлюза
2. Нажмите **"View Agent Script"** и скопируйте однострочную команду установки, затем выполните её на целевом хосте:```bash
# Clash / Mihomo gateway example
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 gateway example
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:```bash
nekoagent list # list all instances
nekoagent status # check running state
nekoagent logs # tail live logs
nekoagent restart # restart
nekoagent upgrade # global upgrade (CLI + binary)
> Скрипт автоматически определяет существующую установку — если `neko-agent` уже присутствует, он только добавляет новый экземпляр без повторной загрузки.
> Несколько экземпляров могут работать на одном хосте (разные `NEKO_INSTANCE_NAME`), каждый указывает на свой шлюз.
### Документация агента
- [Обзор](https://github.com/foru17/neko-master/blob/main/docs/agent/overview.en.md): архитектура, сравнение Direct и Agent, модель безопасности
- [Быстрый старт](https://github.com/foru17/neko-master/blob/main/docs/agent/quick-start.en.md): сквозная настройка от UI до запущенного агента
- [Руководство по установке](https://github.com/foru17/neko-master/blob/main/docs/agent/install.en.md): способы установки, автозапуск systemd / launchd
- [Конфигурация](https://github.com/foru17/neko-master/blob/main/docs/agent/config.en.md): полный справочник по флагам и переменным окружения
- [Процесс релиза](https://github.com/foru17/neko-master/blob/main/docs/agent/release.en.md): политика версионирования и совместимости
- [Устранение неполадок](https://github.com/foru17/neko-master/blob/main/docs/agent/troubleshooting.en.md): типичные ошибки и способы их устранения
## 📖 Первое использование

### Подключение Clash / Mihomo
1. Откройте <http://localhost:3000>
2. При первом посещении появится диалог **Gateway Configuration**
3. Заполните данные подключения к вашему сетевому шлюзу (например, OpenClash):
- **Name**: Произвольное имя (например, "Home Gateway")
- **Type**: Выберите `Clash / Mihomo`
- **Host**: Адрес бэкенда шлюза (например, `192.168.101.1`)
- **Port**: Порт бэкенда шлюза (например, `9090`)
- **Token**: Заполните, если настроен Secret, иначе оставьте пустым
4. Нажмите "Add Backend" для сохранения
5. Система автоматически начнёт собирать и анализировать данные о трафике
> 💡 **Как получить адрес шлюза**: Перейдите в панель управления вашего шлюза (например, OpenClash) → Включите "External Control" → Скопируйте адрес API
### Подключение Surge

Neko Master поддерживает подключение к шлюзам Surge для полной визуализации цепочек правил и анализа трафика.
#### 1. Включите Surge HTTP API
Включите HTTP remote API в конфигурации Surge:```ini
[General]
http-api = 127.0.0.1:9091
http-api-tls = false
http-api-web-dashboard = true
Настройте через графический интерфейс Surge:
Settings → General → HTTP Remote API9091Surge192.168.1.1 или 127.0.0.1)9091)💡 Примечание: Surge использует HTTP-опрос для получения данных (в отличие от WebSocket-потока в реальном времени у Clash), с задержкой обновления данных примерно 2 секунды.
Если вы видите ошибку "port already in use", вот решения:
Создайте файл .env в той же директории, что и docker-compose.yml:```env
WEB_EXTERNAL_PORT=8080 # Change Web UI port
API_EXTERNAL_PORT=8081 # Change API port
WS_EXTERNAL_PORT=8082 # Change WebSocket external port (only for direct access)
COOKIE_SECRET=your-long-random-secret # Strongly recommended to keep fixed
Затем перезапустите:```bash
docker compose down
docker compose up -d
Теперь откройте http://localhost:8080
ports:
> Примечание: если вы используете прямой доступ к WS (без обратного прокси) и внешний порт WS не равен `3002`, задайте `WS_EXTERNAL_PORT=<external-ws-port>`.
### Решение 3: Использование скрипта в один клик```bash
curl -fsSL https://raw.githubusercontent.com/foru17/neko-master/main/setup.sh | bash
Скрипт автоматически обнаружит и предложит доступные порты.
runtime-config.API_URL → NEXT_PUBLIC_API_URL → same-origin /api/api: API_URL (по умолчанию http://localhost:3001, применяется в перезаписях Next.js)runtime-config.WS_URL → NEXT_PUBLIC_WS_URL → авто-кандидаты (когда задан runtime-config.WS_PORT, предпочитается прямой порт; иначе сначала пробуется /_cm_ws)runtime-config.WS_PORT (из WS_EXTERNAL_PORT) → NEXT_PUBLIC_WS_PORT → 3002NODE_ENV=production DB_PATH=/app/data/stats.db COOKIE_SECRET=<at least 32-byte random string>
Используйте `openssl rand -hex 32` для генерации `COOKIE_SECRET`.
Дополнительные рекомендации:
1. Смонтируйте постоянное хранилище (например, `./data:/app/data`), чтобы избежать потери данных и секретов.
2. При использовании прямого доступа по WS и если внешний порт WS не равен `3002`, установите `WS_EXTERNAL_PORT` соответствующим образом.
3. Если порт/адрес API изменяются в исходном развёртывании, обновите также `API_URL`.
4. Для локального поиска по MMDB смонтируйте `./geoip:/app/data/geoip:ro` и переключите источник в `Settings -> Preferences -> IP Lookup Source`.
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 включён, система переходит в **режим двойной записи**:```
BatchBuffer.flush()
│
├──→ SQLite (config / metadata, always written)
└──→ ClickHouse (stats traffic data, dual-write)
└── Buffer tables → SummingMergeTree async merge
Источник чтения управляется параметром STATS_QUERY_SOURCE (по умолчанию: sqlite).
Встроенный в репозиторий docker-compose.yml уже включает сервис ClickHouse, ограниченный
profiles: [clickhouse], поэтому по умолчанию он не запускается. Из корня репозитория выполните:```bash
docker compose --profile clickhouse up -d
> Данные ClickHouse сохраняются в `./data/clickhouse`, отдельно от основного каталога данных приложения.
Если вы используете **пользовательский `docker-compose.yml`** (например, сценарий A/B выше), добавьте
блок сервиса ClickHouse вручную:```yaml
services:
neko-master:
# ... your existing config ...
environment:
# append to existing environment section:
- 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
Добавьте в ваш .env (в том же каталоге, что и docker-compose.yml):```env
CH_ENABLED=1
CH_WRITE_ENABLED=1
STATS_QUERY_SOURCE=auto
CH_HOST=clickhouse CH_PORT=8123 CH_DATABASE=neko_master CH_USER=neko CH_PASSWORD=neko_master
Перезапуск:```bash
docker compose --profile clickhouse up -d
Здоровье и откат: После
CH_UNHEALTHY_THRESHOLDпоследовательных сбоев записи система автоматически помечает ClickHouse как нездоровый и возобновляет запись в SQLite — даже приCH_ONLY_MODE=1. Как только ClickHouse восстанавливается, он снова помечается как здоровый, и это логируется.
Обновляетесь с версии только на SQLite? Ваши данные в безопасности. Файл SQLite (
./data/stats.db) полностью сохраняется. Ниже приведён рекомендуемый путь постепенной миграции:
CH_ENABLED=1 CH_WRITE_ENABLED=1 STATS_QUERY_SOURCE=sqlite # Keep reading from SQLite while CH accumulates data
Начните и отслеживайте логи `[ClickHouse Writer]`, чтобы убедиться в успешной записи.
#### Фаза 2: Переключение источника чтения```env
STATS_QUERY_SOURCE=auto # Smart routing: recent data from CH, historical from SQLite
# or
STATS_QUERY_SOURCE=clickhouse # Force all reads to ClickHouse
Чтобы перенести исторические данные статистики из SQLite в ClickHouse:```bash
./scripts/ch-migrate-docker.sh
./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:```env
CH_ONLY_MODE=1
Даже при
CH_ONLY_MODE=1, если ClickHouse становится неработоспособным, система автоматически переключается на запись в SQLite — без потери данных.
Вы всегда можете полностью откатиться:```env CH_ENABLED=0 CH_WRITE_ENABLED=0 CH_ONLY_MODE=0 STATS_QUERY_SOURCE=sqlite
Перезапустите, и всё вернётся в режим чистого SQLite. Исторические данные останутся нетронутыми.
---
## 🌐 Обратный прокси и туннель
Рекомендуемый подход: держите Web и WS в одном домене с маршрутизацией по путям:
`/` → `3000`, `/_cm_ws` → `3002`.
### Стандартный пример Nginx```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
### Стандартный пример Cloudflare Tunnel
`~/.cloudflared/config.yml`:```yaml
tunnel: <your-tunnel-name-or-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
Запустите:```bash cloudflared tunnel --config ~/.cloudflared/config.yml run
Для маршрутов, управляемых через панель Zero Trust (режим токена), настройте те же два маршрута и разместите `/_cm_ws*` выше `/*`.
### Ключевые замечания
1. Не используйте `ws` (без ведущего слеша) в качестве WS-пути; он может сработать слишком широко и вызвать `/_next/static/...` → `426 Upgrade Required`
2. WS-маршрут должен находиться выше catch-all `/*`
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` внутри контейнера. Смонтируйте его на хост, чтобы предотвратить потерю данных:```yaml
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` только для публичных демонстрационных сред (операции записи ограничены).
Пример:```env
COOKIE_SECRET=<at least 32-byte random string>
# FORCE_ACCESS_CONTROL_OFF=false
# SHOWCASE_SITE_MODE=false
Если вы забыли токен, временно установите FORCE_ACCESS_CONTROL_OFF=true, чтобы войти в режим экстренного доступа.
docker-compose.yml: ```yaml
environment:
3000:3000?О: Да. Основные функции всё ещё работают.
Если WS не маршрутизируется, приложение автоматически переключается на HTTP-опрос.
Для полноценного режима реального времени направьте /_cm_ws на 3002.
О: Создайте/обновите .env (в том же каталоге, что и docker-compose.yml):```env
WEB_EXTERNAL_PORT=8080
API_EXTERNAL_PORT=8081
WS_EXTERNAL_PORT=8082
Затем перезапустите:```bash
docker compose down
docker compose up -d
О: Обычно потому, что COOKIE_SECRET не зафиксирован или каталог данных не сохраняется.
COOKIE_SECRET./data:/app/dataО: Создайте ./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.
О: Проверьте:
О: Сначала резервная копия:```bash cp -r ./data ./data-backup-$(date +%Y%m%d)
Восстановить:```bash
docker compose down
cp -r ./data-backup-YYYYMMDD/. ./data/
docker compose up -d
Если вы хотите быстро понять глубину проектирования системы, читайте в следующем порядке:
RealtimeStore и WS-пушПолный индекс документации: docs/README.md
Эта документация охватывает базовое проектирование сбора, агрегации, кэширования, пуш-уведомлений в реальном времени и управления несколькими бэкендами.
Этот проект использует шаблоны GitHub Issue (Bug / Feature / Support).
Пожалуйста, укажите как минимум:
COOKIE_SECRET=***)docker logs, консоль браузера, сетевые ошибки)neko-master/ ├── docker-compose.yml # Docker Compose config ├── Dockerfile # Docker image build ├── setup.sh # One-click setup script ├── docker-start.sh # Docker container startup script ├── start.sh # Source code dev startup script ├── docs/ # Documentation (see docs/README.md) │ ├── README.md # Documentation index (English default) │ ├── README.zh.md # Documentation index (Chinese) │ ├── README.en.md # Documentation index (English mirror) │ ├── architecture.md # System architecture (Chinese) │ ├── architecture.en.md # System architecture (English) │ ├── release-checklist.md │ ├── agent/ # Agent docs (bilingual) │ │ ├── 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/ # Research reports │ └── dev/ # Internal development docs ├── assets/ # Screenshots and icons ├── apps/ │ ├── collector/ # Data collection service (Node.js + WebSocket) │ ├── agent/ # Agent daemon (Go) │ └── web/ # Next.js frontend app └── packages/ └── shared/ # Shared types and utilities
## 🛠️ Технологический стек
- **Frontend**: [Next.js 16](https://nextjs.org/) + [React 19](https://react.dev/) + [TypeScript](https://www.typescriptlang.org/)
- **Стилизация**: [Tailwind CSS](https://tailwindcss.com/) + [shadcn/ui](https://ui.shadcn.com/)
- **Графики**: [Recharts](https://recharts.org/)
- **i18n**: [next-intl](https://next-intl-docs.vercel.app/)
- **Backend**: [Node.js](https://nodejs.org/) + [Fastify](https://www.fastify.io/) + WebSocket
- **База данных**: [SQLite](https://www.sqlite.org/) ([better-sqlite3](https://github.com/WiseLibs/better-sqlite3)) + [ClickHouse](https://clickhouse.com/) (опционально)
- **Сборка**: [pnpm](https://pnpm.io/) + [Turborepo](https://turbo.build/)
## 🤝 Участие в разработке
Мы приветствуем ваш вклад!
- 🐛 [Сообщить об ошибке](https://github.com/foru17/neko-master/issues/new)
- 💡 [Предложить функцию](https://github.com/foru17/neko-master/issues/new)
- 🔧 [Внести код](https://github.com/foru17/neko-master/pulls)
Перед открытием PR прочитайте [CONTRIBUTING.md](https://github.com/foru17/neko-master/blob/main/CONTRIBUTING.md) (рабочий процесс, проверки, требования к i18n/тёмной теме).
**Разрабатываете с помощью ИИ-инструмента?** (Claude Code, Copilot, Cursor, Codex, ...) Укажите ему на [AGENTS.md](https://github.com/foru17/neko-master/blob/main/AGENTS.md) — соглашения, ключевые контракты и карту проекта — а также на руководства по рабочим процессам для конкретных задач в [`.claude/skills/`](https://github.com/foru17/neko-master/blob/main/.claude/skills). Claude Code подхватывает оба автоматически.
## 📄 Лицензия
[MIT](https://github.com/foru17/neko-master/blob/main/LICENSE) © [foru17](https://github.com/foru17)
---
## ⭐ История звёзд
[](https://www.star-history.com/#foru17/neko-master&type=date&legend=top-left)
---
<p align="center">
<sub>Сделано с ❤️ <a href="https://github.com/foru17">@foru17</a></sub><br>
<sub>Если этот проект вам помог, пожалуйста, поставьте ему ⭐</sub>
</p>
|
|
|
|
| Возможность | Описание |
|---|
| 📊 Мониторинг в реальном времени | Сбор данных в реальном времени через WebSocket с миллисекундной задержкой |
| 📈 Анализ трендов | Многомерные тренды трафика: 30 мин / 1 ч / 24 ч |
| 🌐 Анализ доменов | Просмотр трафика, связанных IP-адресов и количества соединений по домену |
| 🗺️ Анализ IP | Отображение ASN, геолокации и связанных доменов |
| 🚀 Статистика прокси | Распределение трафика и количество соединений по прокси-узлу |
| 📱 Поддержка PWA | Установка как настольное приложение для нативного опыта |
| 🌙 Тёмный режим | Поддержка светлой / тёмной / системной темы |
| 🌍 Поддержка i18n | Бесшовное переключение между английским и китайским |
| 🔄 Мультибэкенд | Одновременный мониторинг нескольких экземпляров OpenClash |
| Порт | Назначение | Требуется извне | Описание |
|---|
| 3000 | Web UI | ✅ | Точка входа фронтенда |
| 3001 | API | Опционально | Фронтенд по умолчанию использует same-origin /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 не является same-origin /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 | Цель перезаписи /api в Next.js (в основном для сборок из исходников/нестандартных) | Адрес прослушивания API изменён |
COOKIE_SECRET | генерируется автоматически | Секрет подписи cookie; если не зафиксирован, сессии могут сбрасываться после перезапуска, когда каталог данных не сохраняется | Настоятельно рекомендуется в продакшене |
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) |
NEXT_PUBLIC_WS_URL обычно не нужен, если только вы не используете нестандартный WS-путь/домен| Переменная | По умолчанию | Описание |
|---|
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) |