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 منٹ پڑھیں2.0k الفاظ|

ہماری Performance & Scalability سیریز کا حصہ

مکمل گائیڈ پڑھیں

Nginx پروڈکشن کنفیگریشن: SSL، کیشنگ، اور سیکیورٹی

Nginx ایک پروڈکشن ویب سرور ہے جو عملی طور پر تمام ہائی ٹریفک ویب تعیناتیوں کو ہینڈل کرتا ہے۔ اچھی طرح سے ترتیب دینے پر، یہ SSL کو ختم کرنے، موثر جامد فائل کی خدمت، WebSocket پراکسینگ، شرح کو محدود کرنے، اور سیکورٹی ہیڈر فراہم کرتا ہے — یہ سب کچھ اس سے پہلے کہ آپ کی Node.js ایپلیکیشن تک پہنچ جائے۔ خراب ترتیب دینے پر، یہ ایک رکاوٹ بن جاتا ہے، ایک حفاظتی ذمہ داری، یا پراسرار Cloudflare ری ڈائریکٹ لوپس کا سبب بن جاتا ہے۔

یہ گائیڈ ایک ملٹی ایپ Node.js تعیناتی کے لیے پروڈکشن گریڈ Nginx کنفیگریشن کا احاطہ کرتی ہے: Next.js فرنٹ اینڈ، NestJS API، اور Docusaurus docs — یہ سب Cloudflare کے پیچھے ایک ہی سرور پر چل رہے ہیں۔

اہم ٹیک ویز

  • Cloudflare کے پیچھے کبھی بھی www اور non-www کو الگ الگ سرور بلاکس میں تقسیم نہ کریں - ری ڈائریکٹ لوپس کا سبب بنتا ہے
  • /etc/nginx/conf.d/ میں ایک واحد Nginx config فائل استعمال کریں — sites-enabled/ میں بھی سملنک نہ کریں۔
  • X-XSS-Protection فرسودہ ہے — اس کے بجائے CSP استعمال کریں؛ X-Frame-Options: DENY اب بھی درست ہے۔
  • proxy_pass میں پاتھ کا سابقہ استعمال کرتے وقت ٹریلنگ سلیش شامل کرنا ضروری ہے۔
  • ٹیکسٹ/* MIME اقسام کے لیے Gzip کمپریشن ہمیشہ فعال کرنے کے قابل ہوتا ہے۔
  • شرح کو محدود کرنے کے لیے limit_req_zone کی http{} سطح پر وضاحت کی ضرورت ہے، نہ کہ server{} سطح پر
  • آئیے Certbot کے ساتھ سرٹیفکیٹس کو خودکار تجدید کو خفیہ کریں؛ تجدید کے بعد Nginx کو دوبارہ لوڈ کرنے کے لیے کرون جاب شامل کریں۔
  • WebSocket پراکسینگ کے لیے مخصوص ہیڈرز کی ضرورت ہوتی ہے: 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;
    }
}

API سرور بلاک

# 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 غلطی کے ساتھ ناکام ہوجاتا ہے۔


براہ راست SSL (کلاؤڈ فلیئر کے بغیر)

اگر Cloudflare استعمال نہیں کر رہے ہیں تو، براہ راست 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 مخصوص کنفیگریشن

Cloudflare کے پیچھے، Nginx صرف Cloudflare کے IPs کو دیکھتا ہے۔ حقیقی کلائنٹ آئی پی کو محفوظ رکھنے کے لیے:

# 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;

نیز: Cloudflare استعمال کرتے وقت کبھی نہیں www.ecosire.com اور ecosire.com کو الگ الگ Nginx سرور بلاکس میں تقسیم کریں۔ Cloudflare اپنے کنارے پر www ری ڈائریکٹ کو ہینڈل کرتا ہے۔ اگر آپ ایک www سرور بلاک شامل کرتے ہیں جو غیر www پر ری ڈائریکٹ ہوتا ہے، اور Cloudflare 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 استعمال کرنا چاہیے؟

کیڈی کو ترتیب دینے میں نمایاں طور پر آسان ہے — یہ Let's Encrypt SSL کو خود بخود ہینڈل کرتا ہے اور باکس سے باہر سمجھدار ڈیفالٹس رکھتا ہے۔ Nginx زیادہ طاقتور ہے اور اس میں ماڈیولز اور دستاویزات کا ایک بڑا ماحولیاتی نظام ہے۔ زیادہ تر نئے منصوبوں کے لیے، Caddy بہتر نقطہ آغاز ہے۔ اگر آپ کو SSL، پیچیدہ اپ اسٹریم روٹنگ، یا Nginx کے مخصوص ماڈیولز پر ٹھیک ٹھیک کنٹرول کی ضرورت ہو تو Nginx پر جائیں۔ موجودہ لینکس سرورز کے لیے جہاں Nginx پہلے سے انسٹال ہے، Nginx کے ساتھ قائم رہیں۔

میں ڈپلیکیٹ limit_req_zone کی غلطی سے کیسے بچ سکتا ہوں؟

limit_req_zone ہدایت کو http{} سیاق و سباق کی سطح پر ظاہر ہونا چاہئے، نہ کہ server{} بلاکس کے اندر۔ Turborepo monorepo کی تعیناتی میں جہاں آپ ایک سے زیادہ کنفگ فائلز کو شامل کر رہے ہیں، اس بات کو یقینی بنائیں کہ تمام شامل فائلوں پر ہدایت صرف ایک بار ظاہر ہو۔ اگر آپ کو خرابی نظر آ رہی ہے تو چیک کریں کہ آیا آپ کے پاس conf.d/app.conf اور sites-enabled/ دونوں ایک ہی فائل کی طرف اشارہ کرنے والا سملنک ہے۔

میں Nginx کو Next.js ISR (انکریمنٹل سٹیٹک ری جنریشن) کے لیے کیسے کنفیگر کروں؟

Next.js اندرونی طور پر ISR کو ہینڈل کرتا ہے — Nginx کو صرف جوابات کیش کیے بغیر Next.js پر تمام درخواستوں کو پراکسی کرنے کی ضرورت ہے۔ Cache-Control ہیڈر شامل نہ کریں جو Next.js کے ISR کیشے ہیڈر میں مداخلت کرتے ہیں۔ /_next/static/ میں جامد اثاثوں کے لیے، immutable کیشے ہیڈر شامل کریں کیونکہ ان فائلوں میں مواد کے ہیشڈ نام ہیں۔ دیگر تمام راستوں کے لیے، Next.js کو کیشے ہیڈر سیٹ کرنے دیں۔

جب Cloudflare فعال ہوتا ہے تو میرا SSL اسکور کیوں گر جاتا ہے؟

جب Cloudflare پراکسی موڈ میں ہوتا ہے، SSL Labs Cloudflare کے SSL کی جانچ کرتی ہے، آپ کی نہیں۔ Cloudflare کے SSL موڈ کو "مکمل (سخت)" پر سیٹ کریں تاکہ یہ یقینی بنایا جا سکے کہ Cloudflare آپ کے اصل سرٹیفکیٹ کی توثیق کرتا ہے۔ اپنے سرور پر Cloudflare Origin Certificate انسٹال کریں - یہ مفت اور 15 سال کے لیے درست ہے۔ آپ کا SSL لیبز کا سکور Cloudflare کا سکور (عام طور پر A+) بن جاتا ہے، جو دراصل خود ساختہ Nginx SSL سیٹ اپ کے مقابلے میں ایک بہتری ہے۔

میں ایک ہی سرور پر متعدد Node.js ایپس کو کیسے ہینڈل کروں؟

ہر ایپ کو ایک مختلف پورٹ پر چلائیں (Next.js on 3000، NestJS on 3001، Docusaurus on 3002، وغیرہ) اور اپنی Nginx config میں ہر ذیلی ڈومین کے لیے ایک سرور بلاک شامل کریں۔ تمام Node.js عمل کو منظم کرنے کے لیے PM2 استعمال کریں۔ Nginx روٹس بذریعہ ذیلی ڈومین (یا پاتھ پریفکس) درست پورٹ تک۔ ہر سرور بلاک کی اپنی شرح محدود، کیشنگ، اور سیکورٹی ہیڈر کنفیگریشن ہو سکتی ہے۔


اگلے اقدامات

ایک پروڈکشن Nginx کنفیگریشن ایک زندہ دستاویز ہے — یہ آپ کی ایپلیکیشن کے تقاضوں میں تبدیلی، آپ کے ٹریفک کے پیٹرن میں تبدیلی، اور سیکیورٹی کے نئے بہترین طریقوں کے سامنے آنے پر تیار ہوتی ہے۔ ECOSIRE Nginx کو پروڈکشن میں ایک سے زیادہ ایپلی کیشنز پیش کرنے، SSL ختم کرنے، شرح کو محدود کرنے، اور تمام ڈومینز میں Cloudflare کے انضمام کو سنبھالتا ہے۔

چاہے آپ کو DevOps مشاورت، پروڈکشن انفراسٹرکچر سیٹ اپ، یا مکمل تعیناتی آرکیٹیکچر ڈیزائن کی ضرورت ہو، یہ دیکھنے کے لیے کہ ہم کس طرح مدد کر سکتے ہیں۔

E

تحریر

ECOSIRE Research and Development Team

ECOSIRE میں انٹرپرائز گریڈ ڈیجیٹل مصنوعات بنانا۔ Odoo انٹیگریشنز، ای کامرس آٹومیشن، اور AI سے چلنے والے کاروباری حل پر بصیرت شیئر کرنا۔

Chat on WhatsApp