248 lines
9.9 KiB
Text
248 lines
9.9 KiB
Text
══════════════════════════════════════════════════════════════════════
|
|
RESETEA.NET — DOCUMENTACIÓN TÉCNICA
|
|
Actualizado: 2026-04
|
|
══════════════════════════════════════════════════════════════════════
|
|
|
|
|
|
PUERTOS
|
|
───────
|
|
80 Nginx — HTTP (redirige a HTTPS automáticamente)
|
|
443 Nginx — HTTPS (SSL/TLS, certificado Let's Encrypt)
|
|
8787 Node.js/Express — Solo escucha en 127.0.0.1 (loopback, no expuesto)
|
|
Nginx hace de proxy inverso: /api/* → 127.0.0.1:8787
|
|
|
|
⚠ El puerto 8787 NO debe abrirse en el firewall. Solo Nginx lo usa.
|
|
|
|
|
|
ENDPOINTS DE LA API
|
|
────────────────────
|
|
Base: https://resetea.net/api/
|
|
|
|
POST /api/erase
|
|
Descripción: Envía carta GDPR Art. 17 al DPO de la plataforma.
|
|
Content-Type: application/json
|
|
Rate limit: 10 peticiones / hora / IP
|
|
Body:
|
|
{
|
|
"provider": "instagram", ← obligatorio
|
|
"email": "tu@email.com",← obligatorio
|
|
"nickname": "usuario123", ← opcional
|
|
"phone": "+34 600...", ← opcional
|
|
"address": "Calle...", ← opcional
|
|
"extra": "Texto libre" ← opcional
|
|
}
|
|
Respuesta OK:
|
|
{ "status": "ok", "message": "...", "reference": "abc123def456" }
|
|
Respuesta proveedor sin email:
|
|
{ "status": "use_form", "formUrl": "https://...", "reference": "..." }
|
|
Respuesta error:
|
|
{ "error": "descripción del error" }
|
|
|
|
GET /api/egosearch?q=<consulta>
|
|
Descripción: Busca en la web menciones del término indicado.
|
|
Rate limit: 8 peticiones / minuto / IP
|
|
Parámetros:
|
|
q (string, 2-150 chars) — nombre o alias a buscar
|
|
Respuesta:
|
|
{ "results": [ { "title", "url", "snippet", "domain", "engine" } ], "query", "total" }
|
|
Nota: sin operadores especiales, la query se envuelve en comillas automáticamente.
|
|
|
|
GET /api/gmail/auth?provider=&name=&email=&...
|
|
Descripción: Inicia flujo OAuth2 para enviar carta desde Gmail del usuario.
|
|
Parámetros: provider, name, email (obligatorios) + nickname, phone, address, extra, requestType (opcionales)
|
|
Respuesta: Redirect a Google OAuth2.
|
|
Requiere: GOOGLE_CLIENT_ID y GOOGLE_CLIENT_SECRET en .env
|
|
|
|
GET /api/gmail/callback?code=&state=&error=
|
|
Descripción: Callback OAuth2 de Google. Envía el email y descarta el token.
|
|
Respuesta: Redirect a /plantillas.html?oauth=ok|cancelled|error|no_email
|
|
|
|
GET /api/health
|
|
Descripción: Health check.
|
|
Respuesta: { "status": "ok" }
|
|
|
|
|
|
VARIABLES DE ENTORNO (.env en api/)
|
|
─────────────────────────────────────
|
|
Obligatorias:
|
|
SALT Cadena aleatoria larga para hash de referencia de auditoría.
|
|
Ejemplo: openssl rand -hex 32
|
|
PORT Puerto del servidor Node.js. Por defecto: 8787
|
|
|
|
Opcionales — Gmail OAuth2 (sin esto el botón "Enviar desde mi Gmail" no funciona):
|
|
GOOGLE_CLIENT_ID ID de cliente OAuth2 de Google Cloud Console
|
|
GOOGLE_CLIENT_SECRET Secreto del cliente OAuth2
|
|
GOOGLE_REDIRECT_URI URI de callback. Valor: https://resetea.net/api/gmail/callback
|
|
|
|
Opcionales — Google Custom Search (sin esto egosearch usa SearXNG):
|
|
GOOGLE_API_KEY API Key de Google Cloud Console (Custom Search API habilitada)
|
|
GOOGLE_CSE_ID ID del motor de búsqueda de Programmable Search Engine
|
|
|
|
Plantilla del archivo .env:
|
|
SALT=<openssl rand -hex 32>
|
|
PORT=8787
|
|
GOOGLE_CLIENT_ID=
|
|
GOOGLE_CLIENT_SECRET=
|
|
GOOGLE_REDIRECT_URI=https://resetea.net/api/gmail/callback
|
|
GOOGLE_API_KEY=
|
|
GOOGLE_CSE_ID=
|
|
|
|
|
|
DEPENDENCIAS DEL BACKEND (npm)
|
|
────────────────────────────────
|
|
Producción (api/package.json):
|
|
express ^4.19.2 Framework HTTP
|
|
helmet ^7.1.0 Cabeceras de seguridad HTTP
|
|
express-rate-limit ^7.3.1 Rate limiting por IP
|
|
nodemailer ^6.9.13 Envío de emails via sendmail local
|
|
googleapis ^144.0.0 Gmail API + OAuth2 (para envío desde Gmail del usuario)
|
|
dotenv ^16.4.5 Carga de variables de entorno desde .env
|
|
|
|
Sin dependencias de frontend (HTML/CSS/JS puro, sin frameworks).
|
|
|
|
|
|
SOFTWARE DEL SISTEMA NECESARIO
|
|
────────────────────────────────
|
|
Obligatorio:
|
|
Node.js >= 18 Servidor backend
|
|
npm >= 8 Gestor de paquetes Node
|
|
Nginx Servidor web / proxy inverso
|
|
Certbot (Let's Encrypt) Certificados SSL — certbot --nginx
|
|
|
|
Para el envío de emails (POST /api/erase):
|
|
Un MTA (Mail Transfer Agent) local que provea /usr/sbin/sendmail.
|
|
Opciones comunes:
|
|
· Postfix: apt install postfix (recomendado, configurar como "Internet Site")
|
|
· msmtp: apt install msmtp msmtp-mta (más simple, relay a servidor externo)
|
|
· Exim4: apt install exim4
|
|
|
|
⚠ SIN MTA el endpoint POST /api/erase fallará silenciosamente.
|
|
El binario /usr/sbin/sendmail debe existir en el sistema.
|
|
Para verificar: which sendmail
|
|
|
|
Dominio de envío configurado en mailer.js:
|
|
From: privacy@resetea.net
|
|
El dominio resetea.net debe tener registros SPF/DKIM/DMARC correctos
|
|
para que los emails no lleguen a spam.
|
|
|
|
|
|
CONFIGURACIÓN DE NGINX
|
|
───────────────────────
|
|
Archivo: infra/nginx-resetea.conf
|
|
Copiar en: /etc/nginx/sites-available/resetea.net
|
|
Activar: ln -s /etc/nginx/sites-available/resetea.net /etc/nginx/sites-enabled/
|
|
nginx -t && nginx -s reload
|
|
|
|
Lo que hace:
|
|
· Puerto 80 → redirect 301 a HTTPS.
|
|
· Puerto 443 → sirve public/ como estático.
|
|
· /api/* → proxy a 127.0.0.1:8787 con X-Real-IP = $remote_addr.
|
|
· Rate limit Nginx: 20 req/s por IP, burst 40 en /api/.
|
|
· Headers de seguridad: HSTS, X-Frame-Options, CSP, Referrer-Policy,
|
|
Permissions-Policy, COOP, X-Content-Type-Options.
|
|
· Timeout proxy: read 15s, connect 5s.
|
|
· server_tokens off (oculta versión de Nginx).
|
|
|
|
SSL (Let's Encrypt):
|
|
certbot --nginx -d resetea.net
|
|
Rutas de certificados:
|
|
/etc/letsencrypt/live/resetea.net/fullchain.pem
|
|
/etc/letsencrypt/live/resetea.net/privkey.pem
|
|
|
|
|
|
FUENTES TIPOGRÁFICAS (public/fonts/)
|
|
──────────────────────────────────────
|
|
RECION.otf / RECION.ttf Títulos (h1, h2, h3, chips, logo)
|
|
Italiana-Regular.ttf Alternativa serif
|
|
CormorantGaramond-Regular.woff2 Cuerpo de texto elegante
|
|
CormorantGaramond-Italic.woff2 Cursiva
|
|
|
|
|
|
ARRANCAR EL BACKEND
|
|
────────────────────
|
|
cd /var/www/resetea.net/api
|
|
npm install ← solo la primera vez o tras cambiar package.json
|
|
node app.js ← arranque simple
|
|
|
|
Para producción (sin systemd todavía):
|
|
npm install -g pm2
|
|
pm2 start app.js --name resetea
|
|
pm2 save
|
|
pm2 startup ← genera el comando para arranque automático
|
|
|
|
Para crear un servicio systemd (recomendado):
|
|
Crear /etc/systemd/system/resetea.service:
|
|
[Unit]
|
|
Description=RESETEA.NET backend
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=www-data
|
|
WorkingDirectory=/var/www/resetea.net/api
|
|
ExecStart=/usr/bin/node app.js
|
|
Restart=on-failure
|
|
EnvironmentFile=/var/www/resetea.net/api/.env
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
|
|
systemctl enable resetea
|
|
systemctl start resetea
|
|
|
|
|
|
APIS EXTERNAS UTILIZADAS
|
|
─────────────────────────
|
|
SearXNG (instancias públicas — sin key, gratuito):
|
|
Se usa como motor de búsqueda para egosurfing cuando no hay Google CSE.
|
|
Instancias hardcodeadas en egosearch.js:
|
|
https://searx.be
|
|
https://priv.au
|
|
https://search.mdosch.de
|
|
https://searxng.site
|
|
Se prueban en orden hasta obtener resultados. Timeout: 7s por instancia.
|
|
|
|
Google Custom Search API (opcional — mejora calidad de resultados):
|
|
https://programmablesearchengine.google.com/
|
|
https://console.cloud.google.com/ → Custom Search API
|
|
Requiere: GOOGLE_API_KEY + GOOGLE_CSE_ID en .env
|
|
|
|
Google Gmail API + OAuth2 (opcional — envío desde Gmail del usuario):
|
|
https://console.cloud.google.com/ → APIs y servicios → Gmail API
|
|
Tipo de credencial: OAuth2, Aplicación web
|
|
URI de redirección autorizado: https://resetea.net/api/gmail/callback
|
|
Scope usado: https://www.googleapis.com/auth/gmail.send
|
|
Requiere: GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET en .env
|
|
El token es de un solo uso (access_type: 'online', no refresh token).
|
|
|
|
Let's Encrypt (Certbot):
|
|
Renovación automática via cron o systemd timer.
|
|
Verificar: certbot renew --dry-run
|
|
|
|
|
|
ESTRUCTURA DE ARCHIVOS
|
|
───────────────────────
|
|
/var/www/resetea.net/
|
|
public/
|
|
index.html Panel principal
|
|
concienciacion.html Derechos GDPR
|
|
plantillas.html Generador de cartas (JS local)
|
|
tipos.html Tipos de información personal
|
|
egosurfing.html Guía OSINT + buscador integrado
|
|
index.css Design system completo (tema cálido, caoba/salvia)
|
|
fonts/ Tipografías locales
|
|
api/
|
|
app.js Entrada: Express + helmet + rate-limit + rutas
|
|
routes/
|
|
erase.js POST /api/erase — validación + envío GDPR
|
|
egosearch.js GET /api/egosearch — búsqueda SearXNG/Google CSE
|
|
gmail_oauth.js GET /api/gmail/auth y /callback — OAuth2 Gmail
|
|
services/
|
|
mailer.js Datos de 12 DPOs + plantilla carta Art.17 + nodemailer
|
|
.env Variables de entorno (NO subir a git)
|
|
package.json Dependencias npm
|
|
infra/
|
|
nginx-resetea.conf Config Nginx lista para copiar
|
|
CONTEXT.txt Contexto del proyecto (este documento complementario)
|
|
DOCS.txt Este archivo
|
|
context_puppeteer.txt Diseño de automatización Puppeteer (pendiente)
|