#!/bin/sh /etc/rc.common # SPDX-License-Identifier: Apache-2.0 # CDN Cache Proxy Init Script # Copyright (C) 2025 CyberMind.fr START=90 STOP=10 USE_PROCD=1 CONF_FILE="/var/etc/cdn-cache-nginx.conf" PID_FILE="/var/run/cdn-cache.pid" validate_section() { uci_load_validate cdn-cache main "$1" "$2" \ 'enabled:bool:0' \ 'cache_dir:string:/var/cache/cdn' \ 'cache_size:uinteger:1024' \ 'max_object_size:uinteger:512' \ 'cache_valid:uinteger:1440' \ 'listen_port:port:3128' \ 'transparent:bool:0' \ 'log_level:string:warn' } generate_nginx_config() { local cache_dir="$1" local cache_size="$2" local max_object="$3" local cache_valid="$4" local listen_port="$5" mkdir -p "$(dirname $CONF_FILE)" mkdir -p "$cache_dir" mkdir -p /var/log/cdn-cache cat > "$CONF_FILE" << EOF # CDN Cache Nginx Configuration # Auto-generated - Do not edit worker_processes auto; pid $PID_FILE; error_log /var/log/cdn-cache/error.log $log_level; events { worker_connections 1024; use epoll; multi_accept on; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format cache '\$time_local|\$remote_addr|\$request|\$status|\$body_bytes_sent|\$upstream_cache_status|\$host'; access_log /var/log/cdn-cache/access.log cache; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; # Cache zone configuration proxy_cache_path $cache_dir levels=1:2 keys_zone=cdn_cache:64m max_size=${cache_size}m inactive=7d use_temp_path=off; proxy_temp_path $cache_dir/temp; # Cache settings proxy_cache_valid 200 ${cache_valid}m; proxy_cache_valid 301 302 10m; proxy_cache_valid 404 1m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_lock on; proxy_cache_lock_timeout 5s; # Upstream settings proxy_connect_timeout 10s; proxy_read_timeout 60s; proxy_send_timeout 60s; proxy_buffering on; proxy_buffer_size 16k; proxy_buffers 8 32k; proxy_max_temp_file_size ${max_object}m; # Resolver for dynamic upstream resolver 8.8.8.8 8.8.4.4 valid=300s ipv6=off; resolver_timeout 5s; server { listen $listen_port; server_name _; # Health check endpoint location /cdn-cache-health { return 200 'OK'; add_header Content-Type text/plain; } # Stats endpoint location /cdn-cache-stats { stub_status; allow 127.0.0.1; deny all; } # Proxy all requests location / { proxy_pass http://\$host\$request_uri; proxy_cache cdn_cache; proxy_cache_key \$scheme\$host\$request_uri; # Add cache status header add_header X-Cache-Status \$upstream_cache_status; add_header X-Cache-Date \$upstream_http_date; # Forward headers proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; # Cache specific content types aggressively proxy_cache_valid 200 301 302 ${cache_valid}m; # Bypass cache for certain requests proxy_cache_bypass \$http_pragma \$http_authorization; proxy_no_cache \$http_pragma \$http_authorization; } # Special handling for update services location ~* \.(exe|msu|cab|msi|deb|rpm|apk|pkg\.tar\.zst)$ { proxy_pass http://\$host\$request_uri; proxy_cache cdn_cache; proxy_cache_key \$scheme\$host\$request_uri; proxy_cache_valid 200 10080m; add_header X-Cache-Status \$upstream_cache_status; proxy_set_header Host \$host; } # Static content with longer cache location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { proxy_pass http://\$host\$request_uri; proxy_cache cdn_cache; proxy_cache_key \$scheme\$host\$request_uri; proxy_cache_valid 200 1440m; add_header X-Cache-Status \$upstream_cache_status; proxy_set_header Host \$host; } } } EOF } start_service() { validate_section main start_cdn_cache } start_cdn_cache() { [ "$2" = 0 ] || { echo "Validation failed" >&2 return 1 } [ "$enabled" = "1" ] || { echo "CDN Cache is disabled" return 0 } generate_nginx_config "$cache_dir" "$cache_size" "$max_object_size" \ "$cache_valid" "$listen_port" procd_open_instance cdn-cache procd_set_param command /usr/sbin/nginx -c "$CONF_FILE" -g "daemon off;" procd_set_param respawn procd_set_param stdout 1 procd_set_param stderr 1 procd_set_param pidfile "$PID_FILE" procd_close_instance logger -t cdn-cache "CDN Cache proxy started on port $listen_port" } stop_service() { logger -t cdn-cache "CDN Cache proxy stopped" } reload_service() { stop start } service_triggers() { procd_add_reload_trigger "cdn-cache" }