From 95d0d094e1a00516a3eaca2d85026d68534d47da Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Wed, 18 Feb 2026 15:57:44 +0100 Subject: [PATCH] feat(infra): configure imgproxy to use next.js rewrite proxy - Added /_img/ rewrite rule in next.config.mjs to proxy image requests to IMGPROXY_URL - Updated lib/imgproxy.ts to use local /_img path instead of exposed public URL - Replaced NEXT_PUBLIC_IMGPROXY_URL (build-time) with IMGPROXY_URL (runtime) - Updated Dockerfile and docker-compose.yml to strip unused build args --- .env.example | 6 +++--- Dockerfile | 2 -- docker-compose.yml | 11 ++++++++++- lib/imgproxy.ts | 6 ++---- next.config.mjs | 9 +++++++++ scripts/audit-local.sh | 2 +- 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/.env.example b/.env.example index daed0d2b..51ccc096 100644 --- a/.env.example +++ b/.env.example @@ -57,9 +57,9 @@ SENTRY_DSN= IMAGE_TAG=latest TRAEFIK_HOST=klz-cables.com ENV_FILE=.env -# IMGPROXY_URL_MAPPING is used to map public domains to internal Docker hostnames -# Example for testing: https://testing.klz-cables.com/:http://klz-app:3000/,https://cms.testing.klz-cables.com/:http://klz-cms:8055/ -IMGPROXY_URL_MAPPING= +# IMGPROXY_URL: The backend URL of the imgproxy instance (e.g. img.infra.mintel.me) +# Next.js will proxy requests from /_img to this URL. +IMGPROXY_URL=https://img.infra.mintel.me # ──────────────────────────────────────────────────────────────────────────── # Varnish Configuration diff --git a/Dockerfile b/Dockerfile index aa2e3a1c..b0e62dea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,6 @@ WORKDIR /app # Arguments for build-time configuration ARG NEXT_PUBLIC_BASE_URL ARG NEXT_PUBLIC_TARGET -ARG NEXT_PUBLIC_IMGPROXY_URL ARG DIRECTUS_URL ARG UMAMI_WEBSITE_ID ARG UMAMI_API_ENDPOINT @@ -14,7 +13,6 @@ ARG NPM_TOKEN # Environment variables for Next.js build ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL ENV NEXT_PUBLIC_TARGET=$NEXT_PUBLIC_TARGET -ENV NEXT_PUBLIC_IMGPROXY_URL=$NEXT_PUBLIC_IMGPROXY_URL ENV DIRECTUS_URL=$DIRECTUS_URL ENV UMAMI_WEBSITE_ID=$UMAMI_WEBSITE_ID ENV UMAMI_API_ENDPOINT=$UMAMI_API_ENDPOINT diff --git a/docker-compose.yml b/docker-compose.yml index 869f5887..5ca3cd90 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,6 @@ services: dockerfile: Dockerfile args: NEXT_PUBLIC_BASE_URL: ${NEXT_PUBLIC_BASE_URL} - NEXT_PUBLIC_IMGPROXY_URL: ${NEXT_PUBLIC_IMGPROXY_URL} DIRECTUS_URL: ${DIRECTUS_URL} image: registry.infra.mintel.me/mintel/klz-cables.com:${IMAGE_TAG:-latest} restart: unless-stopped @@ -116,7 +115,10 @@ services: DB_PASSWORD: ${DIRECTUS_DB_PASSWORD:-120in09oenaoinsd9iaidon} WEBSOCKETS_ENABLED: 'true' PUBLIC_URL: ${DIRECTUS_URL:-https://cms.klz-cables.com} + WEBSOCKETS_ENABLED: 'true' + PUBLIC_URL: ${DIRECTUS_URL:-https://cms.klz-cables.com} HOST: '0.0.0.0' + IMGPROXY_URL: ${IMGPROXY_URL:-http://klz-imgproxy:8080} networks: - default - infra @@ -172,9 +174,16 @@ services: IMGPROXY_DEBUG: "true" labels: - "traefik.enable=true" + # HTTP router (local dev) - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy.rule=Host(`img.${TRAEFIK_HOST:-klz.localhost}`)" - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy.entrypoints=web" - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy.service=${PROJECT_NAME:-klz}-imgproxy-svc" + # HTTPS router (staging/prod) + - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy-secure.rule=Host(`img.${TRAEFIK_HOST:-klz.localhost}`)" + - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy-secure.entrypoints=${TRAEFIK_ENTRYPOINT:-web}" + - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy-secure.tls=${TRAEFIK_TLS:-false}" + - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy-secure.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-}" + - "traefik.http.routers.${PROJECT_NAME:-klz}-imgproxy-secure.service=${PROJECT_NAME:-klz}-imgproxy-svc" - "traefik.http.services.${PROJECT_NAME:-klz}-imgproxy-svc.loadbalancer.server.port=8080" - "traefik.docker.network=infra" - "caddy=http://img.${TRAEFIK_HOST:-klz.localhost}" diff --git a/lib/imgproxy.ts b/lib/imgproxy.ts index b23da396..cebb4364 100644 --- a/lib/imgproxy.ts +++ b/lib/imgproxy.ts @@ -30,10 +30,8 @@ function encodeBase64(str: string): string { } export function getImgproxyUrl(src: string, options: ImgproxyOptions = {}): string { - const baseUrl = process.env.NEXT_PUBLIC_IMGPROXY_URL || 'https://img.infra.mintel.me'; - - // If no imgproxy URL is configured, return the source as is - if (!baseUrl) return src; + // Use local proxy path which is rewritten in next.config.mjs + const baseUrl = '/_img'; // Handle local paths or relative URLs let absoluteSrc = src; diff --git a/next.config.mjs b/next.config.mjs index 6fd4954d..e49b31f4 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -332,11 +332,20 @@ const nextConfig = { const directusUrl = process.env.INTERNAL_DIRECTUS_URL || process.env.DIRECTUS_URL || 'https://cms.klz-cables.com'; + let imgproxyUrl = process.env.IMGPROXY_URL || 'https://img.infra.mintel.me'; + if (!imgproxyUrl.startsWith('http')) { + imgproxyUrl = `https://${imgproxyUrl}`; + } + return [ { source: '/cms/:path*', destination: `${directusUrl}/:path*`, }, + { + source: '/_img/:path*', + destination: `${imgproxyUrl}/:path*`, + }, ]; }, }; diff --git a/scripts/audit-local.sh b/scripts/audit-local.sh index 5eeca499..b1bd668e 100755 --- a/scripts/audit-local.sh +++ b/scripts/audit-local.sh @@ -9,7 +9,7 @@ echo "🚀 Starting High-Fidelity Local Audit..." # 1. Environment and Infrastructure export DOCKER_HOST="unix:///Users/marcmintel/.docker/run/docker.sock" -export NEXT_PUBLIC_IMGPROXY_URL="http://img.klz.localhost" +export IMGPROXY_URL="http://img.klz.localhost" export NEXT_URL="http://klz.localhost" docker network create infra 2>/dev/null || true