Cloudflare Tunnel: publica servicios con HTTPS sin abrir puertos
Publica Immich, Nextcloud u otros contenedores con HTTPS usando cloudflared. Cuándo tiene sentido frente a Tailscale y cómo blindarlo con Cloudflare Access.
Quieres entrar a Immich desde el móvil en la calle, o compartir un enlace de Nextcloud con alguien que no va a instalar Tailscale. Abrir puertos en el router es la tentación rápida — y la forma más habitual de acabar en un scanner de internet. Cloudflare Tunnel (cloudflared) saca un túnel de salida desde tu NAS hacia la red de Cloudflare: HTTPS en un dominio tuyo, sin reenvío de puertos.
No es magia gratis de privacidad. Es una herramienta muy útil con un trade-off claro. Si solo te vas a conectar tú, lee antes Tailscale vs VPN vs abrir puertos y la guía de Tailscale en el NAS: para acceso personal suele ganar Tailscale.
Tunnel brilla cuando necesitas una URL pública con candado HTTPS. Tailscale brilla cuando eres tú (y tu familia) quien entra, sin pasar por el edge de nadie.
Qué es Cloudflare Tunnel, en cristiano
En el NAS (o en un contenedor Docker) corre cloudflared. Ese proceso abre una conexión saliente hacia Cloudflare. En el panel Zero Trust defines un hostname — por ejemplo fotos.tudominio.com — que apunta a un servicio local como http://127.0.0.1:2283 (Immich) o http://192.168.1.50:8080 (Nextcloud).
El visitante llega a Cloudflare por HTTPS. Cloudflare reenvía el tráfico por el túnel hasta tu servicio. El router no tiene el puerto 443 ni el 80 abiertos hacia el NAS. Los scanners de internet ven… nada interesante en tu IP doméstica.
Cuándo usar Tunnel y cuándo Tailscale
| Escenario | Mejor opción | Por qué |
|---|---|---|
| Solo tú / familia con app en el móvil | Tailscale | Mesh privada, sin URL pública |
| Compartir enlace con alguien externo | Cloudflare Tunnel | HTTPS + dominio, sin instalar cliente |
| Webhooks, apps que exigen URL pública | Tunnel | Tailscale no da hostname público fácil |
| Máxima privacidad del tráfico | Tailscale / VPN propia | No terminas TLS en un tercero |
| «Abrir el 443 y ya» | Evitar | Superficie de ataque innecesaria |
Muchas casas usan ambos: Tailscale para administración y apps personales; Tunnel solo para el servicio concreto que debe ser alcanzable por URL (por ejemplo un Immich compartido con cuidado, o un frontend concreto).
Honestidad de privacidad: qué ve Cloudflare
Aquí no vamos a vender humo. Con un túnel típico (origen HTTP en tu red, HTTPS en el visitante), Cloudflare termina el TLS en su edge. Eso significa que, en el tramo visitante ↔ Cloudflare, ellos operan el certificado y pueden ver el contenido de las peticiones HTTPS descifradas en su infraestructura — igual que cualquier CDN o proxy inverso gestionado.
- Ven metadatos: IP del cliente, hostname, rutas, timestamps, volúmenes.
- En el modelo habitual (HTTPS al edge, HTTP o HTTPS al origen vía túnel), el tráfico de aplicación pasa por su red.
- Si usas Cloudflare Access, también gestionan el flujo de login (email OTP, IdP, etc.).
¿Es «igual que Google Photos»? No: los ficheros siguen en tu disco. ¿Es «cero confianza en terceros»? Tampoco. Es un compromiso: comodidad de HTTPS público y menos exposición de tu IP doméstica, a cambio de confiar en Cloudflare como intermediario. Si eso no te encaja, Tailscale o un VPN self-hosted es la respuesta — empieza por la comparativa.
Antes de empezar
2283, Nextcloud detrás de su puerto o proxy, Vaultwarden, etc. El túnel apunta a una URL interna alcanzable desde donde corre cloudflared.Instalar cloudflared en el NAS
Dos caminos habituales: binario en el host o contenedor Docker. En NAS con Docker, el contenedor suele ser más limpio de actualizar.
services:
cloudflared:
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel run
environment:
- TUNNEL_TOKEN=eyJ... # token del panel Zero Trust
# Si apunta a otros contenedores por nombre:
# networks: [tu_red_docker]
El token lo generas en Cloudflare Zero Trust → Networks → Tunnels → Create a tunnel. Cloudflare te da el comando o el token; en Docker la variable TUNNEL_TOKEN evita manejar ficheros credentials.json a mano.
# Ejemplo orientativo (ajusta a tu distro)
curl -L --output cloudflared.deb \\
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb
# Login y creación del túnel (flujo interactivo clásico)
cloudflared tunnel login
cloudflared tunnel create nas-casa
En Synology/QNAP sin SSH cómodo, el contenedor con token es la vía menos dolorosa. Comprueba en el panel que el túnel aparece Healthy antes de mapear hostnames.
Dominio: hostname público → servicio privado
En la configuración del túnel añades Public Hostnames:
- Subdomain:
fotos(ocloud,fotos-familia…) - Domain: tu dominio en Cloudflare
- Service:
http://172.17.0.x:2283o el nombre DNS interno del contenedor Immich
Cloudflare crea el registro DNS CNAME automáticamente si marcas la opción. En unos minutos https://fotos.tudominio.com debería responder — pero aún sin Access cualquiera con el enlace entra al login de Immich.
Cloudflare Access: el candado delante del candado
Access pone una capa de identidad delante de tu app. Flujo típico:
fotos.tudominio.com.tu@correo.com y el de tu pareja. Método: one-time PIN por email o un IdP que ya uses.Access no te absuelve de tener usuarios fuertes dentro de Nextcloud o Immich. Es defensa en profundidad: primero Cloudflare comprueba quién eres; luego la app.
Immich, Nextcloud y otros servicios
Immich: apunta al puerto de la web (por defecto 2283). Tras el túnel, configura en Immich la URL pública si la app móvil la necesita. Sigue siendo buena idea que el backup móvil use Tailscale cuando puedas: menos dependencia del edge.
Nextcloud: tendrás que poner overwriteprotocol / trusted domains / URL pública en la config para que los enlaces y la app no se vuelvan locos con HTTP interno. Documentación de Nextcloud + reverse proxy aplica igual detrás de Tunnel.
Varios hostnames: un solo túnel puede exponer fotos., cloud. y pass. a servicios distintos. No mezcles en el mismo hostname un panel de admin del NAS con Immich.
Errores habituales
Túnel Healthy pero 502 Bad Gateway
cloudflared no alcanza la IP/puerto interno. Revisa red Docker, IP del contenedor y que el servicio escuche en 0.0.0.0, no solo localhost del otro host.
Redirect loops en Nextcloud
Faltan trusted proxies / URL HTTPS. Ajusta config.php (o variables de entorno) para el dominio público.
Publicar y olvidarse de Access
La URL acaba en un pastebin o en el historial del móvil prestado. Access + política mínima de emails.
«Es privado porque no abrí puertos»
No abriste puertos en el router; sí publicaste un servicio en internet vía Cloudflare. Son cosas distintas. Para solo-tú, vuelve a Tailscale.
Checklist Cloudflare Tunnel en casa
- Dominio en Cloudflare; túnel Healthy con token o credentials.
- Hostname → servicio LAN; sin puertos WAN abiertos al NAS.
- Access con política restrictiva delante de la app.
- Aceptar el trade-off: TLS terminado en el edge de Cloudflare.
- Acceso solo-personal → preferir Tailscale; Tunnel para URL pública real.
- Siguiente lectura: comparativa Tailscale vs VPN vs puertos.