feat: Add Varnish caching service and configuration, adjusting Traefik routing and implementing a rate limit middleware.
Some checks failed
Build & Deploy KLZ Cables / 🔍 Prepare Environment (push) Successful in 7s
Build & Deploy KLZ Cables / 🧪 Quality Assurance (push) Successful in 1m34s
Build & Deploy KLZ Cables / 🏗️ Build Gatekeeper (push) Successful in 21s
Build & Deploy KLZ Cables / 🏗️ Build App (push) Failing after 4m59s
Build & Deploy KLZ Cables / 🚀 Deploy (push) Has been skipped
Build & Deploy KLZ Cables / ⚡ PageSpeed (push) Has been skipped
Build & Deploy KLZ Cables / 🔔 Notifications (push) Successful in 2s
Some checks failed
Build & Deploy KLZ Cables / 🔍 Prepare Environment (push) Successful in 7s
Build & Deploy KLZ Cables / 🧪 Quality Assurance (push) Successful in 1m34s
Build & Deploy KLZ Cables / 🏗️ Build Gatekeeper (push) Successful in 21s
Build & Deploy KLZ Cables / 🏗️ Build App (push) Failing after 4m59s
Build & Deploy KLZ Cables / 🚀 Deploy (push) Has been skipped
Build & Deploy KLZ Cables / ⚡ PageSpeed (push) Has been skipped
Build & Deploy KLZ Cables / 🔔 Notifications (push) Successful in 2s
This commit is contained in:
@@ -57,6 +57,11 @@ IMAGE_TAG=latest
|
||||
TRAEFIK_HOST=klz-cables.com
|
||||
ENV_FILE=.env
|
||||
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
# Varnish Configuration
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
VARNISH_CACHE_SIZE=256M
|
||||
|
||||
# ============================================================================
|
||||
# IMPORTANT NOTES
|
||||
# ============================================================================
|
||||
|
||||
@@ -6,6 +6,20 @@ services:
|
||||
- infra
|
||||
env_file:
|
||||
- ${ENV_FILE:-.env}
|
||||
labels:
|
||||
- "traefik.enable=false"
|
||||
|
||||
varnish:
|
||||
image: varnish:7
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
volumes:
|
||||
- ./varnish/default.vcl:/etc/varnish/default.vcl:ro
|
||||
tmpfs:
|
||||
- /var/lib/varnish:exec
|
||||
environment:
|
||||
VARNISH_SIZE: ${VARNISH_CACHE_SIZE:-256M}
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# HTTP ⇒ HTTPS redirect
|
||||
@@ -18,13 +32,13 @@ services:
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}.tls.certresolver=le"
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}.tls=true"
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}.service=${PROJECT_NAME:-klz-cables}"
|
||||
- "traefik.http.services.${PROJECT_NAME:-klz-cables}.loadbalancer.server.port=3000"
|
||||
- "traefik.http.services.${PROJECT_NAME:-klz-cables}.loadbalancer.server.port=80"
|
||||
- "traefik.http.services.${PROJECT_NAME:-klz-cables}.loadbalancer.server.scheme=http"
|
||||
# Forwarded Headers
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-forward.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-forward.headers.customrequestheaders.X-Forwarded-Ssl=on"
|
||||
# Middlewares
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}.middlewares=${PROJECT_NAME:-klz-cables}-forward,${AUTH_MIDDLEWARE:-compress}"
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}.middlewares=${PROJECT_NAME:-klz-cables}-ratelimit,${PROJECT_NAME:-klz-cables}-forward,${AUTH_MIDDLEWARE:-compress}"
|
||||
|
||||
# Gatekeeper Router (to show the login page)
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}-gatekeeper.rule=Host(${TRAEFIK_HOST}) && PathPrefix(`/gatekeeper`)"
|
||||
@@ -34,6 +48,8 @@ services:
|
||||
- "traefik.http.routers.${PROJECT_NAME:-klz-cables}-gatekeeper.service=${PROJECT_NAME:-klz-cables}-gatekeeper"
|
||||
|
||||
# Middleware Definitions
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-ratelimit.ratelimit.average=100"
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-ratelimit.ratelimit.burst=50"
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-auth.forwardauth.address=http://${PROJECT_NAME}-gatekeeper:3000/verify"
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-auth.forwardauth.trustForwardHeader=true"
|
||||
- "traefik.http.middlewares.${PROJECT_NAME:-klz-cables}-auth.forwardauth.authResponseHeaders=X-Auth-User"
|
||||
|
||||
92
varnish/default.vcl
Normal file
92
varnish/default.vcl
Normal file
@@ -0,0 +1,92 @@
|
||||
vcl 4.1;
|
||||
|
||||
import std;
|
||||
|
||||
backend default {
|
||||
.host = "app";
|
||||
.port = "3000";
|
||||
.first_byte_timeout = 60s;
|
||||
}
|
||||
|
||||
acl purge {
|
||||
"localhost";
|
||||
"127.0.0.1";
|
||||
"infra"; # Allow purge from within the infra network
|
||||
}
|
||||
|
||||
sub vcl_recv {
|
||||
# Only allow PURGE from the ACL
|
||||
if (req.method == "PURGE") {
|
||||
if (!client.ip ~ purge) {
|
||||
return (synth(405, "Not allowed."));
|
||||
}
|
||||
return (purge);
|
||||
}
|
||||
|
||||
# Only cache GET and HEAD requests
|
||||
if (req.method != "GET" && req.method != "HEAD") {
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# Bypass cache for Gatekeeper and Directus (already handled by Traefik, but safe to be explicit)
|
||||
if (req.url ~ "^/gatekeeper" || req.url ~ "^/directus" || req.url ~ "^/admin") {
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# Bypass cache for Next.js preview mode / health checks
|
||||
if (req.url ~ "^/api/preview" || req.url ~ "^/health") {
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# Remove all cookies for static files to improve cache hits
|
||||
if (req.url ~ "\.(png|gif|jpg|jpeg|svg|ico|webp|js|css|woff|woff2|otf|ttf)$") {
|
||||
unset req.http.Cookie;
|
||||
}
|
||||
|
||||
# Normalize Cookies: Remove tracking cookies that don't affect page content
|
||||
# This keeps cookies like NEXT_LOCALE or AUTH cookies if needed, but strips others
|
||||
if (req.http.Cookie) {
|
||||
# Strip Google Analytics cookies
|
||||
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__utm.|_ga.|_gid.|_gat)(=[^;]*)?", "");
|
||||
# Strip empty cookies
|
||||
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
|
||||
if (req.http.Cookie ~ "^\s*$") {
|
||||
unset req.http.Cookie;
|
||||
}
|
||||
}
|
||||
|
||||
return (hash);
|
||||
}
|
||||
|
||||
sub vcl_backend_response {
|
||||
# Cache static assets for a long time
|
||||
if (bereq.url ~ "\.(png|gif|jpg|jpeg|svg|ico|webp|js|css|woff|woff2|otf|ttf)$") {
|
||||
set beresp.ttl = 1w;
|
||||
}
|
||||
|
||||
# Respect Cache-Control from Next.js
|
||||
# If the response should not be cached, Next.js will usually send Cache-Control: no-cache, no-store, etc.
|
||||
if (beresp.http.Cache-Control ~ "private" ||
|
||||
beresp.http.Cache-Control ~ "no-cache" ||
|
||||
beresp.http.Cache-Control ~ "no-store") {
|
||||
set beresp.uncacheable = true;
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
# Set a default TTL if none is provided by the backend
|
||||
if (beresp.ttl <= 0s) {
|
||||
set beresp.ttl = 120s;
|
||||
}
|
||||
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
sub vcl_deliver {
|
||||
# Add a debug header to show if it was a hit or miss
|
||||
if (obj.hits > 0) {
|
||||
set resp.http.X-Cache = "HIT";
|
||||
set resp.http.X-Cache-Hits = obj.hits;
|
||||
} else {
|
||||
set resp.http.X-Cache = "MISS";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user