Articles

November 21, 2025

Protect Your Admin Panel with Cloudflare Zero Trust — For Free!

*A quick security win — no coding, no plugins, no cost.* 🎯 **Why protect your Admin Panel?** Admin URLs are like gold mines for attackers. Even if your login is secure, exposing these URLs publicly allows: - Bot scanning - Brute-force attempts - Vulnerability probing The best protection? Make them invisible to the internet. ## 🚀 Solution: Hide Admin Panel behind Cloudflare Zero Trust 🛠️ **What we'll do?** We'll block public access to `/admin` (and related URLs), and allow access only to authorized users — protected by email, Google Login, OTP or identity provider. ### Step-by-Step Setup 1️⃣ **Go to Cloudflare -> Zero Trust** - Login to Cloudflare. Then on the sidebar click **Zero Trust** - Choose the free plan, but Cloudflare will still ask you to provide payment details 2️⃣ **Manage Identity Providers** - On Zero Trust Dashboard, on the sidebar click **Integrations** -> **Identity providers** - These will provide a way for you to authenticate for your login panel. **One-time PIN** is enabled by default — this will send an OTP to the registered email address. - Of course, you can also add other ways to authenticate: ![Zero Trust Login Methods](https://marvinquezon.com/storage/uploads/screenshot-2025-11-21-at-113647-am.png) 3️⃣ **Create a Policy** - On the sidebar click **Access controls** -> **Policies** - On Policy Name: Allow Team Members (or whatever policy name you want that makes sense) - Duration: Set to default: 24 hours - Then on **Add Rules** -> **Selector** choose **Emails** - here you can add the emails of your team members who will need access to your admin panel. - Once done, scroll down and click **Save** 4️⃣ **Add your Application** - On the sidebar click **Access controls** -> **Applications** - Click **Add Application** then select **Self-hosted** - Application Name: **My Website Admin** (or whatever makes sense to you) - Click on **Add public hostname** -> Input your domain and path to admin like so ``` Domain: https://mydomain.com Path: /admin* // This will secure the admin and all related URLs ``` - Then on Access Policies -> click **Select existing policies** then apply the policy that you've created - Then scroll down to **Login Methods** and make sure **Accept all available identity providers** is turned on so that any providers you've setup on the 2nd step will be used. - Then **Save** 5️⃣ **Test** - Visit your admin panel - Instead of admin login, you'll see Cloudflare Access prompt - Provide an email that was added on Step 3 -> enter code that was sent to the email -> Cloudflare grants access - After that, you'll see your normal admin login page — but only after identity check ⭐️ **Why This Works (Even on Free Plan)** ✔️ Access rules (email-based) ✔️ One-time PIN ✔️ Google login ✔️ Protect multiple paths ✔️ Works with Laravel, WordPress, Node, etc. ## 🔚 Final Thoughts This is the fastest way to secure your admin panel — without changing any code, installing any package, or paying for a plan. *Makes your panel invisible, protected, and accessible only to you — for free.*

November 16, 2025

How to Add Cloudflare Turnstile to Laravel in 5 Minutes (No Packages Required)

If you’ve built a public-facing web app, you eventually run into the same annoying problem: bots. They fill out your forms, spam your inbox, and waste your server’s time. Most developers immediately think of Google reCAPTCHA, but there’s a cleaner option that solves the same problem without the tracking baggage: **Cloudflare Turnstile**. Turnstile is Cloudflare’s privacy-friendly CAPTCHA alternative. * ❌ No user friction. * 🚍 No weird “click the traffic lights” puzzles. (ehem.. Google) * ⏲️ And setup takes only a few minutes. In this quick guide, I’ll show you why you should use Turnstile — and how to integrate it into a Laravel app without any third-party packages. ## Why use Cloudflare Turnstile? Here are the biggest reasons I migrated to it: **1. No user frustration** Turnstile doesn’t make users solve puzzles. It verifies silently in the background unless something looks suspicious. **2. Privacy-respecting** Unlike reCAPTCHA, Turnstile doesn’t track users across the web. No profiling, no annoying consent banners. **3. Dead simple to implement** It’s literally: * Load a script * Place a widget * Verify the token server-side Done! **4. Completely free** Cloudflare offers Turnstile with unlimited usage on the free plan. ### Step 1 — Create a Turnstile Widget in Cloudflare 1. Log in to Cloudflare 2. Application Security → Turnstile 3. Click **Add Widget** 4. Set: * Name: e.g: my-domain-name-turnstile * Add Hostnames: If you already have existing hostnames setup in Cloudflare you can select it, or you can just type your domain name manually. You can also add your local domains here - very useful if you are using Herd on your local machine. * Widget Mode: Managed (recommended) * Would you like to opt for pre-clearance for this site?: Just select "No" 5. Copy your **Site Key** and **Secret Key** ### Step 2 — Add the Keys, Widget and Script into Laravel Add these to your `.env` file ``` # Cloudflare Turnstile Captcha TURNSTILE_ENABLED=true # This will be so that you can just disable it quickly, especially on your tests TURNSTILE_URL=https://challenges.cloudflare.com/turnstile/v0/siteverify TURNSTILE_SITE_KEY=Your-Turnstile-Site-Key TURNSTILE_SECRET_KEY=Your-Turnstile-Secret-Key ``` Then, configure these values on your `config/services.php` file ``` // On services.php 'turnstile' => [ 'enabled' => env('TURNSTILE_ENABLED', false), 'turnstile_url' => env('TURNSTILE_URL'), 'site_key' => env('TURNSTILE_SITE_KEY'), 'secret_key' => env('TURNSTILE_SECRET_KEY'), ], ``` Then add the Widget into your Blade template — this usually goes into public facing forms such as registration, forgot password, contact us, etc. ``` ``` Then add their script outside the body of your base template ``` ``` ### Step 3 — Create a Rule class and use it on your form validations This sample rule class below provides a way to ignore `required` validation on the Turnstile field if the `config('services.turnstile.enabled')` is set to `false`. ```

Marvin Quezon · Copyright © 2026 · Privacy · Sitemap