aimeos / pagible-cdn
Pagible CMS CDN cache purging
Requires
- php: ^8.2
- aimeos/pagible-core: *@dev
- friendsofsymfony/http-cache: ^3.2
- php-http/guzzle7-adapter: ^1.1
Requires (Dev)
- larastan/larastan: ^3.9
- orchestra/testbench: ^10.0||^11.0
Suggests
- aimeos/pagible-theme: Provides the page routes whose URLs are purged
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-25 16:30:47 UTC
README
Purges changed pages and removed files of Pagible CMS from CDNs and caching proxies using FOSHttpCache. Supported are Cloudflare, Fastly and Varnish.
This package is part of the Pagible CMS monorepo.
Installation
composer require aimeos/pagible-cdn
php artisan vendor:publish --provider="Aimeos\Cms\CdnServiceProvider"
Purge requests are sent by queued jobs on the CMS queue (CMS_QUEUE_CONNECTION, CMS_QUEUE), so run a
queue worker:
php artisan queue:work
Configuration
Settings are in config/cms/cdn.php. Each client is used as soon as its token or servers are set,
all others are skipped:
| Driver | Environment variables |
|---|---|
cloudflare |
CMS_CDN_CLOUDFLARE_TOKEN (API token with the "Zone.Cache Purge" permission), CMS_CDN_CLOUDFLARE_ZONE |
fastly |
CMS_CDN_FASTLY_TOKEN, CMS_CDN_FASTLY_SERVICE, CMS_CDN_FASTLY_SOFT (default true, marks content as stale) |
varnish |
CMS_CDN_VARNISH_SERVERS, comma separated, e.g. 10.0.0.1:6081,10.0.0.2:6081 |
Further settings:
| Key | Default | Description |
|---|---|---|
url |
APP_URL |
Scheme and host the CDN serves the pages and files from (CMS_CDN_URL) |
delay |
0 |
Seconds to wait before purging changed URLs, can be set per client too (CMS_CDN_DELAY) |
limit |
500 |
More URLs at once remove all content from Cloudflare and Fastly with one request instead, including files and assets, 0 disables it (CMS_CDN_LIMIT) |
maxage |
page setting | Seconds the CDN caches public pages (CMS_CDN_MAXAGE) |
stale |
0 |
Seconds the CDN serves outdated pages while refreshing them or if the server fails (CMS_CDN_STALE) |
timeout |
10 |
Seconds to wait for the response (CMS_CDN_TIMEOUT) |
Cache lifetime
Public pages are sent with Cache-Control: public, s-maxage=... using the cache time of each page,
while pages with access rules and pages viewed by editors are private. As changed pages are purged,
the CDN can keep pages longer, e.g. CMS_CDN_MAXAGE=86400. CMS_CDN_STALE=60 adds
stale-while-revalidate and stale-if-error, so the CDN serves the old page while fetching the new
one or if your server is unavailable. If CMS_CDN_MAXAGE is set, the Expires header is removed so
the CDN can't use the shorter lifetime of the page instead.
Varnish must be configured to accept PURGE requests from the application servers, see the
FOSHttpCache proxy configuration.
Stacked caches
If a CDN caches the responses of Varnish, the inner cache must be purged first, otherwise
the CDN fetches the outdated page from the inner cache again. Set a longer delay for the CDN client,
e.g. 'delay' => 10. cms:cdn:purge purges the clients in the
configured order, so list the inner cache first. If the purge of the inner cache fails, the CDN may
cache the outdated page again until its cache lifetime expires.
Several zones or services
Add a client per zone or service and limit it to its host names with hosts, e.g. for multi-domain
setups with one Cloudflare zone per domain:
'clients' => [ 'shop' => [ 'driver' => 'cloudflare', 'token' => env( 'CMS_CDN_SHOP_TOKEN' ), 'zone' => env( 'CMS_CDN_SHOP_ZONE' ), 'hosts' => ['shop.example.com'], ], 'blog' => [ 'driver' => 'cloudflare', 'token' => env( 'CMS_CDN_BLOG_TOKEN' ), 'zone' => env( 'CMS_CDN_BLOG_ZONE' ), 'hosts' => ['blog.example.com'], ], ],
What is purged
- Pages: The URLs of pages whose published content, route, access rules or files changed, i.e.
the same pages the complete-page cache of the theme package invalidates. A moved page is purged at
its old and new URL. The URLs are generated from the
cms.pageroute andCMS_CDN_URLorAPP_URL, or the page domain ifcms.multidomainis enabled. Without the theme package, no page URLs are purged. - Files: The public URLs of files and previews deleted from storage or moved to the private disk. New uploads always get new file names, so their URLs never serve outdated content.
- Shared content: All pages which use a published, deleted or restored shared element or file.
The pages are found by queued jobs on the core queue (
CMS_QUEUE_CONNECTION,CMS_QUEUE), also if the items are finally removed. Pages using deleted items were purged when the items were deleted, so finally removing them doesn't purge them again.
Not purged are:
- URLs with query strings, e.g. search or pagination parameters. The CDN caches each query string separately, so configure it to ignore query strings for pages that don't use them, e.g. with a Cloudflare cache rule, or keep the cache lifetime of these responses short
- sitemaps, which are updated when their CDN cache expires
- other pages which show the changed page, e.g. in the navigation. They are updated when their CDN cache expires, so keep the cache lifetime of HTML pages short
Editors can purge a page and all its subpages with the "Clear cache" action of the admin panel. For the root page, this purges the whole site and large sites remove all content at once.
Commands
php artisan cms:cdn:purge https://example.com/a /b # purge URLs, paths are relative to CMS_CDN_URL or APP_URL php artisan cms:cdn:purge --all # remove all content, e.g. after theme changes php artisan cms:cdn:purge --all --client=fastly # limit to one or more clients
Removing all content is only supported by Cloudflare and Fastly.
Equal purges which are still queued aren't queued again, so large changes of shared content remove all content only once instead of once per batch of pages.
Removing all content also removes the cached images, CSS and JavaScript files, which are then fetched
from your server again. If shared elements or files like the footer are used by more pages than the
limit, each of their changes does this, so raise the limit or use 0 for large sites with frequent
changes of shared content.
Protected content
Pages which get access rules and files moved to the private disk are only removed from the CDN by their purge. Until it succeeds, the CDN still serves the public copy:
- during the
delayof the client - until the cache lifetime (
maxage) expires if the purge fails after all retries or with thesyncqueue, and duringstaleseconds while your server fails - if the
hostsof the client don't contain the host of the file URLs, e.g.cdn.example.com
For sites with protected content, use a real queue, keep maxage moderate and add the host of the
public files to hosts.
Failures
Failed purges are retried after 10 seconds, 1, 5 and 15 minutes, also if the CDN API rejects requests because of its rate limit. Purges which failed after the last retry are stored as failed jobs by Laravel. Each client uses its own jobs, so a failing CDN doesn't delay the others. The job only contains the client name and URLs; credentials are read from the configuration when the job runs, so changed credentials apply to queued purges too and removed clients don't receive them any more.
With the sync queue, the URLs are purged after the response is sent to keep the admin panel fast.
Failed purges are only reported then and not retried, so use a real queue in production.