El problema: exponer un servicio detrás de NAT
La mayoría de las conexiones residenciales y empresariales colocan tus máquinas detrás de un NAT: ningún puerto entrante es accesible desde el exterior sin configuración explícita en el router. E incluso cuando esa configuración es posible, abre un camino directo hacia tu red local.
Los escenarios reales son frecuentes: un NAS con Nextcloud que quieres compartir con clientes, un homelab en Proxmox con una docena de servicios, una Raspberry Pi para domótica, o una VM de desarrollo local que quieres probar desde fuera. En todos estos casos, la solución habitual — el port forwarding — tiene dos problemas: depende del router y abre un camino directo hacia tu red privada.
Las alternativas comunes tienen sus propias limitaciones: Cloudflare Tunnel pasa todo tu tráfico por los servidores de Cloudflare, lo que plantea dudas de privacidad y crea una dependencia de su infraestructura. Tailscale/Headscale crea una red mesh entre tus máquinas, excelente para acceso punto a punto, pero no está diseñado para exponer públicamente un servicio HTTP(S) con un subdominio dedicado. Pangolin ocupa un espacio diferente: un relay WireGuard self-hosted, con gestión de certificados y subdominios, que controlas completamente desde tu VPS.
Lo que Pangolin aporta frente a las alternativas
- Completamente self-hosted — tu tráfico solo transita por tu VPS, ningún tercero ve tu tráfico de aplicación.
- Sin puerto entrante necesario — la conexión se inicia desde la máquina origen hacia el VPS (saliente), el NAT nunca es un obstáculo.
- HTTPS automático via Let's Encrypt — Pangolin gestiona certificados para cada subdominio expuesto, sin intervención manual.
- Interfaz web integrada — añade túneles y gestiona recursos y usuarios desde un panel web, sin editar archivos de configuración.
- Cifrado WireGuard de extremo a extremo — el túnel entre la máquina origen y el VPS está cifrado a nivel de transporte, independientemente del HTTPS de aplicación.
- Multi-sitio — una única instancia de Pangolin en el VPS puede relayar decenas de servicios desde máquinas distintas, bajo subdominios independientes.
Arquitectura: VPS relay, Gerbil y Newt
Pangolin se apoya en tres componentes que se reparten los roles:
[Máquina origen] [VPS ServOrbit] [Internet]
service:8080 Pangolin (orquestación)
newt (cliente) ←─WireGuard UDP─→ Gerbil (túnel WG) ←─HTTPS──→ visitante
Traefik (reverse proxy)Pangolin es el plano de control: gestiona túneles, subdominios, certificados y usuarios a través de una API REST y una interfaz web. Corre en el VPS.
Gerbil es el par WireGuard del lado del servidor. Abre un puerto UDP, establece túneles con los clientes y enruta el tráfico entrante hacia los servicios expuestos. También corre en el VPS, junto a Pangolin.
Newt es el cliente ligero que corre en la máquina origen (NAS, Pi, VM local). Se conecta a Gerbil en el puerto UDP WireGuard, mantiene el túnel activo y reenvía el tráfico recibido al servicio local en el puerto configurado.
El flujo concreto: un visitante llega a nextcloud.yourdomain.com → Traefik (gestionado por Pangolin) recibe la petición HTTPS → la reenvía a través de Gerbil por el túnel WireGuard activo → Newt la recibe y la relayea hacia localhost:8080 en la máquina origen. El servicio responde por el mismo camino en sentido inverso.
Requisitos previos
En el lado del VPS:
- VPS con acceso root e IPv4 dedicada — el plan {{vps.start.name}} es suficiente para empezar (1 vCPU, 1 GB RAM para cargas ligeras, 2 GB recomendados para múltiples túneles activos).
- Ubuntu 22.04 o 24.04 (Debian 12 también funciona).
- Un puerto UDP libre para WireGuard (por defecto 51820, configurable).
- Un nombre de dominio con acceso a la gestión DNS — necesitarás crear un registro A wildcard *.yourdomain.com apuntando a la IP del VPS.
- Docker y Docker Compose instalados (apt install docker.io docker-compose-plugin).
En el lado de la máquina origen:
- Una máquina Linux (Raspberry Pi, NAS con DSM 7+, VM en Proxmox, servidor físico) con acceso UDP saliente al puerto WireGuard del VPS — la mayoría de ISPs lo permiten.
- Un servicio escuchando en un puerto local (Nextcloud, Gitea, Home Assistant, etc.).
Versión actual: Pangolin 1.23.0 (publicado el 16 de septiembre de 2026).
Despliegue de Pangolin y Gerbil en el VPS
Preparar el VPS y abrir el puerto WireGuard
Conéctate como root al VPS e instala Docker si no está presente:
apt update && apt install -y docker.io docker-compose-plugin ufwAbre el puerto UDP para WireGuard (51820 por defecto) y asegura que los puertos HTTP/HTTPS son accesibles:
ufw allow 80/tcp ufw allow 443/tcp ufw allow 51820/udp ufw enablePara restringir el acceso al panel de administración (puerto 3000 por defecto), limítalo a tu IP:
ufw allow from TU_IP to any port 3000Crear el archivo docker-compose.yml
Crea un directorio de trabajo y el archivo de configuración:
mkdir -p /opt/pangolin && cd /opt/pangolinCrea
docker-compose.ymlcon el siguiente contenido:cat > docker-compose.yml <<'EOF' services: pangolin: image: fosrl/pangolin:1.23.0 container_name: pangolin restart: unless-stopped volumes: - ./config:/app/config - ./data:/app/data ports: - "3000:3000" networks: - pangolin_net gerbil: image: fosrl/gerbil:latest container_name: gerbil restart: unless-stopped cap_add: - NET_ADMIN volumes: - ./data:/var/lib/gerbil ports: - "51820:51820/udp" networks: - pangolin_net depends_on: - pangolin networks: pangolin_net: driver: bridge EOFAdapta el número de versión de la imagen
pangolinal último release disponible en GitHub.Configurar Pangolin e iniciar el stack
Crea el directorio de configuración y un
config.ymlmínimo:mkdir -p /opt/pangolin/config cat > /opt/pangolin/config/config.yml <<'EOF' app: base_domain: yourdomain.com admin_email: [email protected] port: 3000 wireguard: port: 51820 subnet: 10.0.0.0/24 acme: enabled: true staging: false EOFReemplaza
yourdomain.compor tu dominio real. Inicia el stack:cd /opt/pangolin && docker compose up -d docker compose logs -f pangolinPangolin genera una contraseña de administrador en el primer arranque — anótala desde los logs. La interfaz web está disponible en
http://IP_VPS:3000.Configurar el registro DNS wildcard
En tu zona DNS, crea un registro A wildcard apuntando a la IP del VPS:
*.yourdomain.com → A → IP_VPSEn Cloudflare, crea este registro con el proxy desactivado (DNS-only, nube gris) para que los certificados Let's Encrypt puedan emitirse correctamente mediante el desafío HTTP-01 que usa Pangolin.
Crear una unidad systemd para reinicio automático
Docker con
restart: unless-stoppedsuele ser suficiente, pero si prefieres una unidad systemd dedicada:cat > /etc/systemd/system/pangolin.service <<'EOF' [Unit] Description=Pangolin reverse tunnel stack After=docker.service Requires=docker.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=/opt/pangolin ExecStart=/usr/bin/docker compose up -d ExecStop=/usr/bin/docker compose down [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable pangolin
Añadir un túnel con Newt en la máquina origen
Crear un túnel en la interfaz Pangolin
Inicia sesión en la interfaz web de Pangolin en
http://IP_VPS:3000con las credenciales de administrador. Ve a Sites → Add site, dale un nombre (p. ej.homelab) y anota el site token generado. Luego en Resources → Add resource, elige el sitio, escribe el subdominio deseado (nextcloud.yourdomain.com) y el puerto local de la máquina origen (p. ej.8080).Instalar Newt en la máquina origen
En la máquina que aloja tu servicio, descarga el binario Newt para tu arquitectura:
# Linux x86_64 curl -Lo /usr/local/bin/newt \ https://github.com/fosrl/newt/releases/latest/download/newt-linux-amd64 chmod +x /usr/local/bin/newtPara Raspberry Pi (ARM64):
curl -Lo /usr/local/bin/newt \ https://github.com/fosrl/newt/releases/latest/download/newt-linux-arm64 chmod +x /usr/local/bin/newtConfigurar e iniciar Newt
Lanza Newt con el site token obtenido en el paso anterior:
newt \ --server https://yourdomain.com:3000 \ --token TU_SITE_TOKEN \ --target localhost:8080Para arranque automático, crea una unidad systemd:
cat > /etc/systemd/system/newt.service <<'EOF' [Unit] Description=Newt WireGuard tunnel client After=network.target [Service] ExecStart=/usr/local/bin/newt \ --server https://yourdomain.com:3000 \ --token TU_SITE_TOKEN \ --target localhost:8080 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now newtVerificar la conectividad de extremo a extremo
En el VPS, verifica que el túnel WireGuard está establecido:
docker exec gerbil wg showDeberías ver un peer con un
latest handshakereciente. Desde cualquier navegador o línea de comandos:curl -I https://nextcloud.yourdomain.comRespuesta esperada:
HTTP/2 200(o la página de login de tu servicio). El certificado Let's Encrypt se emite automáticamente en el primer acceso.
Exposición de un servicio: ejemplo Nextcloud detrás de NAT
Configurar Nextcloud para aceptar el dominio proxy
Nextcloud bloquea peticiones de dominios no declarados. Añade el dominio público a
config.php:# Desde la máquina origen, en el directorio de Nextcloud nano config/config.phpAñade en el array
trusted_domains:'trusted_domains' => array ( 0 => 'localhost', 1 => 'nextcloud.yourdomain.com', ), 'overwritehost' => 'nextcloud.yourdomain.com', 'overwriteprotocol' => 'https',Verificar el acceso público y el certificado
Espera 30-60 segundos tras el primer acceso para que Let's Encrypt emita el certificado, luego:
curl -v https://nextcloud.yourdomain.com 2>&1 | grep -E 'subject|issuer|HTTP'El certificado está firmado por Let's Encrypt y la URL pública es ahora accesible desde cualquier red, sin ningún puerto abierto en el lado de la red local.
Seguridad: tokens, rotación y control de acceso
Rotación de site token — genera un nuevo token desde la interfaz Pangolin y actualiza la unidad systemd de Newt en la máquina origen. El token anterior queda invalidado inmediatamente. Programa esta rotación cada 90 días o ante cualquier cambio de personal con acceso a la máquina origen.
Whitelist de IPs en Pangolin — para cada recurso expuesto, puedes definir una lista blanca de IPs en Resources → Access Policy. Útil para restringir el acceso al backoffice o herramientas internas a tu rango de IP de oficina.
Acceso autenticado — Pangolin soporta proveedores OIDC (Authentik, Keycloak, Zitadel) para añadir una capa de autenticación delante de cualquier recurso expuesto, sin modificar la aplicación detrás del túnel.
Restringir el puerto de administración — el puerto 3000 de Pangolin no debe ser accesible públicamente. Restríngelo a tu IP con ufw allow from TU_IP to any port 3000 && ufw deny 3000.
Solución de problemas
El túnel no se establece — UDP bloqueado por el ISP. Algunos operadores filtran UDP saliente en puertos no estándar. Prueba desde la máquina origen: nc -u -v IP_VPS 51820. Si la conexión es rechazada, cambia el puerto WireGuard en config.yml a 443 (UDP) o 53 (UDP) — estos puertos pasan casi universalmente. Actualiza ufw en el VPS en consecuencia.
MTU mismatch — latencia o desconexiones aleatorias. WireGuard añade overhead de encapsulación (aproximadamente 60 bytes). Si tu servicio transfiere archivos grandes y observas desconexiones, reduce el MTU de la interfaz WireGuard en la configuración de Gerbil: mtu = 1380 es un valor seguro en la mayoría de enlaces.
Servicio no accesible pese al túnel activo. Primero verifica que el servicio local escucha en 0.0.0.0 y no solo en 127.0.0.1: ss -tlnp | grep 8080. Luego confirma que el puerto configurado en Pangolin coincide con el puerto real del servicio. Finalmente revisa los logs de Newt: journalctl -u newt -f.
Certificado Let's Encrypt no emitido. Pangolin usa el desafío HTTP-01, que requiere que el puerto 80 del VPS sea accesible desde Internet. Verifica que ufw allow 80/tcp está activo y que ningún otro servicio ocupa el puerto 80 (ss -tlnp | grep :80). En Cloudflare, asegúrate de que el registro wildcard está en DNS-only (nube gris).
Interfaz Pangolin inaccesible tras reinicio. Si Docker se reinicia antes de que la red esté disponible, Pangolin puede arrancar sin interfaz de red. Añade network-online.target en la dependencia systemd, o simplemente ejecuta de nuevo docker compose up -d desde /opt/pangolin.
Pangolin vs Cloudflare Tunnel vs Tailscale/Headscale
Desplace la tabla
| Criterio | Pangolin + Gerbil | Cloudflare Tunnel | Tailscale / Headscale |
|---|---|---|---|
| Alojamiento | Self-hosted en tu VPS | SaaS de Cloudflare | SaaS (Tailscale) o self-hosted (Headscale) |
| Coste | Solo el coste del VPS | Gratis hasta ciertos límites, luego suscripción | Gratis (uso personal), suscripción para equipos |
| Cifrado E2E | WireGuard entre máquina y VPS, HTTPS hasta el visitante | TLS hasta los servidores de Cloudflare (descifrado en tránsito) | WireGuard entre todos los nodos (mesh completo) |
| Exposición HTTP pública | Sí, con HTTPS automático y subdominios personalizados | Sí, con certificados gestionados por Cloudflare | No diseñado para ello (requiere un reverse proxy adicional) |
| Complejidad de administración | Media — un stack Docker a mantener, una interfaz web | Baja — el connector es un único binario, todo gestionado por Cloudflare | Baja (Tailscale) a Media (Headscale self-hosted) |
| Privacidad del tráfico | Tráfico visible solo en tu VPS | Tráfico descifrado por Cloudflare en sus servidores | Tráfico mesh cifrado, nunca centralizado |
Ir más allá
Pangolin 1.23.0 introduce soporte de alta disponibilidad en la edición Enterprise y gestión multi-administrador del servidor — funcionalidades útiles en cuanto tu infraestructura crece más allá del uso personal.
Para exponer servicios no-HTTP (SSH privado, bases de datos, protocolos UDP de aplicación), Pangolin soporta ahora recursos privados TCP/UDP accesibles mediante el cliente Newt — sin exponerlos públicamente en una URL, pero haciéndolos accesibles desde tu red WireGuard.
Si tu necesidad es distinta — coordinar el acceso entre varias máquinas sin exposición pública — Headscale en VPS es la herramienta adecuada. Para exposición sin VPS intermedio usando la infraestructura de Cloudflare, Cloudflare Tunnel sigue siendo la opción más sencilla. Y para sentar las bases del cifrado de red en un VPS, la guía de WireGuard en VPS cubre la instalación y configuración de la interfaz WireGuard nativa.