First commit
This commit is contained in:
@@ -0,0 +1,766 @@
|
||||
# TIP — Threat Intelligence Platform
|
||||
|
||||
> Plataforma centralizada de monitoreo e inteligencia de amenazas sobre Telegram.
|
||||
|
||||
---
|
||||
|
||||
## Tabla de Contenidos
|
||||
|
||||
1. [Descripción General](#descripción-general)
|
||||
2. [Arquitectura del Sistema](#arquitectura-del-sistema)
|
||||
3. [Microservicios](#microservicios)
|
||||
4. [Flujo del Alimentador](#flujo-del-alimentador)
|
||||
5. [Requisitos Previos](#requisitos-previos)
|
||||
6. [Instalación y Configuración](#instalación-y-configuración)
|
||||
7. [Gestión de Backups](#gestión-de-backups)
|
||||
8. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## Descripción General
|
||||
|
||||
**TIP (Threat Intelligence Platform)** es una plataforma de monitoreo en tiempo real diseñada para capturar, analizar y gestionar mensajes de grupos y canales de Telegram. Mediante reglas configurables basadas en expresiones regulares, el sistema detecta patrones sospechosos, genera alertas automáticas y mantiene un registro auditable de todas las operaciones.
|
||||
|
||||
### Características Principales
|
||||
|
||||
- **Monitoreo en tiempo real**: Captura automática de mensajes desde grupos y canales de Telegram
|
||||
- **Detección basada en reglas**: Expresiones regulares configurables para identificar patrones de interés
|
||||
- **Gestión de alertas**: Ciclo de vida completo — Pendiente → En Curso → Resuelta — con historial de notas
|
||||
- **Auditoría integral**: Registro de IP, usuario y timestamp en cada operación del sistema
|
||||
- **Exportación de reportes**: Generación de PDFs con trazabilidad completa al cerrar una alerta
|
||||
- **Estadísticas en tiempo real**: Dashboards con métricas, heatmaps y análisis de actividad
|
||||
- **Control de acceso por roles**: Administradores y Operadores con permisos diferenciados
|
||||
- **Sistema de backups**: Exportación e importación de bases de datos, configuración y sesiones de Telegram
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura del Sistema
|
||||
|
||||
TIP está compuesto por **4 microservicios** y **2 bases de datos** independientes, orquestados con Docker Compose y expuestos a través de un proxy NGINX con SSL.
|
||||
|
||||
```
|
||||
╔══════════════════════════════════════════════════════════════════════════════════╗
|
||||
║ INTERNET ║
|
||||
╚══════════════════════════════════════════════╦═══════════════════════════════════╝
|
||||
║ HTTPS :443 / HTTP :80
|
||||
╔════════════════╩════════════════╗
|
||||
║ NGINX Proxy ║
|
||||
║ Terminación SSL · Routing ║
|
||||
╚══════╦══════════╦═══════╦═══════╝
|
||||
║ ║ ║
|
||||
╔══════════════╝ ╔═════╝ ╔══=╩═════════════╗
|
||||
▼ ▼ ▼ ▼
|
||||
╔════════════════╗ ╔══════════════╗ ╔══════════════╗ ╔═══════════════╗
|
||||
║ Frontend ║ ║ API Feeder ║ ║ API Users ║ ║Backup Service ║
|
||||
║ Streamlit ║ ║ FastAPI ║ ║ FastAPI ║ ║ FastAPI ║
|
||||
║ Python 3.11 ║ ║ Python 3.11 ║ ║ Python 3.11 ║ ║ Python 3.11 ║
|
||||
║ :8501 ║ ║ :8000 ║ ║ :8090 ║ ║ :8099 ║
|
||||
╚═══════╦════════╝ ╚══════╦═══════╝ ╚══════╦═══════╝ ╚═══════╦═══════╝
|
||||
║ ║ ║ ║
|
||||
HTTP ║ ╔════════╩══════╗ ║ ║
|
||||
REST ╠ ║ Telegram ║ ║ ║
|
||||
║ ║ API (MTProto)║ ║ ║
|
||||
║ ╚═══════════════╝ ║ ║
|
||||
║ ║ ║ ╔═══════╩══════╗
|
||||
║ ╔════════╩═══════╗ ╔═══════╩══════╗ ║ /config/... ║
|
||||
╚═════════║ MariaDB :3306 ║ ║MariaDB :3307 ║ ║ (volumes) ║
|
||||
║ DB: feeder ║ ║ DB: users ║ ╚══════════════╝
|
||||
╚════════════════╝ ╚══════════════╝
|
||||
```
|
||||
|
||||
### Comunicación entre Servicios
|
||||
|
||||
| Origen | Destino | Protocolo | Propósito |
|
||||
|--------|---------|-----------|-----------|
|
||||
| Frontend | API Feeder | HTTP/REST | Alertas, mensajes, reglas, grupos, estadísticas |
|
||||
| Frontend | API Users | HTTP/REST | Login, gestión de usuarios |
|
||||
| Frontend | Backup Service | HTTP/REST | Estado y descarga de backups |
|
||||
| API Feeder | Telegram | MTProto (Telethon) | Captura de mensajes y adjuntos |
|
||||
| API Feeder | API Feeder (interno) | HTTP/REST | Persistencia de mensajes vía `api_implementations.py` |
|
||||
| Backup Service | MariaDB Feeder | TCP/MySQL | mysqldump para backup |
|
||||
| Backup Service | MariaDB Users | TCP/MySQL | mysqldump para backup |
|
||||
| NGINX | Todos los servicios | HTTP (reverse proxy) | Enrutamiento y terminación SSL |
|
||||
|
||||
### Seguridad
|
||||
|
||||
- **JWT compartido**: Todos los microservicios validan tokens con la misma `SECRET_KEY`
|
||||
- **Roles**: `admin` y `operator` con controles en cada endpoint
|
||||
- **Rate limiting**: Registro público limitado a 5 peticiones/minuto (SlowAPI)
|
||||
- **HTTPS**: Terminación SSL en NGINX con soporte TLSv1.2 y TLSv1.3
|
||||
|
||||
---
|
||||
|
||||
## Microservicios
|
||||
|
||||
### 1. Frontend — Streamlit
|
||||
|
||||
**Propósito**: Interfaz de usuario para el monitoreo y gestión de la plataforma.
|
||||
|
||||
**Lenguaje**: Python **3.11**
|
||||
|
||||
**Ubicación**: `/frontend`
|
||||
|
||||
| Librería | Versión | Propósito |
|
||||
|----------|---------|-----------|
|
||||
| Streamlit | ≥ 1.28.0 | Framework web reactivo |
|
||||
| Requests | ≥ 2.31.0 | Cliente HTTP hacia las APIs |
|
||||
| Pandas | ≥ 2.0.0 | Manipulación de datos en dashboards |
|
||||
| ReportLab | ≥ 3.6.0 | Generación de reportes PDF |
|
||||
| Matplotlib | ≥ 3.7.0 | Gráficos estáticos auxiliares |
|
||||
|
||||
**Funcionalidades**:
|
||||
- Panel de inicio con métricas y estado del alimentador
|
||||
- Gestión de alertas con notas, cambio de estado y exportación PDF
|
||||
- Búsqueda avanzada de mensajes con filtros por texto, grupo, remitente y fecha
|
||||
- Descarga de adjuntos directamente desde Telegram
|
||||
- Exploración de remitentes con historial de mensajes
|
||||
- Estadísticas con gráficos de línea, barras, heatmaps y ranking de senders
|
||||
- Panel de administración para gestión de usuarios, auditoría y backups
|
||||
|
||||
---
|
||||
|
||||
### 2. API Feeder — FastAPI
|
||||
|
||||
**Propósito**: Backend principal. Captura mensajes de Telegram, evalúa reglas y sirve los datos al Frontend.
|
||||
|
||||
**Lenguaje**: Python **3.11**
|
||||
|
||||
**Ubicación**: `/app`
|
||||
|
||||
| Librería | Versión | Propósito |
|
||||
|----------|---------|-----------|
|
||||
| FastAPI | 0.104.1 | Framework REST asíncrono |
|
||||
| Uvicorn | 0.24.0 | Servidor ASGI |
|
||||
| Telethon | 1.28.5 | Cliente MTProto para Telegram |
|
||||
| SQLAlchemy | 2.0.23 | ORM |
|
||||
| PyMySQL | 1.1.0 | Driver MySQL/MariaDB |
|
||||
| Pydantic | 2.11.9 | Validación y serialización |
|
||||
| Alembic | 1.11.1 | Migraciones de base de datos |
|
||||
| python-jose | 3.3.0 | Generación y validación de JWT |
|
||||
| python-dotenv | 1.0.0 | Gestión de variables de entorno |
|
||||
| httpx | latest | Cliente HTTP asíncrono |
|
||||
| aiofiles | 23.2.1 | I/O asíncrono de archivos |
|
||||
| Requests | 2.32.5 | Cliente HTTP síncrono (integraciones internas) |
|
||||
|
||||
**Endpoints principales**:
|
||||
|
||||
| Grupo | Método | Ruta | Descripción |
|
||||
|-------|--------|------|-------------|
|
||||
| Messages | POST | `/messages/` | Crear mensaje + evaluar reglas |
|
||||
| Messages | GET | `/messages/search/` | Búsqueda con filtros |
|
||||
| Alerts | GET | `/alerts/` | Listar con filtros |
|
||||
| Alerts | POST | `/alerts/{id}/resolve` | Cerrar alerta |
|
||||
| Alerts | POST | `/alerts/{id}/in-progress` | Marcar en curso |
|
||||
| Rules | POST | `/rules/` | Crear regla (con apply_to_history) |
|
||||
| Groups | PATCH | `/groups/{id}/update-position` | Actualizar cursor de mensajes |
|
||||
| Attachments | GET | `/attachments/{id}/download` | Descargar adjunto desde Telegram |
|
||||
| Audit | GET | `/audit/` | Consultar logs de auditoría |
|
||||
| Stats | GET | `/stats/` | Métricas y estadísticas agregadas |
|
||||
| Manage | POST | `/manage/` | Agregar grupo/canal de Telegram |
|
||||
| Manage | GET | `/manage/init-session` | Iniciar autenticación Telegram |
|
||||
| Manage | POST | `/manage/verify-code` | Verificar código de autenticación |
|
||||
|
||||
---
|
||||
|
||||
### 3. API Users — FastAPI
|
||||
|
||||
**Propósito**: Gestión de usuarios, autenticación y auditoría de cambios de permisos.
|
||||
|
||||
**Lenguaje**: Python **3.11**
|
||||
|
||||
**Ubicación**: `/usuarios`
|
||||
|
||||
| Librería | Versión | Propósito |
|
||||
|----------|---------|-----------|
|
||||
| FastAPI | 0.104.1 | Framework REST |
|
||||
| Uvicorn | 0.24.0 | Servidor ASGI |
|
||||
| SQLAlchemy | 2.0.23 | ORM |
|
||||
| PyMySQL | 1.1.2 | Driver MySQL/MariaDB |
|
||||
| Pydantic | 2.5.0 | Validación de datos |
|
||||
| passlib[bcrypt] | 1.7.4 | Hash seguro de contraseñas |
|
||||
| bcrypt | 4.0.1 | Backend de hashing |
|
||||
| python-jose | 3.3.0 | JWT |
|
||||
| SlowAPI | latest | Rate limiting en endpoints públicos |
|
||||
| python-multipart | 0.0.6 | Formularios multipart |
|
||||
|
||||
**Endpoints principales**:
|
||||
|
||||
| Método | Ruta | Descripción |
|
||||
|--------|------|-------------|
|
||||
| POST | `/api/v1/login` | Autenticación — devuelve JWT |
|
||||
| GET | `/api/v1/users/` | Listar usuarios (admin) |
|
||||
| GET | `/api/v1/users/pending` | Usuarios pendientes de aprobación |
|
||||
| POST | `/api/v1/users/common` | Registro público (rate-limited) |
|
||||
| PUT | `/api/v1/users/{id}` | Actualizar datos |
|
||||
| PATCH | `/api/v1/users/{id}/role` | Cambiar rol |
|
||||
| POST | `/api/v1/users/{id}/activate` | Activar usuario |
|
||||
| GET | `/api/v1/logs/users` | Historial de modificaciones |
|
||||
|
||||
---
|
||||
|
||||
### 4. Backup Service — FastAPI
|
||||
|
||||
**Propósito**: Centraliza la generación y verificación de backups del sistema completo.
|
||||
|
||||
**Lenguaje**: Python **3.11**
|
||||
|
||||
**Ubicación**: `/backup_service`
|
||||
|
||||
| Librería | Versión | Propósito |
|
||||
|----------|---------|-----------|
|
||||
| FastAPI | 0.104.1 | Framework REST |
|
||||
| Uvicorn | 0.24.0 | Servidor ASGI |
|
||||
| python-jose | 3.3.0 | Validación JWT (mismo SECRET_KEY) |
|
||||
| mysqldump / mysqladmin | sistema | Dump de bases de datos (instalados en Dockerfile) |
|
||||
|
||||
**Endpoints**:
|
||||
|
||||
| Método | Ruta | Descripción |
|
||||
|--------|------|-------------|
|
||||
| GET | `/backup` | Genera y descarga ZIP con los componentes seleccionados |
|
||||
| GET | `/backup/status` | Estado de cada componente sin generar backup |
|
||||
| GET | `/health` | Verificación de salud del servicio |
|
||||
|
||||
**Componentes exportables**:
|
||||
- `databases/` — mysqldump de las bases de datos Feeder y Users
|
||||
- `config/` — nginx.conf y docker-compose.yml
|
||||
- `ssl/` — Certificados SSL
|
||||
- `telegram_sessions/` — Archivos `.session` de autenticación de Telegram
|
||||
|
||||
---
|
||||
|
||||
## Flujo del Alimentador
|
||||
|
||||
El **Feeder** (alimentador) es el núcleo de captura del sistema. Se ejecuta en un hilo de fondo independiente al inicio de la API y opera en ciclos continuos.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ INICIO DE LA API (startup_event) │
|
||||
│ └─► Lanza run_sync_scraper() en thread separado via asyncio.to_thread │
|
||||
└──────────────────────────────┬──────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────────────┐
|
||||
│ CICLO PRINCIPAL (run_sync_scraper) │
|
||||
│ │
|
||||
│ ┌─ INICIO DEL CICLO ──────────────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ 1. TelegramChatSingleton.get_scraper() │ │
|
||||
│ │ └─► ¿Existe instancia singleton? │ │
|
||||
│ │ ├─ NO → TelegramClientManager.connect() │ │
|
||||
│ │ │ └─► Busca session_*.session en /telegram_sessions│ │
|
||||
│ │ │ Autentica con Telethon (MTProto) │ │
|
||||
│ │ └─ SÍ → Reutiliza cliente existente │ │
|
||||
│ │ │ │
|
||||
│ │ 2. scraper.add_chats() │ │
|
||||
│ │ └─► GET /groups/ → obtiene todos los grupos activos │ │
|
||||
│ │ Para cada grupo: │ │
|
||||
│ │ └─► Consulta Telegram con get_entity(id) │ │
|
||||
│ │ Actualiza nombre, tipo y descripción en la DB │ │
|
||||
│ │ │ │
|
||||
│ │ 3. scraper.feeder_loop() │ │
|
||||
│ │ └─► Para cada grupo en la DB: │ │
|
||||
│ │ │ │
|
||||
│ │ a) set_chat_id(group_id) │ │
|
||||
│ │ └─► Configura el canal objetivo en Telethon │ │
|
||||
│ │ │ │
|
||||
│ │ b) self.first_id = group.message_position │ │
|
||||
│ │ └─► Lee el cursor del último mensaje procesado │ │
|
||||
│ │ │ │
|
||||
│ │ c) refresh_chat() │ │
|
||||
│ │ └─► GetHistoryRequest(min_id=first_id) │ │
|
||||
│ │ Descarga en lotes de 100 solo mensajes nuevos │ │
|
||||
│ │ │ │
|
||||
│ │ d) get_and_post_message_info() │ │
|
||||
│ │ │ │ │
|
||||
│ │ ├─► _preload_senders() │ │
|
||||
│ │ │ └─► Para cada sender_id único: │ │
|
||||
│ │ │ GET /senders/{id} → ¿existe? │ │
|
||||
│ │ │ NO → get_entity(id) en Telegram │ │
|
||||
│ │ │ POST /senders/ → crea el remitente │ │
|
||||
│ │ │ │ │
|
||||
│ │ └─► Para cada mensaje descargado: │ │
|
||||
│ │ │ │ │
|
||||
│ │ ├─► Extrae: id, content, date, sender_id, │ │
|
||||
│ │ │ group_id, media (adjunto si existe) │ │
|
||||
│ │ │ │ │
|
||||
│ │ ├─► POST /messages/ (API interna) │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ └─► Endpoint crea el mensaje y: │ │
|
||||
│ │ │ Para cada regla activa: │ │
|
||||
│ │ │ └─► re.search(regex, content) │ │
|
||||
│ │ │ ¿Coincide? → crea Alert(status=open)│ │
|
||||
│ │ │ │ │
|
||||
│ │ └─► Si tiene adjunto → POST /attachments/ │ │
|
||||
│ │ │ │
|
||||
│ │ e) act_message_position(group_id, last_message_id) │ │
|
||||
│ │ └─► PATCH /groups/{id}/update-position │ │
|
||||
│ │ Actualiza el cursor para el próximo ciclo │ │
|
||||
│ │ │ │
|
||||
│ │ 4. Fin del ciclo → sleep(200 segundos) │ │
|
||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ⚠️ Si ocurre una excepción en cualquier punto: │
|
||||
│ └─► scraper_status["last_error"] = str(e) │
|
||||
│ sleep(60 segundos) │
|
||||
│ El singleton mantiene el cliente → intento de reconexión │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Descarga de Adjuntos (bajo demanda)
|
||||
|
||||
Cuando un usuario descarga un adjunto desde la UI, se sigue un flujo independiente para no interferir con el ciclo del Feeder:
|
||||
|
||||
```
|
||||
Frontend
|
||||
└─► GET /attachments/{id}/download
|
||||
│
|
||||
├─► Obtiene metadata del adjunto (group_id, message_id)
|
||||
│
|
||||
├─► TelegramChatSingleton.get_tmp_scraper()
|
||||
│ └─► Crea un TelegramClientManager temporal
|
||||
│ Copia el .session file a un archivo temporal
|
||||
│ Lanza un thread dedicado con su propio event loop
|
||||
│
|
||||
└─► download_attachment_to_buffer(group_id, message_id)
|
||||
└─► client.get_messages(group_id, ids=message_id)
|
||||
client.download_media(message, file=BytesIO())
|
||||
Devuelve los bytes → StreamingResponse al Frontend
|
||||
Elimina la sesión temporal al finalizar
|
||||
```
|
||||
|
||||
### Configuración del Ciclo
|
||||
|
||||
Los parámetros del ciclo se pueden ajustar directamente en `app/main.py`:
|
||||
|
||||
```python
|
||||
scraper_config = {
|
||||
"cicle_time": 200, # segundos entre ciclos (recomendado ≥ 200 para evitar flood)
|
||||
"error_delay": 60, # segundos de espera tras un error antes de reintentar
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Requisitos Previos
|
||||
|
||||
### Hardware Mínimo
|
||||
|
||||
| Recurso | Mínimo | Recomendado |
|
||||
|---------|--------|-------------|
|
||||
| CPU | 2 núcleos | 4 núcleos |
|
||||
| RAM | 4 GB | 8 GB |
|
||||
| Almacenamiento | 20 GB | 50 GB+ |
|
||||
|
||||
### Software Requerido
|
||||
|
||||
| Componente | Versión Mínima | Instalación |
|
||||
|-----------|----------------|-------------|
|
||||
| Docker | 20.10+ | https://docs.docker.com/engine/install/ |
|
||||
| Docker Compose | 1.29+ | Incluido en Docker Desktop |
|
||||
| Git | 2.20+ | https://git-scm.com/downloads |
|
||||
| jq (solo Linux/macOS) | 1.6+ | `sudo apt install jq` o `brew install jq` |
|
||||
|
||||
> **Nota sobre Python**: El proyecto utiliza **Python 3.11** en todos los microservicios. La versión está declarada en cada `Dockerfile` (`FROM python:3.11-slim`). No es necesario tener Python instalado localmente; Docker lo gestiona de forma aislada.
|
||||
|
||||
### Credenciales Necesarias
|
||||
|
||||
- **Telegram API ID y API Hash**: Obtener en https://my.telegram.org/apps con la cuenta que se usará para el monitoreo
|
||||
- **Número de teléfono** de esa cuenta (formato internacional, ej: `+5491112345678`)
|
||||
- Acceso a los grupos/canales de Telegram que se desean monitorear
|
||||
|
||||
---
|
||||
|
||||
## Instalación y Configuración
|
||||
|
||||
### Paso 1 — Clonar el Repositorio
|
||||
|
||||
```bash
|
||||
git clone https://github.com/tu-usuario/tip.git
|
||||
cd tip
|
||||
```
|
||||
|
||||
### Paso 2 — Crear el Archivo `.env`
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edita `.env` con tus valores reales:
|
||||
|
||||
```env
|
||||
# ── TELEGRAM ────────────────────────────────────────────────────────────
|
||||
# Obtener en https://my.telegram.org/apps
|
||||
TELEGRAM_API_ID=123456789
|
||||
TELEGRAM_API_HASH=abcdef0123456789abcdef0123456789
|
||||
TELEGRAM_TELEPHONE=+5491112345678
|
||||
|
||||
# ── SEGURIDAD ────────────────────────────────────────────────────────────
|
||||
# Clave compartida entre todos los microservicios (mínimo 20 caracteres)
|
||||
# Generar con: openssl rand -hex 32
|
||||
SECRET_KEY=reemplazar_con_clave_secreta_minimo_32_chars
|
||||
|
||||
# ── BASES DE DATOS ───────────────────────────────────────────────────────
|
||||
DB_ROOT_PASS_FEEDER=password_feeder
|
||||
DB_ROOT_PASS_USERS=password_users
|
||||
|
||||
# ── ADMIN (creado automáticamente en el primer inicio) ──────────────────
|
||||
ADMIN_EMAIL=admin@tudominio.com
|
||||
ADMIN_PASSWORD=contraseña_admin_segura
|
||||
```
|
||||
|
||||
### Paso 3 — Configurar `docker-compose.yml`
|
||||
|
||||
```bash
|
||||
cp docker-compose_example.yml docker-compose.yml
|
||||
```
|
||||
|
||||
Reemplaza los valores marcados con `YOUR-*`:
|
||||
|
||||
```yaml
|
||||
# Contraseñas de bases de datos
|
||||
database:
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password_feeder # ← cambiar
|
||||
|
||||
database_users:
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password_users # ← cambiar
|
||||
|
||||
# URLs de conexión a las bases de datos
|
||||
api:
|
||||
environment:
|
||||
DATABASE_URL: mariadb+pymysql://root:password_feeder@database:3306/feeder
|
||||
TELEGRAM_API_ID: TU_API_ID
|
||||
TELEGRAM_API_HASH: TU_API_HASH
|
||||
TELEGRAM_TELEPHONE: TU_TELEFONO
|
||||
SECRET_KEY: TU_SECRET_KEY
|
||||
|
||||
api_users:
|
||||
environment:
|
||||
DATABASE_URL: mariadb+pymysql://root:password_users@database_users:3307/users
|
||||
SECRET_KEY: TU_SECRET_KEY # ← debe ser la misma que api
|
||||
ADMIN_EMAIL: admin@tudominio.com
|
||||
ADMIN_PASSWORD: contraseña_admin
|
||||
|
||||
# URLs para el backup service
|
||||
backup:
|
||||
environment:
|
||||
FEEDER_DATABASE_URL: mariadb+pymysql://root:password_feeder@database:3306/feeder
|
||||
USERS_DATABASE_URL: mariadb+pymysql://root:password_users@database_users:3307/users
|
||||
SECRET_KEY: TU_SECRET_KEY
|
||||
```
|
||||
|
||||
### Paso 4 — Configurar NGINX
|
||||
|
||||
```bash
|
||||
mkdir -p nginx/ssl
|
||||
cp nginx/nginx.conf_example nginx/nginx.conf
|
||||
```
|
||||
|
||||
Edita `nginx/nginx.conf` y reemplaza `localhost` con tu dominio:
|
||||
|
||||
```nginx
|
||||
server_name tu_dominio.com;
|
||||
```
|
||||
|
||||
Para **desarrollo local sin SSL**, comenta el bloque HTTPS y usa solo el bloque HTTP.
|
||||
|
||||
**Para producción con Let's Encrypt**:
|
||||
|
||||
```bash
|
||||
# Instalar certbot (fuera de Docker)
|
||||
sudo apt install certbot
|
||||
|
||||
# Generar certificados
|
||||
sudo certbot certonly --standalone -d tu_dominio.com
|
||||
|
||||
# Copiar al directorio del proyecto
|
||||
sudo cp /etc/letsencrypt/live/tu_dominio.com/fullchain.pem ./nginx/ssl/
|
||||
sudo cp /etc/letsencrypt/live/tu_dominio.com/privkey.pem ./nginx/ssl/
|
||||
sudo chown $(whoami):$(whoami) ./nginx/ssl/*
|
||||
```
|
||||
|
||||
### Paso 5 — Iniciar los Contenedores
|
||||
|
||||
```bash
|
||||
# Construir imágenes e iniciar todos los servicios
|
||||
docker compose up -d --build
|
||||
|
||||
# Verificar que todos estén corriendo
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
Resultado esperado:
|
||||
|
||||
```
|
||||
NAME SERVICE STATUS
|
||||
feeder_api api running
|
||||
users_api api_users running
|
||||
frontend frontend running
|
||||
backup_service backup running
|
||||
feeder_db database running (healthy)
|
||||
users_db database_users running (healthy)
|
||||
nginx_proxy nginx running
|
||||
```
|
||||
|
||||
```bash
|
||||
# Ver logs en tiempo real
|
||||
docker compose logs -f api api_users
|
||||
```
|
||||
|
||||
### Paso 6 — Autenticar la Sesión de Telegram
|
||||
|
||||
La primera vez (o tras reinstalación) es necesario autenticar el cliente de Telegram:
|
||||
|
||||
1. Accede a la UI como **admin**: https://tu_dominio.com
|
||||
2. Ve a **Panel de Administración** → **Sistema** → **Alimentador**
|
||||
3. Haz clic en **Iniciar Nueva Sesión**
|
||||
4. Revisa el código de verificación que llegó a tu cuenta de Telegram
|
||||
5. Ingrésalo en el campo correspondiente (más la contraseña 2FA si aplica)
|
||||
6. El alimentador se activará automáticamente
|
||||
|
||||
### Paso 7 — Agregar Grupos a Monitorear
|
||||
|
||||
1. Ve a **Grupos y Canales** → **Agregar grupo**
|
||||
2. Abre el grupo en Telegram Web (`web.telegram.org`)
|
||||
3. Copia la URL completa (contiene el ID: `.../#-100XXXXXXXXX`)
|
||||
4. Pégala en el campo y haz clic en **Agregar Grupo**
|
||||
5. El sistema valida el acceso contra Telegram y lo registra
|
||||
|
||||
---
|
||||
|
||||
## Gestión de Backups
|
||||
|
||||
### Generar un Backup
|
||||
|
||||
#### Desde la UI
|
||||
|
||||
1. Accede como **admin**
|
||||
2. Ve a **Panel de Administración** → **Sistema** → **Backup del Sistema**
|
||||
3. Selecciona los componentes a incluir
|
||||
4. Haz clic en **⬇️ Generar y Descargar Backup**
|
||||
5. Guarda el archivo `tip_backup_YYYYMMDD_HHMMSS.zip` en lugar seguro
|
||||
|
||||
#### Desde la línea de comandos
|
||||
|
||||
```bash
|
||||
# Primero, obtener un token JWT (reemplazar por tus credenciales)
|
||||
TOKEN=$(curl -s -X POST http://localhost:8090/api/v1/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"admin@tudominio.com","password":"tu_password"}' \
|
||||
| jq -r '.access_token')
|
||||
|
||||
# Solicitar el backup
|
||||
curl -X GET \
|
||||
"http://localhost:8099/backup?include_db=true&include_config=true&include_ssl=true&include_sessions=true" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-o "tip_backup_$(date +%Y%m%d_%H%M%S).zip"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Restaurar un Backup
|
||||
|
||||
> ⚠️ **ADVERTENCIA**: La restauración sobrescribe datos existentes. Asegúrate de que es lo que necesitas antes de continuar.
|
||||
|
||||
#### Windows (PowerShell)
|
||||
|
||||
```powershell
|
||||
# 1. Coloca el archivo tip_backup_*.zip en la raíz del proyecto
|
||||
# 2. Abre PowerShell como Administrador y navega al directorio
|
||||
cd C:\ruta\al\proyecto
|
||||
|
||||
# 3. Habilitar ejecución de scripts (si no está habilitado)
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
|
||||
# 4. Ejecutar el script
|
||||
.\restore_backup.ps1
|
||||
```
|
||||
|
||||
#### Linux / macOS (Bash)
|
||||
|
||||
```bash
|
||||
# 1. Coloca el archivo tip_backup_*.zip en la raíz del proyecto
|
||||
# 2. Dar permisos de ejecución al script
|
||||
chmod +x restore_backup.sh
|
||||
|
||||
# 3. Ejecutar el script
|
||||
./restore_backup.sh
|
||||
```
|
||||
|
||||
#### ¿Qué hace el script de restauración?
|
||||
|
||||
```
|
||||
INICIO
|
||||
│
|
||||
├─ 1. Solicita confirmación al usuario
|
||||
│
|
||||
├─ 2. Localiza el tip_backup_*.zip más reciente en el directorio actual
|
||||
│
|
||||
├─ 3. Extrae el contenido en ./temp_restore/
|
||||
│
|
||||
├─ 4. Lee manifest.json → identifica componentes incluidos y advertencias
|
||||
│
|
||||
├─ 5. Obtiene credenciales de las bases de datos desde docker-compose.yml
|
||||
│
|
||||
├─ 6. Por cada componente en el manifiesto:
|
||||
│ ├─ database:feeder → levanta feeder_db y restaura el .sql
|
||||
│ ├─ database:users → levanta users_db y restaura el .sql
|
||||
│ ├─ config:* → copia nginx.conf y/o docker-compose.yml
|
||||
│ ├─ ssl → copia certificados a ./nginx/ssl/
|
||||
│ └─ telegram_sessions → copia .session a ./app/telegram_sessions/
|
||||
│
|
||||
├─ 7. Muestra las advertencias registradas en el manifiesto
|
||||
│
|
||||
├─ 8. Elimina ./temp_restore/
|
||||
│
|
||||
└─ 9. Pregunta si desea reiniciar los contenedores (docker compose down && up)
|
||||
```
|
||||
|
||||
#### Dependencias del Script
|
||||
|
||||
| Dependencia | Windows | Linux/macOS |
|
||||
|-------------|---------|-------------|
|
||||
| Docker + Docker Compose | ✅ Requerido | ✅ Requerido |
|
||||
| jq | No requerido (usa PowerShell nativo) | ✅ `sudo apt install jq` |
|
||||
|
||||
---
|
||||
|
||||
### Buenas Prácticas de Backup
|
||||
|
||||
- **Frecuencia**: Realiza backups diarios en producción, especialmente antes de actualizaciones
|
||||
- **Validación**: Prueba la restauración en un entorno de prueba periódicamente
|
||||
- **Almacenamiento externo**: Guarda copias en un servidor remoto o servicio de almacenamiento (S3, OneDrive, etc.)
|
||||
- **Encriptación**: Si el backup contiene sesiones o datos sensibles, encríptalo antes de transferirlo:
|
||||
```bash
|
||||
# Linux/macOS
|
||||
openssl enc -aes-256-cbc -salt -in tip_backup_*.zip -out tip_backup_encrypted.zip
|
||||
|
||||
# Descifrar
|
||||
openssl enc -d -aes-256-cbc -in tip_backup_encrypted.zip -out tip_backup_restored.zip
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Los contenedores no inician
|
||||
|
||||
```bash
|
||||
# Ver logs completos de todos los servicios
|
||||
docker compose logs
|
||||
|
||||
# Ver logs de un servicio en particular
|
||||
docker compose logs api
|
||||
docker compose logs database
|
||||
|
||||
# Reconstruir imágenes sin caché
|
||||
docker compose down
|
||||
docker compose up -d --build --force-recreate
|
||||
```
|
||||
|
||||
### Error de conexión a la base de datos
|
||||
|
||||
```bash
|
||||
# Verificar que MariaDB está aceptando conexiones
|
||||
docker compose exec database mysql -u root -p -e "SELECT 1;"
|
||||
|
||||
# Verificar conectividad entre contenedores
|
||||
docker compose exec api ping database
|
||||
```
|
||||
|
||||
### El alimentador aparece como inactivo
|
||||
|
||||
```bash
|
||||
# Verificar si hay archivos de sesión de Telegram
|
||||
docker compose exec api ls -la /app/telegram_sessions/
|
||||
|
||||
# Si no hay sesión o está corrupta, eliminarla y autenticar de nuevo desde la UI
|
||||
docker compose exec api rm -f /app/telegram_sessions/session_*
|
||||
# Luego: Panel de Administración → Sistema → Iniciar Nueva Sesión
|
||||
```
|
||||
|
||||
### NGINX devuelve 502 Bad Gateway
|
||||
|
||||
```bash
|
||||
# Verificar que los servicios upstream estén corriendo
|
||||
docker compose ps
|
||||
|
||||
# Validar la configuración de NGINX
|
||||
docker compose exec nginx nginx -t
|
||||
|
||||
# Ver logs de NGINX
|
||||
docker compose logs nginx
|
||||
```
|
||||
|
||||
### Las alertas no se generan automáticamente
|
||||
|
||||
```bash
|
||||
# Verificar que existen reglas activas
|
||||
curl -H "Authorization: Bearer $TOKEN" http://localhost:8000/rules/
|
||||
|
||||
# Verificar que el feeder está capturando mensajes
|
||||
docker compose logs api | grep -E "Feeding|Cycle|feeder_loop"
|
||||
|
||||
# Verificar que no hay errores de regex en las reglas
|
||||
docker compose logs api | grep -i "regex\|WARN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estructura del Proyecto
|
||||
|
||||
```
|
||||
tip/
|
||||
├── app/ # API Feeder
|
||||
│ ├── alembic/ # Migraciones de base de datos
|
||||
│ ├── integrations/ # Cliente Telegram (chats.py, api_implementations.py)
|
||||
│ ├── routers/ # Endpoints REST
|
||||
│ ├── main.py # Entry point + scraper loop
|
||||
│ ├── models.py # Modelos SQLAlchemy
|
||||
│ ├── schemas.py # Schemas Pydantic
|
||||
│ ├── auth.py # JWT helpers
|
||||
│ └── audit.py # Logger de auditoría
|
||||
├── usuarios/ # API Users
|
||||
│ ├── main.py
|
||||
│ ├── models.py
|
||||
│ ├── schemas.py
|
||||
│ ├── crud.py
|
||||
│ ├── services.py
|
||||
│ └── dependencies.py
|
||||
├── frontend/ # UI Streamlit
|
||||
│ ├── app.py
|
||||
│ ├── src/
|
||||
│ │ ├── api.py # Cliente HTTP hacia las APIs
|
||||
│ │ ├── auth.py # Login / sesión
|
||||
│ │ └── pages/
|
||||
│ │ ├── dashboard.py
|
||||
│ │ └── views/ # alerts, messages, rules, groups, stats, ...
|
||||
│ └── .streamlit/
|
||||
│ ├── config.toml # Tema visual
|
||||
│ └── secrets.toml
|
||||
├── backup_service/ # Backup Service
|
||||
│ ├── main.py
|
||||
│ ├── requirements.txt
|
||||
│ └── Dockerfile
|
||||
├── nginx/
|
||||
│ ├── nginx.conf # Configuración del proxy (generada desde el ejemplo)
|
||||
│ └── ssl/ # Certificados SSL (excluidos del repo)
|
||||
├── Dockerfile # Imagen API Feeder
|
||||
├── Dockerfile_users # Imagen API Users
|
||||
├── Dockerfile_frontend # Imagen Frontend
|
||||
├── docker-compose.yml # Orquestación (generado desde el ejemplo)
|
||||
├── docker-compose_example.yml # Plantilla de configuración
|
||||
├── entrypoint.sh # Ejecuta migraciones Alembic antes de iniciar la API
|
||||
├── restore_backup.sh # Script de restauración (Linux/macOS)
|
||||
├── restore_backup.ps1 # Script de restauración (Windows)
|
||||
├── requirements.txt # Dependencias API Feeder
|
||||
├── requirements_users.txt # Dependencias API Users
|
||||
├── requirements_frontend.txt # Dependencias Frontend
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Plataforma desarrollada para uso interno — Municipio de Paraná.*
|
||||
Reference in New Issue
Block a user