Saltar al contenido principal

Haz OpenClaw privado con una VPN mesh de NetBird

· 19 min de lectura
Rafael Fernandes
Ingeniero de PLN y Redactor Técnico en WiLine
Share:
OpenClaw+NetBird

En el Artículo 2 pusimos Caddy delante de OpenClaw para HTTPS, y en el Artículo 3 añadimos un canal de Telegram. El gateway funciona — pero Caddy sigue escuchando en 0.0.0.0, alcanzable por cualquier cosa que pueda enrutar hasta la máquina. Esta es la chave de ouro de la serie: unimos el servidor y tu laptop a una mesh de NetBird, reapuntamos openclaw.local a la IP de la mesh y cerramos los puertos públicos. La misma URL https://openclaw.local/chat sigue funcionando — pero solo para tus dispositivos. Cada comando y error de abajo proviene de la ejecución real.

Reproducibilidad

Continúa desde los Artículos 1–3 en la misma Instancia WEC — Ubuntu, OpenClaw detrás de Caddy 2. Usamos NetBird gestionado (el tier gratuito en app.netbird.io) con el agente 0.73.2 tanto en el servidor (Linux, WireGuard de kernel) como en el cliente (macOS, userspace). NetBird está basado en WireGuard y es open source; también puedes autoalojar el control plane, que es un tema más grande para otro día.

Cómo funciona NetBird (y qué vas a construir)

NetBird tiene dos partes, y la distinción es justamente el punto:

  1. El control plane (el servicio gestionado de management + signal de NetBird) — esto es lo único con presencia pública. Cada dispositivo que quiere unirse se autentica contra él (con tu setup key o login SSO), y él intermedia el intercambio de la clave pública WireGuard de cada peer.
  2. El data plane — una vez autenticados, los peers se hablan directamente entre sí, cifrados de extremo a extremo sobre WireGuard. Tu tráfico real nunca pasa por un puerto público que tú gestiones; el control plane solo hizo las presentaciones.

Así que estás construyendo una mesh donde el Peer A (tu laptop) alcanza al Peer B (la máquina de OpenClaw) por su dirección privada 100.x — y openclaw.local apunta ahí, con Caddy ligado solo a esa interfaz. El lado público/LAN no tiene nada escuchando.

La idea clave para más adelante: la mesh no se limita a dos peers. Autentícate una vez, y cada nuevo servicio — Ollama, un VDI, WordPress — se une como otro peer con su propia dirección 100.x, alcanzable de forma privada con ningún puerto público que abrir. Configuras el modelo de auth una vez; añades servicios para siempre.

La internet pública solo alcanza al control plane de NetBird — y eso solo autentica peers, nunca lleva el tráfico de tu app. Tus servicios no están "bloqueados por firewall" tanto como invisibles: OpenClaw no tiene IP pública, así que simplemente no hay ruta hacia él desde internet. La única forma de entrar es ser un peer autenticado en la mesh.

En este tutorial conectamos los dos primeros peers — tu laptop y la máquina de OpenClaw. Los demás servicios dejan claro el punto: una vez configurada la auth, Ollama, un VDI, WordPress simplemente se unen a la misma mesh como otro peer 100.x — sin puertos públicos, sin exposición por servicio.

Levanta un control plane de NetBird

Toda mesh de NetBird tiene dos roles: peers — tus máquinas, es decir la máquina de OpenClaw de las Partes 1–3 y tu laptop — y un control plane que autentica esos peers y emite sus claves de inscripción. Ya tienes el peer (tu máquina de OpenClaw); ahora necesitas un control plane al que se una. Dos formas de conseguirlo:

  • Opción A — autoalójalo en WiLine (recomendada). Despliega la plantilla NetBird del Marketplace de WEC: una Instancia WEC dedicada que corre tu propio control plane de NetBird — dashboard, certificado de confianza, sin shell. Así tu red privada completa vive en WiLine — la máquina de OpenClaw y su control plane — sin depender de un tercero.
  • Opción B — NetBird gestionado (sin máquina extra). ¿No quieres correr tu propio control plane? Usa el tier gratuito en app.netbird.io — inicia sesión y listo; el control plane es la nube de NetBird. Luego salta a Ahora inscribe tus máquinas.
Dos máquinas, a propósito — y tu máquina de OpenClaw queda intacta

Con la Opción A correrás dos instancias: tu máquina de OpenClaw (Partes 1–3, sin cambios) y una segunda máquina dedicada al control plane (esta plantilla). Esa es la topología correcta — un control plane debe ser su propia máquina, nunca compartiendo con una carga de trabajo. Con la Opción B solo tienes tu única máquina de OpenClaw. En cualquier caso nunca reconstruyes la máquina de OpenClaw — en Ahora inscribe tus máquinas solo instalas el agente de NetBird en ella y se une a la mesh como peer.

Los pasos de abajo configuran la Opción A. WEC ejecuta la instalación; tú aportas un email y una IP pública, y unos minutos después tienes tu propio dashboard de NetBird en https://<your-ip>.apps.wiline.cloud con un certificado válido.

1. Obtén una IP pública (Elastic)

El dashboard necesita una dirección pública. En Networks → Elastic IPs, asigna una IP nueva o elige una libre, y anota su valor (la nuestra: 108.60.112.165). Debe estar en la VPC y zona en la que vas a desplegar. Pasos completos: Configurar Elastic IPs.

Una Elastic IP disponible en Networks → Elastic IPs

2. Despliega una VM con la plantilla

Esta nueva instancia se convierte en tu control plane de NetBird — una máquina aparte de tu instancia de OpenClaw, que queda intacta. Abre Deploy → Deploy a VM (recorrido completo: Desplegar una máquina virtual). Las elecciones que importan aquí:

  • Network — elige la red en la misma VPC/zona que tu Elastic IP (nosotros usamos Local Subnet en Princeton-VPC), para que la IP pueda adjuntarse después.
  • Template → Marketplace → Ubuntu 24.04 LTS Netbird.
  • Template Configuration — tu email de Let's Encrypt y la Elastic IP del paso 1 como dirección externa.

Template Configuration — email de Let&#39;s Encrypt y la Elastic IP

Termina el asistente y despliega.

3. Adjunta la Elastic IP a la nueva instancia

La IP no queda ligada al momento de desplegar — la adjuntas una vez que la VM está arriba. Ve a Networks → Elastic IPs → tu IP → ⋯ → Allocate, y selecciona tu nueva instancia (netbird-tutorial). Solo aparecen en la lista las VMs de la misma VPC.

Asignando la Elastic IP a la nueva VM

4. Espera al primer arranque, luego verifica que está arriba

La instancia muestra Running en Compute → Instances en menos de un minuto — pero la plantilla sigue trabajando unos minutos más después de eso, descargando e iniciando los contenedores de NetBird y levantando el dashboard. No esperes que la URL responda de inmediato.

Comprueba desde tu laptop por HTTPS (no con ping — ICMP está bloqueado por firewall, así que un ping fallido no significa que esté caído):

curl -skS -m 10 -o /dev/null -w "%{http_code}\n" https://<your-ip>.apps.wiline.cloud
  • 000 / connection refused → aún aprovisionando; espera un minuto y reintenta.
  • 301 luego 200 → está arriba (HTTP redirige a HTTPS).

Para verlo directamente, entra por SSH (ssh ubuntu@<your-ip>) y confirma que los contenedores están corriendo y que los puertos están ligados:

cloud-init status
sudo docker ps
sudo ss -tlnp | grep -E ':(80|443)'

Está listo una vez que netbird-dashboard, netbird-traefik y netbird-server muestran Up y 80/443 están escuchando.

5. Abre el dashboard y crea tu cuenta

Abre https://<your-ip>.apps.wiline.cloud — haz clic a través de la advertencia del certificado si aparece (el mismo click-through de certificado autofirmado que el Artículo 2).

Este es tu propio control plane de NetBird, corriendo en tu Instancia WEC. En la primera visita te pide que crees la cuenta de admin — introduce un nombre, email y contraseña, haz clic en Create, luego inicia sesión con esas mismas credenciales. (Esa pantalla de configuración aparece solo una vez; después el dashboard muestra una página normal de Sign in.)

Llegas al dashboard de NetBird — tu control plane privado en tu propio dominio:

El dashboard de NetBird autoalojado

Haz clic en Add Peer y NetBird te entrega el comando de inscripción para tu servidor — fíjate en el --management-url apuntando a tu propio dominio:

Add Peer en el dashboard autoalojado — fíjate en el flag --management-url

curl -fsSL https://pkgs.netbird.io/install.sh | sh
netbird up --management-url https://<your-ip>.apps.wiline.cloud

(Ese segundo comando abre un login SSO en el navegador. Para un servidor headless, añade --setup-key <KEY> desde la página Setup Keys de tu dashboard — igual que el flujo gestionado, solo con --management-url añadido.)

Este es el dashboard donde creas las setup keys que inscriben máquinas — que es exactamente lo que hacemos a continuación.

Ahora inscribe tus máquinas

Ya tienes un control plane (tu propio dashboard de la plantilla, o NetBird gestionado). Ahora pon las dos máquinas en la mesh — la máquina de OpenClaw de las Partes 1–3 y tu laptop — y luego cierra los puertos públicos de la máquina. Estos pasos son los mismos sin importar qué control plane hayas elegido.

De dónde viene tu setup key

Los comandos de abajo usan NetBird gestionado (app.netbird.io) como ejemplo. Si desplegaste la plantilla de WEC en su lugar, es idéntico excepto que: creas la setup key en tu propio dashboard (https://<your-ip>.apps.wiline.cloud) y añades --management-url https://<your-ip>.apps.wiline.cloud a netbird up, para que el agente apunte a tu servidor en lugar de a la nube gestionada.

Requisitos previos: OpenClaw corriendo detrás de Caddy desde los Artículos 1–3 (alcanzable en https://openclaw.local), un control plane del paso anterior, y acceso por shell a la máquina además de admin en tu laptop.

Paso 1 — Instala el agente de NetBird en la máquina de OpenClaw

Esta es la máquina de las Partes 1–3 (una Instancia WEC) — la estamos inscribiendo como peer, lo cual es independiente de cualquier servidor de control plane. NetBird trae un instalador de una línea:

curl -fsSL https://pkgs.netbird.io/install.sh | sh

Trampa (real): en Ubuntu la instalación dispara el diálogo needrestart — una caja azul de "Which services should be restarted?". El Tab entre botones puede ser tragado por algunas configuraciones de SSH/terminal; usa las flechas para moverte, Espacio para alternar, Enter para confirmar (<Ok> es el predeterminado). El paquete ya está en su lugar para cuando aparece esta caja, así que aunque salgas con Ctrl+C, el agente queda instalado — volver a ejecutar el instalador solo te lo dice:

NetBird seems to be installed already, please remove it before proceeding

(Si vuelves a ejecutar el instalador después de este tutorial, verás en cambio NetBird service is running, please stop it before proceeding — el agente ya está arriba, así que no hay nada que reinstalar.)

Confirma la versión:

netbird version
# 0.73.2

Paso 2 — Crea una setup key y une la máquina de OpenClaw

Una setup key es el token que inscribe un dispositivo en tu mesh — ideal para un servidor headless (sin necesidad de SSO en navegador).

¿Primera vez en el dashboard? Evita los desvíos

Algunas cosas intentarán mandarte por el camino equivocado en una cuenta nueva — aquí está la línea recta:

  • ¿Aún sin cuenta? Crea una primero (inicia sesión con Google/GitHub/email). No puedes generar una key hasta que estés dentro.
  • El asistente de onboarding ("Add your first resource" — Single IP / Entire Subnet / Domain) aparece de inmediato. Sáltalo. Los resources son para exponer subredes/dominios; nosotros solo necesitamos dos peers simples, así que no hace falta.
  • El botón naranja "Add Peer" abre el flujo de instalación SSO (descargar la app, registrarse con email, conectar desde la bandeja). Eso está pensado para un escritorio con navegador — no para un servidor headless. No lo sigas.
  • En su lugar, ve directo a la página Setup Keys: https://app.netbird.io/setup-keys.
  1. Abre https://app.netbird.io/setup-keys.
  2. Create Setup Key → nombre openclaw-tutorial, activa Reusable (para que sirva también para la laptop), por lo demás los valores predeterminados.
  3. Copia la key.

Creando una setup key reutilizable en el dashboard de NetBird

Conecta la VM (reemplaza con tu key):

sudo netbird up --setup-key <YOUR_SETUP_KEY>
Trata la setup key como un secreto

Cualquiera con una key reutilizable puede añadir dispositivos a tu red. No la pegues en chats ni commits, y elimínala del dashboard una vez que tus dispositivos estén inscritos (los peers existentes siguen conectados).

Comprueba la conexión:

netbird status

netbird status en la VM — Management &amp; Signal Connected, IP de la mesh 100.87.239.229, Peers count 0/0

Esa NetBird IP (100.87.239.229) es la dirección a la que apunta todo lo de abajo. Peers count: 0/0 es lo esperado — nada más se ha unido todavía.

Paso 3 — Une tu laptop

Instala el cliente de NetBird en lo que estés usando, luego conéctate con la misma setup key reutilizable. El comando de conexión (netbird up --setup-key …) es idéntico en todos los SO — solo difiere la instalación.

Lo ejecutamos en macOS

La salida capturada de abajo es de un Mac. Las pestañas de Windows y Linux dan la instalación equivalente; los pasos de netbird up, netbird status y ping son los mismos en todas partes (Windows usa ping -n en lugar de -c).

Instala vía Homebrew, luego inicia el servicio y conéctate:

brew install netbirdio/tap/netbird
sudo netbird service install
sudo netbird service start
netbird up --setup-key <YOUR_SETUP_KEY>

Puede que veas una advertencia gRPC puntual mientras el socket del daemon aparece un instante después de que el cliente lo llame — termina en Connected, así que es inofensiva:

Salida
WARNING: ... dial unix /var/run/netbird.sock: connect: no such file or directory
Connected

Verifica que los dos nodos se ven entre sí, y que el túnel lleva tráfico:

netbird status
ping -c 3 100.87.239.229 # Windows: ping -n 3 100.87.239.229

netbird status en el Mac mostrando Peers count 1/1 Connected, más un ping exitoso a la IP de la mesh de la VM

Peers count: 1/1 — ese peer es la VM. En el dashboard, ambas máquinas ahora aparecen bajo Peers (como las inscribimos con una setup key en lugar de un login SSO, aparecen bajo Servers en vez de User Devices):

La VM y la laptop ambas conectadas como peers en el dashboard de NetBird

¿Por qué ~200 ms?

Esta ruta pasa por un relay de NetBird (fíjate en Interface type: Userspace en el Mac). Está bien para una UI web, y NetBird a menudo mejorará a un enlace peer-to-peer directo cuando las redes lo permitan. La latencia hacia un peer con relay no es una señal de alarma.

Paso 4 — Reapunta openclaw.local a la IP de la mesh

Desde el Artículo 2, tu archivo hosts mapea openclaw.local a la IP de LAN de la VM (10.80.4.212). Cámbialo por la IP de la mesh (100.87.239.229). La ruta del archivo y el comando de edición difieren por SO:

sed en macOS necesita el -i '' vacío:

grep openclaw /etc/hosts
# 10.80.4.212 openclaw.local
sudo sed -i '' 's/^10\.80\.4\.212 openclaw\.local/100.87.239.229 openclaw.local/' /etc/hosts
grep openclaw /etc/hosts
# 100.87.239.229 openclaw.local

Prueba sobre la mesh — antes de tocar ningún puerto:

curl -kI https://openclaw.local/
Salida
HTTP/2 200
...
via: 1.1 Caddy

via: 1.1 Caddy sobre la IP de la mesh — el chat ahora fluye a través de NetBird. Carga https://openclaw.local/chat?session=main en el navegador para confirmar que se comporta exactamente como antes. El cert TLS sigue coincidiendo porque el hostname no cambió; solo se movió la IP detrás de él.

El chat de OpenClaw cargando sobre la mesh en https://openclaw.local

Paso 5 — Cierra los puertos públicos

Aquí está el estado que estamos arreglando. En la VM:

sudo ss -tlnp | grep -E ':(80|443)'
Salida — escuchando en 0.0.0.0 (todas las interfaces)
LISTEN 0 4096 0.0.0.0:443 ... docker-proxy
LISTEN 0 4096 0.0.0.0:80 ... docker-proxy

Caddy escucha en 0.0.0.0 — todas las interfaces, incluida la LAN (y cualquier NAT delante de ella).

La trampa de ufw

Tu primer instinto es ufw deny 443. No funcionará. Los puertos de Caddy son publicados por Docker, que escribe sus propias reglas de iptables que evitan la cadena INPUT de ufw. Añadirías reglas de ufw, te sentirías seguro, y el 443 seguiría abierto de par en par. En esta máquina ufw estaba incluso inactive — y activarlo no habría cambiado nada para los puertos publicados por Docker.

El arreglo fiable es ligar los puertos publicados a la IP de la mesh en lugar de a 0.0.0.0, para que Caddy solo escuche en wt0. Edita el servicio de Caddy en docker-compose.override.yml (el override del Artículo 2):

cd /home/ubuntu/openclaw
cp docker-compose.override.yml docker-compose.override.yml.bak

Cambia el bloque de ports de:

ports:
- "80:80"
- "443:443"

para ligarlo a la IP de la mesh:

ports:
- "100.87.239.229:80:80"
- "100.87.239.229:443:443"

Recrea solo Caddy y vuelve a comprobar:

docker compose up -d caddy
sudo ss -tlnp | grep -E ':(80|443)'

ss tras el cambio — Caddy ahora escuchando solo en la IP de la mesh 100.87.239.229, ya no en 0.0.0.0

Los puertos ya no están en 0.0.0.0 — viven solo en la interfaz de la mesh.

Orden de arranque

Como el bind apunta a la IP de la mesh, NetBird debe estar arriba antes de que Caddy inicie (p. ej. tras un reinicio, wt0 necesita su IP antes de que Docker se ligue a ella). La política restart: unless-stopped ya cubre esto — Caddy reintenta hasta que la interfaz exista — pero conviene saberlo si alguna vez ves a Caddy en crash-loop justo después de arrancar.

Paso 6 — Demuestra el bloqueo

Ambas direcciones, de la ejecución real.

Aún alcanzable sobre la mesh (laptop):

curl -kI https://openclaw.local/
# HTTP/2 200 ... via: 1.1 Caddy

Ya no alcanzable en la LAN (VM, golpeando su propia IP de LAN):

curl -kI --connect-timeout 5 --resolve openclaw.local:443:10.80.4.212 https://openclaw.local/

En la VM, curl a la antigua IP de LAN ahora devuelve Connection refused

Ese es el resultado: la misma URL, alcanzable solo a través de tu mesh, rechazada en todas las demás partes.

Limpieza

Elimina la setup key reutilizable ahora que ambos dispositivos están inscritos — Setup Keys → delete en el dashboard. Tus peers siguen conectados; solo estás cerrando la puerta que usaste para añadirlos. Para quitar un dispositivo más adelante, elimínalo bajo Peers → User Devices y ejecuta netbird down en esa máquina.

Solución de problemas (real)

  • El diálogo needrestart no acepta Tab. Usa las flechas / Espacio / Enter. El paquete ya está instalado para cuando aparece la caja.
  • Advertencia gRPC de netbird.sock en el primer up. El socket del daemon va un instante por detrás del cliente. Si termina en Connected, ignórala.
  • Las reglas de ufw no bloquean el gateway. Los puertos publicados por Docker evitan ufw — liga el puerto a una IP específica (como arriba) o usa la propia cadena DOCKER-USER de Docker.
  • Caddy en crash-loop tras reiniciar. Arrancó antes de que wt0 tuviera la IP de la mesh. restart: unless-stopped lo recupera; o ordena Docker después de netbird.service.
  • Ping alto hacia un peer. Estás con relay, no directo — funcional, solo más lento. Revisa el Interface type y el detalle del peer en NetBird para el tipo de conexión.

Qué sigue

Eso cierra la serie Self-hosting OpenClaw:

  1. Desplegar OpenClaw en una Instancia WEC con Docker Compose
  2. Asegurar OpenClaw con un proxy inverso Caddy + HTTPS
  3. Añadir un canal de Telegram a OpenClaw
  4. Haz OpenClaw privado con una VPN mesh de NetBird ← estás aquí

Ahora tienes un agente autoalojado que está cifrado en tránsito, emparejado con tus dispositivos, accesible desde tu móvil e invisible para la internet pública — todo en una sola Instancia WEC pequeña.

Continúa el viaje

¿Listo para un agente que recuerda? Empieza la serie Self-hosting HermesAutoaloja el Hermes Agent con memoria persistente — desplegado en esta misma Instancia WEC, con contexto que sobrevive a los reinicios.