I have a Magento 2.4.8 site running on Nginx + Varnish (version 7.5.0).
When I test caching via curl, I get different results for HTTP vs HTTPS: curl -I http://domain/
- shows: X-Magento-Cache-Debug: HIT/MISS
But when I test caching via HTTPS curl : curl -I https://domain/
- does NOT show any Varnish headers (no HIT/MISS, no Via header)
So it looks like Varnish is being bypassed completely for HTTPS traffic. My site URL in Magento configuration is set to use https://domain/.
My Setup
Nginx is used as the web server.
Varnish is listening on port 80.
Backend Nginx for Magento is on port 8080.
Varnish service File (/lib/systemd/system/varnish.service) code:
ExecStart=/usr/sbin/varnishd \
-j unix,user=vcache \
-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,512m
Backend block in /etc/varnish/default.vcl:
backend default {
.host = "127.0.0.1";
.port = "8080";}
Nginx SSL block (/etc/nginx/sites-enabled/default.conf):
server {
listen 8080 default_server;
listen [::]:8080 default_server;
listen 443 ssl;
server_name <server_name>;
set $MAGE_ROOT /var/www/html/magento;
set $MAGE_MODE production;
set $MAGE_RUN_TYPE store;
set $MAGE_RUN_CODE default;
include /var/www/html/magento/nginx.conf.sample;
}
nginx file code :/var/www/html/magento/nginx.conf.sample
root $MAGE_ROOT/pub;
index index.php;
autoindex off;
charset UTF-8;
error_page 404 403 = /errors/404.php;
location /.user.ini {
deny all;
}
pagespeed on;
pagespeed FileCachePath "/home/motorace-www-stage/tmp/pagespeed_cache/";
pagespeed RewriteLevel CoreFilters;
pagespeed EnableFilters remove_quotes;
pagespeed DisableFilters prioritize_critical_css;
pagespeed EnableFilters recompress_images;
pagespeed EnableFilters responsive_images,resize_images;
pagespeed EnableFilters lazyload_images;
pagespeed EnableFilters sprite_images;
pagespeed EnableFilters insert_dns_prefetch;
pagespeed EnableFilters hint_preload_subresources;
pagespeed EnableFilters collapse_whitespace;
pagespeed EnableFilters dedup_inlined_images;
pagespeed EnableFilters inline_preview_images,resize_mobile_images;
pagespeed HttpCacheCompressionLevel 0;
pagespeed FetchHttps enable;
location ~ "^/pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
add_header "" "";
}
location ~* ^/setup($|/) {
root $MAGE_ROOT;
location ~ ^/setup/index.php {
fastcgi_pass 127.0.0.1:19001;
fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off";
fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=600";
fastcgi_read_timeout 600s;
fastcgi_connect_timeout 600s;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ ^/setup/(?!pub/). {
deny all;
}
location ~ ^/setup/pub/ {
add_header X-Frame-Options "SAMEORIGIN";
}
}
location ~* ^/update($|/) {
root $MAGE_ROOT;
location ~ ^/update/index.php {
fastcgi_split_path_info ^(/update/index.php)(/.+)$;
fastcgi_pass 127.0.0.1:19001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
location ~ ^/update/(?!pub/). {
deny all;
}
location ~ ^/update/pub/ {
add_header X-Frame-Options "SAMEORIGIN";
}
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location /pub/ {
location ~ ^/pub/media/(downloadable|customer|import|custom_options|theme_customization/.*\.xml) {
deny all;
}
alias $MAGE_ROOT/pub/;
add_header X-Frame-Options "SAMEORIGIN";
}
location /static/ {
add_header Access-Control-Allow-Origin "*";
location ~ ^/static/version {
rewrite ^/static/(version\d*/)?(.*)$ /static/2ドル last;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|html|json)$ {
add_header Access-Control-Allow-Origin "*";
add_header alt-svc 'h3=":443"; ma=86400';
expires max;
access_log off;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=2ドル last;
rewrite ^/static/(.*)$ /static.php?resource=1ドル last;
}
}
}
location /media/ {
try_files $uri $uri/ /get.php$is_args$args;
location ~ ^/media/theme_customization/.*\.xml {
deny all;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|svgz|webp|avif|avifs|js|css|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
expires +1y;
try_files $uri $uri/ /get.php$is_args$args;
}
location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
expires off;
try_files $uri $uri/ /get.php$is_args$args;
}
add_header X-Frame-Options "SAMEORIGIN";
}
location /media/customer/ {
deny all;
}
location /media/downloadable/ {
deny all;
}
location /media/import/ {
deny all;
}
location /media/custom_options/ {
deny all;
}
location /errors/ {
location ~* \.xml$ {
deny all;
}
}
location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check)\.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:19001;
fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off";
fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=18000";
fastcgi_read_timeout 600s;
fastcgi_connect_timeout 600s;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
gzip on;
gzip_disable "msie6";
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
text/plain
text/css
text/js
text/xml
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/xml+rss
image/svg+xml;
gzip_vary on;
location ~* (\.php$|\.phtml$|\.htaccess$|\.htpasswd$|\.git) {
deny all;
}
How can I configure Nginx and Varnish so that HTTPS requests are correctly passed through Varnish?
Any ideas Please share.
Thank you!
1 Answer 1
The problem
As expected your Nginx setup only acts as a web server and not as a proxy server. This means all requests ending up on Nginx (on ports 8080 & 443) are handled locally.
While that is fine for traffic on port 8080, it's not the case for traffic on port 443. HTTPS traffic should be proxied to Varnish, who in its turn will proxy it to Nginx on port 8080 when a cache miss occurs.
Separate Nginx vhost config for HTTPS traffic
The solution is to create a separate Nginx config for 443 traffic that proxies traffic to Varnish. Here's what that can look like:
server {
listen 443 ssl;
ssl_certificate your-certificate.crt;
ssl_certificate_key your-private-key.key;
location / {
proxy_set_header Host $http_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 $scheme;
proxy_pass http://localhost:80;
}
}
And of course you have to remove listen 443 ssl; from your main Nginx config, because that will only handle traffic on port 8080 after the change.
Outcome
When applying the suggested changes, you'll have 2 separate Nginx configurations:
- A TLS proxying config that sends traffic for port
443to Varnish on port80 - A web server config that receives traffic from Varnish on port
8080and that either serves files locally, or that connects to PHP-FPM to process the request.
/var/www/html/magento/nginx.conf.sampleinclude file. It currently looks like Nginx only acts as a web server, even for traffic on port443. Thenginx.conf.samplewill shed some more light on potential proxy logic to send443traffic to Varnish instead of handling it locally.