Skip to content

Instantly share code, notes, and snippets.

@mklooss
Last active October 26, 2023 06:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mklooss/fb373cdb7e9b47312811c1e04de3d7f7 to your computer and use it in GitHub Desktop.
Save mklooss/fb373cdb7e9b47312811c1e04de3d7f7 to your computer and use it in GitHub Desktop.
shopware 6 varnish sample config
server {
listen 127.0.0.1:8080;
index index.php index.html;
server_name varnish.default.tld;
root /home/USER/htdocs/public/;
location /recovery/install {
index index.php;
try_files $uri /recovery/install/index.php$is_args$args;
}
location /recovery/update/ {
location /recovery/update/assets {
}
if (!-e $request_filename){
rewrite . /recovery/update/index.php last;
}
}
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include /etc/nginx/fastcgi_params;
fastcgi_param HTTP_PROXY "";
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
client_max_body_size 24M;
client_body_buffer_size 128k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php7.4-fpm.sock;
http2_push_preload on;
}
}
server {
listen 80;
listen [::]:80;
server_name varnish.default.tld;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name varnish.default.tld;
# Server certificate and key.
ssl_certificate /opt/cert/self/server.cert;
ssl_certificate_key /opt/cert/self/server.key;
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-agent: *\nDisallow: /\n";
}
location / {
# Forward request to Varnish.
proxy_pass http://127.0.0.1:6081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_hide_header Via;
proxy_redirect off;
}
}
# config/packages/storefront.yaml
storefront:
# csrf:
# enabled: true
# mode: ajax
reverse_proxy:
enabled: true
ban_method: "BAN"
hosts: [ "http://127.0.0.1:6081" ]
max_parallel_invalidations: 3
redis_url: "redis://127.0.0.1"
# note csrf token has been removed in Shopware 6.5
# .env in Shopware dir
SHOPWARE_HTTP_CACHE_ENABLED=1
TRUSTED_PROXIES=127.0.0.1
[Unit]
Description=Varnish Cache, a high-performance HTTP accelerator
Documentation=https://www.varnish-cache.org/docs/ man:varnishd
[Service]
Type=simple
# Maximum number of open files (for ulimit -n)
LimitNOFILE=131072
# Locked shared memory - should suffice to lock the shared memory log
# (varnishd -l argument)
# Default log size is 80MB vsl + 1M vsm + header -> 82MB
# unit is bytes
LimitMEMLOCK=85983232
Environment=LD_PRELOAD=/opt/lib/libmimalloc.so
ExecStart=/usr/sbin/varnishd \
-j unix,user=vcache \
-F \
-a :6081 \
-T localhost:6082 \
-p thread_pool_min=10 \
-p thread_pool_max=500 \
-p http_resp_hdr_len=65536 \
-p http_resp_size=98304 \
-p workspace_backend=320k \
-p workspace_client=320k \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s Cache=malloc,12g \
-s Transient=malloc,512m
ExecReload=/usr/share/varnish/varnishreload
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
[Install]
WantedBy=multi-user.target
vcl 4.0;
import std;
# You should specify here all your app nodes and use round robin to select a backend
backend default {
.host = "127.0.0.1";
.port = "8080";
}
# ACL for purgers IP. (This needs to contain app server ips)
acl purgers {
"127.0.0.1";
"localhost";
"::1";
}
sub vcl_recv {
if (req.restarts > 0) {
set req.hash_always_miss = true;
}
# Mitigate httpoxy application vulnerability, see: https://httpoxy.org/
unset req.http.Proxy;
# Strip query strings only needed by browser javascript. Customize to used tags.
if (req.url ~ "(\?|&)(_bta_c|_bta_tid|_ga|_ke|adgid|adgroupid|adid|awcpk_campaign|camid|campaignid|chl|cof|cx|dm_i|dv|ef_id|epik|fb_action_ids|fb_action_types|fb_source|fbclid|gad_source|gclid|gclsrc|gdffi|gdfms|gdftrk|ie|kw|kwid|matomo_campaign|matomo_cid|matomo_content|matomo_group|matomo_keyword|matomo_kwd|matomo_medium|matomo_placement|matomo_source|mc_cid|mc_eid|mkwid|msclkid|mtm_campaign|mtm_cid|mtm_content|mtm_group|mtm_keyword|mtm_kwd|mtm_medium|mtm_placement|mtm_source|nk|pa|pcrid|piwik_campaign|piwik_kwd|pixelId|pk_campaign|pk_keyword|pk_kwd|pp|redirect_log_mongo_id|redirect_mongo_id|s_kwcid|sb_referer_host|siteurl|sv1|sv_campaign_id|trk_contact|trk_module|trk_msg|trk_sid|utm_[a-z]+)=") {
# see rfc3986#section-2.3 "Unreserved Characters" for regex
set req.url = regsuball(req.url, "(_bta_c|_bta_tid|_ga|_ke|adgid|adgroupid|adid|awcpk_campaign|camid|campaignid|chl|cof|cx|dm_i|dv|ef_id|epik|fb_action_ids|fb_action_types|fb_source|fbclid|gad_source|gclid|gclsrc|gdffi|gdfms|gdftrk|ie|kw|kwid|matomo_campaign|matomo_cid|matomo_content|matomo_group|matomo_keyword|matomo_kwd|matomo_medium|matomo_placement|matomo_source|mc_cid|mc_eid|mkwid|msclkid|mtm_campaign|mtm_cid|mtm_content|mtm_group|mtm_keyword|mtm_kwd|mtm_medium|mtm_placement|mtm_source|nk|pa|pcrid|piwik_campaign|piwik_kwd|pixelId|pk_campaign|pk_keyword|pk_kwd|pp|redirect_log_mongo_id|redirect_mongo_id|s_kwcid|sb_referer_host|siteurl|sv1|sv_campaign_id|trk_contact|trk_module|trk_msg|trk_sid|utm_[a-z]+)=[A-Za-z0-9\-\_\.\~]+&?", "");
}
set req.url = regsub(req.url, "(\?|\?&|&)$", "");
# Normalize query arguments
set req.url = std.querysort(req.url);
# Make sure that the client ip is forward to the client.
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
# Handle BAN
if (req.method == "BAN") {
if (!client.ip ~ purgers) {
return (synth(405, "Method not allowed"));
}
ban("req.url ~ "+req.url);
return (synth(200, "BAN URLs containing (" + req.url + ") done."));
}
# Normalize Accept-Encoding header
# straight from the manual: https://www.varnish-cache.org/docs/3.0/tutorial/vary.html
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
# No point in compressing these
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
# unknown algorithm
unset req.http.Accept-Encoding;
}
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "PATCH" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Don't cache Authenticate & Authorization
if (req.http.Authenticate || req.http.Authorization) {
return (pass);
}
# Always pass these paths directly to php without caching
# Note: virtual URLs might bypass this rule (e.g. /en/checkout)
if (req.url ~ "^/(checkout|account|admin|api)(/.*)?$") {
return (pass);
}
return (hash);
}
sub vcl_hash {
# Consider Shopware HTTP cache cookies
if (req.http.cookie ~ "sw-cache-hash=") {
hash_data("+context=" + regsub(req.http.cookie, "^.*?sw-cache-hash=([^;]*);*.*$", "\1"));
} elseif (req.http.cookie ~ "sw-currency=") {
hash_data("+currency=" + regsub(req.http.cookie, "^.*?sw-currency=([^;]*);*.*$", "\1"));
}
}
sub vcl_hit {
# Consider client states for response headers
if (req.http.cookie ~ "sw-states=") {
set req.http.states = regsub(req.http.cookie, "^.*?sw-states=([^;]*);*.*$", "\1");
if (req.http.states ~ "logged-in" && obj.http.sw-invalidation-states ~ "logged-in" ) {
return (pass);
}
if (req.http.states ~ "cart-filled" && obj.http.sw-invalidation-states ~ "cart-filled" ) {
return (pass);
}
}
}
sub vcl_backend_response {
# Fix Vary Header in some cases
# https://www.varnish-cache.org/trac/wiki/VCLExampleFixupVary
if (beresp.http.Vary ~ "User-Agent") {
set beresp.http.Vary = regsub(beresp.http.Vary, ",? *User-Agent *", "");
set beresp.http.Vary = regsub(beresp.http.Vary, "^, *", "");
if (beresp.http.Vary == "") {
unset beresp.http.Vary;
}
}
# Respect the Cache-Control=private header from the backend
if (
beresp.http.Pragma ~ "no-cache" ||
beresp.http.Cache-Control ~ "no-cache" ||
beresp.http.Cache-Control ~ "private"
) {
set beresp.ttl = 0s;
set beresp.http.X-Cacheable = "NO:Cache-Control=private";
set beresp.uncacheable = true;
return (deliver);
}
# strip the cookie before the image is inserted into cache.
if (bereq.url ~ "\.(png|gif|jpg|swf|css|js|webp)$") {
unset beresp.http.set-cookie;
}
# Allow items to be stale if needed.
set beresp.grace = 6h;
# Save the bereq.url so bans work efficiently
set beresp.http.x-url = bereq.url;
set beresp.http.X-Cacheable = "YES";
# Remove the exact PHP Version from the response for more security
unset beresp.http.x-powered-by;
return (deliver);
}
sub vcl_deliver {
## we don't want the client to cache
set resp.http.Cache-Control = "max-age=0, private";
# remove link header if session is already started to save client resources
if (req.http.cookie ~ "session-") {
unset resp.http.Link;
}
# Set a cache header to allow us to inspect the response headers during testing
if (obj.hits > 0) {
unset resp.http.set-cookie;
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
# Remove the exact PHP Version from the response for more security (e.g. 404 pages)
unset resp.http.x-powered-by;
# invalidation headers are only for internal use
unset resp.http.sw-invalidation-states;
set resp.http.X-Cache-Hits = obj.hits;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment