NUFI Docs

Cloudflare tunnel

Expose an internal NUFI install to the internet without opening a port.

When the server is inside an office network with no inbound access — or you simply do not want to manage TLS and DNS yourself — a Cloudflare tunnel is the path of least resistance.

The tunnel is outbound: cloudflared on the server holds a long-lived connection to Cloudflare. Cloudflare receives requests for your hostnames and forwards them down the tunnel. No public IP, no firewall rules.

Five public hostnames

Following the platform's reference layout:

HostnameTargetNotes
chat.nufi.melibrechat:3080Behind Cloudflare Access (SSO)
console.nufi.meconsole:3000Behind Cloudflare Access (SSO)
langfuse.nufi.melangfuse-web:3000Behind Cloudflare Access (SSO)
grafana.nufi.megrafana:3000Behind Cloudflare Access (SSO)
api.nufi.melitellm-proxy:4000No Access — virtual-key auth only

api.nufi.me is deliberately not behind Access — clients hit it with a gateway-issued API key in the Authorization header, not a browser session.

One-time setup

  1. Add your domain to Cloudflare. Update your registrar's nameservers to Cloudflare's.
  2. Enable Zero Trust (free plan supports up to 50 users).
  3. Create a tunnel. Zero Trust → Networks → Tunnels → Create Tunnel. Name it nufi-prod. Copy the install command.
  4. Install cloudflared on the host as a system service:
    sudo cloudflared service install <token-from-step-3>
    sudo systemctl status cloudflared
  5. Add hostname routes. In the tunnel's UI:
    • chat.nufi.mehttp://librechat:3080
    • console.nufi.mehttp://console:3000
    • etc.

Each route picks its target by Docker service name, because cloudflared runs on the host with access to the npuops network (use --network npuops on the cloudflared container, or run cloudflared inside the compose file with the right network attached).

Lock it down with Access policies

For each hostname except api.nufi.me:

  1. Zero Trust → Access → Applications → Add application.
  2. Type: Self-hosted.
  3. Hostname: pick the same domain.
  4. Add an access policy:
    • Action: Allow
    • Include: Emails ending in @dudaji.com (or your domain).
  5. Save.

Visitors land on a Cloudflare Access login screen, sign in with their corporate email, and are then forwarded to the chat (which then checks its own session).

This is two-factor in a useful sense: even if a the NUFI session is stolen, the attacker still needs an Access-eligible identity to reach the hostname.

The cookie rewrite from SSO + reverse proxy still applies. The cleanest way is to keep Caddy on the host between cloudflared and the compose stack, doing the cookie rewrite, and let Cloudflare just be the public face:

client → Cloudflare → cloudflared → Caddy on host → librechat / console / …

Or skip Caddy and do the cookie rewrite in a Cloudflare Worker — but Caddy is simpler.

Cost

  • Tunnel: free.
  • Access: free up to 50 users; $3/user/month above.
  • TLS: free (Cloudflare-managed).

Troubleshooting

  • 404 from Cloudflare — hostname route missing or pointing at the wrong service name. Check the tunnel's Public Hostnames page.
  • 502 / 521cloudflared can reach Cloudflare but cannot reach the target service. Verify the target hostname resolves inside the same network as cloudflared.
  • Loop redirecting Access — clock skew on the host. Sync NTP.
  • Slow chat completions — Cloudflare has a 100-second timeout on free-plan tunnels. Long streams hit it. Either move to a paid plan (longer timeout) or split big responses into smaller ones.

See also

The platform repo's docs/cloudflare-tunnel-setup.md has the full walkthrough with screenshots.