Allvarnish - Setup Guide
Full-page caching for XenForo 2.3. The add-on writes the VCL and sends the invalidations; installing Varnish and terminating TLS are yours.
One fact drives every setting below: the BAN only reaches Varnish. Cloudflare's copy and the browser's copy can only expire, so their lifetime must be short and must never be overridden.
1. Varnish
Install
Varnish must own port 80. If nginx owns it and Varnish sits on 6081 with nothing pointing at it, nothing is cached and the add-on looks inert. This is the most common installation failure.
Settings that must match reality
The three lifetimes
Changing them is save -> generate VCL -> replace the file -> reload -> Clear Varnish cache.
Never cache these paths is baked into the generated file, not read at runtime - editing the list requires a new VCL. The same four steps as above.
2. Cloudflare
Cloudflare holds its own copy that no BAN reaches. Four things decide whether the site stays correct.
2.1 Browser Cache TTL - the one everybody misses
Speed > Optimization > Browser Cache TTL -> Respect Existing Headers
The default is 4 hours, and Cloudflare uses whichever is higher between that and the origin's max-age. With the add-on sending max-age=300, a 4-hour setting still tells every browser to keep the page for 4 hours. Nothing else in this guide matters if this is wrong.
2.2 Cache level / Cache Everything
Speed > Caching > Cache Level
No Edge TTL override in a Cache Rule, no Edge Cache TTL in a Page Rule, on any expression that matches HTML. An override replaces the origin max-age, and the BAN can then never reach that copy. A long TTL for images/css is fine and unrelated.
2.4 Rule order
Rules run top to bottom, first match wins:
Rule 1 is mandatory. /allvarnish/ hands out the guest CSRF token; if it is cached, every guest gets someone else's token and every form and AJAX call fails with Security error occurred. /admin.php is listed because the zone-level Cache Level still applies to anything no rule matches.
Never append or (not starts_with(path,"/allvarnish/")) to make a rule cover everything. The expression becomes unconditionally true and silently disables every other condition in it, including the /cover.php cookie guard.
3. nginx / Apache
The server behind Varnish must not cache. This is the hardest fault to diagnose because everything else looks right: the add-on can only invalidate Varnish, so a cache between Varnish and PHP serves the same stale page until it expires on its own.
nginx - in the server block Varnish forwards to:
fastcgi_cache is the one that bites PHP-FPM setups; proxy_cache off alone is not enough.
Apache - do not enable mod_cache. If it is loaded:
Also check for a panel-level page cache (LiteSpeed Cache, a CDN plugin, an optimiser) - identical symptom.
4. Verify
Straight at Varnish, bypassing both downstream layers (use the port varnishd -a listens on - usually 80, sometimes 6081):
Through Cloudflare:
max-age=604800 means the old VCL is still answering: the file was replaced but Varnish was not reloaded, or a second varnishd is running. Check ps -eo args | grep varnishd before trusting the port number.
cf-cache-status: DYNAMIC on a page that should be cached means the origin sent private, no-cache - the request took the pass path, which happens whenever the browser carries a session or user cookie. Use a private window with a clean cookie jar to test.
x-xf-cache-status is XenForo's own PageCache header. It is stored inside the Varnish object and appears on real hits too, so never use it to judge the cache. cache-control is the only reliable signal.
Activity:
Real test: post a reply, wait 5 minutes, reload in a private window. The reply must be there - and must have been visible to a logged-in member immediately.
5. Mistakes, by frequency
Clear Varnish cache clears Varnish only. It sends a BAN from PHP, which never passes through Cloudflare. After a template or style change, expect guests to see it within ~10 minutes (two 300s downstream layers), not instantly.
6. Limits
Uninstall: point Varnish back at the web server first, then remove the add-on. Removing it while Varnish still fronts the site leaves a proxy with a stale config and no invalidation.
Full-page caching for XenForo 2.3. The add-on writes the VCL and sends the invalidations; installing Varnish and terminating TLS are yours.
Code:
visitor -> Cloudflare -> Varnish -> nginx/Apache + PHP^ ^BAN on change must have NO cache
One fact drives every setting below: the BAN only reaches Varnish. Cloudflare's copy and the browser's copy can only expire, so their lifetime must be short and must never be overridden.
1. Varnish
Install
- php cmd.php xf:addon-install Lutish/Allvarnish
- ACP > Options > [Lutish] All Varnish - save once to write the defaults.
- ACP > Tools > Allvarnish VCL - press the button, copy the output to /etc/varnish/default.vcl.
- systemctl reload varnish
Code:
ss -lntp | grep ':80 '
Varnish must own port 80. If nginx owns it and Varnish sits on 6081 with nothing pointing at it, nothing is cached and the add-on looks inert. This is the most common installation failure.
Settings that must match reality
| Setting | Must equal |
| Varnish HTTP address | the -a port of varnishd (where BANs are sent) |
| Backend address | your origin listener (e.g. 127.0.0.1:8080), never the CLI port 6082, never the public port |
The three lifetimes
| Setting | Default | Meaning |
| Content page lifetime | 604800 | How long a thread/resource page lives inside Varnish. Refreshed by BAN, so long is correct. |
| List page lifetime | 300 | Forum lists, What's New, resource index. Never BANed, so they just expire. |
| Downstream max-age | 300 | The Cache-Control sent to Cloudflare and the browser. This is the guest staleness ceiling. |
Changing them is save -> generate VCL -> replace the file -> reload -> Clear Varnish cache.
Never cache these paths is baked into the generated file, not read at runtime - editing the list requires a new VCL. The same four steps as above.
2. Cloudflare
Cloudflare holds its own copy that no BAN reaches. Four things decide whether the site stays correct.
2.1 Browser Cache TTL - the one everybody misses
Speed > Optimization > Browser Cache TTL -> Respect Existing Headers
The default is 4 hours, and Cloudflare uses whichever is higher between that and the origin's max-age. With the add-on sending max-age=300, a 4-hour setting still tells every browser to keep the page for 4 hours. Nothing else in this guide matters if this is wrong.
2.2 Cache level / Cache Everything
Speed > Caching > Cache Level
- Standard only caches static extensions, so XenForo HTML is never cached at the edge. Safe, but every guest page view still crosses to your origin - which is the latency you installed the cache to remove.
- Aggressive, or a Cache Rule with Cache Everything, caches HTML too. This is what you want, provided 2.1 and 2.3 are correct.
No Edge TTL override in a Cache Rule, no Edge Cache TTL in a Page Rule, on any expression that matches HTML. An override replaces the origin max-age, and the BAN can then never reach that copy. A long TTL for images/css is fine and unrelated.
2.4 Rule order
Rules run top to bottom, first match wins:
- []/allvarnish/ or /admin.php -> Bypass cache[]static ext, /data/, /js/, /styles/, /cover.php without member cookie -> Cache everything, Edge+Browser TTL = origin
- everything else -> Cache everything, Edge+Browser TTL = origin
Rule 1 is mandatory. /allvarnish/ hands out the guest CSRF token; if it is cached, every guest gets someone else's token and every form and AJAX call fails with Security error occurred. /admin.php is listed because the zone-level Cache Level still applies to anything no rule matches.
Never append or (not starts_with(path,"/allvarnish/")) to make a rule cover everything. The expression becomes unconditionally true and silently disables every other condition in it, including the /cover.php cookie guard.
3. nginx / Apache
The server behind Varnish must not cache. This is the hardest fault to diagnose because everything else looks right: the add-on can only invalidate Varnish, so a cache between Varnish and PHP serves the same stale page until it expires on its own.
nginx - in the server block Varnish forwards to:
Code:
proxy_cache off;fastcgi_cache off;
Apache - do not enable mod_cache. If it is loaded:
Code:
CacheDisable /
Also check for a panel-level page cache (LiteSpeed Cache, a CDN plugin, an optimiser) - identical symptom.
4. Verify
Straight at Varnish, bypassing both downstream layers (use the port varnishd -a listens on - usually 80, sometimes 6081):
Code:
curl -sI -H 'Host: example.com' http://127.0.0.1:80/ | grep -i cache-control
[HEADING=2]expect: cache-control: public, max-age=300[/HEADING]
curl -sI -H 'Host: example.com' http://127.0.0.1:80/threads/some-title.123/ | grep -i cache-control
[HEADING=2]expect: cache-control: public, max-age=300[/HEADING]
Through Cloudflare:
Code:
curl -sI https://example.com/ | grep -iE 'cache-control|cf-cache-status'
[HEADING=2]expect: max-age=300 and cf-cache-status: HIT[/HEADING]
max-age=604800 means the old VCL is still answering: the file was replaced but Varnish was not reloaded, or a second varnishd is running. Check ps -eo args | grep varnishd before trusting the port number.
cf-cache-status: DYNAMIC on a page that should be cached means the origin sent private, no-cache - the request took the pass path, which happens whenever the browser carries a session or user cookie. Use a private window with a clean cookie jar to test.
x-xf-cache-status is XenForo's own PageCache header. It is stored inside the Varnish object and appears on real hits too, so never use it to judge the cache. cache-control is the only reliable signal.
Activity:
Code:
varnishstat -1 | grep -E 'cache_hit|cache_miss'
Real test: post a reply, wait 5 minutes, reload in a private window. The reply must be there - and must have been visible to a logged-in member immediately.
5. Mistakes, by frequency
| Mistake | Symptom | Fix |
| Browser Cache TTL left at 4 hours | guests stale for hours, members fine | 2.1 |
| fastcgi_cache / mod_cache still on | pages never update for guests | 3 |
| Aggressive without 2.1/2.3 | same, at the edge | 2.1 + 2.3, or go back to Standard |
| Edge TTL override on HTML | max-age ignored, BANs look dead | 2.3 |
| /allvarnish/ not bypassed | Security error occurred on AJAX | 2.4 |
| New VCL deployed, Cloudflare not purged | old pages persist | Purge Everything once |
| Exclusion list edited, VCL not regenerated | new paths still cached | regenerate + reload + Clear |
| Web server still owns port 80 | nothing cached | 1 |
Clear Varnish cache clears Varnish only. It sends a BAN from PHP, which never passes through Cloudflare. After a template or style change, expect guests to see it within ~10 minutes (two 300s downstream layers), not instantly.
6. Limits
- []No Cloudflare purge. Downstream copies expire by max-age only - that is why section 2 exists.[]Whole documents only. No ESI, no partial caching.[]Exclusion list is baked into the VCL, not a runtime setting.[]Logged-in users are never cached. Deliberate: a cached page carries someone else's CSRF token.
- Before rebuilding, delete any _output/ folder in the add-on directory or XenForo imports data from there and drops entries missing from it.
Uninstall: point Varnish back at the web server first, then remove the add-on. Removing it while Varnish still fronts the site leaves a proxy with a stale config and no invalidation.
Last edited: