# نقطة واحدة لكل الخدمات الطلبية — التطبيق يغيّر الدومين فقط: # /backend/... → الباك إند الرئيسي (نفس شكل مسارات jordan-siro) # /v2/main/... → خادم المدفوعات # السوكيتات تُنشر مباشرة من حاوياتها (2020 / 3030) — لا تمر من هنا. # ‏مُحلِّل أسماء دوكر المدمج. سببه عطل حقيقي دام أياماً: # # ‏nginx يترجم اسم الـ upstream المكتوب حرفياً في fastcgi_pass **مرة واحدة** # ‏عند تحميل الإعدادات ثم يحتفظ بالعنوان إلى الأبد. وحين أُعيد إنشاء حاوية # ‏php_food انتقلت من 172.24.0.9 إلى 172.24.0.10، بينما بقي nginx يطرق # ‏العنوان القديم — فكل طلبات الطعام تردّ 502 «Connection refused» # ‏والحاوية سليمة تماماً وسجلّها صامت لأن الطلبات لا تصلها أصلاً. تشخيصٌ # ‏مضلِّل إلى أبعد حدّ: كل ما تفحصه يبدو صحيحاً. # # ‏العلاج: تمرير الوجهة عبر متغيّر. عندها يؤجّل nginx الترجمة إلى وقت # ‏الطلب ويستعملُ هذا الـ resolver، فيلتقط أي عنوان جديد خلال 10 ثوانٍ. # ‏فائدة ثانية: بالمتغيّر لا يسقط إقلاع nginx إذا كانت الحاوية الهدف # ‏متوقفة — كان يرفض الإقلاع كلياً فيُسقط الموقع بأسره. resolver 127.0.0.11 valid=10s ipv6=off; server { listen 80; server_name _; root /var/www; index index.php index.html; client_max_body_size 25m; # ‏وجهات fpm كمتغيّرات — انظر تعليق الـ resolver أعلاه. set $upstream_php php:9000; set $upstream_php_food php_food:9000; set $upstream_php_transit php_transit:9000; # ‏عنوان العميل الحقيقي. # ‏السلسلة هي: العميل ← nginx المضيف (CloudPanel) ← nginx الحاوية ← php-fpm، # ‏فكان REMOTE_ADDR يصل إلى PHP دائماً كعنوان الوسيط (172.24.0.1). والنتيجة # ‏أن RateLimiter يضع كل المستخدمين في دلو واحد: محاولات دخول فاشلة من عميل # ‏واحد كانت تحجب الجميع بـ 429 (ظهر ذلك في السجل فعلاً). # ‏نمرّر السلسلة إلى PHP ليقرأها عبر clientIp() في core/helpers.php. set $siro_fwd $http_x_forwarded_for; if ($siro_fwd = "") { set $siro_fwd $remote_addr; } fastcgi_param HTTP_X_FORWARDED_FOR $siro_fwd; fastcgi_param HTTP_X_REAL_IP $remote_addr; # ‏كان access_log off من اختبار ضغط قديم ونُسي مُطفأً، فصار تشخيص أي عطل # ‏مستحيلاً: البحث في سجلّ الوصول يرجع صفراً دائماً فيبدو أن التطبيق لا # ‏يستدعي المسار أصلاً، والحقيقة أن السجلّ فارغ لا الطلبات. أعِده مطفأً # ‏مؤقتاً وقت اختبارات الضغط فقط، ولا تتركه هكذا. access_log /dev/stdout; error_log /dev/stderr warn; # Mawasalati (transit) — حاوية php-fpm معزولة عن الباك إند الرئيسي. # يجب أن يسبق location ~ \.php$ العام حتى لا يلتقطه أولاً. location ~ ^/backend/transit/.*\.php$ { try_files $uri =404; include fastcgi_params; fastcgi_pass $upstream_php_transit; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_read_timeout 60s; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; } # طلبات الطعام — حاوية php-fpm معزولة عن الباك إند الرئيسي. # يجب أن يسبق location ~ \.php$ العام حتى لا يلتقطه أولاً. location ~ ^/backend/food/.*\.php$ { try_files $uri =404; include fastcgi_params; fastcgi_pass $upstream_php_food; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_read_timeout 60s; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; } location ~ \.php$ { try_files $uri =404; include fastcgi_params; fastcgi_pass $upstream_php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_read_timeout 60s; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; } # حالة حوض fpm — من داخل شبكة الحاويات أو من السيرفر نفسه فقط location = /fpm-status { allow 172.16.0.0/12; allow 127.0.0.1; deny all; include fastcgi_params; fastcgi_pass $upstream_php; fastcgi_param SCRIPT_NAME /status; fastcgi_param SCRIPT_FILENAME /status; } location /dashboard/siro-admin { alias /var/www/dashboard/siro-admin; index index.html; try_files $uri $uri/ /dashboard/siro-admin/index.html; } location /dashboard/admin { alias /var/www/dashboard/siro-admin; index index.html; try_files $uri $uri/ /dashboard/admin/index.html; } location /dashboard/siro-service { alias /var/www/dashboard/siro-service; index index.html; try_files $uri $uri/ /dashboard/siro-service/index.html; } location /dashboard/service { alias /var/www/dashboard/siro-service; index index.html; try_files $uri $uri/ /dashboard/service/index.html; } location / { try_files $uri $uri/ =404; } }