VOOZH about

URL: https://dev.to/imrhlrvndrn/secure-any-self-hosted-app-with-cloudflare-access-ck0

⇱ Secure Any Self-Hosted App with Cloudflare Access - DEV Community


If you're exposing self-hosted applications through Cloudflare Tunnel, you're already reducing your attack surface by avoiding port forwarding. However, many administrators stop there and leave their applications publicly accessible.

Cloudflare Access, part of Cloudflare Zero Trust, allows you to place an authentication layer in front of any application before users ever reach your login page.

In this guide, we'll secure a self-hosted application hosted at:

app.example.com

using Cloudflare Access and One-Time PIN (OTP) authentication.

We'll cover:

  • Configuring Cloudflare One-Time PIN authentication

  • Creating reusable Access policies

  • Allowing an entire email domain

  • Whitelisting specific email addresses

  • Protecting a self-hosted application

  • Blocking public access entirely

By the end, only approved users will be able to reach your application.


Why Use Cloudflare Access?

Without Access:

Internet
 |
app.example.com
 |
Application Login Page

Anyone can reach your application.

They may not know the password, but they can:

  • Discover your login page

  • Attempt brute force attacks

  • Probe application vulnerabilities

  • Enumerate users

With Cloudflare Access:

Internet
 |
Cloudflare Access
 |
Authentication
 |
app.example.com
 |
Application

Users must authenticate with Cloudflare before the application is even exposed.

This dramatically reduces your public attack surface.


Prerequisites

Before starting, ensure:

  • Your domain is managed by Cloudflare

  • Cloudflare Tunnel is already configured ( you can also have a VPS with reverse-proxy services like Caddy, Traefik, Ngnix configured )

  • Your application is accessible through:

app.example.com

  • You have access to the Cloudflare Zero Trust dashboard

Step 1: Configure One-Time PIN Authentication

This is the most commonly missed step.

Many users create Access policies and wonder why no login code arrives.

Cloudflare Access only sends One-Time PIN codes if the One-Time PIN Identity Provider has been configured first.

Navigate to:

Zero Trust
 └── Integrations
 └── Identity Providers

Click:

Add New Identity Provider

Select:

One-Time PIN

Save the provider.

That's it.

No SMTP configuration is required because Cloudflare sends the authentication emails on your behalf.


Important: How OTP Delivery Works

When a user attempts to access:

https://app.example.com

they will see a Cloudflare login screen asking for an email address. Cloudflare only sends a login code if that email address matches an Access policy.

Example:

Allowed policy:

example@gmail.com

User enters:

example@gmail.com

Result:

OTP Email Sent

User enters:

unknown@gmail.com

Result:

Access Denied

No authentication code is sent. This behavior helps prevent unauthorized users from discovering who is allowed access.


Step 2: Create a Reusable Access Policy

Cloudflare now supports reusable Access policies that can be attached to multiple applications.

Navigate to:

Zero Trust
 └── Access Controls
 └── Policies

Click:

Add a Policy


Policy Example 1: Allow an Entire Email Domain

This is ideal for organizations.

Policy Name:

Company Employees

Action:

Allow

Rule:

Include
 └── Emails Ending In
 └── company.com

Result:

Allowed:

employee1@company.com
employee2@company.com
employee3@company.com

Denied:

example@gmail.com

Only users with email addresses ending in:

@company.com

can authenticate.

Save the policy.


Policy Example 2: Whitelist Specific Users

For personal applications or small teams.

Policy Name:

Approved Users

Action:

Allow

Rule:

Include
 └── Emails

Example values:

test-user@gmail.com
test-user2@gmail.com
investor@gmail.com

Only these exact users will be allowed access.

Save the policy.


Which Policy Should You Use?

Emails Ending In

Best for:

  • Companies

  • Teams

  • Organizations

Example:

@company.com

Every employee automatically gains access.


Specific Emails

Best for:

  • Homelabs

  • Self-hosted applications

  • Family access

  • Small groups

Example:

test-user2@gmail.com
investor@gmail.com

Only explicitly approved users can log in.


Step 3: Create the Self-Hosted Access Application

Navigate to:

Zero Trust
 └── Access Controls
 └── Applications

Click:

Create New Application

Choose:

Self-hosted and private

This is the current application type used for protecting self-hosted services.


Configure the Application

Application Name:

Internal App

Public Hostname:

app.example.com

Cloudflare will automatically create the Access protection layer for this hostname.


Configure Identity Providers

Under Authentication:

Select:

One-Time PIN

You may also enable:

  • Google

  • GitHub

  • Microsoft Entra ID

  • Okta

if desired.

For this guide we will use:

One-Time PIN Only


Attach the Access Policy

Under Policies:

Add:

Company Employees

or

Approved Users

depending on which policy you created earlier.

Cloudflare Access operates on a deny-by-default model.

If no policy matches:

Access Denied

The application remains inaccessible.

Save the application.


What Happens Now?

A visitor opens:

https://app.example.com

Cloudflare intercepts the request.

They see:

Enter Email Address

User enters:

example@gmail.com

Cloudflare verifies:

  • Is OTP enabled?

  • Does the email match a policy?

If yes:

Send Login Code

User receives a one-time PIN via email.

After entering the PIN:

Cloudflare Access Granted

The request is forwarded to your application.


Public Users Are Now Blocked

Before:

Internet
 |
app.example.com
 |
Application

After:

Internet
 |
Cloudflare Access
 |
Allowed Users Only
 |
Application

Anonymous visitors can no longer reach:

  • Login pages

  • Dashboards

  • Admin panels

  • APIs behind Access

unless they successfully authenticate.


Example Production Setup

Internet
 |
Cloudflare Access
 |
 app.example.com
 |
Cloudflare Tunnel
 |
 VPS
 |
 Docker
 |
 Application

Authentication occurs at Cloudflare's edge before traffic ever reaches your server.

This means:

  • No exposed ports

  • No VPN required

  • No public login page

  • Reduced attack surface

  • Simple email-based authentication


Testing Your Configuration

Open an incognito window.

Visit:

https://app.example.com

Try:

Allowed Email

example@gmail.com

Expected:

Login code arrives

Unauthorized Email

unknown@gmail.com

Expected:

No access granted

The user cannot reach the application.


Final Thoughts

Cloudflare Access is one of the easiest ways to secure self-hosted applications without deploying a VPN or identity platform.

The key configuration many users miss is enabling the One-Time PIN Identity Provider before creating policies. Without it, users will never receive authentication emails.

For personal projects, whitelist specific email addresses.

For organizations, use the "Emails Ending In" rule to automatically allow users from your company domain.

Combined with Cloudflare Tunnel, Access provides a powerful Zero Trust architecture where your application remains private, authenticated, and inaccessible to the public Internet.