Initial commit: MSP Monitor Dashboard
- Next.js 14 frontend with dark cyan/navy theme - tRPC API with Prisma ORM - MeshCentral, LibreNMS, Headwind MDM integrations - Multi-tenant architecture - Alert system with email/SMS/webhook notifications - Docker Compose deployment - Complete documentation
This commit is contained in:
516
docs/api/README.md
Normal file
516
docs/api/README.md
Normal file
@@ -0,0 +1,516 @@
|
||||
# API Reference
|
||||
|
||||
## Vision General
|
||||
|
||||
La API de MSP Monitor Dashboard utiliza [tRPC](https://trpc.io/) para comunicacion type-safe entre frontend y backend. Todos los endpoints estan disponibles bajo `/api/trpc`.
|
||||
|
||||
## Autenticacion
|
||||
|
||||
### Login con Email/Password
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/auth.login
|
||||
const result = await trpc.auth.login.mutate({
|
||||
email: "usuario@example.com",
|
||||
password: "password123"
|
||||
})
|
||||
// Returns: { success: true, user: { id, email, nombre, rol } }
|
||||
```
|
||||
|
||||
### Login con MeshCentral SSO
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/auth.loginMeshCentral
|
||||
const result = await trpc.auth.loginMeshCentral.mutate({
|
||||
username: "meshuser",
|
||||
token: "mesh-auth-token"
|
||||
})
|
||||
```
|
||||
|
||||
### Logout
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/auth.logout
|
||||
await trpc.auth.logout.mutate()
|
||||
```
|
||||
|
||||
### Usuario Actual
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/auth.me
|
||||
const user = await trpc.auth.me.query()
|
||||
// Returns: { id, email, nombre, rol, cliente, permisos }
|
||||
```
|
||||
|
||||
## Clientes (Tenants)
|
||||
|
||||
### Listar Clientes
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/clientes.list
|
||||
const { clientes, pagination } = await trpc.clientes.list.query({
|
||||
search: "term",
|
||||
activo: true,
|
||||
page: 1,
|
||||
limit: 20
|
||||
})
|
||||
```
|
||||
|
||||
### Obtener Cliente
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/clientes.byId
|
||||
const cliente = await trpc.clientes.byId.query({ id: "client-id" })
|
||||
```
|
||||
|
||||
### Crear Cliente
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/clientes.create
|
||||
const cliente = await trpc.clientes.create.mutate({
|
||||
nombre: "Empresa XYZ",
|
||||
codigo: "XYZ",
|
||||
email: "contacto@xyz.com",
|
||||
meshcentralGrupo: "mesh-group-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Estadisticas del Dashboard
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/clientes.dashboardStats
|
||||
const stats = await trpc.clientes.dashboardStats.query({
|
||||
clienteId: "optional-client-id"
|
||||
})
|
||||
// Returns: {
|
||||
// totalDispositivos, dispositivosOnline, dispositivosOffline,
|
||||
// dispositivosAlerta, alertasActivas, alertasCriticas
|
||||
// }
|
||||
```
|
||||
|
||||
## Equipos (PC/Laptop/Servidor)
|
||||
|
||||
### Listar Equipos
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/equipos.list
|
||||
const { dispositivos, pagination } = await trpc.equipos.list.query({
|
||||
clienteId: "client-id",
|
||||
tipo: "SERVIDOR", // PC | LAPTOP | SERVIDOR
|
||||
estado: "ONLINE", // ONLINE | OFFLINE | ALERTA | MANTENIMIENTO
|
||||
search: "term",
|
||||
page: 1,
|
||||
limit: 20
|
||||
})
|
||||
```
|
||||
|
||||
### Obtener Equipo
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/equipos.byId
|
||||
const equipo = await trpc.equipos.byId.query({ id: "device-id" })
|
||||
// Incluye: cliente, ubicacion, software, alertas activas
|
||||
```
|
||||
|
||||
### Obtener Metricas
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/equipos.metricas
|
||||
const metricas = await trpc.equipos.metricas.query({
|
||||
dispositivoId: "device-id",
|
||||
periodo: "24h" // 1h | 6h | 24h | 7d | 30d
|
||||
})
|
||||
```
|
||||
|
||||
### Iniciar Sesion Remota
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/equipos.iniciarSesion
|
||||
const { sesionId, url } = await trpc.equipos.iniciarSesion.mutate({
|
||||
dispositivoId: "device-id",
|
||||
tipo: "desktop" // desktop | terminal | files
|
||||
})
|
||||
// Redirigir a `url` para abrir conexion
|
||||
```
|
||||
|
||||
### Ejecutar Comando
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/equipos.ejecutarComando
|
||||
const resultado = await trpc.equipos.ejecutarComando.mutate({
|
||||
dispositivoId: "device-id",
|
||||
comando: "Get-Process",
|
||||
tipo: "powershell" // powershell | cmd | bash
|
||||
})
|
||||
// Returns: { success: true, output: "..." }
|
||||
```
|
||||
|
||||
### Reiniciar/Apagar
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/equipos.reiniciar
|
||||
await trpc.equipos.reiniciar.mutate({ dispositivoId: "device-id" })
|
||||
|
||||
// POST /api/trpc/equipos.apagar
|
||||
await trpc.equipos.apagar.mutate({ dispositivoId: "device-id" })
|
||||
```
|
||||
|
||||
## Celulares (MDM)
|
||||
|
||||
### Listar Celulares
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/celulares.list
|
||||
const { dispositivos, pagination } = await trpc.celulares.list.query({
|
||||
clienteId: "client-id",
|
||||
estado: "ONLINE",
|
||||
search: "term"
|
||||
})
|
||||
```
|
||||
|
||||
### Obtener Ubicacion
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/celulares.ubicacion
|
||||
const { lat, lng, updatedAt } = await trpc.celulares.ubicacion.query({
|
||||
dispositivoId: "device-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Solicitar Ubicacion
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/celulares.solicitarUbicacion
|
||||
await trpc.celulares.solicitarUbicacion.mutate({
|
||||
dispositivoId: "device-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Bloquear/Desbloquear
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/celulares.bloquear
|
||||
await trpc.celulares.bloquear.mutate({
|
||||
dispositivoId: "device-id",
|
||||
mensaje: "Dispositivo bloqueado por seguridad"
|
||||
})
|
||||
|
||||
// POST /api/trpc/celulares.desbloquear
|
||||
await trpc.celulares.desbloquear.mutate({
|
||||
dispositivoId: "device-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Hacer Sonar
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/celulares.sonar
|
||||
await trpc.celulares.sonar.mutate({
|
||||
dispositivoId: "device-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Enviar Mensaje
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/celulares.enviarMensaje
|
||||
await trpc.celulares.enviarMensaje.mutate({
|
||||
dispositivoId: "device-id",
|
||||
mensaje: "Mensaje para el usuario"
|
||||
})
|
||||
```
|
||||
|
||||
### Borrar Datos (Factory Reset)
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/celulares.borrarDatos
|
||||
// CUIDADO: Esta accion es irreversible
|
||||
await trpc.celulares.borrarDatos.mutate({
|
||||
dispositivoId: "device-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Instalar/Desinstalar App
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/celulares.instalarApp
|
||||
await trpc.celulares.instalarApp.mutate({
|
||||
dispositivoId: "device-id",
|
||||
packageName: "com.example.app"
|
||||
})
|
||||
|
||||
// POST /api/trpc/celulares.desinstalarApp
|
||||
await trpc.celulares.desinstalarApp.mutate({
|
||||
dispositivoId: "device-id",
|
||||
packageName: "com.example.app"
|
||||
})
|
||||
```
|
||||
|
||||
## Red (SNMP/NetFlow)
|
||||
|
||||
### Listar Dispositivos de Red
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/red.list
|
||||
const { dispositivos, pagination } = await trpc.red.list.query({
|
||||
clienteId: "client-id",
|
||||
tipo: "ROUTER", // ROUTER | SWITCH | FIREWALL | AP | IMPRESORA | OTRO
|
||||
estado: "ONLINE"
|
||||
})
|
||||
```
|
||||
|
||||
### Obtener Interfaces
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/red.interfaces
|
||||
const interfaces = await trpc.red.interfaces.query({
|
||||
dispositivoId: "device-id"
|
||||
})
|
||||
// Returns: [{ ifName, ifAlias, ifSpeed, ifOperStatus, ifInOctets_rate, ifOutOctets_rate }]
|
||||
```
|
||||
|
||||
### Obtener Trafico
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/red.trafico
|
||||
const datos = await trpc.red.trafico.query({
|
||||
dispositivoId: "device-id",
|
||||
portId: 123,
|
||||
periodo: "24h"
|
||||
})
|
||||
// Returns: [{ timestamp, in, out }]
|
||||
```
|
||||
|
||||
### Obtener Topologia
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/red.topologia
|
||||
const { nodes, links } = await trpc.red.topologia.query({
|
||||
clienteId: "client-id"
|
||||
})
|
||||
// Para visualizacion con D3.js o similar
|
||||
```
|
||||
|
||||
## Alertas
|
||||
|
||||
### Listar Alertas
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/alertas.list
|
||||
const { alertas, pagination } = await trpc.alertas.list.query({
|
||||
clienteId: "client-id",
|
||||
estado: "ACTIVA", // ACTIVA | RECONOCIDA | RESUELTA
|
||||
severidad: "CRITICAL", // INFO | WARNING | CRITICAL
|
||||
dispositivoId: "device-id",
|
||||
desde: new Date("2024-01-01"),
|
||||
hasta: new Date("2024-01-31")
|
||||
})
|
||||
```
|
||||
|
||||
### Reconocer Alerta
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/alertas.reconocer
|
||||
await trpc.alertas.reconocer.mutate({ id: "alert-id" })
|
||||
```
|
||||
|
||||
### Resolver Alerta
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/alertas.resolver
|
||||
await trpc.alertas.resolver.mutate({ id: "alert-id" })
|
||||
```
|
||||
|
||||
### Conteo de Alertas Activas
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/alertas.conteoActivas
|
||||
const { total, critical, warning, info } = await trpc.alertas.conteoActivas.query({
|
||||
clienteId: "client-id"
|
||||
})
|
||||
```
|
||||
|
||||
## Reglas de Alerta
|
||||
|
||||
### Listar Reglas
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/alertas.reglas.list
|
||||
const reglas = await trpc.alertas.reglas.list.query({
|
||||
clienteId: "client-id"
|
||||
})
|
||||
```
|
||||
|
||||
### Crear Regla
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/alertas.reglas.create
|
||||
const regla = await trpc.alertas.reglas.create.mutate({
|
||||
clienteId: "client-id", // null para regla global
|
||||
nombre: "CPU Alta",
|
||||
metrica: "cpu",
|
||||
operador: ">",
|
||||
umbral: 90,
|
||||
duracionMinutos: 5,
|
||||
severidad: "WARNING",
|
||||
notificarEmail: true,
|
||||
notificarSms: false
|
||||
})
|
||||
```
|
||||
|
||||
## Reportes
|
||||
|
||||
### Reporte de Inventario
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/reportes.inventario
|
||||
const { dispositivos, resumen } = await trpc.reportes.inventario.query({
|
||||
clienteId: "client-id",
|
||||
tipo: "SERVIDOR"
|
||||
})
|
||||
```
|
||||
|
||||
### Reporte de Uptime
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/reportes.uptime
|
||||
const { dispositivos, promedioGeneral } = await trpc.reportes.uptime.query({
|
||||
clienteId: "client-id",
|
||||
desde: new Date("2024-01-01"),
|
||||
hasta: new Date("2024-01-31")
|
||||
})
|
||||
```
|
||||
|
||||
### Reporte de Alertas
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/reportes.alertas
|
||||
const { alertas, resumen } = await trpc.reportes.alertas.query({
|
||||
clienteId: "client-id",
|
||||
desde: new Date("2024-01-01"),
|
||||
hasta: new Date("2024-01-31")
|
||||
})
|
||||
```
|
||||
|
||||
### Exportar a CSV
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/reportes.exportarCSV
|
||||
const { filename, content, contentType } = await trpc.reportes.exportarCSV.mutate({
|
||||
tipo: "inventario", // inventario | alertas | actividad
|
||||
clienteId: "client-id"
|
||||
})
|
||||
// Descargar el contenido como archivo CSV
|
||||
```
|
||||
|
||||
## Usuarios
|
||||
|
||||
### Listar Usuarios
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/usuarios.list
|
||||
const { usuarios, pagination } = await trpc.usuarios.list.query({
|
||||
clienteId: "client-id",
|
||||
rol: "TECNICO",
|
||||
activo: true
|
||||
})
|
||||
```
|
||||
|
||||
### Crear Usuario
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/usuarios.create
|
||||
const usuario = await trpc.usuarios.create.mutate({
|
||||
email: "nuevo@example.com",
|
||||
nombre: "Nuevo Usuario",
|
||||
password: "password123",
|
||||
clienteId: "client-id",
|
||||
rol: "TECNICO"
|
||||
})
|
||||
```
|
||||
|
||||
### Resetear Password
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/usuarios.resetPassword
|
||||
await trpc.usuarios.resetPassword.mutate({
|
||||
id: "user-id",
|
||||
newPassword: "newpassword123"
|
||||
})
|
||||
```
|
||||
|
||||
## Configuracion
|
||||
|
||||
### Obtener Configuracion
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/configuracion.get
|
||||
const config = await trpc.configuracion.get.query({
|
||||
clave: "smtp_host"
|
||||
})
|
||||
```
|
||||
|
||||
### Establecer Configuracion
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/configuracion.set
|
||||
await trpc.configuracion.set.mutate({
|
||||
clave: "smtp_host",
|
||||
valor: "smtp.gmail.com",
|
||||
tipo: "string",
|
||||
categoria: "notificacion"
|
||||
})
|
||||
```
|
||||
|
||||
### Estado de Integraciones
|
||||
|
||||
```typescript
|
||||
// GET /api/trpc/configuracion.integraciones.status
|
||||
const { meshcentral, librenms, headwind } = await trpc.configuracion.integraciones.status.query()
|
||||
// Returns: { configurado: boolean, url?: string }
|
||||
```
|
||||
|
||||
### Configurar MeshCentral
|
||||
|
||||
```typescript
|
||||
// POST /api/trpc/configuracion.integraciones.setMeshCentral
|
||||
await trpc.configuracion.integraciones.setMeshCentral.mutate({
|
||||
url: "https://mesh.tudominio.com",
|
||||
user: "admin",
|
||||
password: "password",
|
||||
domain: "default"
|
||||
})
|
||||
```
|
||||
|
||||
## Codigos de Error
|
||||
|
||||
| Codigo | Descripcion |
|
||||
|--------|-------------|
|
||||
| UNAUTHORIZED | No autenticado |
|
||||
| FORBIDDEN | Sin permisos |
|
||||
| NOT_FOUND | Recurso no encontrado |
|
||||
| CONFLICT | Conflicto (ej: email duplicado) |
|
||||
| BAD_REQUEST | Request invalido |
|
||||
| INTERNAL_SERVER_ERROR | Error del servidor |
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
- API general: 100 requests/minuto
|
||||
- Autenticacion: 10 requests/minuto
|
||||
- Acciones sensibles (wipe, commands): 5 requests/minuto
|
||||
|
||||
## Webhooks
|
||||
|
||||
Las alertas pueden enviar webhooks a URLs configuradas:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "alert-id",
|
||||
"severidad": "CRITICAL",
|
||||
"titulo": "Servidor offline",
|
||||
"mensaje": "El servidor SRV-01 no responde",
|
||||
"dispositivo": "SRV-01",
|
||||
"cliente": "Cliente A",
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
321
docs/arquitectura/README.md
Normal file
321
docs/arquitectura/README.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# Arquitectura del Sistema
|
||||
|
||||
## Vision General
|
||||
|
||||
MSP Monitor Dashboard es una aplicacion web moderna construida con una arquitectura monolitica modular, diseñada para ejecutarse en una unica VM de Proxmox mientras mantiene una clara separacion de responsabilidades.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ NGINX (Proxy) │
|
||||
│ SSL/TLS + Rate Limiting │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┴───────────────┐
|
||||
▼ ▼
|
||||
┌───────────────────────────┐ ┌───────────────────────────────┐
|
||||
│ Next.js Dashboard │ │ Background Workers │
|
||||
│ (Frontend + API Routes) │ │ (BullMQ Jobs) │
|
||||
└───────────────────────────┘ └───────────────────────────────┘
|
||||
│ │
|
||||
└───────────────┬───────────────┘
|
||||
│
|
||||
┌───────────────────────┼───────────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||
│ PostgreSQL │ │ Redis │ │ External │
|
||||
│ (Primary) │ │ (Cache/Queue) │ │ APIs │
|
||||
└───────────────┘ └───────────────┘ └───────────────┘
|
||||
│
|
||||
┌───────────────────────────────┼───────────────────────────────┐
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||
│ MeshCentral │ │ LibreNMS │ │ Headwind MDM │
|
||||
│ (PC/Laptop) │ │ (Network) │ │ (Mobile) │
|
||||
└───────────────┘ └───────────────┘ └───────────────┘
|
||||
```
|
||||
|
||||
## Componentes Principales
|
||||
|
||||
### 1. Frontend (Next.js + React)
|
||||
|
||||
**Ubicacion**: `src/app/`, `src/components/`
|
||||
|
||||
El frontend utiliza Next.js 14 con App Router, proporcionando:
|
||||
|
||||
- **Server Components**: Para renderizado del lado del servidor
|
||||
- **Client Components**: Para interactividad en el navegador
|
||||
- **Tailwind CSS**: Sistema de diseño con tema oscuro cyan/navy
|
||||
- **React Query**: Cache y sincronizacion de estado del servidor
|
||||
|
||||
**Estructura de paginas**:
|
||||
```
|
||||
src/app/
|
||||
├── (dashboard)/ # Grupo de rutas autenticadas
|
||||
│ ├── layout.tsx # Layout con sidebar y header
|
||||
│ ├── page.tsx # Dashboard principal
|
||||
│ ├── equipos/ # Gestion de PCs/laptops/servidores
|
||||
│ ├── celulares/ # Gestion de dispositivos moviles
|
||||
│ ├── red/ # Gestion de dispositivos de red
|
||||
│ ├── alertas/ # Centro de alertas
|
||||
│ ├── reportes/ # Generacion de reportes
|
||||
│ └── configuracion/ # Configuracion del sistema
|
||||
└── api/ # API Routes
|
||||
└── trpc/ # Endpoint tRPC
|
||||
```
|
||||
|
||||
### 2. Backend (tRPC + Prisma)
|
||||
|
||||
**Ubicacion**: `src/server/trpc/`
|
||||
|
||||
El backend utiliza tRPC para APIs type-safe con validacion Zod:
|
||||
|
||||
```typescript
|
||||
// Ejemplo de router
|
||||
export const equiposRouter = router({
|
||||
list: protectedProcedure
|
||||
.input(z.object({ clienteId: z.string().optional() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
return ctx.prisma.dispositivo.findMany({
|
||||
where: input.clienteId ? { clienteId: input.clienteId } : {},
|
||||
})
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
**Routers disponibles**:
|
||||
- `auth` - Autenticacion y sesiones
|
||||
- `clientes` - Gestion de clientes/tenants
|
||||
- `equipos` - PCs, laptops, servidores
|
||||
- `celulares` - Dispositivos moviles
|
||||
- `red` - Dispositivos de red
|
||||
- `alertas` - Sistema de alertas
|
||||
- `reportes` - Generacion de reportes
|
||||
- `usuarios` - Gestion de usuarios
|
||||
- `configuracion` - Configuracion del sistema
|
||||
|
||||
### 3. Servicios de Integracion
|
||||
|
||||
**Ubicacion**: `src/server/services/`
|
||||
|
||||
Clientes para comunicacion con sistemas externos:
|
||||
|
||||
```
|
||||
services/
|
||||
├── meshcentral/
|
||||
│ └── client.ts # Cliente API REST + WebSocket
|
||||
├── librenms/
|
||||
│ └── client.ts # Cliente API REST
|
||||
└── headwind/
|
||||
└── client.ts # Cliente API REST
|
||||
```
|
||||
|
||||
Cada cliente proporciona:
|
||||
- Autenticacion automatica
|
||||
- Manejo de errores
|
||||
- Tipado TypeScript
|
||||
- Cache de conexiones
|
||||
|
||||
### 4. Sistema de Jobs (BullMQ)
|
||||
|
||||
**Ubicacion**: `src/server/jobs/`
|
||||
|
||||
Procesamiento asincronico con BullMQ y Redis:
|
||||
|
||||
```
|
||||
jobs/
|
||||
├── queue.ts # Configuracion de colas
|
||||
├── worker.ts # Worker principal
|
||||
├── sync-meshcentral.job.ts
|
||||
├── sync-librenms.job.ts
|
||||
├── sync-headwind.job.ts
|
||||
├── alert-processor.job.ts
|
||||
├── notification.job.ts
|
||||
└── maintenance.job.ts
|
||||
```
|
||||
|
||||
**Colas**:
|
||||
| Cola | Proposito | Frecuencia |
|
||||
|------|-----------|------------|
|
||||
| sync | Sincronizacion con plataformas | Cada 5 min |
|
||||
| alerts | Procesamiento de alertas | Bajo demanda |
|
||||
| notifications | Envio de notificaciones | Bajo demanda |
|
||||
| maintenance | Tareas de mantenimiento | Diario/Horario |
|
||||
|
||||
### 5. Base de Datos (PostgreSQL + Prisma)
|
||||
|
||||
**Ubicacion**: `prisma/schema.prisma`
|
||||
|
||||
Modelo de datos multi-tenant:
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────────┐
|
||||
│ Cliente │────<│ Dispositivo │
|
||||
└─────────────┘ └─────────────────┘
|
||||
│ │
|
||||
│ ┌───────┴───────┐
|
||||
│ ▼ ▼
|
||||
│ ┌───────────────┐ ┌───────────────┐
|
||||
│ │ Metrica │ │ Software │
|
||||
│ └───────────────┘ └───────────────┘
|
||||
│
|
||||
├───<│ Usuario │
|
||||
│
|
||||
└───<│ Alerta │
|
||||
```
|
||||
|
||||
**Tablas principales**:
|
||||
- `clientes` - Tenants del sistema
|
||||
- `dispositivos` - Todos los tipos de dispositivos
|
||||
- `alertas` - Alertas y eventos
|
||||
- `usuarios` - Usuarios y permisos
|
||||
- `configuracion` - Settings del sistema
|
||||
|
||||
## Flujo de Datos
|
||||
|
||||
### 1. Sincronizacion de Dispositivos
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Plataforma │────>│ Worker │────>│ PostgreSQL │
|
||||
│ Externa │ │ (BullMQ) │ │ │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
▲ │
|
||||
│ ▼
|
||||
│ ┌─────────────┐
|
||||
│ │ Redis │
|
||||
│ │ (Cache) │
|
||||
│ └─────────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌─────────────┐
|
||||
└────────────│ Alerta │
|
||||
│ Processor │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
### 2. Consulta de Dispositivos
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Browser │────>│ Next.js │────>│ tRPC │
|
||||
│ │<────│ (SSR) │<────│ Router │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ Prisma │
|
||||
│ Client │
|
||||
└─────────────┘
|
||||
│
|
||||
┌───────────────────┴───────────────────┐
|
||||
▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ Redis │ │ PostgreSQL │
|
||||
│ (Cache) │ │ │
|
||||
└─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
### 3. Sesion Remota
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Usuario │────>│ Dashboard │────>│ MeshCentral │
|
||||
│ │ │ │ │ (iframe) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────┐ │
|
||||
│ │ Audit Log │<───────────┘
|
||||
│ └─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ WebSocket (MeshCentral) │
|
||||
│ Desktop / Terminal / Files │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Seguridad
|
||||
|
||||
### Autenticacion
|
||||
|
||||
- **MeshCentral SSO**: Integracion con autenticacion de MeshCentral
|
||||
- **JWT Sessions**: Tokens firmados con expiracion de 24h
|
||||
- **Password Hashing**: bcrypt con salt factor 12
|
||||
|
||||
### Autorizacion
|
||||
|
||||
```typescript
|
||||
// Roles jerarquicos
|
||||
enum RolUsuario {
|
||||
SUPER_ADMIN, // Acceso total
|
||||
ADMIN, // Admin de cliente
|
||||
TECNICO, // Operaciones
|
||||
CLIENTE, // Solo lectura
|
||||
VIEWER // Vista limitada
|
||||
}
|
||||
```
|
||||
|
||||
### Aislamiento de Datos
|
||||
|
||||
- Cada consulta filtra por `clienteId`
|
||||
- Middleware verifica permisos en cada request
|
||||
- Audit log de todas las acciones sensibles
|
||||
|
||||
## Escalabilidad
|
||||
|
||||
### Horizontal (futuro)
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ HAProxy │
|
||||
│ (LB) │
|
||||
└─────────────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
┌───────────┐ ┌───────────┐ ┌───────────┐
|
||||
│ Node 1 │ │ Node 2 │ │ Node 3 │
|
||||
│ (Next.js) │ │ (Next.js) │ │ (Worker) │
|
||||
└───────────┘ └───────────┘ └───────────┘
|
||||
│ │ │
|
||||
└───────────────┼───────────────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
┌───────────┐ ┌───────────┐ ┌───────────┐
|
||||
│ PostgreSQL│ │ Redis │ │ Redis │
|
||||
│ Primary │ │ Primary │ │ Replica │
|
||||
└───────────┘ └───────────┘ └───────────┘
|
||||
```
|
||||
|
||||
### Vertical (actual)
|
||||
|
||||
- **CPU**: Escalable segun carga
|
||||
- **RAM**: Minimo 4GB recomendado
|
||||
- **Disco**: SSD para BD, puede usar storage separado para backups
|
||||
|
||||
## Monitoreo del Sistema
|
||||
|
||||
### Health Checks
|
||||
|
||||
```bash
|
||||
# Endpoints de health
|
||||
GET /health # Estado general
|
||||
GET /api/health # Estado de API
|
||||
```
|
||||
|
||||
### Metricas
|
||||
|
||||
- CPU/RAM/Disco del servidor
|
||||
- Latencia de BD
|
||||
- Tamano de colas
|
||||
- Errores de sincronizacion
|
||||
|
||||
### Logs
|
||||
|
||||
```bash
|
||||
# Ver logs de contenedores
|
||||
docker-compose logs -f dashboard
|
||||
docker-compose logs -f worker
|
||||
```
|
||||
332
docs/guias/configuracion.md
Normal file
332
docs/guias/configuracion.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# Guia de Configuracion
|
||||
|
||||
## Configuracion General
|
||||
|
||||
### Variables de Entorno
|
||||
|
||||
El archivo `.env` contiene toda la configuracion del sistema:
|
||||
|
||||
```env
|
||||
# ==================== BASE DE DATOS ====================
|
||||
# URL de conexion a PostgreSQL
|
||||
DATABASE_URL="postgresql://usuario:password@host:5432/database?schema=public"
|
||||
|
||||
# Credenciales para Docker
|
||||
POSTGRES_USER=mspmonitor
|
||||
POSTGRES_PASSWORD=password-seguro
|
||||
POSTGRES_DB=msp_monitor
|
||||
|
||||
# ==================== CACHE Y COLAS ====================
|
||||
# URL de conexion a Redis
|
||||
REDIS_URL="redis://localhost:6379"
|
||||
|
||||
# ==================== SEGURIDAD ====================
|
||||
# Clave secreta para JWT (minimo 32 caracteres)
|
||||
JWT_SECRET="clave-muy-segura-de-al-menos-32-caracteres"
|
||||
|
||||
# ==================== INTEGRACIONES ====================
|
||||
# MeshCentral
|
||||
MESHCENTRAL_URL="https://mesh.tudominio.com"
|
||||
MESHCENTRAL_USER="admin"
|
||||
MESHCENTRAL_PASS="password"
|
||||
MESHCENTRAL_DOMAIN="default"
|
||||
|
||||
# LibreNMS
|
||||
LIBRENMS_URL="https://librenms.tudominio.com"
|
||||
LIBRENMS_TOKEN="tu-token-api"
|
||||
|
||||
# Headwind MDM
|
||||
HEADWIND_URL="https://mdm.tudominio.com"
|
||||
HEADWIND_TOKEN="tu-token-api"
|
||||
|
||||
# ==================== NOTIFICACIONES ====================
|
||||
# SMTP
|
||||
SMTP_HOST="smtp.gmail.com"
|
||||
SMTP_PORT="587"
|
||||
SMTP_USER="tu-email@gmail.com"
|
||||
SMTP_PASS="tu-app-password"
|
||||
SMTP_FROM="MSP Monitor <noreply@tudominio.com>"
|
||||
|
||||
# Twilio (opcional)
|
||||
TWILIO_ACCOUNT_SID=""
|
||||
TWILIO_AUTH_TOKEN=""
|
||||
TWILIO_PHONE_NUMBER=""
|
||||
|
||||
# ==================== APLICACION ====================
|
||||
# URL publica de la aplicacion
|
||||
NEXT_PUBLIC_APP_URL="https://monitor.tudominio.com"
|
||||
|
||||
# Entorno
|
||||
NODE_ENV="production"
|
||||
```
|
||||
|
||||
## Configuracion de Integraciones
|
||||
|
||||
### MeshCentral
|
||||
|
||||
1. **Crear usuario API en MeshCentral**:
|
||||
- Acceder a MeshCentral como admin
|
||||
- Ir a "My Account" > "Security" > "Create Login Token"
|
||||
- O crear usuario dedicado con permisos de API
|
||||
|
||||
2. **Configurar en el dashboard**:
|
||||
- Ir a Configuracion > Integraciones
|
||||
- Ingresar URL, usuario y password
|
||||
- Probar conexion
|
||||
|
||||
3. **Mapear grupos**:
|
||||
- Cada cliente puede tener un grupo de MeshCentral asignado
|
||||
- Los dispositivos del grupo se sincronizaran automaticamente
|
||||
|
||||
### LibreNMS
|
||||
|
||||
1. **Crear API Token en LibreNMS**:
|
||||
- Ir a "Settings" > "API" > "API Settings"
|
||||
- Crear nuevo token con permisos de lectura
|
||||
|
||||
2. **Configurar en el dashboard**:
|
||||
- Ir a Configuracion > Integraciones
|
||||
- Ingresar URL y token
|
||||
- Probar conexion
|
||||
|
||||
3. **Mapear grupos de dispositivos**:
|
||||
- Crear grupos en LibreNMS para cada cliente
|
||||
- Asignar el grupo al cliente en el dashboard
|
||||
|
||||
### Headwind MDM
|
||||
|
||||
1. **Obtener API Token**:
|
||||
- Acceder a panel de admin de Headwind
|
||||
- Ir a configuracion de API
|
||||
- Copiar token de acceso
|
||||
|
||||
2. **Configurar en el dashboard**:
|
||||
- Ir a Configuracion > Integraciones
|
||||
- Ingresar URL y token
|
||||
- Probar conexion
|
||||
|
||||
## Configuracion de Notificaciones
|
||||
|
||||
### Email (SMTP)
|
||||
|
||||
Para Gmail:
|
||||
1. Habilitar autenticacion de dos factores
|
||||
2. Crear "App Password" en configuracion de seguridad
|
||||
3. Usar el app password en `SMTP_PASS`
|
||||
|
||||
```env
|
||||
SMTP_HOST="smtp.gmail.com"
|
||||
SMTP_PORT="587"
|
||||
SMTP_USER="tu-cuenta@gmail.com"
|
||||
SMTP_PASS="xxxx-xxxx-xxxx-xxxx" # App password
|
||||
SMTP_FROM="MSP Monitor <noreply@tudominio.com>"
|
||||
```
|
||||
|
||||
Para otros proveedores:
|
||||
|
||||
| Proveedor | Host | Puerto |
|
||||
|-----------|------|--------|
|
||||
| Gmail | smtp.gmail.com | 587 |
|
||||
| Office 365 | smtp.office365.com | 587 |
|
||||
| SendGrid | smtp.sendgrid.net | 587 |
|
||||
| Mailgun | smtp.mailgun.org | 587 |
|
||||
|
||||
### SMS (Twilio)
|
||||
|
||||
1. Crear cuenta en Twilio
|
||||
2. Obtener Account SID y Auth Token
|
||||
3. Comprar numero de telefono
|
||||
4. Configurar en `.env`:
|
||||
|
||||
```env
|
||||
TWILIO_ACCOUNT_SID="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
TWILIO_AUTH_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
TWILIO_PHONE_NUMBER="+1234567890"
|
||||
```
|
||||
|
||||
### Webhooks
|
||||
|
||||
Los webhooks se configuran por regla de alerta:
|
||||
|
||||
1. Crear regla de alerta
|
||||
2. Habilitar "Notificar por Webhook"
|
||||
3. Ingresar URL del endpoint
|
||||
|
||||
Formato del payload:
|
||||
```json
|
||||
{
|
||||
"id": "alert-id",
|
||||
"severidad": "CRITICAL",
|
||||
"titulo": "Titulo de la alerta",
|
||||
"mensaje": "Descripcion detallada",
|
||||
"dispositivo": "Nombre del dispositivo",
|
||||
"cliente": "Nombre del cliente",
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Configuracion de Usuarios y Permisos
|
||||
|
||||
### Roles de Usuario
|
||||
|
||||
| Rol | Descripcion | Permisos |
|
||||
|-----|-------------|----------|
|
||||
| SUPER_ADMIN | Administrador global | Todo |
|
||||
| ADMIN | Admin de cliente | Gestion de su cliente |
|
||||
| TECNICO | Soporte tecnico | Operaciones y monitoreo |
|
||||
| CLIENTE | Usuario cliente | Solo lectura |
|
||||
| VIEWER | Vista limitada | Dashboard basico |
|
||||
|
||||
### Crear Usuario
|
||||
|
||||
1. Ir a Configuracion > Usuarios
|
||||
2. Click en "Nuevo Usuario"
|
||||
3. Completar:
|
||||
- Email
|
||||
- Nombre
|
||||
- Rol
|
||||
- Cliente (opcional)
|
||||
- Password (o usar SSO de MeshCentral)
|
||||
|
||||
### Permisos Granulares
|
||||
|
||||
Ademas del rol, se pueden asignar permisos especificos:
|
||||
|
||||
```
|
||||
recursos: dispositivos, alertas, reportes, configuracion, usuarios
|
||||
acciones: read, write, delete, execute
|
||||
```
|
||||
|
||||
## Configuracion de Alertas
|
||||
|
||||
### Reglas Predefinidas
|
||||
|
||||
El sistema incluye reglas por defecto:
|
||||
|
||||
| Regla | Metrica | Umbral | Severidad |
|
||||
|-------|---------|--------|-----------|
|
||||
| CPU Alta | cpu | > 90% | WARNING |
|
||||
| CPU Critica | cpu | > 95% | CRITICAL |
|
||||
| RAM Alta | ram | > 85% | WARNING |
|
||||
| Disco Lleno | disco | > 90% | WARNING |
|
||||
| Temperatura Alta | temperatura | > 80 | WARNING |
|
||||
| Bateria Baja | bateria | < 15 | WARNING |
|
||||
|
||||
### Crear Regla Personalizada
|
||||
|
||||
1. Ir a Alertas > Reglas
|
||||
2. Click en "Nueva Regla"
|
||||
3. Configurar:
|
||||
- Nombre descriptivo
|
||||
- Tipo de dispositivo (opcional)
|
||||
- Metrica a monitorear
|
||||
- Condicion (>, <, >=, <=, ==)
|
||||
- Valor umbral
|
||||
- Duracion minima (evitar falsos positivos)
|
||||
- Severidad
|
||||
- Canales de notificacion
|
||||
|
||||
## Configuracion de Backups
|
||||
|
||||
### Backup Automatico
|
||||
|
||||
Agregar al crontab del servidor:
|
||||
|
||||
```bash
|
||||
# Backup diario a las 2am
|
||||
0 2 * * * /opt/msp-monitor/scripts/backup-db.sh >> /var/log/msp-backup.log 2>&1
|
||||
```
|
||||
|
||||
### Configuracion de Backup
|
||||
|
||||
Variables en `.env`:
|
||||
|
||||
```env
|
||||
# Directorio de backups
|
||||
BACKUP_DIR="/backups"
|
||||
|
||||
# Dias de retencion
|
||||
RETENTION_DAYS=30
|
||||
|
||||
# S3 (opcional)
|
||||
S3_BUCKET="mi-bucket-backups"
|
||||
AWS_ACCESS_KEY_ID="..."
|
||||
AWS_SECRET_ACCESS_KEY="..."
|
||||
```
|
||||
|
||||
### Restaurar Backup
|
||||
|
||||
```bash
|
||||
./scripts/restore-db.sh /backups/msp_monitor_20240115_020000.sql.gz
|
||||
```
|
||||
|
||||
## Configuracion de SSL
|
||||
|
||||
### Renovacion Automatica
|
||||
|
||||
El contenedor de Certbot renueva automaticamente. Verificar:
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml logs certbot
|
||||
```
|
||||
|
||||
### Certificado Manual
|
||||
|
||||
1. Copiar certificados a `docker/nginx/ssl/`
|
||||
2. Actualizar paths en `docker/nginx/conf.d/default.conf`
|
||||
3. Reiniciar Nginx: `docker compose restart nginx`
|
||||
|
||||
## Configuracion de Logs
|
||||
|
||||
### Niveles de Log
|
||||
|
||||
En `.env`:
|
||||
```env
|
||||
# Nivel de log: debug, info, warn, error
|
||||
LOG_LEVEL="info"
|
||||
```
|
||||
|
||||
### Rotacion de Logs
|
||||
|
||||
Docker maneja la rotacion. Configurar en `/etc/docker/daemon.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Personalizacion
|
||||
|
||||
### Tema Visual
|
||||
|
||||
Editar `tailwind.config.ts` para cambiar colores:
|
||||
|
||||
```typescript
|
||||
colors: {
|
||||
primary: {
|
||||
500: '#06b6d4', // Color principal
|
||||
// ...
|
||||
},
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Logo
|
||||
|
||||
Reemplazar archivo en `public/logo.png`
|
||||
|
||||
### Titulo
|
||||
|
||||
Editar `src/app/layout.tsx`:
|
||||
|
||||
```typescript
|
||||
export const metadata: Metadata = {
|
||||
title: 'Mi Dashboard MSP',
|
||||
// ...
|
||||
}
|
||||
```
|
||||
359
docs/guias/instalacion.md
Normal file
359
docs/guias/instalacion.md
Normal file
@@ -0,0 +1,359 @@
|
||||
# Guia de Instalacion
|
||||
|
||||
## Requisitos del Sistema
|
||||
|
||||
### Hardware Minimo
|
||||
|
||||
| Componente | Minimo | Recomendado |
|
||||
|------------|--------|-------------|
|
||||
| CPU | 2 cores | 4+ cores |
|
||||
| RAM | 4 GB | 8+ GB |
|
||||
| Disco | 40 GB SSD | 100+ GB SSD |
|
||||
| Red | 100 Mbps | 1 Gbps |
|
||||
|
||||
### Software
|
||||
|
||||
- **Sistema Operativo**: Ubuntu 22.04 LTS o Debian 12
|
||||
- **Docker**: 24.0+
|
||||
- **Docker Compose**: 2.20+
|
||||
- **Node.js**: 20.x (solo para desarrollo)
|
||||
|
||||
### Requisitos de Red
|
||||
|
||||
- Puerto 80 (HTTP)
|
||||
- Puerto 443 (HTTPS)
|
||||
- Puerto 5432 (PostgreSQL, solo interno)
|
||||
- Puerto 6379 (Redis, solo interno)
|
||||
- Acceso a MeshCentral, LibreNMS y/o Headwind MDM
|
||||
|
||||
## Instalacion en Produccion
|
||||
|
||||
### 1. Preparar el Servidor
|
||||
|
||||
```bash
|
||||
# Actualizar sistema
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# Instalar dependencias
|
||||
sudo apt install -y curl git
|
||||
|
||||
# Instalar Docker
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
sudo sh get-docker.sh
|
||||
|
||||
# Agregar usuario al grupo docker
|
||||
sudo usermod -aG docker $USER
|
||||
newgrp docker
|
||||
|
||||
# Instalar Docker Compose
|
||||
sudo apt install -y docker-compose-plugin
|
||||
```
|
||||
|
||||
### 2. Clonar el Repositorio
|
||||
|
||||
```bash
|
||||
# Crear directorio
|
||||
sudo mkdir -p /opt/msp-monitor
|
||||
cd /opt/msp-monitor
|
||||
|
||||
# Clonar repositorio
|
||||
git clone https://git.consultoria-as.com/msp/msp-monitor-dashboard.git .
|
||||
|
||||
# Configurar permisos
|
||||
sudo chown -R $USER:$USER /opt/msp-monitor
|
||||
```
|
||||
|
||||
### 3. Configurar Variables de Entorno
|
||||
|
||||
```bash
|
||||
# Copiar archivo de ejemplo
|
||||
cp .env.example .env
|
||||
|
||||
# Editar configuracion
|
||||
nano .env
|
||||
```
|
||||
|
||||
Configuracion minima requerida:
|
||||
|
||||
```env
|
||||
# Seguridad - CAMBIAR ESTOS VALORES
|
||||
POSTGRES_PASSWORD=<password-seguro>
|
||||
JWT_SECRET=<clave-jwt-minimo-32-caracteres>
|
||||
|
||||
# MeshCentral (opcional si no se usa)
|
||||
MESHCENTRAL_URL=https://mesh.tudominio.com
|
||||
MESHCENTRAL_USER=admin
|
||||
MESHCENTRAL_PASS=password
|
||||
MESHCENTRAL_DOMAIN=default
|
||||
|
||||
# LibreNMS (opcional si no se usa)
|
||||
LIBRENMS_URL=https://librenms.tudominio.com
|
||||
LIBRENMS_TOKEN=tu-api-token
|
||||
|
||||
# Headwind MDM (opcional si no se usa)
|
||||
HEADWIND_URL=https://mdm.tudominio.com
|
||||
HEADWIND_TOKEN=tu-api-token
|
||||
|
||||
# Email (para notificaciones)
|
||||
SMTP_HOST=smtp.gmail.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=tu-email@gmail.com
|
||||
SMTP_PASS=tu-app-password
|
||||
SMTP_FROM=MSP Monitor <noreply@tudominio.com>
|
||||
|
||||
# URL de la aplicacion
|
||||
APP_URL=https://monitor.tudominio.com
|
||||
```
|
||||
|
||||
### 4. Configurar SSL
|
||||
|
||||
#### Opcion A: Certificado Let's Encrypt (recomendado)
|
||||
|
||||
```bash
|
||||
# Crear directorios
|
||||
mkdir -p docker/nginx/ssl
|
||||
|
||||
# Iniciar Nginx sin SSL primero
|
||||
docker compose -f docker/docker-compose.yml up -d nginx
|
||||
|
||||
# Obtener certificado
|
||||
docker compose -f docker/docker-compose.yml run --rm certbot certonly \
|
||||
--webroot \
|
||||
--webroot-path=/var/www/certbot \
|
||||
-d monitor.tudominio.com \
|
||||
--email tu-email@tudominio.com \
|
||||
--agree-tos \
|
||||
--no-eff-email
|
||||
|
||||
# Reiniciar con SSL
|
||||
docker compose -f docker/docker-compose.yml restart nginx
|
||||
```
|
||||
|
||||
#### Opcion B: Certificado Propio
|
||||
|
||||
```bash
|
||||
# Copiar certificados
|
||||
cp /ruta/certificado.crt docker/nginx/ssl/live/monitor.tudominio.com/fullchain.pem
|
||||
cp /ruta/certificado.key docker/nginx/ssl/live/monitor.tudominio.com/privkey.pem
|
||||
```
|
||||
|
||||
### 5. Configurar Nginx
|
||||
|
||||
Editar `docker/nginx/conf.d/default.conf`:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name monitor.tudominio.com; # Cambiar por tu dominio
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/live/monitor.tudominio.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/live/monitor.tudominio.com/privkey.pem;
|
||||
|
||||
# ... resto de configuracion
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Iniciar Servicios
|
||||
|
||||
```bash
|
||||
# Construir imagenes
|
||||
docker compose -f docker/docker-compose.yml build
|
||||
|
||||
# Iniciar servicios
|
||||
docker compose -f docker/docker-compose.yml up -d
|
||||
|
||||
# Verificar estado
|
||||
docker compose -f docker/docker-compose.yml ps
|
||||
```
|
||||
|
||||
### 7. Aplicar Migraciones
|
||||
|
||||
```bash
|
||||
# Ejecutar migraciones
|
||||
docker compose -f docker/docker-compose.yml exec dashboard npx prisma db push
|
||||
|
||||
# Verificar conexion a BD
|
||||
docker compose -f docker/docker-compose.yml exec dashboard npx prisma studio
|
||||
```
|
||||
|
||||
### 8. Crear Usuario Administrador
|
||||
|
||||
```bash
|
||||
# Conectar a la BD
|
||||
docker compose -f docker/docker-compose.yml exec postgres psql -U mspmonitor -d msp_monitor
|
||||
|
||||
# Crear usuario (dentro de psql)
|
||||
INSERT INTO usuarios (id, email, nombre, password_hash, rol, activo, created_at, updated_at)
|
||||
VALUES (
|
||||
gen_random_uuid(),
|
||||
'admin@tudominio.com',
|
||||
'Administrador',
|
||||
'$2a$12$hash-del-password', -- Generar con bcrypt
|
||||
'SUPER_ADMIN',
|
||||
true,
|
||||
NOW(),
|
||||
NOW()
|
||||
);
|
||||
```
|
||||
|
||||
O usando el script de setup interactivo:
|
||||
|
||||
```bash
|
||||
./scripts/setup.sh
|
||||
```
|
||||
|
||||
### 9. Verificar Instalacion
|
||||
|
||||
1. Acceder a `https://monitor.tudominio.com`
|
||||
2. Iniciar sesion con las credenciales creadas
|
||||
3. Verificar conexion a MeshCentral, LibreNMS, Headwind
|
||||
4. Revisar logs: `docker compose -f docker/docker-compose.yml logs -f`
|
||||
|
||||
## Instalacion en Desarrollo
|
||||
|
||||
### 1. Requisitos
|
||||
|
||||
- Node.js 20+
|
||||
- npm o yarn
|
||||
- Docker (para PostgreSQL y Redis)
|
||||
|
||||
### 2. Configurar Entorno
|
||||
|
||||
```bash
|
||||
# Clonar repositorio
|
||||
git clone https://git.consultoria-as.com/msp/msp-monitor-dashboard.git
|
||||
cd msp-monitor-dashboard
|
||||
|
||||
# Instalar dependencias
|
||||
npm install
|
||||
|
||||
# Configurar variables
|
||||
cp .env.example .env
|
||||
# Editar .env con configuracion local
|
||||
```
|
||||
|
||||
### 3. Iniciar Servicios de Base de Datos
|
||||
|
||||
```bash
|
||||
# Solo PostgreSQL y Redis
|
||||
docker compose -f docker/docker-compose.yml up -d postgres redis
|
||||
```
|
||||
|
||||
### 4. Configurar Base de Datos
|
||||
|
||||
```bash
|
||||
# Generar cliente Prisma
|
||||
npm run db:generate
|
||||
|
||||
# Aplicar schema
|
||||
npm run db:push
|
||||
|
||||
# (Opcional) Abrir Prisma Studio
|
||||
npm run db:studio
|
||||
```
|
||||
|
||||
### 5. Iniciar Desarrollo
|
||||
|
||||
```bash
|
||||
# Iniciar servidor de desarrollo
|
||||
npm run dev
|
||||
|
||||
# En otra terminal, iniciar workers (opcional)
|
||||
npm run jobs:start
|
||||
```
|
||||
|
||||
Acceder a `http://localhost:3000`
|
||||
|
||||
## Actualizacion
|
||||
|
||||
### Actualizacion en Produccion
|
||||
|
||||
```bash
|
||||
cd /opt/msp-monitor
|
||||
|
||||
# Detener servicios
|
||||
docker compose -f docker/docker-compose.yml down
|
||||
|
||||
# Actualizar codigo
|
||||
git pull origin main
|
||||
|
||||
# Reconstruir imagenes
|
||||
docker compose -f docker/docker-compose.yml build
|
||||
|
||||
# Iniciar servicios
|
||||
docker compose -f docker/docker-compose.yml up -d
|
||||
|
||||
# Aplicar migraciones si hay cambios de BD
|
||||
docker compose -f docker/docker-compose.yml exec dashboard npx prisma db push
|
||||
```
|
||||
|
||||
### Actualizacion en Desarrollo
|
||||
|
||||
```bash
|
||||
# Actualizar codigo
|
||||
git pull origin main
|
||||
|
||||
# Actualizar dependencias
|
||||
npm install
|
||||
|
||||
# Regenerar cliente Prisma
|
||||
npm run db:generate
|
||||
|
||||
# Aplicar migraciones
|
||||
npm run db:push
|
||||
```
|
||||
|
||||
## Solucion de Problemas
|
||||
|
||||
### Error de Conexion a Base de Datos
|
||||
|
||||
```bash
|
||||
# Verificar que PostgreSQL esta corriendo
|
||||
docker compose -f docker/docker-compose.yml ps postgres
|
||||
|
||||
# Ver logs de PostgreSQL
|
||||
docker compose -f docker/docker-compose.yml logs postgres
|
||||
|
||||
# Verificar conectividad
|
||||
docker compose -f docker/docker-compose.yml exec postgres pg_isready
|
||||
```
|
||||
|
||||
### Error de Conexion a Redis
|
||||
|
||||
```bash
|
||||
# Verificar que Redis esta corriendo
|
||||
docker compose -f docker/docker-compose.yml ps redis
|
||||
|
||||
# Probar conexion
|
||||
docker compose -f docker/docker-compose.yml exec redis redis-cli ping
|
||||
```
|
||||
|
||||
### Dashboard no Carga
|
||||
|
||||
```bash
|
||||
# Ver logs del dashboard
|
||||
docker compose -f docker/docker-compose.yml logs dashboard
|
||||
|
||||
# Verificar variables de entorno
|
||||
docker compose -f docker/docker-compose.yml exec dashboard env
|
||||
|
||||
# Reiniciar servicio
|
||||
docker compose -f docker/docker-compose.yml restart dashboard
|
||||
```
|
||||
|
||||
### Workers no Procesan Jobs
|
||||
|
||||
```bash
|
||||
# Ver logs del worker
|
||||
docker compose -f docker/docker-compose.yml logs worker
|
||||
|
||||
# Verificar colas en Redis
|
||||
docker compose -f docker/docker-compose.yml exec redis redis-cli KEYS "bull:*"
|
||||
```
|
||||
|
||||
## Proximos Pasos
|
||||
|
||||
- [Configuracion del Sistema](configuracion.md)
|
||||
- [Integracion con MeshCentral](../integraciones/meshcentral.md)
|
||||
- [Integracion con LibreNMS](../integraciones/librenms.md)
|
||||
- [Integracion con Headwind MDM](../integraciones/headwind.md)
|
||||
Reference in New Issue
Block a user