Haz OpenClaw privado con una VPN mesh de 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.
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:
- 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.
- 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.
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.

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 SubnetenPrinceton-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.

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.

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.301luego200→ 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:

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:

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.
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).
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.
- Abre
https://app.netbird.io/setup-keys. - Create Setup Key → nombre
openclaw-tutorial, activa Reusable (para que sirva también para la laptop), por lo demás los valores predeterminados. - Copia la key.

Conecta la VM (reemplaza con tu key):
sudo netbird up --setup-key <YOUR_SETUP_KEY>
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

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.
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).
- macOS
- Windows
- Linux
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:
WARNING: ... dial unix /var/run/netbird.sock: connect: no such file or directory
Connected
Descarga y ejecuta el instalador de NetBird para Windows desde
app.netbird.io (Add Peer → Windows) o
pkgs.netbird.io. Instala una app de bandeja del sistema y la
CLI netbird. Luego, en PowerShell como Administrador, conéctate con tu key:
netbird up --setup-key <YOUR_SETUP_KEY>
(También puedes hacer clic en Connect desde el icono de la bandeja y autenticarte vía SSO, pero la setup key es el mismo flujo de un solo paso que en las otras plataformas.)
El mismo instalador de una línea que la VM, luego conéctate:
curl -fsSL https://pkgs.netbird.io/install.sh | sh
sudo netbird up --setup-key <YOUR_SETUP_KEY>
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

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):

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:
- macOS
- Linux
- Windows
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
El sed de GNU acepta -i sin argumento:
grep openclaw /etc/hosts
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
El archivo hosts está en C:\Windows\System32\drivers\etc\hosts y necesita admin.
En PowerShell como Administrador:
$h = "$env:WINDIR\System32\drivers\etc\hosts"
(Get-Content $h) -replace '^10\.80\.4\.212 openclaw\.local','100.87.239.229 openclaw.local' | Set-Content $h
Select-String openclaw $h
(O abre ese archivo en Notepad ejecutado como Administrador y cambia la IP a mano.)
Prueba sobre la mesh — antes de tocar ningún puerto:
curl -kI https://openclaw.local/
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.

Paso 5 — Cierra los puertos públicos
Aquí está el estado que estamos arreglando. En la VM:
sudo ss -tlnp | grep -E ':(80|443)'
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).
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)'

Los puertos ya no están en 0.0.0.0 — viven solo en la interfaz de la mesh.
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/

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
needrestartno aceptaTab. Usa las flechas / Espacio / Enter. El paquete ya está instalado para cuando aparece la caja. - Advertencia gRPC de
netbird.socken el primerup. El socket del daemon va un instante por detrás del cliente. Si termina enConnected, ignórala. - Las reglas de
ufwno bloquean el gateway. Los puertos publicados por Docker evitan ufw — liga el puerto a una IP específica (como arriba) o usa la propia cadenaDOCKER-USERde Docker. - Caddy en crash-loop tras reiniciar. Arrancó antes de que
wt0tuviera la IP de la mesh.restart: unless-stoppedlo recupera; o ordena Docker después denetbird.service. - Ping alto hacia un peer. Estás con relay, no directo — funcional, solo más lento. Revisa el
Interface typey el detalle del peer en NetBird para el tipo de conexión.
Qué sigue
Eso cierra la serie Self-hosting OpenClaw:
- Desplegar OpenClaw en una Instancia WEC con Docker Compose
- Asegurar OpenClaw con un proxy inverso Caddy + HTTPS
- Añadir un canal de Telegram a OpenClaw
- 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 Hermes — Autoaloja el Hermes Agent con memoria persistente — desplegado en esta misma Instancia WEC, con contexto que sobrevive a los reinicios.
