Skip to content

Commit

Permalink
Merge pull request #4 from shopware/cleanup-config
Browse files Browse the repository at this point in the history
feat: cleanup varnish config
  • Loading branch information
shyim authored Sep 10, 2024
2 parents ebaf247 + 259ec5e commit 4bcbf19
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 88 deletions.
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ RUN set -e; \
apk upgrade --no-cache; \
apk add --no-cache $VMOD_DEPS; \
\
# install one, possibly multiple vmods
# install one, possibly multiple vmods
install-vmod https://github.com/varnish/varnish-modules/releases/download/0.24.0/varnish-modules-0.24.0.tar.gz; \
\
# clean up
# clean up
apk del --no-network $VMOD_DEPS
USER varnish
ENV SHOPWARE_BACKEND_HOST=localhost \
SHOPWARE_BACKEND_PORT=8000
SHOPWARE_BACKEND_PORT=8000 \
SHOPWARE_ALLOWED_PURGER_IP='"127.0.0.1"'

COPY --chown=1000 rootfs /
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ docker run \
- `SHOPWARE_BACKEND_HOST` - The host of the Shopware backend. Default: `localhost`
- `SHOPWARE_BACKEND_PORT` - The port of the Shopware backend. Default: `8000`
- `SHOPWARE_SOFT_PURGE` - If set to `1`, the soft purge feature is enabled. Default: `0`
- `SHOPWARE_ALLOWED_PURGER_IP` - The IP address of the allowed purger. Default: `"127.0.0.1"`

The `SHOPWARE_ALLOWED_PURGER_IP` can be a single IP like `"172.17.0.1"` or a subnet like `"172.17.0.0"/24`. Take care that the ip address inside the environment variable needs to be double quoted.

## Further information

Expand Down
13 changes: 13 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
services:
varnish:
image: local/varnish
build: .
environment:
SHOPWARE_BACKEND_HOST: host.docker.internal
SHOPWARE_ALLOWED_PURGER_IP: '"172.17.0.0"/24'
ports:
- "80:80"
develop:
watch:
- path: rootfs
action: rebuild
153 changes: 68 additions & 85 deletions rootfs/etc/varnish/default.vcl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ vcl 4.1;

import std;
import xkey;
import cookie;

# Specify your app nodes here. Use round-robin balancing to add more than one.
backend default {
Expand All @@ -14,29 +15,10 @@ acl purgers {
"127.0.0.1";
"localhost";
"::1";
__SHOPWARE_ALLOWED_PURGER_IP__;
}

sub vcl_recv {
# Ignore query strings that are only necessary for the js on the client. Customize as needed.
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)=") {
# see rfc3986#section-2.3 "Unreserved Characters" for regex
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, "(\?|\?&|&)$", "");

# Normalize query arguments
set req.url = std.querysort(req.url);

# Set a header announcing Surrogate Capability to the origin
set req.http.Surrogate-Capability = "shopware=ESI/1.0";

# 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 PURGE
if (req.method == "PURGE") {
if (client.ip !~ purgers) {
Expand All @@ -53,48 +35,31 @@ sub vcl_recv {

if (req.method == "BAN") {
if (!client.ip ~ purgers) {
return (synth(405, "Method not allowed"));
return (synth(403, "Forbidden"));
}

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;
}
}
# Only handle relevant HTTP request 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 != "PATCH" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
return (pipe);
}
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
if (req.http.Authorization) {
return (pass);
}
# Don't cache Authenticate & Authorization
if (req.http.Authenticate || req.http.Authorization) {
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
Expand All @@ -104,23 +69,52 @@ sub vcl_recv {
return (pass);
}
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, ""));
}
# Ignore query strings that are only necessary for the js on the client. Customize as needed.
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)=") {
# see rfc3986#section-2.3 "Unreserved Characters" for regex
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, "(\?|\?&|&)$", "");
# Normalize query arguments
set req.url = std.querysort(req.url);
# Set a header announcing Surrogate Capability to the origin
set req.http.Surrogate-Capability = "shopware=ESI/1.0";
# 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;
}
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"));
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 {
# 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) {
if (req.http.states ~ "logged-in" && obj.http.sw-invalidation-states ~ "logged-in" ) {
return (pass);
}
Expand All @@ -131,57 +125,46 @@ sub vcl_hit {
}
}
sub vcl_backend_fetch {
unset bereq.http.cache-hash;
unset bereq.http.currency;
unset bereq.http.states;
}
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;
}
}
# Serve stale content for three days after object expiration
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);
}
# 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);
if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
# 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;
if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
unset beresp.http.Set-Cookie;
}
# Allow items to be stale if needed.
set beresp.grace = 24h;
# Save the bereq.url so bans work efficiently
set beresp.http.x-url = bereq.url;
set beresp.http.X-Cacheable = "YES";
return (deliver);
}
sub vcl_deliver {
## we don't want the client to cache
set resp.http.Cache-Control = "max-age=0, private";
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";
}
# invalidation headers are only for internal use
unset resp.http.sw-invalidation-states;
unset resp.http.xkey;
set resp.http.X-Cache-Hits = obj.hits;
unset resp.http.X-Varnish;
unset resp.http.Via;
unset resp.http.Link;
}
1 change: 1 addition & 0 deletions rootfs/usr/local/bin/docker-varnish-entrypoint
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set -eo pipefail

sed -i "s|__SHOPWARE_BACKEND_HOST__|${SHOPWARE_BACKEND_HOST}|g" /etc/varnish/default.vcl
sed -i "s|__SHOPWARE_BACKEND_PORT__|${SHOPWARE_BACKEND_PORT}|g" /etc/varnish/default.vcl
sed -i 's|__SHOPWARE_ALLOWED_PURGER_IP__|'"${SHOPWARE_ALLOWED_PURGER_IP}"'|g' /etc/varnish/default.vcl

if [[ "${SHOPWARE_SOFT_PURGE}" ]]; then
sed -i "s|xkey.purge|xkey.softpurge|g" /etc/varnish/default.vcl
Expand Down

0 comments on commit 4bcbf19

Please sign in to comment.