
How do I set up Cloudflare Tunnel (cloudflared) to publish an internal app without opening inbound ports?
Cloud teams, security teams, and lone admins all ask for the same thing: “How do I put this internal app on the Internet without cracking open a single inbound port?” Cloudflare Tunnel (via the cloudflared daemon) is built specifically for that use case — you run a lightweight connector inside your environment, it makes an outbound-only connection to Cloudflare’s network, and Cloudflare’s edge becomes your secure reverse proxy.
Quick Answer: Cloudflare Tunnel lets you publish internal web apps to the Internet over an outbound-only connection using
cloudflared. You remove inbound ports and VPN dependence by routing user requests through Cloudflare’s edge, where identity, security, and logging are enforced before any traffic reaches your app.
The Quick Overview
- What It Is: A secure, outbound-only tunnel (Cloudflare Tunnel, powered by
cloudflared) that connects your internal app to Cloudflare’s global edge so you can publish it over HTTPS without opening any inbound firewall ports. - Who It Is For: Security, IT, and platform teams that want to expose internal tools, admin panels, dev/test apps, or legacy on‑prem applications safely — and often replace or reduce VPN usage.
- Core Problem Solved: It eliminates the need to punch holes in your firewall or maintain complex ACLs, and lets every request be evaluated for identity and context at the edge instead of trusting a “private” network.
How It Works
At a high level, Cloudflare Tunnel flips the old model on its head. Instead of exposing your app to the Internet and letting anyone hit an open port, you:
- Run
cloudflarednext to your app (VM, container, bare metal, Kubernetes, etc.). cloudflaredestablishes an outbound-only, encrypted tunnel to Cloudflare’s network.- Cloudflare’s edge terminates user HTTPS connections, applies Zero Trust policies (Cloudflare Access), and forwards only authorized requests down the tunnel to your app.
From the Internet’s perspective, the only thing that exists is a DNS record pointing at Cloudflare. There are no open inbound ports on your infrastructure; your firewall can stay locked down.
1. Connect your app with an outbound-only tunnel
cloudflared runs in your environment and:
- Makes outbound-only calls to Cloudflare (no inbound listening sockets required).
- Authenticates to your Cloudflare account.
- Registers one or more tunnels and their routes (hostname → local service).
This is powered by Cloudflare Tunnel (previously called Argo Tunnel). Regardless of whether your app is on‑prem or in a cloud VPC, cloudflared connects it to the Cloudflare connectivity cloud without changing your network perimeter.
2. Route user traffic through Cloudflare’s edge
When a user visits your published hostname (for example, internal-app.example.com):
- DNS for
internal-app.example.compoints to Cloudflare. - The user’s request is terminated at the Cloudflare edge, within ~50ms of almost any Internet user.
- Policies are enforced there, at the edge:
- For public apps: WAF, DDoS, bot defenses, caching, etc. (Cloudflare Application Services).
- For private apps: identity-based access via Cloudflare Access (part of Cloudflare One).
Cloudflare uses Argo Smart Routing inside its network to take the fastest, least-congested path between the user and your tunnel, improving both performance and reliability.
3. Deliver only authorized requests to your internal app
After Cloudflare has evaluated the request:
- Only approved traffic is sent down the established tunnel to
cloudflared. cloudflaredproxies the traffic to your local app (http://localhost:8000, for example).- Responses are sent back over the tunnel to the edge and from there to the user.
Your app never needs to be directly reachable from the public Internet. The tunnel acts as a tightly controlled artery between Cloudflare’s edge and your private service.
Step‑by‑Step: Setting Up Cloudflare Tunnel with cloudflared
Below is the practical “how do I do this” sequence to publish an internal app without opening inbound ports.
Prerequisites
- A Cloudflare account with a zone (domain) onboarded, e.g.,
example.com. - Access to a server where your internal app runs (Linux, macOS, or Windows).
- Ability to install and run
cloudflared. - (Recommended) A Zero Trust account configured with your identity provider (Okta, Azure AD, Google Workspace, etc.) for Cloudflare Access.
1. Install cloudflared on the app host (or nearby)
On Linux (Debian/Ubuntu-style example):
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
You can also install via package managers (e.g., apt, brew, choco) depending on your OS. The official docs list current options.
2. Authenticate cloudflared to your Cloudflare account
Run:
cloudflared login
This will:
- Open a browser window (or give a URL) where you log in to Cloudflare.
- Ask you to select the zone (domain) for which you want to authorize tunnels.
- Store a certificate locally so
cloudflaredcan create tunnels on behalf of your account.
3. Create a named tunnel
Give your tunnel a friendly name tied to this app or host, for example:
cloudflared tunnel create internal-app-tunnel
This command will output:
- A tunnel UUID
- The location of a credentials file (e.g.,
/etc/cloudflared/<UUID>.json)
You’ll use this UUID in configuration and when registering DNS routes.
4. Configure the tunnel to route to your internal app
Create or edit the cloudflared config file (commonly /etc/cloudflared/config.yml):
tunnel: <TUNNEL-UUID>
credentials-file: /etc/cloudflared/<TUNNEL-UUID>.json
ingress:
- hostname: internal-app.example.com
service: http://localhost:8000
- service: http_status:404
Key points:
hostnameis the public name you want users to hit.serviceis howcloudflaredreaches your app internally.http://localhost:8000for a local web server.- Or
http://10.0.0.5:8080for another host in your private network.
- The final
http_status:404rule is a catch‑all.
This defines a simple mapping: “traffic for internal-app.example.com arrives at Cloudflare → Cloudflare sends that traffic down this tunnel → cloudflared proxies it to http://localhost:8000.”
5. Create a DNS record that points to the tunnel
Register the hostname with Cloudflare using a CNAME that targets the tunnel:
cloudflared tunnel route dns internal-app-tunnel internal-app.example.com
Cloudflare will create the appropriate DNS record in your zone, with Cloudflare’s proxy enabled, so traffic for internal-app.example.com hits Cloudflare’s edge first.
6. Run the tunnel and enable it as a service
Test it interactively:
cloudflared tunnel run internal-app-tunnel
If everything’s configured correctly, visiting https://internal-app.example.com should now reach your internal app through the tunnel.
Once you’ve verified it works, configure cloudflared as a system service so it starts on boot. Example for Linux (systemd):
sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
Your exact commands may differ by OS, but the goal is the same: keep the tunnel running and reconnecting automatically.
7. (Strongly Recommended) Add Zero Trust access controls
Right now, you’ve published an internal app without opening inbound ports. The next step is making sure only the right people can reach it.
Use Cloudflare Access to put an identity-aware “bouncer” in front of your hostname:
- In the Cloudflare Zero Trust dashboard, go to Access → Applications.
- Add a new Self‑hosted application.
- Set Application domain to
internal-app.example.com. - Choose your identity provider (Okta, Azure AD, Google, etc.).
- Define Access policies:
- Example: only members of a certain group, only corporate email domains, enforce MFA, restrict by country, device posture, or other context.
- Save and enable the policy.
From now on:
- Users hitting
internal-app.example.comare redirected to your IdP for SSO. - Cloudflare’s edge evaluates every request for identity and context.
- Only authenticated, authorized requests are allowed through the tunnel to your app.
To users, it feels like logging into a SaaS app. To you, it removes “trusted internal network” assumptions and replaces them with explicit identity‑driven access.
Features & Benefits Breakdown
| Core Feature | What It Does | Primary Benefit |
|---|---|---|
| Outbound‑only connectivity | cloudflared initiates all connections from your environment to Cloudflare, no inbound ports required. | Eliminates the need to open firewall ports or manage inbound ACLs; reduces attack surface. |
| Edge‑enforced Zero Trust | Integrates with Cloudflare Access so every request is checked for identity and context at the edge. | Replaces or reduces VPN, enforces least-privilege access, and centralizes authentication. |
| Global routing & protection | Uses Cloudflare’s global network and Argo Smart Routing, plus WAF/DDoS/bot defenses for your hostname. | Improves performance and resilience while adding enterprise-grade security in front of your app. |
Ideal Use Cases
- Best for publishing internal admin tools or control panels: Because you can expose them over HTTPS with SSO and MFA at the edge, while keeping your infrastructure completely closed to inbound traffic.
- Best for replacing fragile VPN access to specific apps: Because users reach
internal-app.example.comdirectly and authenticate with Cloudflare Access, offloading traffic and complexity from traditional VPNs.
Additional common scenarios:
- Dev/test tools (Jenkins, Grafana, Kibana, internal dashboards).
- Legacy line‑of‑business apps in a datacenter.
- On‑prem APIs consumed by external services.
- SSH, RDP, and other non‑HTTP protocols when paired with Cloudflare Access and
cloudflaredTCP support.
Limitations & Considerations
- You still need strong internal segmentation: Cloudflare Tunnel secures access to the published app, but you must still apply proper network segmentation and least privilege inside your environment. Treat the app as an Internet-facing service, even if the port isn’t open.
- High availability requires more than one connector: For production, you should run multiple
cloudflaredinstances (on different hosts/zones) for redundancy. The tunnel service supports this, but it’s not automatic if you only deploy a single connector.
Other practical considerations:
- Make sure
cloudflaredcan reach your internal service (firewall, local DNS, etc.). - Use infrastructure as code or config management to manage
cloudflaredconfigs at scale. - For very latency-sensitive apps, validate performance with Argo Smart Routing enabled.
Pricing & Plans
Cloudflare Tunnel itself is available across Cloudflare plans; many organizations start on standard plans and then scale up as they centralize Zero Trust and network services.
For organizations standardizing on Cloudflare for Zero Trust, SASE, and network modernization:
- Pro / Business / Zero Trust Standard tiers: Best for smaller teams or project‑based deployments needing secure publishing for a limited set of apps with basic Access policies and DNS protection.
- Enterprise: Best for large or regulated organizations needing advanced Zero Trust policies, full Cloudflare One (SASE) capabilities, 100% uptime SLAs, dedicated support, and the ability to protect a wide portfolio of apps, networks, and AI workloads on a unified connectivity cloud.
To scope Enterprise pricing, deployment patterns, and migration plans, contact Cloudflare sales:
- Get Started (Enterprise contact): https://www.cloudflare.com/plans/enterprise/contact/
Frequently Asked Questions
Do I really not need to open any inbound ports on my firewall?
Short Answer: Correct — Cloudflare Tunnel works with outbound-only connections, so you can close inbound ports used for application delivery.
Details: cloudflared initiates the tunnel from your environment out to Cloudflare’s network. There’s no need for the Internet to initiate a connection into your infrastructure. That means you can:
- Remove public NAT/port forwards for the app.
- Close listening ports on your perimeter firewall for that service.
- Let the DNS record be the only public artifact of the app, protected by Cloudflare’s edge (WAF, DDoS, Access).
This aligns with Zero Trust guidance: avoid exposing open inbound ports that can be scanned and exploited, and put a tightly controlled, identity-aware reverse proxy in front instead.
Can Cloudflare Tunnel replace my VPN for internal apps?
Short Answer: For many web and app protocols, yes — Cloudflare Access plus Tunnel is designed to replace VPN access to those resources.
Details: Cloudflare Access secures:
- Web apps (HTTP/HTTPS)
- SSH
- RDP
- SMB fileshares
- Arbitrary TCP services (via
cloudflared)
When you protect internal tools with Access and publish them through Cloudflare Tunnel:
- Users sign in through your identity provider (Okta, Azure AD, etc.) with MFA.
- Every request is evaluated at the edge for identity and policies.
- The experience feels like SaaS apps rather than a clunky VPN.
You may still keep a VPN for very specific, low‑level access (e.g., broad network administration), but for most internal apps, Cloudflare Tunnel + Access lets you move away from VPN licenses, hardware bottlenecks, and flat “trusted” network access.
Summary
Cloudflare Tunnel (cloudflared) lets you publish internal apps to the Internet without opening inbound ports by flipping the connectivity model: your environment initiates an outbound-only connection to Cloudflare, and Cloudflare’s edge becomes the secure front door. Every request to your app is routed through Cloudflare’s global network, where it can be protected with WAF and DDoS mitigation and, crucially, evaluated for identity and context through Cloudflare Access.
The result is a defensible architecture: no exposed listening ports, clear visibility and logging at the edge, and identity-driven access that makes internal apps feel like SaaS — all without redesigning your entire network or relying on brittle VPNs.