Greetings! I'm Aneesh Sreedharan, CEO of 2Hats Logic Solutions. At 2Hats Logic Solutions, we are dedicated to providing technical expertise and resolving your concerns in the world of technology. Our blog page serves as a resource where we share insights and experiences, offering valuable perspectives on your queries.

Many official resources and community tutorials on installing Varnish for Shopware 6.7 focus only on standard HTTP setups. They often overlook the critical need for securing your site with SSL.
But for today’s e-commerce retailers, performance and security are equally essential for earning customer trust and ensuring a smooth shopping experience.
This in-depth guide walks you through installing and configuring Varnish for Shopware 6.7 with full SSL termination. By following these steps, you’ll combine Varnish’s powerful caching capabilities with the security of HTTPS. This will results in a lightning-fast, secure storefront.
We’ll cover how to:
- Prepare your system
- Compile the required Varnish version (7.6+)
- Integrate Varnish with Shopware’s HTTP cache
- Configure Nginx to handle SSL termination cleanly
This guide assumes your Shopware instance is already running on Nginx with SSL enabled. Our goal is to evolve that setup into Nginx + Varnish, with SSL termination handled by Nginx itself.
Important: The default Varnish package in Ubuntu repositories lacks modules required for Shopware compatibility. We’ll show you how to manually compile Varnish 7.6+ to ensure optimal functionality.
Whether you’re optimizing an existing store or setting up a new one, this hands-on tutorial will give you the confidence to deliver a secure, high-performance Shopware 6.7 site.
Let’s get started.
We’ve already implemented this Varnish + SSL setup for a few of our Shopware clients. If you’re tackling something similar and need technical support, our team is happy to help.
Varnish Installation and Configuration
Let’s walk through the process of installing and configuring Varnish 7.7 for Shopware 6.7, with full SSL support handled via Nginx.
Step 1: Let’s Install the Build Dependencies for Compiling Varnish
1 | sudo apt update && sudo apt install -y build-essential autotools-dev libtool pkg-config libedit-dev libpcre3-dev libpcre2-dev libjemalloc-dev python3-docutils python3-sphinx python3-venv libssl-dev libsystemd-dev |
Step 2: Download and Extract Varnish
Download Varnish Package
1 | wget https://varnish-cache.org/downloads/varnish-7.7.1.tgz |
Extract and navigate to the directory
1 | tar -xvf varnish-7.7.1.tgz && cd varnish-7.7.1 |
Step 3: Compile and Install Varnish
Prepare the build system.
1 | ./autogen.sh |
Configure the build
1 | ./configure |
Build the source
1 | make |
Install Varnish
1 | sudo make install |
Step 4: Install Varnish modules for Shopware
Download the Varnish module for Shopware
1 | cd .. && git clone https://github.com/varnish/varnish-modules.git && cd varnish-modules |
Use a branch matching your Varnish version (e.g., 7.7)
1 | git checkout 7.7 |
Compile and install them
1 2 3 4 | ./bootstrap ./configure make make install |
Step 5: Create Varnish Configuration File
Create the Varnish Configuration file /etc/default/varnish.vcl with the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | vcl 4.1; import std; import xkey; import cookie; backend default { .host = "127.0.0.1"; .port = "8080"; } acl purgers { "127.0.0.1"; "localhost"; "::1"; } sub vcl_recv { # Bypass Let's Encrypt ACME challenge requests if (req.url ~ "^/.well-known/acme-challenge/") { return (pass); } # Handle PURGE if (req.method == "PURGE") { if (client.ip !~ purgers) { return (synth(403, "Forbidden")); } if (req.http.xkey) { set req.http.n-gone = xkey.purge(req.http.xkey); return (synth(200, "Invalidated " + req.http.n-gone + " objects")); } else { return (purge); } } # Handle BAN if (req.method == "BAN") { if (!client.ip ~ purgers) { return (synth(403, "Forbidden")); } ban("req.url ~ " + req.url); return (synth(200, "BAN URLs containing (" + req.url + ") done.")); } # Allow only supported HTTP methods if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "PATCH" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "DELETE") { return (pipe); } # Allow static files to be cached even with Authorization if (req.http.Authorization && req.url !~ "\.(css|js?|woff2?|ttf|eot|svg|png|jpe?g|gif|webp|ico)$") { return (pass); } # Strip Authorization for static files if (req.url ~ "\.(css|js?|woff2?|ttf|eot|svg|png|jpe?g|gif|webp|ico)$") { unset req.http.Authorization; } # Only cache GET and HEAD if (req.method != "GET" && req.method != "HEAD") { return (pass); } # Exclude special paths from cache if (req.url ~ "^/(checkout|account|admin|api)(/.*)?$") { return (pass); } # Parse Shopware cookies cookie.parse(req.http.cookie); set req.http.cache-hash = cookie.get("sw-cache-hash"); set req.http.currency = cookie.get("sw-currency"); set req.http.states = cookie.get("sw-states"); if (req.url == "/widgets/checkout/info" && !req.http.states ~ "cart-filled") { return (synth(204, "")); } # Strip tracking/query noise if (req.url ~ "(\?|&)(pk_campaign|piwik_campaign|pk_kwd|piwik_kwd|pk_keyword|pixelId|kwid|kw|adid|chl|dv|nk|pa|camid|adgid|cx|ie|cof|siteurl|utm_[a-z]+|_ga|gclid)=") { set req.url = regsuball(req.url, "(pk_campaign|piwik_campaign|pk_kwd|piwik_kwd|pk_keyword|pixelId|kwid|kw|adid|chl|dv|nk|pa|camid|adgid|cx|ie|cof|siteurl|utm_[a-z]+|_ga|gclid)=[A-Za-z0-9\-\_\.\~%]+&?", ""); } set req.url = regsub(req.url, "(\?|\?&|&)$", ""); set req.url = std.querysort(req.url); # Forward client IP 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; } # Enable ESI support set req.http.Surrogate-Capability = "shopware=ESI/1.0"; return (hash); } sub vcl_hash { if (req.http.cache-hash != "") { hash_data("+context=" + req.http.cache-hash); } elseif (req.http.currency != "") { hash_data("+currency=" + req.http.currency); } } sub vcl_hit { if (req.http.states) { 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_fetch { unset bereq.http.cache-hash; unset bereq.http.currency; unset bereq.http.states; } sub vcl_backend_response { set beresp.grace = 3d; unset beresp.http.X-Powered-By; unset beresp.http.Server; if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; return (deliver); } if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") { set beresp.do_gzip = true; } if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) { unset beresp.http.Set-Cookie; } } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } if (resp.http.Cache-Control !~ "private" && req.url !~ "^/(theme|media|thumbnail|bundles)/") { set resp.http.Pragma = "no-cache"; set resp.http.Expires = "-1"; set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0"; } unset resp.http.sw-invalidation-states; unset resp.http.xkey; unset resp.http.X-Varnish; unset resp.http.Via; unset resp.http.Link; } |
Step 6: Set Up a Systemd Service for Varnish
Create a SystemD service file for Varnish and enable it to startup during boot /etc/systemd/system/varnish.service and reload the systemd daemon to apply.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [Unit] Description=Varnish HTTP accelerator After=network.target [Service] Type=forking ExecStart=/usr/local/sbin/varnishd \ -a :6081 \ -f /etc/default/varnish.vcl \ -s malloc,512m ExecReload=/usr/local/sbin/varnishreload ProtectSystem=full ProtectHome=true PrivateTmp=true LimitNOFILE=131072 [Install] WantedBy=multi-user.target |
Then reload the systemd daemon:
1 | systemctl daemon-reload |
Step 7: Ensure Varnish Finds Installed Modules
Since we installed Varnish modules manually, Varnish won’t be able to find those modules. Let’s fix that. Create a file /etc/ld.so.conf.d/local-lib.conf with the following content:
1 | /usr/local/lib |
Run the following commands to make sure libvarnishapi is loaded
1 2 | sudo ldconfig ldd /usr/local/lib/varnish/vmods/libvmod_xkey.so |
Expected Output: (note the libvarnishapi)
1 2 3 4 5 6 7 | root@ip-172-31-37-228:~# ldd /usr/local/lib/varnish/vmods/libvmod_xkey.so linux-vdso.so.1 (0x00007ffc383aa000) libvarnishapi.so.3 => /usr/local/lib/libvarnishapi.so.3 (0x000079fd9ee60000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000079fd9ec00000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x000079fd9eb66000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000079fd9ea7d000) /lib64/ld-linux-x86-64.so.2 (0x000079fd9eeb0000) |
Step 8: Start and Enable the Varnish Service
Start Varnish service and enable it to start during boot
1 | systemctl start varnish.service && systemctl enable varnish.service |
Need speed? We’ll configure Varnish & Nginx for Shopware.
Nginx Configuration for SSL Termination and Varnish Proxy
With Varnish now installed and configured, it’s time to adjust your Nginx setup to act as the SSL terminator and proxy incoming HTTPS requests to Varnish.
Now, let’s move to nginx
Update your nginx vhost configuration accordingly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | # HTTP: Redirect all traffic to HTTPS server { listen 80; server_name <domain.com>; return 301 https://$host$request_uri; } # HTTPS: Terminate SSL and proxy to Varnish (port 6081) server { listen 443 ssl http2; server_name <domain.com>; ssl_certificate /etc/letsencrypt/live/<domain.com>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<domain.com>/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { 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; } } # Internal backend: Shopware actual handler (port 8080) server { listen 8080; server_name localhost; index index.php index.html; root /var/www/shopware/public; client_max_body_size 128M; # Shopware install / update location /shopware-installer.phar.php { try_files $uri /shopware-installer.phar.php$is_args$args; } location ~ ^/shopware-installer\.phar\.php/.+\.(?:css|js|png|svg|woff)$ { try_files $uri /shopware-installer.phar.php$is_args$args; } # Deny access to dot files location ~ /\. { deny all; } # Deny access to .php files in public directories location ~ ^/(media|thumbnail|theme|bundles|sitemap).*\.php$ { deny all; } location ~ ^/(theme|media|thumbnail|bundles|css|fonts|js|recovery|sitemap)/ { expires 1y; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; log_not_found off; tcp_nodelay off; open_file_cache max=3000 inactive=120s; open_file_cache_valid 45s; open_file_cache_min_uses 2; open_file_cache_errors off; location ~* ^.+\.svg { add_header Content-Security-Policy "script-src 'none'"; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; log_not_found off; } } location ~* ^.+\.(?:css|cur|js|jpe?g|gif|ico|png|svg|webp|html|woff|woff2|xml)$ { expires 1y; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; access_log off; log_not_found off; tcp_nodelay off; open_file_cache max=3000 inactive=120s; open_file_cache_valid 45s; open_file_cache_min_uses 2; open_file_cache_errors off; try_files $uri /index.php$is_args$args; } location ~* ^.+\.svg$ { add_header Content-Security-Policy "script-src 'none'"; } location / { try_files $uri /index.php$is_args$args; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi.conf; fastcgi_param HTTP_PROXY ""; fastcgi_buffers 8 16k; fastcgi_buffer_size 32k; proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; send_timeout 300s; client_body_buffer_size 128k; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } } |
After applying the changes, ensure the configuration is valid and reload Nginx:
1 | nginx -t && systemctl restart nginx |
Shopware Configuration for Varnish Compatibility
Now, let’s move to the configuration of Shopware.
Create the following configuration file in your Shopware installation config/packages/shopware.yml
1 2 3 4 5 6 7 8 | shopware: http_cache: reverse_proxy: enabled: true use_varnish_xkey: true hosts: - localhost:6081 |
Also, in your .env or .env.local, make sure to enable
1 | SHOPWARE_HTTP_CACHE_ENABLED=1 |
Create a configuration config/packages/trusted_env.yaml with the following content to trust the proxy because we have multi-layer routing.
(If we don’t do this, Shopware resources will be loaded over HTTP, resulting in a mixed content error and broken styles.)
1 2 3 4 5 | parameters: env(TRUSTED_PROXIES): '' framework: trusted_proxies: '%env(TRUSTED_PROXIES)%' |
Add/Update your .env.local file with the following
1 | TRUSTED_PROXIES=127.0.0.1,::1 |
Now navigate to your project directory and clear cache
1 | php bin/console cache:clear |
Restart Varnish to clear the cache one more time
1 | systemctl restart varnish.service |
To make sure the varnish cache is working properly, you can try this in a terminal. After running this curl command 2 or more times, you should eventually land a response with “HIT”
1 | curl -I https://<domain.com>/ | grep x-cache |
Note: In some cases, there might be plugins that cause Shopware to send a no-cache
header, which can prevent Varnish from delivering a cache HIT for certain resources. Be sure to check your plugin settings and headers thoroughly during your setup and troubleshooting.
Conclusion
This guide covered installing Varnish Cache with Nginx SSL termination for Shopware 6.7. This helps to create a secure, high-performance e-commerce infrastructure. At 2hats Logic Solutions, we work with implementing and supporting these advanced caching setups for Shopware stores. This combination dramatically improves page load times while maintaining enterprise-grade security. Contact us to work with experts who can implement this for you.
Want expert help speeding up your Shopware store with Varnish and Nginx? We’re here to support.
FAQ
Can I use the standard Varnish installation for Shopware 6.7 speed improvement?
No, the standard version doesn't include the special features Shopware needs. You need to install a custom version with extra components to make your Shopware store work properly with caching.
How does Varnish work with SSL certificates on Shopware stores?
Varnish doesn't handle SSL directly. Your web server (Nginx) manages the SSL security, then sends requests to Varnish for caching, which then connects to your Shopware store. This keeps your site secure while making it faster.
Will my Shopware admin area still work with Varnish caching?
Yes, the setup automatically skips caching for admin pages, checkout, and customer accounts. Your admin panel and customer login areas will work exactly as before, while your product pages load much faster.

Related Articles
