commit 23e7aa3cb6b4d9016ea6768be253994fc4655a26 Author: PhatPhuckDave Date: Wed Jan 7 19:09:13 2026 +0100 Initial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f55a7d7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM nginx:alpine + +# Copy nginx configuration +COPY nginx.conf /etc/nginx/nginx.conf + +# Create cache directory +RUN mkdir -p /var/cache/nginx && \ + chown nginx:nginx /var/cache/nginx + +# Expose port +EXPOSE 3000 + +# Start nginx +CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..0eef793 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# Nginx Cache Proxy + +An nginx proxy server that caches requests only when explicitly requested via the `X-Cache: 1` header. + +## Configuration + +The nginx configuration implements an inverted caching logic: +- **Default behavior**: Requests are NOT cached +- **Cached behavior**: Only requests with `X-Cache: 1` header are cached + +## Usage + +```bash +# Normal request - NOT cached (default) +curl http://localhost:3000/?url=https://api.example.com/data + +# Cached request - add the header +curl -H "X-Cache: 1" http://localhost:3000/?url=https://api.example.com/data +``` + +## Features + +- Cache path: `/var/cache/nginx` +- Cache zone: `api_cache` (10MB) +- Max cache size: 1GB +- Cache validity: 365 days for 200 responses +- Cache key: Based on scheme, host, URI, and query parameters +- Cache status header: `X-Cache-Status` shows cache hit/miss status + +## In n8n + +Add the `X-Cache: 1` header only to requests you want cached. All other requests will bypass the cache completely. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..8df1c40 --- /dev/null +++ b/build.sh @@ -0,0 +1,87 @@ +#!/bin/bash +  +# ============================================================================ +# CONFIGURATION - Modify these for your project +# ============================================================================ +  +# Docker registry and image name +DOCKER_REPO="docker.site.quack-lab.dev" +IMAGE_NAME="nginx-cache-proxy" +  +# ============================================================================ +# VALIDATE CONFIGURATION +# ============================================================================ + +echo "Validating nginx configuration..." +nginx -t -c /dev/stdin <<< "$(cat nginx.conf)" + +if [ $? -ne 0 ]; then + echo "Error validating nginx configuration" + exit 1 +fi + +# ============================================================================ +# DOCKER BUILD AND TAG +# ============================================================================ +  +COMMIT_SHA=$(git rev-parse --short HEAD) +IMAGE_BASE="${DOCKER_REPO}/${IMAGE_NAME}" +  +echo "" +echo "Building Docker image..." +docker build -t "${IMAGE_BASE}:${COMMIT_SHA}" . +  +if [ $? -ne 0 ]; then + echo "Error building agx Docker image" + exit 1 +fi +  +echo "Tagging as latest..." +docker tag "${IMAGE_BASE}:${COMMIT_SHA}" "${IMAGE_BASE}:latest" +  +TAGS=$(git tag --points-at HEAD) +if [ -n "$TAGS" ]; then + echo "Found tags on current commit:" + while IFS= read -r tag; do + if [ -n "$tag" ]; then + echo "Tagging as ${tag}..." + docker tag "${IMAGE_BASE}:${COMMIT_SHA}" "${IMAGE_BASE}:${tag}" + fi + done <<< "$TAGS" +fi +  +# ============================================================================ +# PUSH IMAGES +# ============================================================================ +  +echo "" +echo "Pushing Docker images..." +docker push "${IMAGE_BASE}:${COMMIT_SHA}" +docker push "${IMAGE_BASE}:latest" +  +if [ -n "$TAGS" ]; then + while IFS= read -r tag; do + if [ -n "$tag" ]; then + docker push "${IMAGE_BASE}:${tag}" + fi + done <<< "$TAGS" +fi +  +# ============================================================================ +# SUMMARY +# ============================================================================ +  +echo "" +echo "Build complete! Image pushed as:" +echo " - ${IMAGE_BASE}:${COMMIT_SHA}" +echo " - ${IMAGE_BASE}:latest" +if [ -n "$TAGS" ]; then + while IFS= read -r tag; do + if [ -n "$tag" ]; then + echo " - ${IMAGE_BASE}:${tag}" + fi + done <<< "$TAGS" +fi +  +  +  \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cf9137c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.8' + +services: + nginx-cache-proxy: + build: . + ports: + - "3000:3000" + volumes: + - nginx_cache:/var/cache/nginx + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/?url=http://httpbin.org/get"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + +volumes: + nginx_cache: diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..1693ef5 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,41 @@ +http { + + proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=365d; + + server { + + listen 3000; + + location / { + + proxy_cache api_cache; + + proxy_cache_valid 200 365d; + + # Only cache if X-Cache header is present + + proxy_cache_bypass $http_x_cache_inverse; + + proxy_no_cache $http_x_cache_inverse; + + # Set inverse variable (cache disabled by default) + + set $http_x_cache_inverse 1; + + if ($http_x_cache) { + + set $http_x_cache_inverse 0; + + } + + proxy_cache_key $scheme$proxy_host$uri$is_args$args; + + proxy_pass $arg_url; + + add_header X-Cache-Status $upstream_cache_status; + + } + + } + +}