ما هو nginx، والوظائف الخمس التي يقوم بها
nginx (يُنطق "إنجن إكس") خادم ومُوكِّل HTTP مفتوح المصدر. كتبه إيغور سيسويف للحفاظ على عشرة آلاف اتصال متزامن مفتوحة على جهاز واحد، في وقت كان ذلك يُسقط معظم الخوادم، وأصدره عام 2004. هو اليوم أحد أكثر خادمي الويب انتشارًا، جنبًا إلى جنب مع Apache، والمحرك داخل كثير من موازنات الأحمال، ووحدات تحكم Ingress في Kubernetes، وشبكات CDN. النسخة مفتوحة المصدر موجودة على nginx.org؛ وF5، التي استحوذت على الشركة التي تقف خلفه عام 2019، تبيع نسخة تجارية باسم NGINX Plus.
يغطي الاسم خمسة أدوار، ويمكن لضبط واحد أن يجمعها كلها:
خادم ويب. يقرأ الملفات من القرص ويرسلها: HTML، وCSS، وJavaScript، والصور، والتنزيلات. هذا أسرع ما يفعله، حيث يُسلّم النسخ إلى النواة عبر sendfile.
وكيل عكسي. يستقبل الطلب ويمرره إلى تطبيق لا ينبغي أن يواجه الإنترنت مباشرة: PHP-FPM، أو Node.js، أو Python، أو Go، أو Java، أو حاوية. الموضوع كاملًا، بما فيه الترويسات التي يجب تمريرها، موجود في دليل الوكيل العكسي.
موازن أحمال. يوزّع الطلبات على عدة نسخ من ذلك التطبيق، ويتوقف عن إرسال حركة المرور إلى نسخة فشلت.
ذاكرة تخزين مؤقت. يخزّن استجابات المصدر على القرص ويجيب عن الطلبات المتكررة دون سؤال التطبيق مرة أخرى.
منهي TLS. يحمل الشهادات، ويتحدث HTTPS وHTTP/2 وHTTP/3 مع المتصفح، ويتحدث HTTP عاديًا مع التطبيق على عنوان خاص.
ما هو ليس إياه: خادم تطبيقات. لا يُنفّذ nginx كود PHP أو Python أو Ruby الخاص بك. يسلّم تلك الطلبات إلى عملية تفعل ذلك، ويعيد الرد.
مدفوع بالأحداث: لماذا يحتفظ nginx بهذا العدد من الاتصالات
عند بدء nginx، تقرأ عملية رئيسية (master process) الضبط، وتفتح منافذ الاستماع، وتبدأ عددًا قليلًا من عمليات العامل (worker processes)، عادةً واحدة لكل نواة معالج (worker_processes auto). العملية الرئيسية لا تخدم حركة المرور أبدًا. هي تدير العمال، وهي ما يجعل إعادة التحميل سَلِسة.
كل عامل أحادي الخيط ويشغّل حلقة أحداث (event loop). يسأل النواة، عبر epoll على Linux أو kqueue على BSD وmacOS، أيّ اتصالاته لديه شيء جاهز: طلب جديد، أو عميل يستطيع استقبال بايتات أكثر، أو مصدر (upstream) أجاب. يقوم بقطعة عمل قصيرة على كل اتصال جاهز وينتقل؛ لا شيء ينتظر. اتصال keep-alive خامل بين الطلبات، أو عميل جوّال بطيء يرسل طلبه بالتنقيط، يكلّف العامل كيلوبايتات قليلة من الذاكرة ولا وحدة معالجة مركزية.
نموذج Apache الكلاسيكي هو العكس. تمنح وحدة MPM prefork كل اتصال عمليته الخاصة، وتمنحه وحدة MPM worker خيطه الخاص، وتبقى تلك العملية أو الخيط مشغولة طوال مدة الاتصال، سواء كانت تعمل أو خاملة. عشرة آلاف اتصال keep-alive مفتوح تعني عشرة آلاف عملية أو خيط، بما يحمله ذلك من ذاكرة وتبديل سياق. وحدة MPM event الأحدث في Apache تضع اتصالات keep-alive الخاملة عند خيط مستمع واحد، ما يضيّق الفارق، لكن كل طلب نشط لا يزال يشغل خيطًا.
القاعدة الناتجة: لا يجوز لعامل أن يُحجَب أبدًا. العمل الذي يستغرق وقتًا حقًّا، مثل تشغيل PHP أو الاستعلام من قاعدة بيانات، يحدث في عملية أخرى، ويعامل nginx الرد كمجرد حدث آخر. مجموع السعة هو worker_processes × worker_connections، وعندما يتوسّط nginx، يستخدم كل عميل فتحتين من تلك الفتحات: واحدة إلى المتصفح، وواحدة إلى المصدر.
أعلى nginx.conf: عملية رئيسية واحدة، وعامل لكل نواة، وحلقة أحداث في كل منها
user www-data;
worker_processes auto; # one worker per CPU core
error_log /var/log/nginx/error.log warn;
events {
worker_connections 1024; # per worker: clients + upstream connections
}
http {
include mime.types;
sendfile on;
keepalive_timeout 65s;
include /etc/nginx/conf.d/*.conf; # one file per site
}
فيم يُستخدم nginx
في الممارسة، يقف nginx في أحد هذه المواضع، وغالبًا في عدة منها معًا.
تقديم موقع ثابت أو حزمة واجهة أمامية. حزمة React أو Vue أو Astro، أو وثائق، أو صفحة هبوط: ملفات على القرص وnginx أمامها، لا شيء آخر.
أمام PHP. تعمل WordPress وLaravel ومعظم تطبيقات PHP كـnginx بالإضافة إلى PHP-FPM. يقدّم nginx الصور وCSS وJavaScript بنفسه، ويمرر طلبات .php إلى FPM عبر مقبس Unix بـfastcgi_pass.
أمام خادم تطبيقات. خدمات Node.js، وPython (Gunicorn، Uvicorn)، وRuby (Puma)، وGo تستمع على منفذ محلي. يُنهي nginx HTTPS، ويستوعب العملاء البطيئين بتخزين الطلب مؤقتًا، ثم يحيله بـproxy_pass، فلا يرى التطبيق إلا طلبات سريعة وكاملة.
موازنة الأحمال عبر عدة نسخ من التطبيق، ويُغطّى باختصار أدناه.
TLS والبروتوكولات الحديثة لتطبيق لا يملك شيئًا منها: الشهادات (يحصل عليها معظم الناس بـcertbot وLet's Encrypt)، وHTTP/2 بـhttp2 on;، وHTTP/3 بـlisten 443 quic; على nginx 1.25 وما بعده. ما الذي تغيّره البروتوكولات موجود في HTTP/2 مقابل HTTP/3.
قواعد عند الباب: إعادة التوجيه، وتحديد معدل الطلبات بـlimit_req، وقوائم السماح والرفض بحسب IP، وضغط gzip، وترويسات الاستجابة. أي الترويسات تُرسل، ولماذا، موجود في ترويسات أمان HTTP.
كتلة server أدنى، سطرًا بسطر
كتلة server هي موقع واحد. يختارها nginx بحسب المنفذ الذي وصل عليه الطلب وبحسب ترويسة Host، مقارنة بـserver_name. وبداخلها، تطابق كتل location مسارات الروابط. الكتلة أدناه تقدّم موقعًا ثابتًا وتمرر /api/ إلى تطبيق على المنفذ 3000.
listen هو المنفذ، مرة لـIPv4 ومرة لـIPv6.
server_name يسرد أسماء المضيفين التي تجيب عنها هذه الكتلة. الطلب الذي لا يطابق Host خاصته أي كتلة يذهب إلى الخادم الافتراضي للمنفذ: الكتلة المعلّمة بـdefault_server، أو أول كتلة قرأها nginx إن لم توجد. لهذا يُظهر اسم مضيف غير معروف موجَّه إلى عنوان IP الخاص بك موقعًا آخر. كتلة شاملة تجيب بـreturn 444; (إغلاق الاتصال) تمنع ذلك.
root هو المكان الذي تُبحث فيه الملفات: يصبح /about.html هو /var/www/example/about.html.
try_files يحاول الملف، ثم مجلدًا، ثم الحل الاحتياطي. لتطبيق صفحة واحدة (SPA)، استبدل =404 بـ/index.html كي تُحمَّل مسارات جانب العميل من داخل التطبيق.
مطابقة location لها ترتيب يفاجئ الناس. المطابقة التامة (=) تفوز مباشرة. وإلا يتذكر nginx أطول بادئة مطابقة، ثم يجرّب التعبيرات النمطية (~، ~*) بترتيب الملف ويأخذ أول ما يطابق؛ ولا تُستخدم البادئة المتذكَّرة إلا إن لم يطابق شيء. البادئة ^~ تتجاوز خطوة التعبيرات النمطية. في هذا المثال يُقدَّم /api/logo.png بتعبير الصور النمطي، لا بـ/api/، وهذا هو الجواب المعتاد لسؤال "لماذا تُتجاهَل location خاصتي".
expires يضبط Cache-Control: max-age وExpires على الأصول ذات البصمة. اختر القيم بمساعدة دليل Cache-Control.
هذه الكتلة HTTP عادي. أضِف الشهادة بـcertbot، الذي يعدّل الكتلة من أجلك، وأعِد توجيه المنفذ 80 إلى 443.
/etc/nginx/conf.d/example.conf: موقع ثابت مع واجهة برمجية خلفه
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;
location / {
try_files $uri $uri/ =404;
}
location ~* \.(?:css|js|woff2|png|jpg|webp|avif|svg)$ {
expires 30d;
access_log off;
}
location /api/ {
proxy_pass http://127.0.0.1:3000;
# plus the forwarded headers from the reverse proxy guide
}
}
التثبيت والاختبار وإعادة التحميل: الأوامر التي تستخدمها كل يوم
تضع حزم التوزيعات الملف الرئيسي في /etc/nginx/nginx.conf. يحتفظ Debian وUbuntu بالمواقع في /etc/nginx/sites-available/ ويفعّلانها برابط رمزي داخل sites-enabled/؛ وتقرأ RHEL وRocky وAlpine وحزم nginx.org من /etc/nginx/conf.d/*.conf. تذهب السجلات إلى /var/log/nginx/.
عادتان تمنعان معظم الأعطال التي تُسبّبها بنفسك. شغّل nginx -t قبل كل إعادة تحميل: يحلّل الضبط كاملًا ويسمّي ملف وسطر أي خطأ. وأعد التحميل بدل إعادة التشغيل. عند إعادة التحميل تبدأ العملية الرئيسية عمالًا جددًا بالضبط الجديد وتترك القدامى يُنهون طلباتهم المفتوحة، فلا يُقطع أي اتصال؛ وإن لم يُحمَّل الضبط الجديد، تحتفظ العملية الرئيسية بالعمال القدامى عاملين وتسجّل السبب.
تطبع nginx -T الضبط الكامل كما يراه nginx، بكل include مُوسَّع. وعندما يبدو أن إعدادًا بلا أثر، فعادةً ما يكون مُتجاوَزًا في ملف نسيته، وتُظهر لك -T أيّه.
# Debian / Ubuntu
sudo apt install nginx
nginx -v # version; -V adds build options and modules
# check the syntax, then apply without dropping connections
sudo nginx -t && sudo systemctl reload nginx
# the whole effective configuration, includes expanded
sudo nginx -T | less
# which names and ports are configured
sudo nginx -T | grep -E '^\s*(server_name|listen)'
# watch errors while you test
sudo tail -f /var/log/nginx/error.log
nginx مقابل Apache
كلاهما ناضج ومجاني وسريع بما يكفي لأي موقع تقريبًا. الفروق التي تحسم الاختيار فعليًا:
نموذج الاتصال. تحتفظ حلقة أحداث nginx بالاتصالات الخاملة والبطيئة تقريبًا بلا تكلفة؛ يربط Apache عملية أو خيطًا بكل طلب نشط، وخارج وحدة MPM event بكل اتصال خامل أيضًا. مع كثير من اتصالات keep-alive المتزامنة يستخدم nginx ذاكرة أقل بكثير.
الضبط. مع تفعيل AllowOverride، يقرأ Apache ملفات .htaccess من كل مجلد على مسار كل طلب، فيستطيع المستخدم تغيير القواعد دون لمس ضبط الخادم. لا يملك nginx نظيرًا لذلك: كل قاعدة تعيش في الضبط المركزي وتُحلَّل مرة واحدة عند التحميل. هذا أسرع وأسهل تدقيقًا، لكن ملف .htaccess لـWordPress أو Laravel يجب إعادة كتابته كقواعد location وtry_files عند الانتقال.
PHP. يستطيع Apache تشغيل PHP داخل عملياته الخاصة بـmod_php؛ بينما يتحدث nginx دائمًا مع مجمع PHP-FPM منفصل. كثير من إعدادات Apache الحالية تستخدم PHP-FPM أيضًا، فهذا الآن فرق في الإعدادات الافتراضية أكثر من كونه فرقًا جوهريًا.
الوحدات. يحمّل Apache الوحدات وقت التشغيل من فهرس كبير جدًا. يدعم nginx الوحدات الديناميكية، لكن يجب بناء كل وحدة مقابل إصدار nginx الذي تشغّله بالضبط، فكثير من الإضافات يعني الترجمة.
الملفات الثابتة والتوكيل هما المجالان اللذان يتفوق فيهما nginx. لهذا يضع الهجين الشائع nginx في المقدمة، يقدّم الملفات ويُنهي TLS، وApache خلفه يشغّل تطبيقًا يعتمد على .htaccess.
الخلاصة الصادقة: عند البدء من الصفر، nginx هو الخيار الافتراضي لمعظم الفرق. لكن استبدال Apache عامل لن يجعل موقعًا بطيئًا سريعًا. الجزء البطيء هو التطبيق أو المسافة إلى الزائر تقريبًا دومًا، لا خادم الويب.
وكيل عكسي، موازن أحمال، وذاكرة تخزين مؤقت: النسخة المختصرة
التوكيل توجيه واحد، proxy_pass، بالإضافة إلى الترويسات التي تخبر التطبيق من هو العميل فعليًا. تلك الترويسات، ودعم WebSocket، وproxy_cache مشروحة في دليل الوكيل العكسي، فلا تكرّرها هذه الصفحة.
تضيف موازنة الأحمال كتلة upstream تسمّي الخوادم. الافتراضي هو Round Robin. يرسل least_conn كل طلب إلى الخادم ذي أقل الاتصالات النشطة، وهذا يناسب الطلبات ذات الطول المتفاوت، ويحافظ ip_hash أو hash على العميل عند الخادم نفسه. فحص الصحة في nginx مفتوح المصدر سلبي: بعد max_fails فشلًا خلال fail_timeout، يُتجاوز خادم طوال تلك المدة، ويعيد proxy_next_upstream محاولة الطلب على خادم آخر. الفحوص النشطة التي تستجوب رابطًا على جدول زمني ميزة في NGINX Plus. للصورة الأوسع انظر ما الذي يفعله موازن الأحمال.
التخزين المؤقت يعمل جيدًا، مع ثغرة واحدة يجب معرفتها مسبقًا: لا يملك nginx مفتوح المصدر أمرًا لإفراغ (purge) رابط مخزَّن. تنتظر انتهاء صلاحية المدخلة أو تحذف الملفات من مجلد التخزين المؤقت على كل خادم. هذه الثغرة من أكثر الأسباب شيوعًا لنقل الفرق التخزينَ المؤقت العام إلى CDN.
ثلاثة خوادم تطبيقات خلف nginx واحد
upstream app {
least_conn;
server 10.0.0.11:3000 max_fails=3 fail_timeout=10s;
server 10.0.0.12:3000 max_fails=3 fail_timeout=10s;
server 10.0.0.13:3000 backup; # used only when the others are down
keepalive 32; # reuse connections to the app
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Connection ""; # required for upstream keepalive
proxy_next_upstream error timeout http_502;
# plus the forwarded headers from the reverse proxy guide
}
}
502 و504 و413: ما الذي يقوله nginx لك
رمز الحالة الذي يراه الزائر هو الملخص؛ سجل الأخطاء هو التفسير. يترك كل من هذه الأخطاء سطرًا مميزًا هناك.
502 Bad Gateway يعني أن nginx لم يحصل على رد صالح من المصدر. connect() failed (111: Connection refused) يعني أن لا شيء يستمع على العنوان في proxy_pass: التطبيق متوقف أو على منفذ آخر. وconnect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) هو مسار مقبس PHP-FPM لا يطابق إصدار PHP المثبَّت، و(13: Permission denied) على السطر نفسه هو مقبس لا يستطيع مستخدم nginx فتحه. upstream prematurely closed connection يعني أن التطبيق تعطّل أو قُتل في منتصف الطلب؛ اقرأ سجله الخاص ورسائل نفاد الذاكرة من النواة. upstream sent too big header يعني أن ترويسات الاستجابة، غالبًا كومة من ملفات تعريف الارتباط، لا تناسب المخزن المؤقت: رفع proxy_buffer_size، أو fastcgi_buffer_size لـPHP. التشخيص الكامل، بما فيه حالة وجود CDN أمامه، في 502 Bad Gateway.
504 Gateway Timeout يعني أن المصدر قبِل الطلب ولم يُجب خلال proxy_read_timeout (أو fastcgi_read_timeout)، وقيمته الافتراضية 60 ثانية. يقول السجل upstream timed out (110: Connection timed out) while reading response header from upstream. مهلة أطول مناسبة لتصدير أو تقرير معروف ببطئه؛ أما للصفحات العادية فهي تخفي فقط استعلامًا بطيئًا أو مجمع عمال ممتلئًا. كل وكيل في السلسلة له حده الخاص، فقد يستسلم موازن أحمال أو CDN أمامه قبل nginx نفسه.
413 Request Entity Too Large يعني أن جسم الطلب أكبر من client_max_body_size، وقيمته الافتراضية 1 ميغابايت: الصورة أو نسخة النسخ الاحتياطي الكلاسيكية الفاشلة. يقول السجل client intended to send too large body. رفع الحد في server أو location التي تستقبل الرفع بدل أن تفعل ذلك عامًا، ولـPHP رفع upload_max_filesize وpost_max_size ليطابقا، وإلا رفض PHP ما سمح له nginx بالعبور.
503 من nginx غالبًا ما يكون limit_req أو limit_conn الخاص به يرفض طلبًا؛ هذا والأسباب الأخرى في 503 Service Unavailable. وdirectory index of "/var/www/..." is forbidden هو 403 لمجلد بلا ملف فهرسة، مشروح في 403 Forbidden.
أسطر سجل الأخطاء والتوجيه الذي يشير إليه كل منها
# /var/log/nginx/error.log (abridged)
connect() failed (111: Connection refused) while connecting to upstream -> 502
upstream prematurely closed connection while reading response header -> 502
upstream sent too big header while reading response header from upstream -> 502
upstream timed out (110: Connection timed out) while reading response header -> 504
client intended to send too large body: 52428800 bytes -> 413
# the matching fixes, in the server or location that needs them
client_max_body_size 64m; # PHP: raise upload_max_filesize and post_max_size too
proxy_read_timeout 300s; # only for a known slow endpoint
proxy_buffer_size 16k; # large response headers and cookies
proxy_buffers 8 16k;
متى تضع CDN أمام nginx
يخدم nginx واحد حركة مرور كثيرة. ما لا يستطيع تغييره هو مكانه. الزائر في بلد آخر ينتظر في كل رحلة ذهاب وعودة إلى مركز بياناتك الواحد؛ وذروة حركة مرور معظمها طلبات متكررة لا تزال تصل إلى جهازك الواحد؛ وهجوم يستهدف عنوان IP الخاص بك يصل إلى الخادم الذي يشغّل موقعك. هذه هي اللحظات لإضافة CDN: جمهورك بعيد عن الخادم، وحركة المرور القابلة للتخزين المؤقت حصة كبيرة من الحمل، وتحتاج إفراغ التخزين المؤقت على أكثر من جهاز، أو ينبغي أن يتوقف المصدر عن كونه قابلًا للوصول إليه مباشرة.
تحتفظ بـnginx؛ وظيفته تتغيّر. يصبح CDN الباب الأمامي العام ويصبح nginx المصدر (origin)، يقدّم الملفات ويوجّه إلى التطبيق بينما تتولى الحافة المسافة والتخزين المؤقت والتصفية. ثلاثة أشياء يجب ضبطها من جهة nginx. أرسل ترويسات Cache-Control صحيحة، لأن الحافة تتبعها. استعِد عنوان IP الخاص بالزائر بوحدة realip (set_real_ip_from لعناوين CDN، وreal_ip_header للترويسة التي يرسلها)، وإلا رأى كل سطر سجل وكل منطقة limit_req الحافةَ بدل الزائر. ولا تسمح إلا لـCDN بالوصول إلى المصدر، كي لا تستطيع الهجمات تجاوزه.
تعمل حافة CDN.com.tr على nginx نفسه: يطبّق ضبطها حجم ملف باقتك كـclient_max_body_size، فالرفع الذي يعبر CDN يحتاج ذلك الحد كبيرًا بما يكفي أيضًا، لا حدّك الخاص وحده. أمام مصدرك، تخزّن شبكة الحافة، بخوادم في تركيا وخارجها، مؤقتًا بحسب قواعد تسليم لكل مسار، وتُفرَغ فورًا بمسار أو مجلد محدد من اللوحة أو سطر أوامر cdnctl أو REST API. يعمل WAF، وحماية DDoS، وحماية البوتات بتحدٍّ JavaScript، وقواعد البلد وIP، وتحديد معدل الطلبات قبل أن يصل الطلب إلى خادمك، وتُصدر وتُجدَّد شهادات Let's Encrypt لكل نطاق متصل.
تفصيلان يجعلان التحقق من الانتقال أسهل. تبقى الصفحات الموجودة أصلًا في ذاكرة الحافة المؤقتة تُقدَّم بينما مصدرك متوقف، وتُظهر ترويسة الاستجابة X-Proxy-Cache-MT قيمة HIT أو MISS، فتستطيع معرفة هل وصل طلب إلى nginx خاصتك أصلًا. وترسل الحافة أيضًا SNI إلى المصدر، فيعرض nginx بعدة كتل server من HTTPS الشهادة الصحيحة.
أسئلة شائعة حول nginx
كيف يُنطَق nginx؟
"إنجن إكس". يُستخدم nginx وNGINX كلاهما؛ والصيغة بحروف صغيرة هي اسم المشروع مفتوح المصدر وملفه التنفيذي.
هل nginx مجاني؟
النسخة مفتوحة المصدر من nginx.org مجانية بترخيص BSD من نوع two-clause، حتى للاستخدام التجاري. وNGINX Plus اشتراك مدفوع من F5 يضيف فحوص صحة نشطة، وواجهة برمجية لإفراغ التخزين المؤقت وتغيير المصادر وقت التشغيل، ولوحة حالة مباشرة، ودعمًا.
هل nginx خادم ويب أم وكيل عكسي؟
كلاهما، غالبًا في الضبط نفسه. location بـroot يقدّم الملفات من القرص، وواحدة بـproxy_pass أو fastcgi_pass تسلّم الطلب إلى تطبيق. تفعل معظم المواقع كليهما: الأصول الثابتة مباشرة، وكل ما هو ديناميكي عبر الوكيل.
هل nginx أفضل من Apache؟
للملفات الثابتة والتوكيل وأعداد كبيرة من الاتصالات المتزامنة يستخدم ذاكرة أقل، وهو الخيار المعتاد للإعدادات الجديدة. يناسب Apache أكثر عندما تعتمد على .htaccess أو وحدة خاصة بـApache فقط. لموقع نموذجي، لا خادم الويب هو عنق الزجاجة؛ بل التطبيق والمسافة إلى الزوار.
لماذا يُظهر نطاقي موقعًا آخر على nginx؟
لم يطابق أي server_name ترويسة Host في الطلب، فاستخدم nginx الخادم الافتراضي لذلك المنفذ: الكتلة المعلّمة بـdefault_server، أو أول ما حمّله. تحقق من الأسماء بـnginx -T | grep server_name، وأضِف كتلة شاملة تُرجع 444 كي لا يحصل المضيفون غير المعروفون على شيء.
هل أحتاج nginx إن استخدمت CDN؟
عادة نعم، كمصدر: ما زال يجب أن يقدّم شيء الملفات ويوجّه الطلبات إلى تطبيقك، وCDN يسحب منه. على تطبيقات حاويات CDN.com.tr تستطيع تجاوزه للنشر، لأن الحافة تصل إلى كل تطبيق عبر مسار منصة داخلي بلا حاوية وكيل عكسي بينهما.