Cloudflare Access can protect your internal applications by acting as a secure gateway, verifying every user and device before granting access, effectively replacing traditional VPNs and perimeter-based security.

Let’s see this in action. Imagine you have a Jenkins server running on an internal IP address, say 10.0.0.5, accessible only from your corporate network. You want to make it accessible to your remote team via Cloudflare’s network without exposing it directly to the internet.

First, you’ll need to set up Cloudflare Tunnel. This is a lightweight daemon that runs on a server within your internal network and establishes an outbound-only connection to Cloudflare’s edge.

On your internal server (e.g., jenkins-server), install cloudflared:

wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

Next, authenticate cloudflared with your Cloudflare account:

cloudflared login

This will open a browser window for you to authorize the connection.

Now, create a tunnel. Give it a name, like jenkins-tunnel:

cloudflared tunnel create jenkins-tunnel

This command outputs a tunnel ID and creates a credentials.json file in ~/.cloudflared/. You’ll need this file to run the tunnel.

Configure the tunnel to point to your Jenkins server. Create a configuration file, e.g., /etc/cloudflared/config.yml:

tunnel: <YOUR_TUNNEL_ID>
credentials-file: /etc/cloudflared/credentials.json

ingress:
  - hostname: jenkins.yourdomain.com
    service: http://10.0.0.5:8080
  - service: http_status:404

Replace <YOUR_TUNNEL_ID> with the ID from the create tunnel command and ensure jenkins.yourdomain.com is a DNS record in your Cloudflare account pointing to your tunnel. The http://10.0.0.5:8080 is the internal address of your Jenkins server.

Start the tunnel:

cloudflared tunnel run jenkins-tunnel

At this point, jenkins.yourdomain.com will resolve to Cloudflare’s edge. However, no one can access it yet. We need to define an Access Policy.

In the Cloudflare dashboard, navigate to "Access" -> "Applications". Click "Add an application", choose "Self-hosted", and enter jenkins.yourdomain.com as the Application domain.

Now, configure the Access Policy. For example, to allow only users in your organization’s Google Workspace who are in the "developers" group:

  • Policy Name: Allow Developers
  • Action: Allow
  • Configure rules:
    • If Emails ending in @yourdomain.com
    • AND Google Workspace Group developers

This policy ensures that only authenticated users from your domain, belonging to the specified Google Workspace group, can reach your Jenkins server. Cloudflare Access intercepts the request, performs the identity check, and only forwards authorized traffic to your cloudflared tunnel, which then proxies it to your internal Jenkins server.

The surprising truth is that Cloudflare Access isn’t just about authentication; it’s about authorization at the edge, making your internal applications act as if they are part of Cloudflare’s network, not your private one. This fundamentally shifts the security perimeter from your network boundary to the identity of the user and the posture of their device.

When a user tries to access jenkins.yourdomain.com, Cloudflare checks for a valid identity token. If none exists, it redirects the user to your configured identity provider (e.g., Google, Azure AD, Okta). After successful authentication, the IdP sends a token back to Cloudflare. Cloudflare then evaluates this token against your Access policies. If the user is authorized according to the rules, Cloudflare establishes a secure connection to your cloudflared tunnel, which then forwards the request to your internal Jenkins server. The entire process happens without the user needing a VPN connection or your Jenkins server needing a public IP address.

Crucially, the service: http_status:404 line in the config.yml is the catch-all. Any traffic that doesn’t match a specific hostname rule in the ingress section will result in a 404 Not Found error being returned by cloudflared itself, before it even hits Cloudflare Access policies. This is a simple yet effective way to prevent accidental exposure of other internal services that haven’t been explicitly configured.

The next step in securing your internal applications might involve integrating device posture checks, ensuring that only compliant devices can access your resources.

Want structured learning?

Take the full Cloudflare course →