Update Docker documentation and README for SQLite storage and environment variables
Publish Docker image / build-and-push (push) Successful in 2m13s

- Enhanced Docker.md with detailed instructions on building and running Docker images, including environment variable requirements and tag usage.
- Updated README.md to reflect the current architecture using SQLite for data storage and clarified environment variable settings for backend and frontend operations.
- Removed references to AWS S3, emphasizing local storage for MikroTik backups and SQLite database management.

Made-with: Cursor
This commit is contained in:
2026-04-26 01:45:43 +07:00
parent 50f9c91843
commit cf3437c70c
2 changed files with 204 additions and 474 deletions
+76 -294
View File
@@ -1,347 +1,129 @@
# Router Lists UI
Полноценный UI/Backend для управления списками BGP (домены, IP-диапазоны, ASNs), фильтрами и конфигурациями MikroTik на базе S3 (Yandex Object Storage). Интерфейс построен на Tabler, frontend — Vite + React, backend — Express.
UI/Backend для управления BGP-списками, фильтрами и конфигурациями MikroTik.
Текущая модель хранения: **SQLite + локальная файловая система** (для `.rsc` backup MikroTik).
## Актуальная архитектура хранения
- Основные данные и объекты приложения хранятся в SQLite (через `better-sqlite3`).
- MikroTik backup-файлы (`.rsc`) хранятся в локальной ФС в каталоге `MIKROTIK_BACKUP_DIR`.
- AWS SDK/S3 в runtime не используются.
- Часть имен API/сервисов (`s3*`) сохранена для обратной совместимости, но фактический backend storage — SQLite.
## Быстрый старт
### Требования
- Node.js 18+
- S3-совместимое хранилище (Yandex Object Storage)
- Доступы AWS: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `S3_BUCKET_NAME`, `AWS_REGION`
- npm
### Запуск backend
```powershell
cd backend
npm i
npm install
# создайте .env и заполните (пример ниже)
npm start
```
Сервис поднимется на `http://localhost:3001`.
Backend поднимется на `http://localhost:3001`.
### Запуск frontend
```bash
```powershell
cd frontend
npm i
npm install
npm run dev
```
Frontend доступен на `http://localhost:5173` (по умолчанию). Production-сборка: `npm run build`.
## Главные особенности
- Единая UX/UI библиотека Tabler, адаптивные панели действий и навигация.
- Онлайн-обновление (WebSocket) BGP c потоковым логом и фоновое обновление (HTTP POST) из UI.
- Блокировки (soft-lock) ресурсов с TTL, чтобы избежать гонок при одновременном редактировании.
- Версионирование данных (история/откат), если включено версии в бакете.
- Генерация конфигурации MikroTik из фильтров (`/api/filters/generate-config`) и экспорт в S3.
- Метрики Prometheus: `/metrics`, health/ready: `/health`, `/ready`.
Frontend доступен на `http://localhost:5173`.
### Важные переменные окружения
- `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, `S3_BUCKET_NAME` — доступ к Object Storage
- `ENCRYPTION_KEY` — ключ шифрования (64 hex символа) для IPSec и MikroTik паролей
- `CORS_ORIGINS` — список разрешённых Origin через запятую (если пусто — разрешены все)
- `LOG_LEVEL` — уровень логов pino (`info` по умолчанию)
- `PORT` — порт backend (по умолчанию 3001)
- `BGP_BACKGROUND_URL` — адрес фонового обновления BGP, например:
- `http://77.232.38.173:8080/api/update_bgp/background?api_key=...`
- Используется эндпоинтом прокси `POST /api/update-bgp/background` для обхода CORS
## Важные переменные окружения
- `SQLITE_PATH` — путь к файлу SQLite (по умолчанию `backend/data/router-lists.db`).
- `MIKROTIK_BACKUP_DIR` — каталог для локальных `.rsc` backup-файлов MikroTik.
- `ENCRYPTION_KEY` — 64 hex-символа для шифрования секретов (IPSec/MikroTik).
- `EVOBGP_API_URL`, `EVOBGP_API_TOKEN` — если используете интеграцию EvoBGP.
- `CORS_ORIGINS`, `LOG_LEVEL`, `PORT` — эксплуатационные настройки сервиса.
- `BGP_BACKGROUND_URL` — URL фонового обновления BGP для прокси-эндпоинта `POST /api/update-bgp/background`.
Пример `.env`:
```dotenv
PORT=3001
LOG_LEVEL=info
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=ru-central1
S3_BUCKET_NAME=...
SQLITE_PATH=./data/router-lists.db
MIKROTIK_BACKUP_DIR=./data/backups/mikrotik
ENCRYPTION_KEY=<64-hex>
CORS_ORIGINS=http://localhost:5173
BGP_BACKGROUND_URL=http://77.232.38.173:8080/api/update_bgp/background?api_key=denozord2502
BGP_BACKGROUND_URL=http://77.232.38.173:8080/api/update_bgp/background?api_key=...
```
## API (backend)
Все ответы об ошибке имеют единый формат:
Формат ошибок:
```json
{ "code": "E_*", "message": "...", "details": {}, "requestId": "..." }
```
Успешные POST/PUT возвращают:
Формат успешных `POST/PUT`:
```json
{ "ok": true, "etag": "...", "lastModified": "ISO", "contentLength": 123 }
```
И всегда выставляют заголовки `ETag`, `Last-Modified`, `Content-Length-Source` (если есть). GET поддерживают `countOnly=true` там, где это логично.
### Данные
- GET `/api/domains-new` — список доменов `{ domain, community }`
- `?q=`, `?offset=`, `?limit=`, `?countOnly=true`, `?format=std`
- POST `/api/domains-new``{ domains: [{domain, community}], etag }`
### Примечание по legacy-терминам
- GET `/api/ip-ranges` — список `[{ ipRange, community }]`
- POST `/api/ip-ranges``{ ipRanges: [{ipRange, community}], etag }`
- `GET /api/s3/last-modified` и функции вида `readS3*`/`writeS3*` — это **legacy-названия**.
- Фактически эти операции работают с SQLite-backed хранилищем.
- GET `/api/asns` — список `[{ domain, type }]` (domain = AS, type = community)
- POST `/api/asns``{ domains: [{domain, type}], etag }`
### Основные эндпоинты
- GET `/api/communities` — справочник community (JSON)
- POST `/api/communities` `{ communities: [...] }` (валидация уникальности value)
- Данные: `/api/domains-new`, `/api/ip-ranges`, `/api/asns`, `/api/communities`
- Фильтры/конфиги: `/api/filters`, `/api/server-configs`, `/api/server-filters`
- MikroTik: `/api/mikrotik/generate`, `/api/mikrotik/generate-interfaces`, `/api/mikrotik/generate-recursive-routes`, `/api/mikrotik/test-connection`, `/api/mikrotik/apply`
- Прочее: `/api/servers`, `/api/billing`, `/api/auto-urls`, `/api/servers/availability`, `/api/locks/:resource`, `/api/history/:resource`
### Фильтры и конфигурации
- GET `/api/filters` / POST `/api/filters` — фильтры для всех серверов.
- GET `/api/filters/generate-config?format=text|json` — сгенерировать конфиг MikroTik из `filters.json`.
- POST `/api/filters/export-config` — сохранить сгенерированный конфиг в S3 (`mikrotik-frouting-config.txt`).
## Docker
- GET `/api/server-configs` / POST `/api/server-configs` — список серверов (id, name, ...).
- GET `/api/server-configs/:serverId` / POST `/api/server-configs/:serverId` — конфиг конкретного сервера.
- DELETE `/api/server-configs/:serverId` — удалить конфиг.
- DELETE `/api/server-configs/:serverId/complete` — удалить конфиг и фильтры.
Полная инструкция: [DOCKER.md](DOCKER.md).
- GET `/api/server-filters/:serverId` — фильтры сервера.
- POST `/api/server-filters/:serverId` — сохранить фильтры сервера.
- POST `/api/server-filters/generate-config` — сгенерировать конфиг MikroTik на лету из переданных `{ filters, format?: 'text'|'json' }`.
- POST `/api/mikrotik/generate` — сгенерировать конфиг интерфейсов и маршрутов. Body: `{ format?: 'text'|'json', type?: 'interfaces'|'recursive'|'all', serverId?: string, config?, servers? }`. Возвращает `{ blocks }` — массив блоков с полем `code` (text) или `operations` (json).
- GET `/api/mikrotik/generate-interfaces?format=text|json&serverId=` — только интерфейсы.
- GET `/api/mikrotik/generate-recursive-routes?format=text|json&serverId=` — только рекурсивные маршруты.
- POST `/api/mikrotik/test-connection` — проверить соединение с MikroTik. Body: `{ serverId }` или `{ host, port?, user?, password }`.
- POST `/api/mikrotik/apply` — применить конфигурацию на MikroTik по API. Body: `{ serverId, type?: 'interfaces'|'recursive'|'all', dryRun?: boolean }`. Только для jumphost.
Критично для production:
### Прочее
- GET `/api/servers` / POST `/api/servers` — список серверов.
- GET `/api/billing` / POST `/api/billing` — биллинг (ноды, статусы и т.п.).
- GET `/api/auto-urls` / POST `/api/auto-urls` — список авто-URL.
- POST `/api/auto-urls/process` — обработать авто-URL и добавить IP в `bgp_data/ips.txt`.
- GET `/api/servers/availability?ttlSeconds=60` — быстрый TCP‑чек доступности нод.
- GET `/api/s3/last-modified` — метаданные S3 (etag/lastModified/contentLength) по ключевым файлам.
- POST `/api/update-bgp/background` — прокси к фоновой задаче обновления BGP. Требует `BGP_BACKGROUND_URL` в `.env`.
- Locks: GET `/api/locks/:resource`, POST `/api/locks/:resource`, DELETE `/api/locks/:resource` (опциональные soft-locks для редактирования; доступ к S3 и долгие операции вроде speed-test блокировок не используют).
- History: GET `/api/history/:resource`, POST `/api/history/:resource/rollback`.
- Обязательно смонтировать volume для пути с `SQLITE_PATH`.
- Обязательно смонтировать volume для `MIKROTIK_BACKUP_DIR`, иначе `.rsc` backup-файлы потеряются при пересоздании контейнера.
- Использовать стабильный `ENCRYPTION_KEY` между перезапусками.
## Frontend
- Vite + React, Tabler CSS/JS (`@tabler/core`).
- Общий компонент `PageHeaderActions` — единый toolbar на страницах данных.
- Модалка `WsUpdateModal` — поток логов online-обновления (ws).
- Доступность: роли, подписи, фокус-кольца, hot-path без мыши.
Пример запуска:
### Скрипты
```bash
npm run dev # dev-сервер
npm run build # продакшн сборка
```
## Структура репозитория
```
backend/ # Express API
frontend/ # Vite React UI
```
## Безопасность и эксплуатация
- Helmet, RateLimit, CORS, отключён слабый etag на JSON.
- Prometheus метрики по умолчанию.
- Для истории версий включите versioning в бакете S3.
## Лицензия
MIT
# 📂 RouterOS Manager
Веб-интерфейс для удобного управления файлами в S3-совместимом хранилище Yandex Cloud. Приложение позволяет в реальном времени просматривать, добавлять, редактировать, удалять и массово изменять записи в следующих файлах:
- **domains.txt** - список доменов и их шлюзов
- **asns.txt** - список AS номеров и их шлюзов
- **servers.json** - список серверов с расширенной информацией (IP, DNS, страна, провайдер, тип туннеля)
## ✨ Возможности
- **Три режима работы:** Управление списками доменов, AS-номеров и серверов через вкладки.
- **CRUD операции:** Полный набор действий: создание, чтение, обновление и удаление записей.
- **Поиск в реальном времени:** Мгновенная фильтрация списков по мере ввода.
- **Массовая замена:** Быстрое обновление шлюзов для сотен записей в один клик.
- **Сохранение в S3:** Все изменения сохраняются непосредственно в файлах в бакете Yandex Cloud.
- **Docker-контейнеризация:** Готовый `Dockerfile` для сборки и запуска приложения в изолированном окружении.
- **CI/CD с Gitea Actions:** Автоматическая сборка и публикация Docker-образа в Gitea Registry при пуше в `main`.
- **Современный интерфейс:** Полностью интегрированный Tabler UI с официальными компонентами.
## 🛠️ Технологический стек
| Область | Технология |
|--------------|-----------------------------------------------------------------------------------------------------------|
| **Фронтенд** | [**React**](https://reactjs.org/) + [**Vite**](https://vitejs.dev/) |
| | [**@tabler/core**](https://tabler.io/) (UI-компоненты для Tabler версии) |
| | [**Tabler Icons**](https://tabler-icons.io/) (иконки) |
| | [**Axios**](https://axios-http.com/) (HTTP-клиент) |
| **Бэкенд** | [**Node.js**](https://nodejs.org/) + [**Express**](https://expressjs.com/) |
| | [**AWS SDK for JS**](https://aws.amazon.com/sdk-for-javascript/) (для работы с Yandex Cloud S3) |
| **CI/CD** | [**Docker**](https://www.docker.com/), [**Gitea Actions**](https://gitea.com/blog/2022/10/01/gitea-actions/) |
## 🏗️ Архитектура
Приложение состоит из двух основных частей: фронтенд на React и бэкенд на Node.js/Express, которые взаимодействуют через REST API.
```mermaid
graph TD
subgraph Browser
A[React Frontend]
end
subgraph Server
B(Node.js/Express API)
end
subgraph Yandex Cloud
C{S3 Bucket}
D1[domains.txt]
D2[asns.txt]
D3[servers.json]
end
A -- HTTP Requests --> B
B -- AWS SDK --> C
C --- D1
C --- D2
```
## 🚀 Установка и запуск
### Предварительные требования
- [Node.js](https://nodejs.org/) (v20.x или выше)
- [npm](https://www.npmjs.com/) или [yarn](https://yarnpkg.com/)
- Доступ к бакету Yandex Cloud S3 и сервисный аккаунт с правами на чтение и запись.
### 1. Настройка бэкенда
1. Перейдите в директорию `backend`:
```bash
cd backend
```
2. Создайте файл `.env` на основе примера `.env.example`. Заполните его вашими учетными данными от Yandex Cloud S3:
```env
# .env
S3_ACCESS_KEY_ID=ВАШ_КЛЮЧ_ДОСТУПА
S3_SECRET_ACCESS_KEY=ВАШ_СЕКРЕТНЫЙ_КЛЮЧ
S3_BUCKET_NAME=ИМЯ_ВАШЕГО_БАКЕТА
```
3. Установите зависимости:
```bash
npm install
```
### 2. Настройка фронтенда
1. Перейдите в директорию `frontend`:
```bash
cd ../frontend
```
2. Установите зависимости:
```bash
npm install
```
### 3. Запуск приложения
1. **Запустите бэкенд-сервер.** В директории `backend` выполните:
```bash
npm start
```
Сервер запустится на `http://localhost:3001`.
2. **Запустите фронтенд.** В новой вкладке терминала, в директории `frontend`, выполните:
```bash
npm run dev
```
Приложение будет доступно по адресу `http://localhost:5173` и будет автоматически проксировать API-запросы на бэкенд.
## 🐳 Docker
Приложение полностью готово к запуску в Docker с двумя вариантами интерфейса.
### Доступные образы
#### Основная версия (main branch)
```bash
git.shts.su/[repository]:latest
```
#### Tabler версия (tabler branch)
```bash
git.shts.su/[repository]:tabler
```
### Быстрый запуск
#### Основная версия
```bash
docker run -d \
--name s3-lists-manager \
-p 3001:3001 \
--env-file ./backend/.env \
```powershell
docker run -d `
--name router-lists-ui `
-p 3001:3001 `
--env-file ./backend/.env `
-e SQLITE_PATH=/data/router-lists.db `
-e MIKROTIK_BACKUP_DIR=/data/backups/mikrotik `
-v router-lists-data:/data `
git.shts.su/[repository]:latest
```
#### Tabler версия
```bash
docker run -d \
--name s3-lists-manager-tabler \
-p 3002:3001 \
--env-file ./backend/.env \
git.shts.su/[repository]:tabler
## Чек-лист проверки соответствия (S3 -> SQLite)
1. В `backend/package.json` нет зависимостей AWS SDK.
2. Приложение стартует с `SQLITE_PATH` и создает/использует файл БД.
3. CRUD по основным данным (`/api/domains-new`, `/api/ip-ranges`, `/api/asns`) работает после перезапуска контейнера с тем же volume.
4. Созданный MikroTik backup появляется как локальный `.rsc` файл в каталоге `MIKROTIK_BACKUP_DIR`.
5. После перезапуска контейнера с тем же volume backup-файл остается доступным.
6. `GET /api/s3/last-modified` возвращает метаданные, но интерпретируется как legacy endpoint поверх SQLite.
## Структура репозитория
```text
backend/ Express API
frontend/ Vite + React UI
```
### Локальная сборка
## Лицензия
Для сборки образа выполните команду в корневой директории проекта:
```bash
docker build -t s3-lists-manager .
```
### Запуск контейнера
Для запуска контейнера необходимо передать переменные окружения. Это можно сделать с помощью флага `-e` или через `--env-file`.
```bash
docker run --rm -p 3001:3001 --env-file ./backend/.env s3-lists-manager
```
После этого приложение будет доступно по адресу `http://localhost:3001`.
### Docker Compose
Создайте файл `docker-compose.yml`:
```yaml
version: '3.8'
services:
s3-lists-manager:
image: git.shts.su/[repository]:latest
container_name: s3-lists-manager
ports:
- "3001:3001"
restart: unless-stopped
env_file:
- ./backend/.env
s3-lists-manager-tabler:
image: git.shts.su/[repository]:tabler
container_name: s3-lists-manager-tabler
ports:
- "3002:3001"
restart: unless-stopped
env_file:
- ./backend/.env
```
Запуск:
```bash
docker-compose up -d
```
Подробная документация по Docker образам доступна в файле [DOCKER.md](DOCKER.md).
## ⚙️ API Endpoints
| Метод | Путь | Описание |
|--------|---------------|----------------------------------|
| `GET` | `/api/domains`| Получить список всех доменов. |
| `POST` | `/api/domains`| Сохранить изменения в `domains.txt`. |
| `GET` | `/api/asns` | Получить список всех AS. |
| `POST` | `/api/asns` | Сохранить изменения в `asns.txt`. |
| `GET` | `/api/servers`| Получить список всех серверов. |
| `POST` | `/api/servers`| Сохранить изменения в `servers.json`. |
MIT