This commit is contained in:
@@ -40,6 +40,7 @@ jobs:
|
|||||||
- name: Build image
|
- name: Build image
|
||||||
run: |
|
run: |
|
||||||
docker build \
|
docker build \
|
||||||
|
--pull \
|
||||||
-t registry.infra.mintel.me/mintel/klz-cables.com:latest .
|
-t registry.infra.mintel.me/mintel/klz-cables.com:latest .
|
||||||
|
|
||||||
# --- Push image ---
|
# --- Push image ---
|
||||||
@@ -63,6 +64,13 @@ jobs:
|
|||||||
rsync -av ./docker-compose.y*ml \
|
rsync -av ./docker-compose.y*ml \
|
||||||
deploy@alpha.mintel.me:/home/deploy/sites/klz-cables.com/
|
deploy@alpha.mintel.me:/home/deploy/sites/klz-cables.com/
|
||||||
|
|
||||||
|
# --- Sync varnish config (optional) ---
|
||||||
|
- name: Sync varnish config
|
||||||
|
run: |
|
||||||
|
if [ -d ./varnish ]; then
|
||||||
|
rsync -av ./varnish/ deploy@alpha.mintel.me:/home/deploy/sites/klz-cables.com/varnish/
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Deploy ---
|
# --- Deploy ---
|
||||||
- name: Deploy on server
|
- name: Deploy on server
|
||||||
run: |
|
run: |
|
||||||
@@ -70,5 +78,6 @@ jobs:
|
|||||||
cd /home/deploy/sites/klz-cables.com &&
|
cd /home/deploy/sites/klz-cables.com &&
|
||||||
docker compose -f docker-compose.yml pull 2>/dev/null ||
|
docker compose -f docker-compose.yml pull 2>/dev/null ||
|
||||||
docker compose -f docker-compose.yaml pull &&
|
docker compose -f docker-compose.yaml pull &&
|
||||||
|
docker image prune -f &&
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
'
|
'
|
||||||
|
|||||||
@@ -1,4 +1,50 @@
|
|||||||
services:
|
services:
|
||||||
|
# Varnish sits between Traefik and the application.
|
||||||
|
#
|
||||||
|
# Flow:
|
||||||
|
# Client -> Traefik -> Varnish -> app
|
||||||
|
#
|
||||||
|
# Traefik keeps TLS + compression; Varnish adds HTTP caching for static assets.
|
||||||
|
varnish:
|
||||||
|
image: varnish:7
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- infra
|
||||||
|
depends_on:
|
||||||
|
- app
|
||||||
|
command: >-
|
||||||
|
varnishd
|
||||||
|
-F
|
||||||
|
-f /etc/varnish/default.vcl
|
||||||
|
-s malloc,${VARNISH_CACHE_SIZE:-256m}
|
||||||
|
volumes:
|
||||||
|
- ./varnish/default.vcl:/etc/varnish/default.vcl:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:80/health || wget --quiet --tries=1 --spider http://localhost:80/ || true"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 10s
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
# HTTP → HTTPS redirect (Challenge-Schutz für ALLE)
|
||||||
|
- "traefik.http.routers.klz-cables-web.rule=(Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)) && !PathPrefix(`/.well-known/acme-challenge/`)"
|
||||||
|
- "traefik.http.routers.klz-cables-web.entrypoints=web"
|
||||||
|
- "traefik.http.routers.klz-cables-web.middlewares=redirect-https"
|
||||||
|
# HTTPS router (für ALLE drei Domains)
|
||||||
|
- "traefik.http.routers.klz-cables.rule=Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)"
|
||||||
|
- "traefik.http.routers.klz-cables.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.klz-cables.tls.certresolver=le"
|
||||||
|
- "traefik.http.routers.klz-cables.tls=true"
|
||||||
|
- "traefik.http.routers.klz-cables.service=klz-cables"
|
||||||
|
- "traefik.http.services.klz-cables.loadbalancer.server.port=80"
|
||||||
|
- "traefik.http.services.klz-cables.loadbalancer.server.scheme=http"
|
||||||
|
# Forwarded Headers (für Apps, die HTTPS erwarten)
|
||||||
|
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||||
|
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Ssl=on"
|
||||||
|
# Middlewares anhängen
|
||||||
|
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
||||||
|
|
||||||
app:
|
app:
|
||||||
image: registry.infra.mintel.me/mintel/klz-cables.com:latest
|
image: registry.infra.mintel.me/mintel/klz-cables.com:latest
|
||||||
restart: always
|
restart: always
|
||||||
@@ -20,25 +66,6 @@ services:
|
|||||||
# Redis (app-spezifischer DB-Index)
|
# Redis (app-spezifischer DB-Index)
|
||||||
- REDIS_URL=${REDIS_URL:-redis://redis:6379/2}
|
- REDIS_URL=${REDIS_URL:-redis://redis:6379/2}
|
||||||
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX:-klz:}
|
- REDIS_KEY_PREFIX=${REDIS_KEY_PREFIX:-klz:}
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
# HTTP → HTTPS redirect (Challenge-Schutz für ALLE)
|
|
||||||
- "traefik.http.routers.klz-cables-web.rule=(Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)) && !PathPrefix(`/.well-known/acme-challenge/`)"
|
|
||||||
- "traefik.http.routers.klz-cables-web.entrypoints=web"
|
|
||||||
- "traefik.http.routers.klz-cables-web.middlewares=redirect-https"
|
|
||||||
# HTTPS router (für ALLE drei Domains)
|
|
||||||
- "traefik.http.routers.klz-cables.rule=Host(`klz-cables.com`) || Host(`www.klz-cables.com`) || Host(`staging.klz-cables.com`)"
|
|
||||||
- "traefik.http.routers.klz-cables.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.klz-cables.tls.certresolver=le"
|
|
||||||
- "traefik.http.routers.klz-cables.tls=true"
|
|
||||||
- "traefik.http.routers.klz-cables.service=klz-cables"
|
|
||||||
- "traefik.http.services.klz-cables.loadbalancer.server.port=3000"
|
|
||||||
- "traefik.http.services.klz-cables.loadbalancer.server.scheme=http"
|
|
||||||
# Forwarded Headers (für Apps, die HTTPS erwarten)
|
|
||||||
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Proto=https"
|
|
||||||
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Ssl=on"
|
|
||||||
# Middlewares anhängen
|
|
||||||
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
infra:
|
infra:
|
||||||
|
|||||||
90
varnish/default.vcl
Normal file
90
varnish/default.vcl
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
vcl 4.1;
|
||||||
|
|
||||||
|
# Minimal, safe Varnish config for a Next.js-style app.
|
||||||
|
# - Cache static assets aggressively
|
||||||
|
# - Avoid caching HTML/auth/api by default
|
||||||
|
# - Preserve websockets / upgrade
|
||||||
|
|
||||||
|
backend default {
|
||||||
|
.host = "app";
|
||||||
|
.port = "3000";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_recv {
|
||||||
|
# Health endpoint should always work.
|
||||||
|
if (req.url == "/health") {
|
||||||
|
return (pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Websocket / Upgrade should not be cached.
|
||||||
|
if (req.http.Upgrade ~ "(?i)websocket") {
|
||||||
|
return (pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only cache GET/HEAD.
|
||||||
|
if (req.method != "GET" && req.method != "HEAD") {
|
||||||
|
return (pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
# If cookies are present, do not cache (safe default).
|
||||||
|
if (req.http.Cookie) {
|
||||||
|
return (pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Never cache Next.js data requests (often personalized) unless you explicitly want to.
|
||||||
|
if (req.url ~ "^/_next/data/") {
|
||||||
|
return (pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache immutable build assets.
|
||||||
|
if (req.url ~ "^/_next/static/") {
|
||||||
|
unset req.http.Cookie;
|
||||||
|
return (hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache common static files.
|
||||||
|
if (req.url ~ "\.(?:css|js|mjs|map|png|jpg|jpeg|gif|webp|svg|ico|woff2?|ttf|otf)$") {
|
||||||
|
unset req.http.Cookie;
|
||||||
|
return (hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default: don't cache HTML.
|
||||||
|
return (pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_backend_response {
|
||||||
|
# Cache immutable Next build assets for a long time.
|
||||||
|
if (bereq.url ~ "^/_next/static/") {
|
||||||
|
set beresp.ttl = 365d;
|
||||||
|
set beresp.grace = 1h;
|
||||||
|
set beresp.http.Cache-Control = "public, max-age=31536000, immutable";
|
||||||
|
unset beresp.http.Set-Cookie;
|
||||||
|
return (deliver);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache static files for 7 days (safe default).
|
||||||
|
if (bereq.url ~ "\.(?:css|js|mjs|map|png|jpg|jpeg|gif|webp|svg|ico|woff2?|ttf|otf)$") {
|
||||||
|
set beresp.ttl = 7d;
|
||||||
|
set beresp.grace = 1h;
|
||||||
|
if (!beresp.http.Cache-Control) {
|
||||||
|
set beresp.http.Cache-Control = "public, max-age=604800";
|
||||||
|
}
|
||||||
|
unset beresp.http.Set-Cookie;
|
||||||
|
return (deliver);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Everything else: don't cache by default.
|
||||||
|
set beresp.ttl = 0s;
|
||||||
|
set beresp.uncacheable = true;
|
||||||
|
return (deliver);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vcl_deliver {
|
||||||
|
# Helpful debug header; remove if you don't want this visible.
|
||||||
|
if (obj.hits > 0) {
|
||||||
|
set resp.http.X-Cache = "HIT";
|
||||||
|
} else {
|
||||||
|
set resp.http.X-Cache = "MISS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user