Files
TIP/README.md
T
2026-06-09 21:18:13 -03:00

767 lines
33 KiB
Markdown

# 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á.*