I’m struggling with my Cloudflare Tunnel setup on TrueNAS SCALE and need assistance. Here’s my setup:
TrueNAS SCALE: Running NGINX Proxy Manager (NPM) and services.
NPM: Configured at 192.168.1.100:30020 (admin), 30021 (HTTP), 30022 (HTTPS).
Services: Jellyfin (192.168.1.100:8096) and TrueNAS GUI (192.168.1.100:80).
Cloudflare Tunnel: Status Healthy, UDP 7844 open. Tunnel routes to [http]://192.168.1.100:30021.
DNS: CNAMEs for domain and wildcard subdomain to .cfargotunnel.com, Proxied.
SSL: Valid Let’s Encrypt wildcard certificate in NPM. Also tried making certs for each subdomain and that still had the same issue.
Cloudflare: SSL/TLS mode Full (strict), Always Use HTTPS and HSTS enabled.
Issues:
Tunnel Tests Fail: curl -v http://.cfargotunnel.com and curl -v https://.cfargotunnel.com fail or hang. Direct test (curl -v --resolve .cfargotunnel.com:443:192.168.1.100 [http]://192.168.1.100:30021) returns 404, so NPM is reachable locally.
Redirect Loop: Enabling Force SSL in NPM causes a 301 loop on the subdomains. Disabling Force SSL allows connections to go through. root domain is accessible but has no proxy hosts it’s setup to return a 404.
Tunnel DNS Port: Set to 8053 in cloudflared config, but no DNS server runs on this port. Should this be unset or set to 53?
Tried:
Verified tunnel routes to [http]://192.168.1.100:30021.
Disabled Always Use HTTPS temporarily.
Turned off Force SSL → working access but not secure.
Questions:
Is the 8053 DNS port inside the cloudflared app config causing tunnel failures? Should it be 0 or 53?
Why do tunnel curl tests fail despite a Healthy status?
How do I fix the 301 loop with Force SSL to secure my setup?
Please share any advice! I can provide sanitized cloudflared or NPM logs or curl outputs if needed. I’m also pretty new to this network stuff.
Another option would be to add an IP alias to the existing interface and let NPM live there, leaving both the GUI and NPM on their respective 80/443 ports.
I moved TN GUI ports to 8080 and 8443, and reinstalled NPM using ports 80 and 443, just to be sure. I think the issue is that my tunnel is set to connect to port 80, which is HTTP, and cloudflare doesn’t like that and wants HTTPS, but NPM kicks it back to 80. However if I try and set the tunnel to connect to the 443 port for HTTPS, I get a 502 error. Even when trying to access 192.168.1.100:443 causes an ERR_SSL_UNRECOGNIZED_NAME_ALERT
Yes, the only thing that works right now is setting the cloudflare tunnel at the HTTP NPM port and disabling Force SSL on proxy hosts. I think this is still secure however as I am encrypted through to NPM and that is all internal
I have resolved this issue, and I have to be completely honest I think it’s hacky but functional!
Fixing Cloudflare Tunnel TLS Error and 502 Bad Gateway on TrueNAS SCALE with NGINX Proxy Manager
Problem: I was running NGINX Proxy Manager (NPM) on TrueNAS SCALE (25.04, Docker-based) with a Cloudflare Tunnel to expose my domain and subdomains using a Let’s Encrypt certificate. Accessing the root domain via HTTPS resulted in a 502 Bad Gateway error, and cloudflared logs showed a tls: unrecognized name error when connecting to the NPM HTTPS port on the host IP. Subdomains had redirect loops when using HTTP, and I wanted internal TLS for security.
Symptoms:
A curl test with SNI resolution to the host IP and HTTPS port worked, serving NPM’s default page with the correct certificate.
A direct curl to the host IP’s HTTPS port with --insecure failed with tls: unrecognized name (no SNI provided).
cloudflared logs reported: Unable to reach the origin service... tls: unrecognized name for the HTTPS service.
The tunnel was “Healthy,” with No TLS Verify and originServerName set to the domain.
Cause:
The tls: unrecognized name error occurred because cloudflared sent the domain as the SNI, but NPM lacked a proxy host for the root domain, causing requests to hit the default server block, which rejected the SNI. The 502 error resulted from NPM not responding with valid content (no backend or default page configured). TrueNAS SCALE’s shift to Docker (no Kubernetes) meant services use host IP/ports, not internal DNS.
Solution:
The fix involved creating a dedicated proxy host in NPM to handle the root domain with a static default page, ensuring the TLS handshake succeeded. Here’s how it was resolved:
Verified Tunnel Configuration:
In Cloudflare Zero Trust > Networks > Tunnels > Public Hostname:
Set the root domain and wildcard subdomains to use the HTTPS service with the host IP and port (e.g., https://<host-ip>:443).
Enabled No TLS Verify to skip certificate validation.
Set Server Name to the root domain to match SNI.
Confirmed DNS: Root domain as a CNAME to the tunnel UUID, Proxied: On.
Restarted cloudflared in TrueNAS (Apps > Cloudflared > Restart).
Added Proxy Host in NPM:
In NPM’s UI (e.g., http://<host-ip>:<admin-port>):
Created a proxy host for the root domain:
Domain Names: Root domain.
Scheme: http (dummy, no real backend).
Forward Hostname/IP: 127.0.0.1 (dummy).
Port: 80 (dummy).
SSL: Selected Let’s Encrypt cert (covering root and wildcard), enabled Force SSL, HTTP/2, HSTS (max-age=63072000, includeSubDomains, preload), and set TLS v1.2+.
Advanced: Added custom NGINX config to serve the default page:
location / {
return 200 '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Default Site</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<style>
.jumbotron { margin-top: 50px; }
</style>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Congratulations!</h1>
<p>You\'ve successfully started the Nginx Proxy Manager.</p>
<p>If you\'re seeing this site then you\'re trying to access a host that isn\'t set up yet.</p>
<p>Log in to the Admin panel to get started.</p>
</div>
<p class="text-center"><small>Powered by <a href="https://github.com/jc21/nginx-proxy-manager" target="_blank">Nginx Proxy Manager</a></small></p>
</div>
</body>
</html>';
add_header Content-Type text/html;
}
Saved and reloaded NPM.
Verified Networking:
Confirmed NPM listens on the host IP and HTTPS port (netstat -tuln | grep :443).
Checked router for open TCP/7844 (cloudflared outbound) and internal traffic to the host IP’s HTTPS port.
Tested:
A curl test with SNI resolution returned 200 OK with the default page.
Browser access to the root domain showed the default page, no 502.
Subdomains worked without redirect loops, as Force SSL was compatible with HTTPS origin.
Outcome:
The proxy host ensured NPM recognized the root domain in the TLS handshake, eliminating the tls: unrecognized name error. The static HTML response avoided backend issues, fixing the 502. Internal TLS was maintained (tunnel → NPM over HTTPS), and subdomains functioned correctly with Force SSL.
Tips:
For subdomains, ensure proxy hosts use correct backend IPs/ports.