Nginx وApache: الـ Reverse Proxy والـ SSL من الصفر

في المقال اللي فات، كتبنا في الـ Dockerfile بتاع الفرونت إند سطر FROM nginx:alpine وعدّينا عليه بسرعة كأنه تفصيلة بسيطة. بس Nginx ده مش تفصيلة، ده الطبقة اللي بتقف قدام تطبيقك بالكامل وبتستقبل كل طلب قبل ما يوصله. ولو مفهمتش هي بتعمل إيه بالظبط، هتلاقي نفسك في مشاكل غريبة أول ما تنشر على دومين حقيقي.

ده المقال التاني في سلسلة “من الكود للإنتاج”. هنفهم الفرق بين Nginx وApache، ومعنى الـ Reverse Proxy والـ Load Balancer، وإزاي تحط SSL على مشروعك، كل ده بكونفيج حقيقي على نفس مشروع الميرن ستاك بتاعنا، مش شرح نظري.

المحتويات

أولاً: سيرفر الويب بيعمل إيه أصلاً

خلينا نفرق بين حاجتين بيتلخبطوا على المبتدئين. سيرفر التطبيق (Application Server) هو الكود بتاعك اللي بيشتغل، زي Express اللي بنيناه في مقال الـ REST API: بيستقبل طلب، يشتغل شوية، ويرجع رد. أما سيرفر الويب (Web Server) زي Nginx وApache، فهو متخصص في حاجة تانية: يستقبل الطلبات الجاية من الإنترنت، يقدم الملفات الثابتة (صور، HTML، CSS) بسرعة رهيبة، ويوجّه باقي الطلبات للمكان الصح.

ممكن تسأل: طيب Express نفسه يقدر يقدم ملفات ثابتة، ليه محتاج طبقة زيادة؟ الإجابة إن سيرفر الويب متخصص في الشغلانة دي ومكتوب عشانها بالذات، فبيعملها بكفاءة أعلى بمراحل من Node، وكمان بيوفرلك حاجات تانية (زي الـ SSL والضغط والتحكم في المرور) من غير ما تكتب سطر كود واحد في تطبيقك. بدل ما تشغل Node في حاجة مش تخصصه، سيبه يركز على منطق التطبيق وسيب الباقي لسيرفر الويب.

ثانياً: Nginx ولا Apache؟ الفرق الحقيقي

الاتنين سيرفرات ويب ناجحة وشغالة على ملايين المواقع، بس بيشتغلوا بفلسفتين مختلفتين تمامًا، والفرق ده هو سبب اختيار واحد منهم على التاني.

Apache (اللي بدأ سنة 1995) بيشتغل بنموذج بيخصص process أو thread منفصل لكل اتصال جديد بيوصله. يعني لو عندك ألف زائر في نفس اللحظة، عندك ألف عملية شغالة. ده بيبقى سهل في الفهم والتنظيم، بس بياكل ذاكرة كتير لما الأعداد تكبر.

Nginx (ظهر سنة 2004 كرد مباشر على المشكلة دي) بيستخدم نموذج مختلف اسمه event-driven: عدد قليل جدًا من العمليات، وكل عملية بتتعامل مع آلاف الاتصالات في نفس الوقت من غير ما تستنى أي واحد منهم يخلص. شبه نادل شاطر بيخدم عشر ترابيزات بالتبادل بدل ما تجيب عشر نُدُل، كل واحد واقف على ترابيزة واحدة مستني.

النتيجة العملية للفرق ده:

  • الأداء تحت ضغط عالي: Nginx بيتفوق بوضوح لما يبقى فيه اتصالات كتير في نفس اللحظة، وبياكل ذاكرة أقل بكتير.
  • الملفات الثابتة: Nginx أسرع في تقديمها، وعشان كده استخدمناه في مقال Docker عشان يقدم ملفات الـ React بعد الـ build.
  • المرونة والإضافات: Apache بيكسب هنا، عنده مكتبة موديولات ضخمة وبيسمحلك بإعدادات على مستوى كل مجلد (ملف .htaccess المشهور)، وده مفيد جدًا في الاستضافة المشتركة.
  • الانتشار: لو اشتغلت على ووردبريس أو استضافة cPanel قبل كده، فإنت غالبًا كنت بتستخدم Apache من غير ما تدري.

الخلاصة اللي تهمك كمطور ميرن ستاك: Nginx هو الاختيار الافتراضي لتطبيقات Node.js الحديثة، عشان طبيعته الـ event-driven متوافقة مع طريقة شغل Node نفسه، وعشان الأدوار اللي هنشرحها دلوقتي هو متخصص فيها.

ثالثاً: الـ Reverse Proxy وليه مشروعك محتاجه

الـ Proxy العادي بيقف قدام المستخدم ويخفي هويته عن المواقع. الـ Reverse Proxy بيعمل العكس بالظبط: بيقف قدام السيرفرات بتاعتك ويخفيها عن العالم. المستخدم بيكلم Nginx وهو فاكر إنه بيكلم تطبيقك، وNginx هو اللي بيوصل الطلب للمكان الصح جوه شبكتك.

تخيلها زي موظف الاستقبال في شركة كبيرة: الزوار بيكلموه هو بس، وهو اللي بيعرف مين في أنهي مكتب ويوصلهم. محدش من بره محتاج يعرف خريطة المكاتب الداخلية، وده بالظبط اللي بيحصل مع سيرفراتك.

الفوايد العملية لمشروعنا تحديدًا:

  • حل مشكلة الـ CORS من جذورها: فاكر مشكلة الـ CORS اللي قابلتنا في مقال React؟ لما الفرونت إند والباك إند يبقوا وراء نفس الدومين بفضل الـ Reverse Proxy، المشكلة دي بتختفي تمامًا لأن المتصفح بيشوفهم مصدر واحد.
  • إخفاء البورتات: بدل ما المستخدم يكتب yoursite.com:3000، بيكتب yoursite.com عادي وNginx بيوجه داخليًا.
  • طبقة حماية: سيرفر Express بتاعك مش مكشوف للإنترنت مباشرة، ده بيقلل مساحة الهجوم عليه.
  • مكان مركزي للـ SSL: بتظبط الشهادة مرة واحدة في Nginx بدل ما تظبطها في كل تطبيق لوحده.

رابعاً: كونفيج عملي لمشروع الميرن ستاك

ده ملف nginx.conf حقيقي بيخدم الفرونت إند ويوجّه طلبات الـ API للباك إند، مكتوب على نفس مشروعنا.

server {
    listen 80;
    server_name yoursite.com;

    # ملفات الـ React الثابتة بعد الـ build
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }

    # أي طلب بيبدأ بـ api/ يروح للباك إند
    location /api/ {
        proxy_pass http://backend:3000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

خلينا نفك السطور المهمة. try_files $uri $uri/ /index.html دي مهمة جدًا لأي تطبيق React: معناها لو المستخدم فتح رابط داخلي مباشرة، ابحث عن ملف بالاسم ده، ولو ملقتش رجّع index.html وسيب React يتصرف. من غير السطر ده هتلاقي صفحة 404 لما حد يعمل refresh على أي صفحة داخلية.

وproxy_pass http://backend:3000/ هي قلب الـ Reverse Proxy: كلمة backend هنا هي بالظبط اسم السيرفس اللي عرفناه في ملف docker-compose.yml في المقال اللي فات، وDocker بيحولها تلقائيًا لعنوان الحاوية الصح. ملحوظة مهمة: هيدر الـ Authorization اللي بيحمل التوكن اللي شرحناه في مقال الـ JWT بيتمرر للباك إند تلقائيًا من غير ما تحدده، مش محتاج سطر إضافي عشانه. اللي محتاج توضحه فعلاً هو X-Forwarded-Proto: لما نضيف الـ SSL بعد شوية، الطلب هيوصل لـ Nginx مشفر (https) بس هيوصل من Nginx للباك إند من غير تشفير داخليًا، فالهيدر ده بيقول للباك إند “الطلب الأصلي كان https” حتى لو هو مستقبله كـ http عادي.

خامساً: الـ Load Balancer لما مشروعك يكبر

فاكر لما اتكلمنا عن الـ horizontal scaling في مقال الـ API وفي مقال الـ JWT؟ الفكرة كانت إن بدل ما تشتري سيرفر أقوى، بتشغل أكتر من نسخة من نفس التطبيق. الـ Load Balancer هو اللي بيوزع الزوار على النسخ دي بالعدل.

# مجموعة السيرفرات اللي هيتوزع عليهم الحمل
upstream backend_servers {
    server backend1:3000;
    server backend2:3000;
    server backend3:3000;
}

server {
    listen 80;

    location /api/ {
        proxy_pass http://backend_servers/;
    }
}

بالشكل ده، Nginx هيوزع الطلبات على التلات نسخ بالتبادل تلقائيًا، ولو واحدة منهم وقعت هيعدّيها ويكمل على الباقي. وهنا بالظبط بتظهر قيمة قرار الـ Stateless اللي اخدناه في مقال الـ JWT: لأن كل نسخة تقدر تتحقق من التوكن لوحدها من غير ما تحتاج تسأل حد، مش فارقة مع المستخدم أي نسخة تخدمه. لو كنا استخدمنا Sessions مخزنة في ذاكرة السيرفر، كان المستخدم هيتسجل خروج فجأة كل ما الطلب يروح لنسخة مختلفة.

سادساً: SSL وTLS والقفل الأخضر

أول حاجة: SSL وTLS عمليًا نفس الحاجة. SSL هو الاسم القديم للبروتوكول، وTLS هو النسخة الحديثة اللي بتستخدم فعليًا دلوقتي، بس الاسم القديم فضل شايع فبنقول “شهادة SSL” وإحنا بنقصد TLS. الفكرة إن الاتصال بين متصفح المستخدم وسيرفرك بيتشفر، فلو حد اعترض البيانات في النص مش هيفهم منها حاجة.

ده مش رفاهية لمشروعنا بالذات: في مقال الـ JWT المستخدم بيبعت الإيميل وكلمة السر في طلب تسجيل الدخول، وبيبعت التوكن مع كل طلب بعد كده. من غير تشفير، أي حد على نفس شبكة الـ WiFi يقدر يقرا التوكن ده ويستخدمه. كمان جوجل بتفضل المواقع المشفرة في نتايج البحث، والمتصفحات بتحذر المستخدم صراحة من المواقع اللي من غيرها.

الخبر الحلو إن الشهادات بقت مجانية بفضل Let’s Encrypt، وأداة اسمها Certbot بتظبطلك كل حاجة بأمر واحد.

# بيجيب الشهادة ويعدل كونفيج Nginx تلقائيًا
sudo certbot --nginx -d yoursite.com

الأمر ده هيضيف قسم جديد في الكونفيج بتاعك بيسمع على بورت 443 (بورت HTTPS)، وهيحوّل أي حد بيدخل على HTTP العادي للنسخة المشفرة تلقائيًا. الشهادة بتنتهي كل 3 شهور، بس Certbot بيسجل مهمة تلقائية بتجددها لوحدها.

سابعاً: أخطاء شائعة هتقابلك

  • نسيان try_files في قسم الـ React، وده بيدي 404 لما المستخدم يعمل refresh على أي صفحة داخلية.
  • الغلط في وجود أو غياب الشرطة الأخيرة في proxy_pass، بيغير شكل المسار اللي بيوصل للباك إند.
  • إضافة سطر تمرير يدوي لهيدر Authorization رغم إنه بيتمرر تلقائيًا، سطر زيادة مش لازم.
  • تعديل الكونفيج ونسيان nginx -s reload بعده، فالتغيير مش بيتفعل.
  • الاعتماد على HTTP في الإنتاج وتأجيل الـ SSL لبعدين، وده بيكشف كلمات السر والتوكنز.
  • نسيان app.set(‘trust proxy’, 1) في Express، فهيدر X-Forwarded-Proto بيوصله بس بيتجاهله.

ثامناً: خطوة قبل النشر

قبل ما تعتمد الكونفيج بتاعك، اختبره الأول بأمر nginx -t، ده بيفحص الملف ويقولك لو فيه خطأ في الصيغة قبل ما تعيد التشغيل وتكتشف إن الموقع وقع. وخد بالك إن الكونفيج اللي كتبناه هنا مناسب للتطوير والمشاريع الصغيرة، الإنتاج الحقيقي بيحتاج إعدادات زيادة زي حدود لحجم الطلبات ومهلة زمنية للاتصالات.

دلوقتي بقى عندك الصورة كاملة: مشروع معزول في حاويات، وقدامه طبقة Nginx بتوزع الطلبات وبتشفر الاتصال. الخطوة الجاية في السلسلة هي ناخد كل ده وننشره فعليًا على سيرفر حقيقي عشان أي حد في العالم يقدر يفتح تطبيقك. لو عندك سؤال عن أي جزء من الكونفيج، قولّي في التعليقات.


اكتشاف المزيد من كود التطور

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك رد

Scroll to Top