📅 Published: March 2026 | ✍️ By Brad Andrews | ⏱️ 7 min read
If you’ve already got Home Assistant running and you want to access it securely from outside your home, you’ve probably run into the same advice repeated everywhere: open a port on your router and point it at your server.
Don’t do that!
Open ports are an attack surface. Once something is reachable on the public internet, it gets probed constantly, automatically, by bots that don’t care who you are. Your Home Assistant login page becomes a target. Your server fingerprint gets logged. Brute force attempts roll in whether you’re watching or not.
There’s a better way, and it’s free.
What Is a Cloudflare Tunnel And Why Does It Matter?
A Cloudflare Tunnel (formerly Argo Tunnel) creates an outbound-only encrypted connection from your server to Cloudflare’s network. Your Home Assistant never listens on a public IP. No ports open. No firewall rules to maintain. Cloudflare sits in front of everything, and traffic only flows through the tunnel your server reaches out to Cloudflare, never the other way around.
What that means in practice:
- No open ports on your router
- Your Home Assistant IP is never exposed to the public internet
- Cloudflare handles TLS termination at the edge
- You get a clean
https://home.yourdomain.caURL that works anywhere in the world - The whole thing runs on Cloudflare’s free tier no credit card, no catch
I ran Nabu Casa for remote access for years, and I still pay for it it’s a great product and that subscription directly funds Home Assistant development. I’d encourage you to keep it if you have it. But I wanted a security layer that goes beyond a login page, and Cloudflare Tunnel is the foundation for that. I’ll show you what I mean at the end of this guide.
Note on existing guides: Cloudflare has overhauled their Zero Trust dashboard significantly. Most guides you’ll find are using outdated screenshots and menu paths. This guide is written for the current interface as of April 2026 if something looks different on your screen, the dashboard has probably changed again. The concepts are the same; the clicks may have moved.
What You Need Before You Start
- A domain name with DNS managed by Cloudflare. Your registrar doesn’t matter I use Namecheap but you need to point your nameservers at Cloudflare and manage DNS from their dashboard. If you haven’t done this yet, Cloudflare’s documentation walks through it.
- A free Cloudflare account with Zero Trust enabled. The free tier is more than sufficient for home use it supports up to 50 users on Access policies, which is well beyond what any home setup needs.
- A machine running
cloudflaredthis is the tunnel connector. It can run anywhere on your network: a Docker host, a Synology NAS, a Raspberry Pi, an LXC container on Proxmox. As long as it can reach your Home Assistant on the local network, you’re good. - Home Assistant already running on your network. If you’re not there yet, start with the Getting Started Blueprint.
Step 1: Set Up Cloudflare Zero Trust
- Log into your Cloudflare dashboard at dash.cloudflare.com
- In the left sidebar, click Zero Trust
- If this is your first time, you’ll be prompted to choose a team name this becomes part of your Zero Trust org identifier. Pick something simple. It doesn’t affect your tunnel URL.
- Select the Free plan when prompted
You’re now inside the Zero Trust dashboard. This is where tunnels, access policies, and eventually mTLS all live.
Step 2: Create the Tunnel
- In the Zero Trust dashboard, navigate to Networks → Connectors
- Click Create a tunnel
- Choose Cloudflared as the connector type
- Give your tunnel a name something like
home-assistantorhomelab. This is just a label for your own reference. - Click Save tunnel
Cloudflare will now show you installation instructions for cloudflared. Don’t follow those instructions yet they’re for running it directly on a machine. We’re going to run it in Docker, which is more portable. What you need from this screen is the tunnel token it’s the long string in the install command after --token. Copy it and keep it somewhere safe. You’ll need it in the next step.
- For now, click Next past the connector installation screen we’ll come back to verify the connection after we run the container.
Step 3: Run cloudflared in Docker
On whatever machine you’re running Docker on, create the following docker-compose.yml:
yaml
# cloudflared tunnel connector
# Connects your local network to Cloudflare's Zero Trust network
# Replace YOUR_TUNNEL_TOKEN_HERE with the token from the Cloudflare dashboard
services:
cloudflared:
image: cloudflare/cloudflared:latest # Official Cloudflare image
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run # Run tunnel, disable auto-update (we manage updates manually)
environment:
- TUNNEL_TOKEN=YOUR_TUNNEL_TOKEN_HERE # Paste your tunnel token here
network_mode: host # Host networking allows the container to reach your local network
Security note: If you prefer not to put the token directly in the compose file, use a
.envfile alongside it and reference it as${TUNNEL_TOKEN}. Never commit a tunnel token to a public Git repository.
Start the container:
bash
docker compose up -d
Check the logs to confirm it connected:
bash
docker logs cloudflared
You should see something like Registered tunnel connection with a Cloudflare edge location. If you see connection errors, verify your token is correct and that the container has outbound internet access.
Back in the Cloudflare dashboard under Networks → Tunnels, your tunnel should now show a green Healthy status.
Step 4: Configure the Tunnel Route
This is where you tell Cloudflare what hostname to expose and where to send the traffic internally.
- In the Zero Trust dashboard, go to Networks → Connectors
- Click the three-dot menu next to your tunnel → Configure
- Click the Published Application Routes
- Click Add a published application route
Fill in the following:
| Field | Value |
|---|---|
| Subdomain | home |
| Domain | yourdomain.ca |
| Type | HTTP |
| URL | 10.0.X.X:8123 |
Why HTTP and not HTTPS here? The connection between
cloudflaredand your Home Assistant is on your local network you control both ends. Cloudflare handles TLS from the outside world to their edge. The internal hop is HTTP and that’s fine. You can add a self signed cert to Home Assistant using a proxy like NGINX or Synology built in reverse proxy, but that is not covered in this guide. I do recommend doing this and will look to cover in a future article as that would add https encryption on the back end between CloudFlare and your reverse proxy internal to your network.
- Click Save hostname
At this point, https://home.yourdomain.ca should resolve and show your Home Assistant login page. If it doesn’t, check that your DNS is pointing at Cloudflare (orange-clouded in your DNS dashboard) and give it a few minutes to propagate.
Step 5: Configure Home Assistant
Home Assistant needs to know to trust the proxy headers coming from cloudflared. Without this, you’ll see 400 errors or Home Assistant will reject requests thinking they’re coming from an untrusted source.
Add the following to your configuration.yaml:
yaml
# Proxy configuration for Cloudflare Tunnel
# Required so Home Assistant trusts forwarded headers from cloudflared
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1 # Localhost
- ::1 # IPv6 localhost
- !secret cloudflare_tunnel_host # IP address of your cloudflared container host
In your secrets.yaml, add:
yaml
# IP address of the machine running your cloudflared Docker container
cloudflare_tunnel_host: 10.0.X.X
Replace 10.0.X.X with the actual local IP of the machine running your cloudflared container.
Restart Home Assistant to apply the changes: Settings → System → Restart.
Why
!secrethere? Your local network IP layout is useful information for anyone who gets access to your config. Usingsecrets.yamlkeeps it out of any config you might share publicly a habit worth building from the start. See the Home Assistant docs on secrets if this is new to you.
Step 6: Test Your Setup
Open a browser on a device not connected to your home Wi-Fi use mobile data or a VPN and navigate to https://home.yourdomain.ca.
You should see your Home Assistant login page over a valid HTTPS connection (Cloudflare handles the certificate automatically).
If it’s not working, check these in order:
- Is the
cloudflaredcontainer running and showing Healthy in the Cloudflare dashboard? - Does the public hostname URL match your actual Home Assistant IP and port exactly?
- Did you restart Home Assistant after adding the
http:block? - Is the
trusted_proxiesIP pointing at the correct host? - Check Settings → System → Logs in Home Assistant for any proxy-related errors
Connecting the Home Assistant Companion App
In the HA Companion App, go to Settings → Companion App → [your server] → Connection.
Add https://home.yourdomain.ca as an External URL. The app will use your local address when you’re on home Wi-Fi and the external URL when you’re away.
A Note on Nabu Casa
If you’re currently using Nabu Casa for remote access, you don’t need to cancel it to use this setup. I still pay for my subscription the money goes directly toward funding Home Assistant development, and I also buy merch from the Open Home Foundation store for the same reason. They’re building something worth supporting.
What I’ve done is shifted my day-to-day remote access to the Cloudflare Tunnel because it gives me a foundation for the next layer of security: mTLS authentication. With Nabu Casa still connected, it’s also a useful fallback and my Tesla browser still uses it for now since it doesn’t support mTLS. That’s a problem I’m actively working on solving via a Cloudflare Access policy using ISP cellular range and user agent rules to create a narrow, specific bypass I’ll document that once it’s running.
What’s Next: Lock the Door Completely
Right now, https://home.yourdomain.ca shows your Home Assistant login page to anyone who visits it. That’s already vastly better than port forwarding but the login page itself is still reachable. Someone with enough patience can still probe it for vulnerabilities, try to brute-force credentials, or fingerprint what software is running.
The next Blueprint in this series fixes that entirely.
The Blueprint: Locking Down Home Assistant With mTLS So Hackers Can’t Even Find the Door →
With mTLS in place, anyone without a valid client certificate installed on their device gets a Cloudflare access denied screen before they ever touch your network. Your login page becomes invisible. Your server becomes unreachable. It’s free, it runs entirely within Cloudflare Zero Trust, and the setup takes less than an hour.
The Bottom Line
Cloudflare Tunnel gives you everything port forwarding gives you remote access from anywhere, a clean HTTPS URL with none of the risk. No open ports. No exposed IP. No attack surface on your router.
It takes about 30 minutes to set up. The security improvement is permanent.
Join the Network. Get the Blueprint. Unlock the Truth.
Helpful Links
- Cloudflare Tunnel documentation official setup reference
- Home Assistant HTTP integration docs trusted proxies configuration
- kcore.org: Using Cloudflare Zero Trust and mTLS with Home Assistant A very helpful guide I originally used but some of the screenshots may now be out of date
Smart Home Secrets is reader-supported. We may earn a commission if you buy through our links.

