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) | No | ZeroClaw consulta api.telegram.org, funciona detrás de NAT |
| Matrix / Mattermost / Nextcloud Talk | No | Sync/WebSocket, solo saliente |
| Discord / Slack (Modo de socket) | No | WebSocket de salida |
Signal (signal-cli-rest-api) | No | Contenedor de localhost |
| Nostr / IMAP / MQTT | No | Todos los salientes |
| Webhooks (GitHub, Slack Events API, WhatsApp, bot de Nextcloud Talk, personalizado) | Sí | Se requiere un punto de conexión POST público |
| Emparejamiento de puerta de enlace desde LAN | Sí (alcance de LAN) | Vincular a 0.0.0.0 o usar un túnel |
| Discord / Slack (Eventos HTTP) | Sí | 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:
| Proveedor | Configurar fricción | Costo | Bueno para |
|---|---|---|---|
tailscale | Cuenta + cliente | Capa gratuita | URLs estables a largo plazo |
cloudflare | Cuenta + cloudflared + token | Gratis | Dominios personalizados |
ngrok | Cuenta + agente + token | Gratis con límites | Pruebas, de corta duración |
pinggy | SSH, sin cuenta | Capa gratuita | URLs rápidas de un solo uso |
openvpn | Tu propio egress OpenVPN | Autoalojado | Infraestructura VPN existente |
custom | Un comando bajo [tunnel.custom] | Depende de | Algo 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:
-
ps aux | grep zeroclawy confirma que solo se está ejecutando un daemon. -
Verifica que no tengas
cargo run --bin zeroclaw -- channel start telegramde una sesión de desarrollo pendiente. -
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:
secretconfigurado 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_secen la configuración del canal de webhook
Consulta Canales → Webhooks para ver el conjunto completo de opciones.
Ver también
- Configuración → Contenedor: configuración de red específica de Docker
- Configuración → Gestión de servicios: integración del servicio de la plataforma
- Operaciones → Resumen
- Seguridad → Resumen