Configuring Varnish for 1C-Bitrix
A PHP Bitrix process generates a catalog page in 200–800 milliseconds. With 100 concurrent users, the server hits CPU and memory limits. Varnish caches the HTTP response and serves subsequent requests in 1–5 ms without PHP involvement. However, there are several conflicts between Varnish and Bitrix that break authentication, cart, and personalized content.
Architecture: Varnish in Front of Nginx
Standard scheme: client → Varnish (:80/:443) → Nginx (:8080) → PHP-FPM. Nginx is switched to port 8080. Varnish receives requests, caches cacheable ones, and sends non-cacheable ones directly to the backend.
client → varnish:80 → nginx:8080 → php-fpm:9000
↓ (cache hit)
varnish cache (RAM)
Installation on CentOS/RHEL (typical for Bitrix VM):
yum install varnish
systemctl enable varnish
Key Integration Issues with Bitrix
Bitrix uses session cookies PHPSESSID and authentication cookies BITRIX_SM_*. Varnish by default doesn't cache requests with cookies — this is correct but overly conservative. An anonymous user with an empty cart still gets a session cookie and misses the cache.
Another conflict is HTTPS. Varnish doesn't terminate SSL. You need Nginx or HAProxy in front of Varnish for SSL termination. The scheme becomes more complex: client → Nginx(:443, SSL) → Varnish(:80) → Nginx(:8080) → PHP-FPM.
VCL Configuration for Bitrix
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
.connect_timeout = 5s;
.first_byte_timeout = 120s;
}
sub vcl_recv {
# Force HTTP/1.1 (Varnish doesn't support HTTP/2 with backend)
set req.http.X-Forwarded-For = client.ip;
# Don't cache admin panel and login
if (req.url ~ "^/bitrix/" || req.url ~ "^/area51/") {
return (pass);
}
# Don't cache POST and authenticated users
if (req.method == "POST" || req.method == "PUT") {
return (pass);
}
# Authenticated user — BITRIX_SM_UIDH cookie
if (req.http.Cookie ~ "BITRIX_SM_UIDH") {
return (pass);
}
# Cart not empty
if (req.http.Cookie ~ "BX_BASKET_ADD") {
return (pass);
}
# Remove cookies that don't affect content (analytics, ads)
set req.http.Cookie = regsuball(req.http.Cookie,
"(^|;\s*)(_ga|_gid|_gat|_fbp|_ym_uid|_ym_d|_ym_isad)[^;]*", "");
# If no cookies remain — can cache
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
return (hash);
}
sub vcl_backend_response {
# Don't cache responses with Set-Cookie (auth)
if (beresp.http.Set-Cookie ~ "BITRIX_SM_") {
set beresp.uncacheable = true;
return (deliver);
}
# Cache static files for long
if (bereq.url ~ "\.(css|js|png|jpg|webp|gif|woff2|ico)$") {
set beresp.ttl = 30d;
set beresp.grace = 1d;
unset beresp.http.Set-Cookie;
return (deliver);
}
# HTML pages — 5 minutes with 1 hour grace
if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 5m;
set beresp.grace = 1h;
}
return (deliver);
}
sub vcl_deliver {
# Debug header — remove in production
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
Cache Invalidation from Bitrix
When a product is updated or news is published, Varnish continues serving the old page until TTL expires. You need a mechanism for forced invalidation.
In bitrix/php_interface/init.php add an infoblock event handler:
AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', 'PurgeVarnishCache');
AddEventHandler('iblock', 'OnAfterIBlockElementAdd', 'PurgeVarnishCache');
function PurgeVarnishCache($arFields) {
$url = 'http://127.0.0.1/';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PURGE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// For selective invalidation by tag:
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-Cache-Tags: catalog']);
curl_exec($ch);
curl_close($ch);
}
In VCL, add handling for PURGE requests from localhost:
sub vcl_recv {
if (req.method == "PURGE") {
if (client.ip != "127.0.0.1") {
return (synth(403, "Not allowed"));
}
return (purge);
}
}
Varnish and Bitrix Composite
If Bitrix Composite is used (composite pages with AJAX loading of dynamic blocks), Varnish shouldn't cache the HTML basis of the page, otherwise Composite breaks. Either disable HTML caching through Varnish and keep it only for static files, or configure Composite for specific components without caching the entire page through Varnish.







