nexxai / laravel-cfcache
A handful of Cloudflare cache helpers for Laravel
Requires
- php: ^8.3
- illuminate/console: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- laravel/pint: ^1.25.0
- mockery/mockery: ^1.4.4
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^4.1
- pestphp/pest-plugin-laravel: ^4.0
- phpunit/phpunit: ^11.0|^12.0
This package is auto-updated.
Last update: 2026-06-06 20:08:11 UTC
README
Laravel Cloudflare Cache
This package provides tools to manage Cloudflare integration with your Laravel application. It includes commands for generating Cloudflare security rules and purging cached content.
The WAF rule generation was inspired by Jason McCreary's tweet: https://x.com/gonedark/status/1978458884948775294
Requirements
A Laravel application running Laravel 12 or higher. Not running a stable version of Laravel? Upgrade with Shift.
Installation / Updating
You can install this package by running the following command:
composer require -W nexxai/laravel-cfcache
To publish the configuration file (needed for WAF rule syncing):
php artisan vendor:publish --tag=cfcache-config
Basic Usage
WAF Rule Generation
Generate the WAF rule expression for your Laravel routes:
php artisan cloudflare:waf-rule
Once generated, you can copy and paste the expression into your domain's security rules by going to Security -> Security Rules -> Create Rule -> Custom Rule -> Edit expression
Cache Purging
Purge all cached content or specific paths/routes:
# Purge all cache php artisan cloudflare:purge --all # Purge all cache without confirmation php artisan cloudflare:purge --all --force # Purge specific paths (absolute or relative, separated by spaces, wildcards supported) php artisan cloudflare:purge / /about https://example.com/faq https://example.com/our-team/* # Purge by route names php artisan cloudflare:purge --route=home --route=users.index --route=auth.login # Purge everything under one or more URL prefixes php artisan cloudflare:purge --prefix=www.example.com/ # Purge everything cached for one or more hosts php artisan cloudflare:purge --host=www.example.com # Schedule a purge for later php artisan cloudflare:purge /about --schedule="2026-06-03 10:00:00" php artisan cloudflare:purge --route=home --schedule="tomorrow 02:00"
Please see the Notes section below for additional information and examples, and potential gotchas.
Advanced Usage
Cloudflare API Configuration
To use the live Cloudflare features, you need to configure your Cloudflare API
credentials. Add the following to your .env file:
CFCACHE_API_TOKEN=your-api-token-here CFCACHE_ZONE_ID=your-zone-id-here
Getting Your Cloudflare Credentials
-
API Token:
- Go to Cloudflare Dashboard
- Click "Create Token"
- Use the "Custom token" template
- Name the token "CFCache package token"
- Based on the features you need, grant the following permissions:
- WAF rules: Zone -> Firewall Services -> Edit
- Cache purging: Zone -> Cache Purge -> Purge
- Include your specific zone(s) in the Zone Resources
- Create the token and copy it to your
.envfile asCFCACHE_API_TOKEN
-
Zone ID:
- Go to your domain's overview page in Cloudflare
- Find the Zone ID in the right sidebar under "API"
- Copy it to your
.envfile asCFCACHE_ZONE_ID
Note
You may create a single token that applies to multiple zones, but ensure that you
use the correct zone ID as the CFCACHE_ZONE_ID in each respective app's
.env file.
Sync to Cloudflare API
Automatically create or update the WAF rule in Cloudflare:
php artisan cloudflare:waf-rule --sync
Configuration
After publishing the configuration file, you can customize additional settings in config/cfcache.php:
return [ 'api' => [ 'token' => env('CFCACHE_API_TOKEN'), 'zone_id' => env('CFCACHE_ZONE_ID'), 'settings' => [ 'base_url' => env('CFCACHE_API_BASE_URL', 'https://api.cloudflare.com/client/v4'), 'timeout' => env('CFCACHE_API_TIMEOUT', 30), 'retry_attempts' => env('CFCACHE_API_RETRY_ATTEMPTS', 3), 'retry_delay' => env('CFCACHE_API_RETRY_DELAY', 1000), ], ], 'scheduled_purges' => [ 'file' => env('CFCACHE_SCHEDULED_PURGES_FILE', storage_path('app/laravel-cfcache/scheduled-purges.json')), ], 'features' => [ 'waf' => [ 'rule_identifier' => env('CFCACHE_RULE_ID', 'laravel-waf-rule'), 'rule_description' => env('CFCACHE_RULE_DESCRIPTION', 'Valid Laravel Routes'), 'rule_action' => env('CFCACHE_RULE_ACTION', 'block'), 'hostnames' => env('CFCACHE_RULE_HOSTNAMES') ? array_filter(array_map('trim', explode(',', env('CFCACHE_RULE_HOSTNAMES')))) : [], 'ignorable_paths' => ['/_dusk/*'], 'forced_allowed_paths' => [], ], ], ];
Available Rule Actions
block- Block the request entirelychallenge- Present a challenge to the visitorjs_challenge- Present a JavaScript challengemanaged_challenge- Use Cloudflare's managed challengeallow- Allow the requestlog- Log the request without taking actionbypass- Bypass all security features
Ignorable Paths
You can configure paths that should be excluded from the WAF rule generation. This is useful for local development routes that shouldn't be included in production security rules:
'ignorable_paths' => [ '/_dusk/*', // Laravel Dusk testing routes '/admin/test', // Specific test routes '/debug/*', // Debug routes ],
The patterns support wildcards using Laravel's Str::is() syntax:
/_dusk/*matches/dusk/login,/dusk/test, etc./admin/*matches any path under/admin/- Exact matches like
/debugwork too
By default, only /_dusk/* is ignored to prevent Dusk testing routes from being
included in production rules.
Forced Allowed Paths
Paths that are not part of your Laravel routes but must be allowed by the WAF (e.g. Cloudflare-injected scripts like Zaraz) can be added so they are always included in the allowlist:
'forced_allowed_paths' => [ '/cdn-cgi/zaraz/s.js', // Cloudflare Zaraz '/cdn-cgi/monitor/xhr', // Optional: other edge-injected paths ],
Wildcards are supported (e.g. /cdn-cgi/zaraz/*). Paths are normalized with a
leading slash if omitted.
Hostnames
When using multiple hostnames or subdomains in the same zone, you can restrict
the generated WAF rule so it only applies to specific hosts. If hostnames is
empty (default), the rule applies to all hostnames.
Set hostnames in config or via .env:
// config/cfcache.php — rule applies only when Host matches one of these 'hostnames' => ['app.example.com', 'www.example.com'],
# .env — comma-separated CFCACHE_RULE_HOSTNAMES=app.example.com,www.example.com
Cache Purging
This package also provides commands to purge Cloudflare's cache for specific paths or routes in your Laravel application.
Basic Cache Purging
Purge all cached content from Cloudflare:
php artisan cloudflare:purge --all
Add --force to skip the confirmation prompt when purging all cached content:
php artisan cloudflare:purge --all --force
Purge Specific Paths
Purge specific paths (relative paths will be prefixed with your app URL):
# Purge specific relative paths php artisan cloudflare:purge / /about /contact # Purge full URLs php artisan cloudflare:purge https://example.com/page1 https://example.com/page2 # Mix relative and full URLs php artisan cloudflare:purge /blog https://example.com/api/data # Purge by route names php artisan cloudflare:purge --route=home --route=users.index --route=auth.login # Wildcards are supported php artisan cloudflare:purge /blog/*
Purge by Route Names
Purge cache for specific Laravel routes by name (route parameters are converted to wildcards):
# Purge by route names php artisan cloudflare:purge --route=home --route=about --route=users.show # Combine routes and paths php artisan cloudflare:purge /blog --route=contact --route=api.users.index
Purge by Prefix or Host
Use --prefix when you want to purge every cached URL under a specific prefix without purging the whole zone. This is useful for deploys where one Cloudflare zone contains multiple sites or subdomains:
# Purge the marketing site only php artisan cloudflare:purge --prefix=www.example.com/ # Purge multiple URL prefixes php artisan cloudflare:purge --prefix=www.example.com/blog/ --prefix=www.example.com/docs/
Use --host when you want to purge everything cached for a host:
# Purge all cached content for one host php artisan cloudflare:purge --host=www.example.com # Purge all cached content for multiple hosts php artisan cloudflare:purge --host=www.example.com --host=marketing.example.com
--prefix and --host are exclusive purge modes. They cannot be used together, and neither option can be combined with paths, --route, or --all.
Scheduled Cache Purges
Add --schedule with any timestamp Carbon can parse to store a purge for later:
# Schedule specific paths php artisan cloudflare:purge /about /contact --schedule="2026-06-03 10:00:00" # Schedule route-based purges php artisan cloudflare:purge --route=home --route=users.index --schedule="tomorrow 02:00" # Schedule a full cache purge php artisan cloudflare:purge --all --force --schedule="2026-06-03 10:00:00" # Schedule a prefix purge php artisan cloudflare:purge --prefix=www.example.com/ --schedule="2026-06-03 10:00:00"
Scheduled purges are stored on disk at the path configured by
cfcache.scheduled_purges.file, which defaults to
storage/app/laravel-cfcache/scheduled-purges.json. The stored command
parameters do not include --schedule, so due purges are re-run as normal
cloudflare:purge commands.
Note
This package does NOT automatically register a Laravel scheduled task. You must opt in by adding one to your application. This is intentional because scheduled tasks can have a financial impact on hosting providers such as Laravel Cloud.
Add this to your routes/console.php:
use Illuminate\Support\Facades\Schedule; use JTSmith\Cloudflare\Support\ScheduledPurgeStore; Schedule::call(fn (ScheduledPurgeStore $store) => $store->runDue()) ->name('cloudflare-scheduled-cache-purges') ->everyMinute() ->withoutOverlapping();
Cloudflare API Configuration for Cache Purging
To use cache purging, you need to configure your Cloudflare API credentials with
cache purge permissions. Add the following to your .env file:
CFCACHE_API_TOKEN=your-api-token-here CFCACHE_ZONE_ID=your-zone-id-here
Getting Cache Purge Permissions
For cache purging, your API token needs the following permission:
- Zone -> Cache Purge -> Edit
You can create a token with both WAF and Cache Purge permissions if you plan to use both features.
Notes
Multiple subdomains
If you use multiple subdomains (e.g., example.com and sub.example.com) in the
same zone, set the hostnames option in config/cfcache.php (see
Hostnames) so the generated WAF rule only
applies to the hostnames you specify. Otherwise the rule would apply to every
hostname on the zone.
Certbot / .well-known
If you're using Certbot and the .well-known directory
to manage your SSL certificates (or for other purposes), you will need to manually
add a .well-known/* rule to the wildcard section of your WAF rule.
Cache Purging Notes
- Route parameters (like
{id}) are converted to wildcards (*) for Cloudflare compatibility - Relative paths are automatically prefixed with your
APP_URL - Full URLs (starting with
http://orhttps://) are used as-is - Unknown route names are silently skipped
- Add
--forcewith--allto skip the confirmation prompt - Use
--prefixto purge every cached URL under a URL prefix - Use
--hostto purge everything cached for a host --prefixand--hostcannot be combined with each other, paths, routes, or--all- Cache purging requires different API permissions than WAF rule management
Contributing
Contributions to this project are welcome. You may open a Pull Request against
the main branch. Please ensure you write a clear description (ideally with
code samples) and all workflows are passing. PRs without tests confirming
the proposed behavior will not be accepted.