# ============================================================================ # AUTO-GENERATED NGINX UPSTREAM CONFIGURATION # Application: {{ app_name }} # Environment: {{ deploy_env }}{{ env_tag | default('') }} # Generated: {{ ansible_date_time.iso8601 }} # Replicas: {{ replica_count }} # ============================================================================ {% if framework is defined and framework == "nextjs" %} map $arg_url ${{app_name | regex_replace('[^A-Za-z0-9_]', '_')}}_clean_url { ~^(?.+)%3Fv%3D\d+$ $base; # chỉ có ?v=xxx ~^(?.+)%3Fv%3D\d+%26(?.+)$ $base?$rest; # có ?v=xxx&... → giữ lại phần sau default $arg_url; # mặc định giữ nguyên } {% endif %} upstream {{ upstream_name | regex_replace('[^A-Za-z0-9_]', '_') }} { # Load balancing method {% if load_balancing_method is defined %} {{ load_balancing_method }}; {% else %} least_conn; {% endif %} # Health check configuration {% if health_check_interval is defined %} health_check interval={{ health_check_interval }} fails={{ health_check_fails | default(1) }} passes={{ health_check_passes | default(2) }}; {% endif %} # Upstream servers (auto-generated from active ports) {% for port in active_ports %} server localhost:{{ port }} weight={{ server_weight | default(1) }} max_fails={{ max_fails | default(1) }} fail_timeout={{ fail_timeout | default(10) }}s; {% endfor %} # Backup server (optional) {% if backup_server is defined %} server {{ backup_server }} backup; {% endif %} # Keep-alive connections keepalive {{ keepalive_connections | default(64) }}; } {% if framework is defined and framework == "nextjs" %} proxy_cache_path /var/cache/nginx/{{app_name | regex_replace('[^A-Za-z0-9_]', '_')}}_cache levels=1:2 keys_zone={{app_name | regex_replace('[^A-Za-z0-9_]', '_')}}_cache:512m inactive=30d max_size=100g use_temp_path=off; #levels=1:2: Tạo cây thư mục theo hash key để phân bổ file. #keys_zone=tkl_web_img_cache:512m: Tăng RAM dùng cho metadata (1MB chứa được ~8000 keys) → 2G = ~16 triệu keys. #inactive=30d: Nếu file không được truy cập trong 30 ngày → bị xóa. #max_size=100g: Giới hạn tối đa 100GB cache disk. #use_temp_path=off: Ghi thẳng vào cache thay vì ghi tạm → hiệu quả hơn. {% endif %} server { listen {{ base_port }}; server_name localhost; {% if framework is defined and framework == "nextjs" %} location ~* /_next/image { access_log off; proxy_pass http://{{ upstream_name | regex_replace('[^A-Za-z0-9_]', '_') }}; # upstream load balancing proxy_cache {{app_name | regex_replace('[^A-Za-z0-9_]', '_')}}_cache; proxy_cache_key "url=${{app_name | regex_replace('[^A-Za-z0-9_]', '_')}}_clean_url&w=$arg_w&q=$arg_q"; proxy_cache_valid 200 180d; proxy_cache_use_stale error timeout updating http_502 http_503 http_504; proxy_next_upstream error timeout http_502 http_503 http_504; proxy_next_upstream_tries 3; # Chống cache stampede (bottleneck) proxy_cache_lock on; proxy_cache_lock_timeout 10s; proxy_cache_lock_age 5s; # Timeout & buffering proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; send_timeout 60s; # Ignore upstream cache headers (Next.js gửi max-age + vary) proxy_ignore_headers Cache-Control Vary; proxy_hide_header Set-Cookie; proxy_set_header Connection $connection_upgrade; proxy_http_version 1.1; # Chuẩn hóa Accept để tránh tạo nhiều cache key khác nhau proxy_set_header Accept "image/webp,image/*,*/*;q=0.8"; add_header X-Cache-Status $upstream_cache_status; #add_header X-Cache-Key "url=${{app_name | regex_replace('[^A-Za-z0-9_]', '_')}}_clean_url&w=$arg_w&q=$arg_q"; # Keepalive settings (optional) keepalive_timeout 64; } {% endif %} location / { access_log off; proxy_pass http://{{ upstream_name | regex_replace('[^A-Za-z0-9_]', '_') }}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_http_version 1.1; proxy_cache off; proxy_next_upstream error timeout http_502 http_503 http_504; proxy_next_upstream_tries 3; # Timeout & buffering proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; send_timeout 60s; proxy_buffering on; client_max_body_size 256M; # Keepalive settings (optional) keepalive_timeout 64; } } # ============================================================================ # CONFIGURATION METADATA (for debugging) # ============================================================================ # Configuration Details: # - Base Port: {{ base_port }} # - Load Balancing: {{ load_balancing_method | default('least_conn') }} # - Max Fails: {{ max_fails | default(1) }} # - Fail Timeout: {{ fail_timeout | default(10) }}s # - Health Check: {{ 'enabled' if enable_health_check_endpoint | default(true) else 'disabled' }} # ============================================================================