Nginx Production Configuration: SSL, Caching, and Security

Nginx production configuration guide: SSL termination, HTTP/2, caching headers, security headers, rate limiting, reverse proxy setup, and Cloudflare integration patterns.

E
ECOSIRE Research and Development Team
|19 मार्च 20269 मिनट पढ़ें1.9k शब्द|

हमारी Performance & Scalability श्रृंखला का हिस्सा

पूरी गाइड पढ़ें

Nginx उत्पादन कॉन्फ़िगरेशन: SSL, कैशिंग और सुरक्षा

Nginx एक उत्पादन वेब सर्वर है जो वस्तुतः सभी उच्च-ट्रैफ़िक वेब परिनियोजन को संभालता है। जब अच्छी तरह से कॉन्फ़िगर किया जाता है, तो यह एसएसएल समाप्ति, कुशल स्थैतिक फ़ाइल सेवा, वेबसॉकेट प्रॉक्सीइंग, दर सीमित करना और सुरक्षा हेडर प्रदान करता है - यह सब एक अनुरोध आपके Node.js एप्लिकेशन तक पहुंचने से पहले होता है। जब खराब तरीके से कॉन्फ़िगर किया जाता है, तो यह एक बाधा, एक सुरक्षा दायित्व या रहस्यमय क्लाउडफ्लेयर रीडायरेक्ट लूप का कारण बन जाता है।

यह मार्गदर्शिका मल्टी-ऐप Node.js परिनियोजन के लिए प्रोडक्शन-ग्रेड Nginx कॉन्फ़िगरेशन को कवर करती है: Next.js फ्रंटएंड, NestJS API, और Docusaurus डॉक्स - सभी Cloudflare के पीछे एक ही सर्वर पर चल रहे हैं।

मुख्य बातें

  • क्लाउडफ़ेयर के पीछे कभी भी www और गैर-www को अलग-अलग सर्वर ब्लॉक में विभाजित न करें - रीडायरेक्ट लूप का कारण बनता है
  • /etc/nginx/conf.d/ में एकल Nginx कॉन्फ़िगरेशन फ़ाइल का उपयोग करें - sites-enabled/ में सिम्लिंक भी न करें
  • X-XSS-Protection को हटा दिया गया है - इसके बजाय CSP का उपयोग करें; X-Frame-Options: DENY अभी भी मान्य है
  • पथ उपसर्ग का उपयोग करते समय proxy_pass में अनुगामी स्लैश शामिल होना चाहिए
  • टेक्स्ट/* MIME प्रकारों के लिए Gzip संपीड़न हमेशा सक्षम करने योग्य होता है
  • दर सीमित करने के लिए limit_req_zone को http{} स्तर पर परिभाषित करना आवश्यक है, न कि server{} स्तर पर
  • आइए Certbot के साथ प्रमाणपत्रों को स्वतः नवीनीकृत करें; नवीनीकरण के बाद Nginx को पुनः लोड करने के लिए क्रॉन जॉब जोड़ें
  • वेबसॉकेट प्रॉक्सी के लिए विशिष्ट हेडर की आवश्यकता होती है: Upgrade और Connection

निर्देशिका संरचना

Nginx कॉन्फ़िगरेशन को व्यवस्थित रखें:

/etc/nginx/
  nginx.conf                    — Main config (rarely touch this)
  conf.d/
    ecosire-production.conf     — All your server blocks in ONE file
  snippets/
    ssl-params.snippet          — SSL hardening (included by server blocks)
    proxy-params.snippet        — Common proxy headers
    security-headers.snippet    — Security headers

महत्वपूर्ण: अपना सारा कॉन्फ़िगरेशन conf.d/ecosire-production.conf में रखें। इसे sites-enabled/ में भी न जोड़ें - इससे Nginx को कॉन्फ़िगरेशन को दो बार संसाधित करना पड़ता है, जिससे डुप्लिकेट limit_req_zone त्रुटियां और अप्रत्याशित व्यवहार होता है।


दर सीमित क्षेत्र

अपने कॉन्फ़िगरेशन में http{} स्तर पर दर सीमित क्षेत्र परिभाषित करें। उन्हें server{} ब्लॉक के अंदर परिभाषित नहीं किया जा सकता:

# /etc/nginx/conf.d/ecosire-production.conf

# Must be at http{} level — these are in the main conf or conf.d root
limit_req_zone $binary_remote_addr zone=api_general:10m rate=60r/m;
limit_req_zone $binary_remote_addr zone=api_auth:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=api_public:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=static_files:10m rate=200r/m;

मुख्य एप्लिकेशन सर्वर ब्लॉक

# Main web application — Next.js on port 3000
server {
    listen 80;
    listen [::]:80;
    server_name ecosire.com www.ecosire.com;

    # Cloudflare handles SSL termination — Nginx only sees HTTP
    # (If direct SSL, add listen 443 ssl and certificate paths)

    # Security headers
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    # CSP — adjust based on your needs
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; frame-src https://js.stripe.com; connect-src 'self' https://api.ecosire.com;" always;

    # Remove server version from responses
    server_tokens off;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
      text/plain
      text/css
      text/javascript
      application/javascript
      application/json
      application/xml
      image/svg+xml
      font/woff2;
    gzip_min_length 1024;

    # ─── Static Files: Next.js build output ─────────────────────────
    location /_next/static/ {
        proxy_pass http://127.0.0.1:3000;
        add_header Cache-Control "public, max-age=31536000, immutable";
        # Files include content hash in filename — safe to cache forever
    }

    # ─── Public static assets ────────────────────────────────────────
    location /assets/ {
        proxy_pass http://127.0.0.1:3000;
        add_header Cache-Control "public, max-age=86400";  # 1 day
    }

    # ─── Well-known files (no locale prefix) ─────────────────────────
    location /.well-known/ {
        proxy_pass http://127.0.0.1:3000;
        add_header Cache-Control "public, max-age=86400";
    }

    # ─── App routes (rate limited) ───────────────────────────────────
    location / {
        limit_req zone=api_general burst=20 nodelay;
        limit_req_status 429;

        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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 X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

एपीआई सर्वर ब्लॉक

# NestJS API — port 3001
server {
    listen 80;
    listen [::]:80;
    server_name api.ecosire.com;

    server_tokens off;

    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # CORS — handled by NestJS, but Nginx can add preflight response
    # for performance (avoids reaching Node.js for OPTIONS)
    location / {
        if ($request_method = 'OPTIONS') {
            add_header Access-Control-Allow-Origin "https://ecosire.com";
            add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS";
            add_header Access-Control-Allow-Headers "Content-Type, Authorization";
            add_header Access-Control-Allow-Credentials "true";
            add_header Access-Control-Max-Age 1728000;
            add_header Content-Length 0;
            return 204;
        }

        limit_req zone=api_general burst=30 nodelay;

        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        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 X-Forwarded-Proto $scheme;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # Stricter rate limits for auth endpoints
    location ~ ^/api/auth/(login|exchange|callback) {
        limit_req zone=api_auth burst=5 nodelay;
        limit_req_status 429;

        proxy_pass http://127.0.0.1:3001;
        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 X-Forwarded-Proto $scheme;
    }

    # Health check — no rate limiting
    location /api/health {
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header Host $host;
        access_log off;  # Don't log health check spam
    }

    # Stripe webhook — needs raw body
    location /api/billing/webhook {
        proxy_pass http://127.0.0.1:3001;
        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 X-Forwarded-Proto $scheme;
        # No rate limiting on webhooks — Stripe IPs are trusted
        # NestJS validates the Stripe signature
    }
}

वेबसॉकेट प्रॉक्सीइंग

यदि आपका एप्लिकेशन WebSockets (Socket.IO, NestJS WebSocket गेटवे) का उपयोग करता है, तो प्रॉक्सी कॉन्फ़िगरेशन को विशिष्ट हेडर की आवश्यकता होती है:

# WebSocket upgrade handling
location /ws/ {
    proxy_pass http://127.0.0.1:3001;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";  # Capital U required
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    # WebSocket connections can be long-lived
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
}

Upgrade और Connection हेडर के बिना, ब्राउज़र का WebSocket हैंडशेक 426 Upgrade Required या 101 Switching Protocols त्रुटि के साथ विफल हो जाता है।


डायरेक्ट एसएसएल (क्लाउडफ्लेयर के बिना)

यदि क्लाउडफ़ेयर का उपयोग नहीं कर रहे हैं, तो सीधे Nginx में SSL समाप्ति को संभालें:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name ecosire.com;

    ssl_certificate /etc/letsencrypt/live/ecosire.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ecosire.com/privkey.pem;

    # SSL hardening
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # ... rest of server block
}

# HTTP to HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name ecosire.com www.ecosire.com;
    return 301 https://ecosire.com$request_uri;
}

क्लाउडफ्लेयर-विशिष्ट कॉन्फ़िगरेशन

Cloudflare के पीछे, Nginx केवल Cloudflare के IP देखता है। वास्तविक ग्राहक आईपी को संरक्षित करने के लिए:

# Real IP from Cloudflare — add this in http{} or at top of server{}
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
real_ip_header CF-Connecting-IP;

इसके अलावा: क्लाउडफ्लेयर का उपयोग करते समय कभी भी www.ecosire.com और ecosire.com को अलग-अलग Nginx सर्वर ब्लॉक में विभाजित न करें। Cloudflare अपने किनारे पर www रीडायरेक्ट को संभालता है। यदि आप एक www सर्वर ब्लॉक जोड़ते हैं जो गैर-www पर रीडायरेक्ट करता है, और क्लाउडफ्लेयर भी www को रीडायरेक्ट कर रहा है, तो आपको एक रीडायरेक्ट लूप (ERR_TOO_MANY_REDIRECTS) मिलता है।


लॉग कॉन्फ़िगरेशन

# Custom log format with useful fields
log_format json_combined escape=json
  '{'
  '"time":"$time_iso8601",'
  '"remote_addr":"$remote_addr",'
  '"cf_ip":"$http_cf_connecting_ip",'
  '"method":"$request_method",'
  '"uri":"$request_uri",'
  '"status":$status,'
  '"body_bytes":$body_bytes_sent,'
  '"response_time":$request_time,'
  '"referrer":"$http_referer",'
  '"user_agent":"$http_user_agent"'
  '}';

access_log /var/log/nginx/ecosire-access.log json_combined;
error_log /var/log/nginx/ecosire-error.log warn;

आपके कॉन्फ़िगरेशन का परीक्षण करना

# Test syntax before applying
nginx -t

# Reload without downtime
nginx -s reload

# Check which config file is active
nginx -T | grep "configuration file"

# Test a specific server block
curl -I https://ecosire.com
curl -I https://api.ecosire.com/api/health

# Check security headers
curl -I https://ecosire.com | grep -E "X-Frame|X-Content|Referrer|Content-Security"

अक्सर पूछे जाने वाले प्रश्न

क्या मुझे नए प्रोजेक्ट के लिए Nginx या Caddy का उपयोग करना चाहिए?

कैडी को कॉन्फ़िगर करना काफी सरल है - यह लेट्स एनक्रिप्ट एसएसएल को स्वचालित रूप से संभालता है और बॉक्स से बाहर समझदार डिफ़ॉल्ट रखता है। Nginx अधिक शक्तिशाली है और इसमें मॉड्यूल और दस्तावेज़ीकरण का एक बड़ा पारिस्थितिकी तंत्र है। अधिकांश नई परियोजनाओं के लिए, कैडी बेहतर प्रारंभिक बिंदु है; यदि आपको SSL, जटिल अपस्ट्रीम रूटिंग, या Nginx-विशिष्ट मॉड्यूल पर सूक्ष्म नियंत्रण की आवश्यकता है, तो Nginx पर स्विच करें। मौजूदा Linux सर्वरों के लिए जहां Nginx पहले से स्थापित है, Nginx के साथ बने रहें।

मैं डुप्लिकेट लिमिट_रेक_ज़ोन त्रुटि से कैसे बचूं?

limit_req_zone निर्देश http{} संदर्भ स्तर पर प्रकट होना चाहिए, server{} ब्लॉक के अंदर नहीं। टर्बोरेपो मोनोरेपो परिनियोजन में जहां आप एकाधिक कॉन्फ़िगरेशन फ़ाइलें शामिल कर रहे हैं, सुनिश्चित करें कि निर्देश सभी शामिल फ़ाइलों में केवल एक बार दिखाई देता है। यदि आप त्रुटि देख रहे हैं, तो जांचें कि क्या आपके पास conf.d/app.conf और sites-enabled/ सिम्लिंक दोनों एक ही फ़ाइल की ओर इशारा कर रहे हैं।

मैं Next.js ISR (वृद्धिशील स्थैतिक पुनर्जनन) के लिए Nginx को कैसे कॉन्फ़िगर करूं?

Next.js ISR को आंतरिक रूप से संभालता है - Nginx को प्रतिक्रियाओं को कैश किए बिना Next.js पर सभी अनुरोधों को प्रॉक्सी करने की आवश्यकता है। Cache-Control हेडर न जोड़ें जो Next.js के ISR कैश हेडर में हस्तक्षेप करते हैं। /_next/static/ में स्थिर संपत्तियों के लिए, immutable कैश हेडर जोड़ें क्योंकि इन फ़ाइलों में सामग्री-हैशेड नाम हैं। अन्य सभी मार्गों के लिए, Next.js को कैश हेडर सेट करने दें।

क्लाउडफ्लेयर सक्षम होने पर मेरा एसएसएल स्कोर क्यों गिर जाता है?

जब क्लाउडफ़ेयर प्रॉक्सी मोड में होता है, तो एसएसएल लैब्स क्लाउडफ़ेयर के एसएसएल का परीक्षण करता है, आपका नहीं। यह सुनिश्चित करने के लिए कि क्लाउडफ़ेयर आपके मूल प्रमाणपत्र को मान्य करता है, क्लाउडफ़ेयर के एसएसएल मोड को "पूर्ण (सख्त)" पर सेट करें। अपने सर्वर पर क्लाउडफ्लेयर ओरिजिन सर्टिफिकेट इंस्टॉल करें - यह मुफ़्त है और 15 वर्षों के लिए वैध है। आपका एसएसएल लैब्स स्कोर क्लाउडफ्लेयर का स्कोर (आमतौर पर ए+) बन जाता है, जो वास्तव में एक विशिष्ट स्व-कॉन्फ़िगर किए गए नग्नेक्स एसएसएल सेटअप पर एक सुधार है।

मैं एक ही सर्वर पर एकाधिक Node.js ऐप्स को कैसे संभालूं?

प्रत्येक ऐप को एक अलग पोर्ट पर चलाएं (3000 पर Next.js, 3001 पर NestJS, 3002 पर Docusaurus, आदि) और अपने Nginx कॉन्फ़िगरेशन में प्रत्येक उपडोमेन के लिए एक सर्वर ब्लॉक जोड़ें। सभी Node.js प्रक्रियाओं को प्रबंधित करने के लिए PM2 का उपयोग करें। Nginx उपडोमेन (या पथ उपसर्ग) द्वारा सही पोर्ट तक रूट करता है। प्रत्येक सर्वर ब्लॉक की अपनी दर सीमित, कैशिंग और सुरक्षा हेडर कॉन्फ़िगरेशन हो सकती है।


अगले चरण

एक उत्पादन Nginx कॉन्फ़िगरेशन एक जीवित दस्तावेज़ है - यह आपके एप्लिकेशन की आवश्यकताओं में बदलाव, आपके ट्रैफ़िक पैटर्न में बदलाव और नई सुरक्षा सर्वोत्तम प्रथाओं के उभरने के साथ विकसित होता है। ECOSIRE उत्पादन में Nginx चलाता है जो कई अनुप्रयोगों की सेवा प्रदान करता है, सभी डोमेन में SSL समाप्ति, दर सीमित करने और Cloudflare एकीकरण को संभालता है।

चाहे आपको DevOps परामर्श, उत्पादन अवसंरचना सेटअप, या पूर्ण परिनियोजन आर्किटेक्चर डिज़ाइन की आवश्यकता हो, हमारी सेवाओं का अन्वेषण करें यह देखने के लिए कि हम कैसे मदद कर सकते हैं।

शेयर करें:
E

लेखक

ECOSIRE Research and Development Team

ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।

WhatsApp पर चैट करें