Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Despliegue de red

Desplegar ZeroClaw para que pueda recibir tráfico entrante: exposición del gateway, canales de webhook, túneles y configuraciones solo para LAN frente a configuraciones públicas. Las Raspberry Pi y otros hosts de la red doméstica son objetivos principales aquí.

Cuando importan los puertos de entrada

Modo¿Puerto de entrada?Notas
Telegram (polling largo)NoZeroClaw consulta api.telegram.org, funciona detrás de NAT
Matrix / Mattermost / Nextcloud TalkNoSync/WebSocket, solo saliente
Discord / Slack (Modo de socket)NoWebSocket de salida
Signal (signal-cli-rest-api)NoContenedor de localhost
Nostr / IMAP / MQTTNoTodos los salientes
Webhooks (GitHub, Slack Events API, WhatsApp, bot de Nextcloud Talk, personalizado)Se requiere un punto de conexión POST público
Emparejamiento de puerta de enlace desde LANSí (alcance de LAN)Vincular a 0.0.0.0 o usar un túnel
Discord / Slack (Eventos HTTP)Si no usas el Modo de Sockets

Conclusión: un bot exclusivo de Telegram se ejecuta en una Pi detrás de un router doméstico sin ningún reenvío de puertos. Cualquier cosa basada en webhooks necesita una URL accesible, que es donde entran en juego los túneles.

Vinculando la puerta de enlace

De forma predeterminada, el gateway se vincula a 127.0.0.1, inaccesible desde otros dispositivos. Tres opciones para exponerlo:

Opción 1: Vinculación pública (LAN)

Entonces cualquier dispositivo en la LAN puede acceder a http://<pi-ip>:42617. No sirve para webhooks accesibles desde internet, la IP pública de tu router no está redirigida a la Pi.

Seguridad: Es necesario establecer allow_public_bind = true porque vincularse a 0.0.0.0 representa un cambio significativo en la configuración de seguridad. Sin esta opción, el demonio se niega a ejecutarse. Esto es intencional.

Opción 2: Túnel (accesible desde internet)

Luego reinicia el daemon; el túnel se gestiona de forma declarativa desde la configuración, iniciándose junto con el gateway.

El túnel reenvía desde una URL pública hacia el gateway en 127.0.0.1. Sin configuración del router, sin puertos abiertos. Establece tunnel.tunnel_provider en uno de los valores compatibles; cada uno funciona de manera similar:

ProveedorConfigurar fricciónCostoBueno para
tailscaleCuenta + clienteCapa gratuitaURLs estables a largo plazo
cloudflareCuenta + cloudflared + tokenGratisDominios personalizados
ngrokCuenta + agente + tokenGratis con límitesPruebas, de corta duración
pinggySSH, sin cuentaCapa gratuitaURLs rápidas de un solo uso
openvpnTu propio egress OpenVPNAutoalojadoInfraestructura VPN existente
customUn comando bajo [tunnel.custom]Depende deAlgo más

tunnel_provider = "none" (el valor predeterminado) mantiene el gateway local sin túnel. Consulta la Referencia de configuración para los campos [tunnel.<provider>] de cada proveedor.

Opción 3: Proxy inverso

Ejecuta nginx / Caddy / Traefik delante de la puerta de enlace. Termina TLS allí y reenvía la conexión a localhost:42617. Adecuado para:

  • Servidores con una IP pública real
  • Configuraciones de proxy inverso existentes con Let’s Encrypt
  • Servir múltiples servicios en el mismo host

Una configuración mínima de Caddy:

agent.example.com {
    reverse_proxy localhost:42617
}

El gateway permanece vinculado a 127.0.0.1, el proxy es el que escucha.

Autenticación de webhook de puerta de enlace genérica

Las rutas POST /webhook y POST /sop/* exclusivas de SOP de la puerta de enlace pueden requerir, independientemente del emparejamiento, un encabezado de secreto compartido que coincida exactamente:

[gateway]
webhook_secret = "replace-with-a-random-secret"

Envía el valor como X-Webhook-Secret. Cuando require_pairing = true y webhook_secret está configurado, los clientes deben enviar tanto el token bearer emparejado como el secreto del webhook. El secreto de la puerta de enlace genérica está deliberadamente separado de [channels.webhook.<alias>].secret; los alias de canal utilizan sus propios listeners y, en su lugar, la verificación HMAC del cuerpo.

Las escrituras de configuración de Gateway surten efecto mediante la vista de configuración activa de Gateway. Las ediciones directas de archivos requieren la recarga normal del demonio (o un reinicio independiente de Gateway).

Recarga remota del daemon

POST /admin/reload vuelve a leer config.toml y reconstruye cada subsistema en el mismo proceso (mismo PID, tiempo de inactividad inferior a un segundo). Es la forma admitida de aplicar cambios de configuración sin un reinicio completo. De forma predeterminada solo acepta llamadas de loopback, por lo que un panel remoto o un curl desde otra máquina recibe 403 Forbidden.

Para permitir recargas remotas autenticadas:

[gateway]
allow_remote_admin = true    # off by default
require_pairing = true        # required for remote reload (also the default)

Con esto habilitado, un llamador que no sea de loopback puede acceder a /admin/reload solo si también pasa la autenticación de emparejamiento (Authorization: Bearer <token>). Los llamadores de loopback (la CLI local) siempre están permitidos y no necesitan token. /admin/shutdown y los endpoints de código de emparejamiento permanecen restringidos a localhost independientemente de este flag.

Debido a que el acceso remoto se aplica mediante emparejamiento, allow_remote_admin no tiene efecto a menos que require_pairing también esté activado: si el emparejamiento está deshabilitado, un llamador remoto no puede ser autenticado, por lo que la solicitud se rechaza con 403 Forbidden en lugar de permitirse de forma anónima. Esto hace imposible exponer una recarga remota sin autenticación cambiando un solo indicador.

Seguridad: deja allow_remote_admin desactivado a menos que necesites específicamente recargar desde otro host. Mantén require_pairing = true (el valor predeterminado) para que las recargas no puedan activarse de forma anónima.

Despliegue en Raspberry Pi

Requisitos previos

  • Raspberry Pi 3/4/5 (u otra SBC similar) con Raspberry Pi OS o Alpine
  • Conectividad de red (WiFi o Ethernet)
  • Opcional: periféricos USB para la integración de hardware

Instalar

Clona y ejecuta el instalador. Sin flags, entra en un selector interactivo donde eliges el tipo de build y qué características compilar, incluyendo las características de hardware para GPIO/I2C/SPI. En la Pi también usa los perfiles de cargo ajustados para la Pi; consulta Configuración de Raspberry Pi para la configuración de swap y la matriz de builds por modelo.

Raspberry Pi OS

git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
./install.sh

Alpine

apk add curl rust cargo openssl-dev pkgconf git
git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
./install.sh

Otorga acceso a GPIO, I2C, SPI a través de rppal cuando seleccionas las características de hardware. La unidad de servicio predeterminada ya agrega al usuario a los grupos gpio, spi, i2c.

Lista de verificación

  • Instala el binario (./install.sh, elige tus características en el selector)
  • Ejecuta zeroclaw quickstart
  • Configura tus canales. Telegram no necesita puerto; los webhooks necesitan un túnel
  • Instala el servicio: zeroclaw service install && zeroclaw service start
  • Para el acceso LAN: establece [gateway] host = "0.0.0.0" + allow_public_bind = true
  • Para webhooks: configura [tunnel] con un proveedor

Alpine Linux (OpenRC)

Los servicios de OpenRC se ejecutan a nivel del sistema. Instálelos como root:

sh

sudo zeroclaw service install

Crea:

  • /etc/init.d/zeroclaw: script de inicio
  • /etc/zeroclaw/: directorio de configuración
  • /var/log/zeroclaw/: archivos de registro

Habilitar y comenzar:

sh

sudo rc-update add zeroclaw default
sudo rc-service zeroclaw start
sudo rc-service zeroclaw status

Registros:

sh

sudo tail -f /var/log/zeroclaw/error.log

Notas de OpenRC

  • El servicio se ejecuta como zeroclaw:zeroclaw (menor privilegio)
  • Solo a nivel de sistema: no hay servicios OpenRC a nivel de usuario
  • Todas las operaciones de servicio requieren sudo.

Advertencia sobre el polling de Telegram

El método getUpdates de la Telegram Bot API es de un solo poller por token de bot. No puedes ejecutar dos instancias con el mismo token; la segunda recibe Conflict: terminated by other getUpdates request.

Si ves esto:

  1. ps aux | grep zeroclaw y confirma que solo se está ejecutando un daemon.

  2. Verifica que no tengas cargo run --bin zeroclaw -- channel start telegram de una sesión de desarrollo pendiente.

  3. Si está desactualizado, restablece la sesión de la encuesta de Telegram:

    sh

    curl -X POST "https://api.telegram.org/bot$TOKEN/close"
    

Exponer webhooks de forma segura

Una URL de webhook accesible públicamente es una superficie de ataque. Como mínimo:

  • Verificación de firma HMAC: secret configurado en cada canal de webhook
  • Lista de IPs permitidos de origen donde el servicio tiene IPs de salida fijas (GitHub, AWS SNS)
  • Limitación de tasa: rate_limit_per_sec en la configuración del canal de webhook

Consulta Canales → Webhooks para ver el conjunto completo de opciones.

Ver también