Itโs common for homes nowadays to have private home lab hosting services, like a media server or FTP server. In some cases, users would want to make these private services accessible anywhere on the internet.
Not every internet subscription comes with a dedicated public IP address. But even so, configuring your internal network to be accessible publicly is not typically a simple task for most home users.
Getting Started: Prerequisites and Tunnel Creation
So whatโs the alternative? You should consider using the Cloudflare tunnel, part of the Cloudflare Zero Trust, which exposes your private network to the Cloudflare global network. There are several subscription options to Cloudflare Zero Trust, but the free option should be sufficient for a home lab.
Stay with me, and I will show you how to set up Cloudflare Tunnel and use your private services online!
How Cloudflare Tunnel works
Cloudflare Tunnel establishes an outbound tunnel connection from an internal server to the Cloudflare network. This allows you to expose services without opening inbound ports on your router/firewall.
Traffic to the published app is routed through Cloudflare and securely forwarded to the internal service through the outbound tunnel connection.
Requirements for Setting Up Cloudflare Tunnel
To follow along, make sure you have these prerequisites.
- A server in your internal network. This server can be any computer that hosts your private services. This demo uses Ubuntu Server 24.04 LTS.
- Docker is installed on your server. Although Cloudflare Tunnel (cloudflared) can run as a standalone service, installing it as a Docker container makes it more convenient and consistent across platforms.
- You must already have a domain configured and active in your Cloudflare account. In this example, weโll use example.com as a placeholder. Replace it with a real domain that you have added to your Cloudflare account.
Create a Cloudflare Tunnel via Zero Trust Dashboard
Suppose you already have a Cloudflare account, follow these steps to create a new tunnel.
- Login to your Cloudflare account and click on the Zero Trust link.

- Go to Networking โ Tunnels in the Cloudflare dashboard and click Create a tunnel.

- Next, type a descriptive name for the tunnel youโre creating. In this example, weโll name the tunnel homelab to indicate that this tunnel we are creating for our home lab network. Once youโve entered the tunnel name, click Save tunnel.

Installing and Connecting the Cloudflared Connector
After saving the new Cloudflare tunnel, the next step requires installing the Cloudflare Tunnel connector on your server.
Choosing the Environment (Linux, Windows, Docker)
On the Choose your environment, select the operating system of your server. The connector can be installed on Windows, Mac, Linux, and as a Docker container. In this example, Iโll install the connector as a Docker application.

Running the Tunnel Connector as a Docker Container
The instructions or command to install the connector for your chosen environment appears below. In this example, thereโs only one command to execute to run the Cloudflare tunnel connector as a Docker container. Copy this command.
docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <TOKEN>

Before running the docker run command, letโs insert the -d option to run the container in detached mode, and the –name <name> argument to name the container:
docker run -d --name homelab_tunnel cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <TUNNEL_TOKEN>
Don’t forget to replace <TUNNEL_TOKEN> with the token generated for your Cloudflare Tunnel. Treat the token as a secret: anyone who has the token can run the tunnel. If the token is exposed, revoke or rotate it in the Cloudflare dashboard.
The –no-autoupdate option disables automatic updates of cloudflared. When running cloudflared in Docker, it is generally preferable to manage the version through the Docker image rather than allowing the app inside the container to update itself.
This makes container updates more predictable and allows you to control when a new cloudflared version is deployed:

Now, run the command in your serverโs terminal. As you can see below, Docker downloads the cloudflare/cloudflared image from the Docker Hub and starts the new container.

Option: Run Cloudflared with Docker Compose
For a persistent home lab deployment, you can also use Docker Compose. This keeps the tunnel config in a Compose file and avoids putting the tunnel token directly in the command line.ย Create a .env file in the same directory as your compose.yaml file:
TUNNEL_TOKEN=<YOUR_TUNNEL_TOKEN>
Then create a compose.yaml file:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: homelab_tunnel
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
TUNNEL_TOKEN: ${TUNNEL_TOKEN}
Now start the Cloudflared container:
docker compose up -d
After that. check the container status:
docker compose ps
Security note. The `.env` file contains the Cloudflare Tunnel token and should be treated as a secret. Do not commit it to a public or shared Git repository. If you use Git for your Compose configuration, add .env to .gitignore.
For example, if you use Git to manage the config, add the following entry to .gitignore:
.env
Confirming Connector Status and Health
Letโs confirm that the Cloudflare Tunnel container is running (if you used Docker Compose, you can also run docker compose ps from the directory containing compose.yaml):
docker ps -f 'name=homelab_tunnel'

Go back to the Cloudflare dashboard and check the connector status. After the cloudflared container starts successfully, the connector should appear as Connected.

Exposing a Web Application (HTTP/S Service)
In my home lab setup, Cockpit is installed on my Ubuntu server and accessible on https://192.168.1.20:9090.

In this example, letโs expose this web application through the Cloudflare tunnel network and make it accessible to the internet.
Security note. When you expose a service through Cloudflare Tunnel, by default it does not autoenforce the authentication. So, to restrict who can access the application, you need to configure Cloudflare Access policies.
In case you won’t configure access policies, your service is publicly available for anyone who have a service’s URL.
Configuring a Public Hostname and Internal URL
- Enter the subdomain that you want to assign to the service. In this example, letโs call it cockpit.
- Choose the domain from the dropdown list.
Note. You must already have a DNS domain configured in Cloudflare DNS for this step. Otherwise, there will be no domain available in the list. - Choose HTTPS from the Type selection.
- Enter the web service URL inside the URL box. This URL is the internal address of the web service, such as https://192.168.1.20:9090 for Cockpit.
Using Additional Application Settings (No TLS Verify Note)

Click on Additional application settings.
Expand TLS and Enable the No TLS Verify option.
Note that you should enable this option only in case your internal service uses a self-signed certificate. This disables certificate validation and it’s not a good idea to use this in production environments unless necessary.
Click Save to create the route.
Note. This step is applicable only if the service youโre exposing is using HTTPS and the certificate is not from a public certificate provider.

At this point, you now have a Cloudflare tunnel:
- Named homelab with one configured route to cockpit.example.com.
- The tunnel status is Healthy.
- The connector status is Connected.

- A proxied CNAME record pointing to the tunnel hostname (.cfargotunnel.com). Cloudflare automatically creates a proxied CNAME record for the public hostname. This allows traffic to reach the service through Cloudflare without exposing the origin server’s public IP address.

Final Verification and Testing Public Access

Finally, test whether you can access the web application on the internet by opening the public hostname in a web browser. As you can see below, opening the https://cockpit.example.com URL loads the Cockpit interface of my internal server.
Add a Cloudflare Tunnel SSH Access
Apart from web-based applications, you can also expose non-HTTP services through different protocols. One example is SSH access.
Creating a Public Hostname for SSH
Exposing your serverโs SSH access via Cloudflare Tunnel, you only need to create the public hostname in the existing tunnel. No need to open new ports in the firewall.
- Open your tunnel in Networking โ Tunnels.

- Open the Routes tab and click Add route.

- Select Published application.
- Enter the subdomain and select the domain. Choose SSH as the service type, and enter the serverโs internal IP address name and port in the URL field.
As you can see below, this example has the following values.- Subdomain+Domain = terminal.example.com
- Type = SSH
- Service URL = ssh://192.168.1.20:22
- Click Save.

- You now have an SSH published application route configured for your Cloudflare Tunnel.

Connecting to the Cloudflare Tunnel SSH Endpoint
To connect to the Cloudflare Tunnel SSH endpoint you created, you must first install the cloudflared binary to your client computer.
- Open a browser on your computer and open the Cloudflare Tunnel downloads page.
- On the page, download the cloudflared binary for your computerโs operating system. In this example, Iโll download the executable for Windows since Iโm using a Windows 11 computer.

- After downloading the file, move it to a convenient directory. In this example, weโve moved the file to C:\Tools\cloudflared-windows-amd64.exe.

Configuring the Native SSH Client (~/.ssh/config)
Next, edit your SSH client configuration.
- Open the file ~/.ssh/config in your text editor. Append the following configuration entry for your Cloudflare Tunnel SSH public hostname.
- Make sure to replace terminal.example.com with your SSH public hostname and C:\Tools\cloudflared-windows-amd64.exe with your correct executable location.
Host terminal.example.com
ProxyCommand C:\Tools\cloudflared-windows-amd64.exe access ssh --hostname %hThis config says the SSH client to route the connection through the Cloudflare Tunnel using the cloudflared client instead of direct connection.

- Save and close the config file.
- Open a terminal (PowerShell on Windows) and run the following command:
ssh <username>@<public-hostname>

Conclusion
Cloudflare Tunnel really changes the game. Imagine hosting many applications inside your home network and then configuring which ones to make available to the internet.
For example, you can host your own password manager instance and make it available even when traveling and not connected to your home network! You can make your media server available online and share it with your family and friends across different locations.
What are the prerequisites for setting up a Cloudflare Tunnel?
You need three main things:
- An internal server: Any computer on your network that hosts the services you want to expose (e.g., Ubuntu Server, Windows, or a Raspberry Pi).
- A DNS domain: You must have a DNS domain registered and actively managed within your Cloudflare account.
- The connector (cloudflared): The client application installed on your internal server. Using Docker to run the connector is a common and convenient method.
How do I install the cloudflared connector on my internal server?
The cloudflared connector can be installed on various operating systems (Linux, Windows, macOS) or run as a Docker container. The recommended method is often Docker due to its consistency.
After creating your tunnel in the Cloudflare Zero Trust dashboard, the interface provides a specific docker run command for your tunnel. You run this command on your server’s terminal to download the image and start the secure connection.
Can I expose non-HTTP services like SSH access through Cloudflare Tunnel?
Yes, Cloudflare Tunnel supports exposing non-HTTP protocols, including SSH. You create a new Public Hostname in the tunnel configuration, selecting SSH as the service type, and entering the internal IP address and port (e.g., 192.168.1.20:22) as the URL.
How do I connect to the SSH endpoint once the tunnel is configured?
Connecting to the SSH endpoint requires installing the cloudflared binary on your client computer (the one you are connecting from).
You must then configure your local SSH client to use cloudflared as a proxy by editing the ~/.ssh/config file. This uses the ProxyCommand directive to instruct your SSH client to tunnel the connection through cloudflared when connecting to that specific hostname:
ssh <username>@<public-hostname>



Hello. Thanks a lot for this useful post.
I am travelling to a country where the internet is under massive censorship (including YouTube, …!!!)
I would like to connect to my home internet and bypass this censorship through Cloudflare. I have a PC at home and I have set up my cloudshare site and tunnel and all seems healthy. The public hostname of this Tunnel uses the IP address of this PC at home with an open port through HTTPS (let’s say 192.168.2.42:8080).
I still cant connect to my home network and I cannot access my router (192.168.1.1).
Do you have any idea how i can resolve this issue?
Does this work if the server is on a network that uses CGNAT?
I have no way to test this right now, but the idea is to simplify publishing internal services to the internet via the tunnel without worrying about the in-between network. So long as the connector is installed on your host and it can reach the ZeroTrust network.
Appears to already be out-dated by Cloudflare’s recent changes. I have a tunnel and a route to a machine. Can’t figure out how to configure from there to do anything with it. Sure did like the old days of just using dynamic routes from the command line.