Publicar Atalaya en internet

Esta guía explica cómo administrar Atalaya desde fuera de tu red y cómo recibir en él los datos de agentes y satélites que están en otras redes, poniendo delante un proxy nginx. Atalaya no se expone directamente: todo pasa por el proxy.

internet :443  → nginx (termina TLS con Let's Encrypt)  → Atalaya :443  (web y API)
internet :8443 → nginx (stream, TLS sin terminar)       → Atalaya :8443 (agentes y satélites, mTLS)
internet :8444 → nginx (stream, TLS sin terminar)       → Atalaya :443  (alta de agentes)

Antes de abrir nada, lee los avisos de seguridad del final y activa la verificación en dos pasos obligatoria.

Qué hace cada puerto

Los agentes y satélites que están en una red sin salida directa hacia fuera de la LAN no necesitan puertos abiertos en su router: son ellos los que conectan hacia el 8443 y el 8444 del dominio público.

En Atalaya

En /etc/atalaya/atalaya.conf, sección [http], la dirección del proxy (o su red):

[http]
trusted_proxies = 192.168.1.50

Sin esto, Atalaya cree que todo el mundo viene de la IP del proxy: el límite de intentos de acceso sería uno solo para todo internet (cinco fallos de un atacante bloquearían a todos) y el registro no tendría las IP reales. Con trusted_proxies, Atalaya lee la IP real de X-Forwarded-For y solo se fía de esa cabecera cuando la conexión viene de uno de esos proxies. Reinicia el servicio tras cambiarlo.

Ajusta también Ajustes → Avisos → Dirección de la web a https://atalaya.EJEMPLO.TLD para que los avisos lleven el enlace correcto, y activa Verificación en dos pasos obligatoria.

Desde la 0.9.0, Atalaya envía por sí mismo la cabecera Strict-Transport-Security (HSTS, un año) mientras sirva TLS (lo normal): no la añadas también en nginx. La cookie de sesión lleva Secure tanto si Atalaya sirve TLS como si la petición llega por un proxy de confianza.

En nginx

Ejemplo (sustituye el dominio y la IP de Atalaya, 192.168.1.239 aquí):

stream {
    limit_conn_zone $binary_remote_addr zone=agentes:10m;
    server {
        listen 8443;
        limit_conn agentes 20;
        proxy_connect_timeout 10s;
        proxy_timeout 10m;
        proxy_pass 192.168.1.239:8443;
    }
    server {
        listen 8444;
        limit_conn agentes 10;
        proxy_pass 192.168.1.239:443;
    }
}

http {
    limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

    server {
        listen 80;
        server_name atalaya.EJEMPLO.TLD;
        location /.well-known/acme-challenge/ { root /var/www/acme; }
        location / { return 301 https://$host$request_uri; }
    }
    server {
        listen 443 ssl;
        http2 on;
        server_name atalaya.EJEMPLO.TLD;
        ssl_certificate     /etc/letsencrypt/live/atalaya.EJEMPLO.TLD/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/atalaya.EJEMPLO.TLD/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        server_tokens off;
        client_max_body_size 1m;

        # Estas dos no se publican: Prometheus y los agentes de IA entran por la red local o una VPN.
        location /metrics { return 404; }
        location /mcp     { return 404; }

        location = /api/v1/session       { limit_req zone=login burst=5 nodelay; include snippets/atalaya-proxy.conf; }
        location = /api/v1/session/mfa   { limit_req zone=login burst=5 nodelay; include snippets/atalaya-proxy.conf; }
        location = /api/v1/agents/enroll { limit_req zone=login burst=5 nodelay; include snippets/atalaya-proxy.conf; }
        location /                       { include snippets/atalaya-proxy.conf; }
    }
}

Y en snippets/atalaya-proxy.conf:

proxy_pass https://192.168.1.239:443;
proxy_ssl_verify off;                      # el certificado de Atalaya es propio; el tramo es interno
proxy_http_version 1.1;
proxy_set_header Host $host;               # necesario: Atalaya compara Origin con Host
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;

(X-Forwarded-For $remote_addr sustituye lo que mande el cliente: nunca uses $proxy_add_x_forwarded_for sin entenderlo.)

El certificado se pide con certbot certonly --webroot -w /var/www/acme -d atalaya.EJEMPLO.TLD y se renueva solo con su temporizador (--deploy-hook "systemctl reload nginx").

Dar de alta agentes y satélites externos

Cortafuegos y seguridad