Update codebase
This commit is contained in:
+53
-15
@@ -1,13 +1,13 @@
|
||||
# ============================================================
|
||||
# Siro Docker Environment Variables
|
||||
# Tripz Docker Environment Variables
|
||||
# ============================================================
|
||||
|
||||
# --- 1. Core Settings ---
|
||||
PHP_VERSION=8.2
|
||||
HTTP_PORT=8183
|
||||
APP_DOMAIN=api.tripz-egypt.com
|
||||
APP_ISSUER=SiroApp
|
||||
APP_DEBUG=true
|
||||
APP_ISSUER=TripzApp
|
||||
APP_DEBUG=false
|
||||
APP_COUNTRY=Jordan
|
||||
APP_CURRENCY=JOD
|
||||
|
||||
@@ -46,6 +46,14 @@ DB_TRANSIT_NAME=transitDB
|
||||
DB_TRANSIT_USER=transitUser
|
||||
DB_TRANSIT_PASS=Tr4ns!t_Tr!pz_P@ss2026
|
||||
|
||||
# قاعدة طلبات الطعام — منفصلة عن بقية القواعد (انظر mysql/init/06-foodDB.sql)
|
||||
DB_FOOD_HOST=mysql
|
||||
DB_FOOD_PORT=3306
|
||||
DB_FOOD_NAME=tripz_food
|
||||
DB_FOOD_USER=tripz_food
|
||||
# ⚠️ يجب أن تطابق mysql/init/06-foodDB.sql — غيّرها قبل الإقلاع الأول.
|
||||
DB_FOOD_PASS=CHANGE_ME_STRONG_PASSWORD
|
||||
|
||||
# --- 3. Redis ---
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
@@ -62,6 +70,13 @@ RIDE_SOCKET_URL=http://socket_passenger:3031
|
||||
# وهو داخل حاوية socket_driver يشير لنفسها، فلا يصل الراكب أي تحديث موقع.
|
||||
PASSENGER_SOCKET_INTERNAL_URL=http://socket_passenger:3031
|
||||
|
||||
# --- 4.5 Host Socket Ports (على سيرفر مشترك مع نسخ أخرى) ---
|
||||
# siro يحجز: 12020/13030/14040 · intaleq يحجز: 12032/13032
|
||||
# تربز يعمل على المنافذ التالية — لا تغيّرها إلا بعد التحقق من ss -tlnp
|
||||
DRIVER_SOCKET_PORT=12022
|
||||
PASSENGER_SOCKET_PORT=13033
|
||||
FOOD_SOCKET_PORT=14042
|
||||
|
||||
# --- 5. External Sockets & URLs ---
|
||||
LOCATION_SOCKET_URL=http://socket_driver:2021
|
||||
PASSENGER_SOCKET_URL=http://socket_passenger:3031
|
||||
@@ -95,6 +110,20 @@ WALLET_SECRET_KEY_PATH=/keys/.secret_key_pay
|
||||
ENCRYPTION_KEY_PATH=/keys/.enckey
|
||||
PAYMENT_INTERNAL_KEY_PATH=/keys/.internal_socket_key
|
||||
|
||||
# --- 6.b خادم TURN (مكالمات الصوت: الرحلات + توصيل الطعام) ---
|
||||
# ⚠️ منافذ TURN مختلفة عن نسخة سيرو على نفس السيرفر:
|
||||
# سيرو: 3478 / relay 49160–49300 · تربز هنا: 3479 / relay 49301–49400
|
||||
TURN_HOST=turn.api.tripz-egypt.com
|
||||
TURN_EXTERNAL_IP=
|
||||
TURN_REALM=api.tripz-egypt.com
|
||||
TURN_PORT=3479
|
||||
# لا تجعلها true إلا بعد تركيب شهادة TLS فعلياً على coturn (انظر turnserver.conf)
|
||||
TURN_TLS_ENABLED=false
|
||||
TURN_TLS_PORT=5350
|
||||
TURN_SECRET_PATH=/keys/turn_secret
|
||||
TURN_STATIC_AUTH_SECRET=
|
||||
TURN_CREDENTIAL_TTL=43200
|
||||
|
||||
# --- 7. Third-Party APIs ---
|
||||
GEMINI_API_KEY=AIzaSyDHp0yXCGWqnd4ynlCCWzDz9Un1EJOKeW8
|
||||
SMS_API_ENDPOINT=https://sms.kazumi.me/api/sms/send-sms
|
||||
@@ -122,28 +151,37 @@ APP_SIGNATURE_SERVICE_IOS=com.example.serviceIntaleq
|
||||
# --- 9. Nabeh & Transit & Commisions ---
|
||||
NABEH_EMAIL=hamza@test.com
|
||||
NABEH_PASSWORD=Test1234!
|
||||
NABEH_API_KEY=siro_integration_key_789
|
||||
NABEH_API_KEY=tripz_integration_key_789
|
||||
NABEH_OTP_APP_KEY=f3a9e7c1b8d5f2a4c6e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1
|
||||
|
||||
VITE_API_BASE=https://jordan-siro.intaleqapp.com/backend/transit
|
||||
VITE_API_BASE=https://api.tripz-egypt.com/backend/transit
|
||||
TRANSIT_STUDENT_ID_KEY=zH34tS6xMMSamq6uqv1WZWlDrmjAbnMk
|
||||
TRANSIT_ADMIN_ORIGINS=https://transit.siromove.com,https://admin.siromove.com
|
||||
APP_DEEP_LINK_BASE=https://siromove.com/driver/transit-activate
|
||||
TRANSIT_ADMIN_ORIGINS=https://transit.tripz-egypt.com,https://admin.tripz-egypt.com
|
||||
APP_DEEP_LINK_BASE=https://api.tripz-egypt.com/driver/transit-activate
|
||||
|
||||
SIRO_COMMISSION_JO=0.15
|
||||
SIRO_COMMISSION_SY=0.12
|
||||
SIRO_COMMISSION_EG=0.10
|
||||
SIRO_COMMISSION_IQ=0.14
|
||||
TRIPZ_COMMISSION_JO=0.15
|
||||
TRIPZ_COMMISSION_SY=0.12
|
||||
TRIPZ_COMMISSION_EG=0.10
|
||||
TRIPZ_COMMISSION_IQ=0.14
|
||||
|
||||
# --- 9.b Food Orders (طلبات الطعام) ---
|
||||
FOOD_ENABLED=true
|
||||
FOOD_SOCKET_URL=http://socket_food:4041
|
||||
FOOD_SOCKET_PORT=14042
|
||||
FOOD_MERCHANT_ORIGINS=https://food-merchant.tripz-egypt.com,https://admin.tripz-egypt.com
|
||||
FOOD_COMMISSION_PERCENT=15
|
||||
FOOD_DELIVERY_BASE_FEE=
|
||||
FOOD_MAX_ACTIVE_ORDERS_PER_USER=3
|
||||
|
||||
# --- 10. Admin & Access ---
|
||||
ADMIN_TOOL_IPS=92.241.36.211,92.241.36.165,92.241.37.3
|
||||
ALLOWED_UPLOAD_HOST=siromove.com
|
||||
ALLOWED_TESTER_EMAILS=driver_tester@siromove.com,passenger_tester@siromove.com
|
||||
ALLOWED_UPLOAD_HOST=api.tripz-egypt.com
|
||||
ALLOWED_TESTER_EMAILS=driver_tester@tripz-egypt.com,passenger_tester@tripz-egypt.com
|
||||
# ⚠️ لازم يغطّي كل قيمة في القسم 4/5 أعلاه: isAllowedSocketUrl() تعمل
|
||||
# str_starts_with، وأي عنوان غير مغطّى تُسقَط رسائله (بلا أي أثر قبل هذا الإصلاح).
|
||||
# أسماء حاويات Docker إجبارية هنا — لا تحذفها واستبدلها بالـ IP فقط.
|
||||
ALLOWED_SOCKET_URLS=http://socket_driver,http://socket_passenger,http://nginx,http://188.68.36.205:2021,http://188.68.36.205:3031,https://location.intaleq.xyz
|
||||
ALLOWED_ORIGIN=https://siromove.com
|
||||
ALLOWED_SOCKET_URLS=http://socket_driver,http://socket_passenger,http://socket_food,http://nginx
|
||||
ALLOWED_ORIGIN=https://api.tripz-egypt.com
|
||||
ADMIN_PHONE_NUMBERS=963992952235,963942542053,962772735902
|
||||
SERVICE_PHONE1=963952475740
|
||||
SERVICE_PHONE2=963952475742
|
||||
|
||||
+40
-50
@@ -1,20 +1,24 @@
|
||||
# سيرو في حاويات — دليل التشغيل والفحص
|
||||
# تربز في حاويات — دليل التشغيل والفحص
|
||||
|
||||
> الهدف: نسخة سيرو كاملة على سيرفر واحد داخل compose واحدة، والتطبيق لا يتغير فيه
|
||||
> شيء سوى الـ base URLs (تُبنى مرة واحدة بـ `.env` الجديد — envied وقت الترجمة).
|
||||
> القرارات والأسباب في `Tripz/docs/30-siro-port-plan.md` §5.
|
||||
> الهدف: نسخة تربز كاملة على سيرفر واحد داخل compose واحدة، والتطبيق لا يتغير
|
||||
> فيه شيء سوى الـ base URLs (تُبنى مرة واحدة بـ `.env` الجديد).
|
||||
>
|
||||
> البورتات مخصصة لتربز ولا تتصادم مع نسخ سيرو/intaleq على السيرفر نفسه:
|
||||
> HTTP 8183 · driver 12022 · passenger 13033 · food 14042 · mysql 33063 · pma 8084 · TURN 3479
|
||||
|
||||
## 0) قبل أي شيء — على السيرفر
|
||||
```bash
|
||||
df -h / # ⚠️ الصندوق المشترك مزمنياً ~90% ممتلئ — الصور والقواعد تحتاج ~4-6GB
|
||||
df -h / # التأكد من المساحة — الصور والقواعد تحتاج ~4-6GB
|
||||
docker image prune -f # نظّف أولاً، وإن لم تكفِ المساحة فالفحص على صندوق آخر
|
||||
ss -tlnp | grep -E ':(1202|1303|1404|3306|3478|808)[0-9]' # تأكد الفارغة
|
||||
```
|
||||
|
||||
## 1) الإعداد (مرة واحدة)
|
||||
```bash
|
||||
cd /path/to/Siro/docker
|
||||
cp .env.example .env && nano .env # املأ الأسرار من قيم اللايف — خاصة JWT_SECRET وكلمات MySQL
|
||||
# ⚠️ طابق أسماء القواعد في mysql/init/00-databases.sql مع ما يتوقعه الكود
|
||||
cd /path/to/Tripz/docker
|
||||
cp .env.example .env && nano .env # املأ الأسرار — خاصة JWT_SECRET وكلمات MySQL
|
||||
# ⚠️ طابق أسماء القواعد في mysql/init/ مع ما يتوقعه الكود
|
||||
# ⚠️ توجد قاعدة طعام منفصلة tripz_food (06-foodDB.sql) — اضبط DB_FOOD_PASS
|
||||
docker compose build
|
||||
# تبعيات composer للخدمات التي لا تحمل vendor/ داخلها:
|
||||
docker compose run --rm socket_driver composer install
|
||||
@@ -26,54 +30,40 @@ docker compose run --rm --workdir /var/www/backend php composer install
|
||||
```bash
|
||||
docker compose up -d
|
||||
# استيراد السكيمات (أول مرة فقط):
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" siro_primary < ../backend/schema_primary.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" siro_ride < ../backend/schema_ride.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" siro_tracking < ../backend/schema_tracking.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" siro_wallet < ../payment_server/WalletDB.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" siro_location < ../loction_server/locationDB.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" mainDB < ../backend/schema_primary.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" ridesDB < ../backend/schema_ride.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" locationDB < ../backend/schema_tracking.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" paymentDB < ../payment_server/WalletDB.sql
|
||||
docker compose exec -T mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" locationDB < ../loction_server/locationDB.sql
|
||||
```
|
||||
|
||||
## 3) التحقق
|
||||
```bash
|
||||
docker compose ps # الست خدمات up
|
||||
curl -s http://localhost:8080/backend/index.html # nginx→ملفات
|
||||
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8080/backend/connect.php # يرد (401/400 طبيعي بلا JWT)
|
||||
curl -s http://localhost:8080/fpm-status # حالة حوض fpm
|
||||
docker compose ps # كل الخدمات up
|
||||
curl -s http://localhost:8183/backend/index.html # nginx→ملفات
|
||||
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8183/backend/connect.php # يرد (401/400 طبيعي بلا JWT)
|
||||
curl -s http://localhost:8183/fpm-status # حالة حوض fpm
|
||||
docker compose logs socket_driver | tail # Workerman أقلع على 2020/2021
|
||||
docker compose logs socket_food | tail # سوكيت الطعام على 4040
|
||||
```
|
||||
اتصال التطبيق للتجربة: `http://IP:8080/backend` + سوكيت `http://IP:2020` — فقط بدّل
|
||||
الـ base URLs في `.env` تبع التطبيق وأعد البناء. `APP_DOMAIN` فارغ = حارس
|
||||
REGION_MISMATCH متعطل أثناء التجربة.
|
||||
اتصال التطبيق للتجربة: `https://api.tripz-egypt.com/backend` + سوكيتات
|
||||
`https://api.tripz-egypt.com:2020` / `:3030` / `:4040` (منفذة TLS عبر
|
||||
`/etc/nginx/sites-enabled/tripz-sockets-tls.conf` على المضيف).
|
||||
|
||||
## 4) اختبار الضغط (الهدف: 10-20 ألف رحلة/ساعة)
|
||||
```bash
|
||||
cd ../stress_test && npm install
|
||||
# دخان أولاً (الأداة القديمة، دفعة صغيرة):
|
||||
node load_test.js --trips=10 -b http://localhost:8080/backend -s http://localhost:2020
|
||||
# ثم المعدل المستمر:
|
||||
node rate_test.js --rate 10000 --duration 10 -b http://localhost:8080/backend -s http://localhost:2020
|
||||
node rate_test.js --rate 20000 --duration 10 -b http://localhost:8080/backend -s http://localhost:2020
|
||||
node rate_test.js --rate 30000 --duration 5 ... # حد الانهيار — أين تبدأ p95 بالقفز؟
|
||||
```
|
||||
**أثناء التشغيل راقب من طرفية ثانية:**
|
||||
```bash
|
||||
docker stats # cpu/ذاكرة كل حاوية
|
||||
docker compose exec mysql sh -c 'tail -f /var/lib/mysql/slow.log' # استعلامات >200ms
|
||||
watch -n2 'curl -s http://localhost:8080/fpm-status' # طابور fpm (listen queue)
|
||||
```
|
||||
## 4) الخدمات المنفصلة (transit / food / TURN)
|
||||
- **php_transit** — حوض fpm معزول (16 عاملاً) يخدم `/backend/transit/*` فقط.
|
||||
- **php_food** — حوض fpm معزول (24 عاملاً) يخدم `/backend/food/*` فقط،
|
||||
وقاعدة `tripz_food` منفصلة.
|
||||
- **socket_food** — سوكيت الطعام على 127.0.0.1:14042 (يفسد من المضيف على 4040).
|
||||
- **coturn** — مكالمات الصوت على TCP/UDP 3479 + نطاق 49301–49400 UDP
|
||||
(افتحهما على جدار الحماية؛ النطاق 49160–49300 محجوز لنسخة سيرو).
|
||||
|
||||
### قواعد قراءة النتيجة بصدق
|
||||
1. **سيناريو الاختبار أخف من الرحلة الحقيقية بـ 3-5×** (4 نداءات API + 6 نبضات موقع؛
|
||||
الحقيقية فيها تسعير وبحث وقرب ودردشة). لتبنّي رقم "10k رحلة حقيقية بالذروة"
|
||||
يجب أن يعبر الاختبار **30k** بنجاح >99% و p95<500ms.
|
||||
2. الصندوق مشغول ~40% بغيرنا — **افحص خارج الذروة وبجولات قصيرة (5-10 د)**،
|
||||
وأعد الجولة مرتين للتأكد من ثبات الرقم.
|
||||
3. مولّد الحمل على نفس الصندوق يسرق ~5% CPU عند هذه المعدلات — مقبول؛ الأدق
|
||||
تشغيله من جهاز آخر نحو `http://IP:8080`.
|
||||
4. المُلتزم به للعملاء = الرقم الذي عبر الاختبار، لا أكثر.
|
||||
## 5) أدوات الإدارة
|
||||
- phpMyAdmin: `ssh -L 8084:127.0.0.1:8084 user@server` ثم `http://127.0.0.1:8084`
|
||||
- MySQL من السيرفر: `mysql -h127.0.0.1 -P33063 -uroot -p`
|
||||
- المهام المجدولة: انسخ `crontab.production` (ضمنف داخل حاوية php).
|
||||
|
||||
## 5) ملاحظات أداء محسومة (لماذا الحاويات لا تبطئنا)
|
||||
- الحاوية على لينكس = عمليات عادية بنفس النواة (namespaces/cgroups) — **لا محاكاة ولا آلة افتراضية**. حمل CPU/ذاكرة ≈ صفر.
|
||||
- المكان الوحيد الذي يُخسر فيه أداء فعلاً: كتابة قاعدة البيانات فوق overlayfs — **محلول** بـ volume مسمّى (`mysql-data`).
|
||||
- أداء PHP الحقيقي يصنعه opcache + مقاس حوض fpm + فهارس MySQL — كلها مضبوطة في `php/` وليست متعلقة بالدوكر أصلاً.
|
||||
- التقسيم إلى 6 حاويات لا يكلف أداءً (نفس العمليات) ويعطي: إعادة تشغيل خدمة وحدها، حدود ذاكرة لكل خدمة، لوغات منفصلة، واستنساخ عميل = `clone + .env + up`.
|
||||
## 6) ملاحظات أداء محسوسة
|
||||
- الحاوية على لينكس = عمليات عادية بنفس النواة — لا محاكاة، حمل CPU/ذاكرة ≈ صفر.
|
||||
- المكان الوحيد الذي يُخسر فيه أداء فعلاً: كتابة MySQL فوق overlayfs — محلول بـ volume.
|
||||
- أداء PHP الحقيقي = opcache + مقاس حوض fpm + فهارس MySQL — مضبوطة في `php/`.
|
||||
@@ -0,0 +1,69 @@
|
||||
# ============================================================
|
||||
# turnserver.conf — خادم TURN (coturn) لمكالمات تربز الصوتية
|
||||
# ------------------------------------------------------------
|
||||
# لماذا TURN أصلاً: STUN وحده يكفي فقط حين يستطيع الطرفان رؤية بعضهما
|
||||
# مباشرة. سائق وزبون كلاهما على بيانات الجوال يقعان غالباً خلف CGNAT
|
||||
# (Symmetric NAT)، فتفشل المسارات المباشرة وتبقى المكالمة صامتة رغم
|
||||
# نجاح الإشارات. TURN يمرّر الصوت عبر الخادم كملاذ أخير.
|
||||
#
|
||||
# المصادقة: use-auth-secret (بيانات مؤقتة عبر HMAC) — لا كلمات مرور
|
||||
# ثابتة في التطبيق. المفتاح السرّي يُمرَّر من docker-compose، ونفسه
|
||||
# يستعمله backend/ride/call/turn_credentials.php لتوليد البيانات.
|
||||
#
|
||||
# ⚠️ بورتات تربز مختلفة عن نسخة سيرو على نفس السيرفر:
|
||||
# سيرو: listening-port=3478 relay 49160–49300
|
||||
# تربز: listening-port=3479 relay 49301–49400
|
||||
# ============================================================
|
||||
|
||||
listening-port=3479
|
||||
|
||||
# TLS (turns:) معطّل افتراضياً عمداً: بلا شهادة صالحة يرفض coturn تشغيل
|
||||
# مستمع TLS ويسجّل خطأ فقط، فيصير عنوان turns: في قائمة ICE مساراً
|
||||
# ميتاً يبطئ التفاوض. لتفعيله: ضع شهادة النطاق وامنح الحاوية قراءتها،
|
||||
# ثم أزل التعليق عن الأسطر الثلاثة، واضبط TURN_TLS_ENABLED=true في .env
|
||||
# كي يُعلنه الباك إند للتطبيق.
|
||||
# tls-listening-port=5350
|
||||
# cert=/keys/turn/fullchain.pem
|
||||
# pkey=/keys/turn/privkey.pem
|
||||
|
||||
fingerprint
|
||||
use-auth-secret
|
||||
# static-auth-secret و realm و external-ip تُمرَّر كوسائط من docker-compose
|
||||
# (من .env) حتى لا يُخزَّن السر داخل ملف متعقَّب في Git.
|
||||
|
||||
# نطاق منافذ التمرير — كل مكالمة تحجز منفذاً أو اثنين.
|
||||
# يجب فتح هذا النطاق UDP على جدار الحماية وإلا فشل التمرير بصمت.
|
||||
# (النطاق 49160–49300 محجوز لنسخة سيرو على السيرفر نفسه)
|
||||
min-port=49301
|
||||
max-port=49400
|
||||
|
||||
# ── تقييد الوجهات ──────────────────────────────────────────
|
||||
# بلا هذا يصير TURN بوابة تصل للشبكة الداخلية: أي مستخدم يملك بيانات
|
||||
# اعتماد صالحة يطلب من السلر فتح مسار إلى 127.0.0.1 أو 172.x فيصل
|
||||
# إلى mysql/redis/الحاويات. نمنع كل النطاقات الخاصة صراحةً.
|
||||
no-multicast-peers
|
||||
denied-peer-ip=0.0.0.0-0.255.255.255
|
||||
denied-peer-ip=10.0.0.0-10.255.255.255
|
||||
denied-peer-ip=127.0.0.0-127.255.255.255
|
||||
denied-peer-ip=169.254.0.0-169.254.255.255
|
||||
denied-peer-ip=172.16.0.0-172.31.255.255
|
||||
denied-peer-ip=192.168.0.0-192.168.255.255
|
||||
denied-peer-ip=100.64.0.0-100.127.255.255
|
||||
denied-peer-ip=::1
|
||||
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
|
||||
# ── حدود الاستهلاك ─────────────────────────────────────────
|
||||
# TURN يمرّر كل بايت من الصوت، فبلا سقف تصير الفاتورة والنطاق مفتوحين.
|
||||
# مكالمة صوتية Opus ≈ 40 kbps لكل اتجاه — 500 kbps سقف سخيّ جداً للصوت
|
||||
# ويقطع أي وقت يستعمله الخادم كبروكسي فيديو أو تنزيل.
|
||||
user-quota=12
|
||||
total-quota=1200
|
||||
max-bps=64000
|
||||
bps-capacity=0
|
||||
|
||||
# ── تشغيل ──────────────────────────────────────────────────
|
||||
no-cli
|
||||
stale-nonce=600
|
||||
# لا نُسجّل كل مسارات — الأخطاء فقط
|
||||
simple-log
|
||||
@@ -0,0 +1,84 @@
|
||||
# ============================================================
|
||||
# جدول المهام المجدولة — تربز (بعد الانتقال إلى دوكر)
|
||||
# ============================================================
|
||||
# المشكلة التي يعالجها هذا الملف:
|
||||
#
|
||||
# الجدول القديم كان يشغّل كل السكربتات على المضيف مباشرة.
|
||||
# بعد الانتقال إلى دوكر لم تعد هذه السكربتات قادرة على العمل:
|
||||
#
|
||||
# • Redis لا ينشر أي بورت إلى المضيف — يُرى فقط من داخل شبكة دوكر.
|
||||
# • MySQL منشور على 127.0.0.1:33063 وليس 3306، فأي .env على
|
||||
# المضيف ما زال يشير إلى 3306 يفشل في الاتصال.
|
||||
# • bootstrap.php يستنتج مسار .env من __DIR__ — الحاويات تقرأ
|
||||
# متغيّراته من docker/.env.
|
||||
#
|
||||
# الحل: تشغيل كل شيء داخل حاوية php، حيث أسماء الشبكة (mysql / redis)
|
||||
# والمتغيّرات صحيحة.
|
||||
#
|
||||
# ------------------------------------------------------------
|
||||
# التركيب:
|
||||
# crontab -e ثم الصق المحتوى أدناه
|
||||
#
|
||||
# ملاحظة: المستخدم الذي يملك الـ crontab يجب أن يكون عضواً في مجموعة
|
||||
# docker، وإلا فشل كل سطر بخطأ صلاحيات.
|
||||
# ------------------------------------------------------------
|
||||
|
||||
TRIPZ=/home/tripz-egypt-api/htdocs/api.tripz-egypt.com/tripz/docker
|
||||
DEX=/usr/bin/docker compose -f $TRIPZ/docker-compose.yml exec -T php php
|
||||
|
||||
# ============================================================
|
||||
# المواصلات (Transit)
|
||||
# ============================================================
|
||||
*/1 * * * * $DEX /var/www/backend/transit/cron_approaching_alerts.php >> /var/log/transit_alerts.log 2>&1
|
||||
0 3 * * * $DEX /var/www/backend/transit/cron_sync_members.php >> /var/log/transit_sync.log 2>&1
|
||||
30 3 * * * $DEX /var/www/backend/transit/cron_cleanup.php >> /var/log/transit_cleanup.log 2>&1
|
||||
|
||||
# ============================================================
|
||||
# محرّك التسعير والبوتات
|
||||
# ============================================================
|
||||
*/15 * * * * $DEX /var/www/backend/bot/push_10_tasks.php >> /var/log/bot_tasks.log 2>&1
|
||||
|
||||
*/5 * * * * $DEX /var/www/backend/bot/cron_kazan_adjuster.php >> /var/log/bot_kazan.log 2>&1
|
||||
*/10 * * * * $DEX /var/www/backend/bot/cron_surge_opportunity.php >> /var/log/bot_surge.log 2>&1
|
||||
*/16 * * * * $DEX /var/www/backend/bot/cron_generate_heatmap_cache.php >> /var/log/bot_heatmap.log 2>&1
|
||||
0 * * * * $DEX /var/www/backend/bot/cron_seasonal_pricing.php >> /var/log/bot_seasonal.log 2>&1
|
||||
0 * * * * $DEX /var/www/backend/bot/cron_predictive_demand.php >> /var/log/bot_demand.log 2>&1
|
||||
0 */3 * * * $DEX /var/www/backend/bot/cron_ai_engine.php >> /var/log/bot_ai.log 2>&1
|
||||
0 */3 * * * $DEX /var/www/backend/bot/cron_pricing_stability_engine.php >> /var/log/bot_stability.log 2>&1
|
||||
|
||||
# لقطة لوحة المعلومات — التشغيل الساعي يغطي الأسبوعي واليومي.
|
||||
0 * * * * $DEX /var/www/backend/bot/cron_dashboard_snapshot.php >> /var/log/bot_snapshot.log 2>&1
|
||||
|
||||
# ============================================================
|
||||
# الحجز المسبق (Scheduled Rides)
|
||||
# ============================================================
|
||||
*/2 * * * * $DEX /var/www/backend/bot/cron_scheduled_rides.php >> /var/log/scheduled_rides.log 2>&1
|
||||
|
||||
# ============================================================
|
||||
# الطلب بلا إنترنت — SMS
|
||||
# ============================================================
|
||||
*/1 * * * * $DEX /var/www/backend/bot/cron_sms_requests.php >> /var/log/sms_requests.log 2>&1
|
||||
|
||||
# ============================================================
|
||||
# التزامات السائق (تأمين، وقود، صيانة)
|
||||
# ============================================================
|
||||
15 0 * * * $DEX /var/www/backend/bot/cron_insurance_premiums.php >> /var/log/insurance.log 2>&1
|
||||
|
||||
# محرك التسوية — 23:30 يقرأ يوم عمل مكتملاً تقريباً.
|
||||
30 23 * * * $DEX /var/www/backend/bot/cron_obligation_settlement.php >> /var/log/obligations.log 2>&1
|
||||
|
||||
# ============================================================
|
||||
# الإشعارات والتسويق
|
||||
# ============================================================
|
||||
0 * * * * $DEX /var/www/backend/bot/cron_auto_marketing_pusher.php >> /var/log/bot_pusher.log 2>&1
|
||||
0 10 * * * $DEX /var/www/backend/bot/cron_passenger_reengagement.php >> /var/log/bot_reengage.log 2>&1
|
||||
0 0 * * 0 $DEX /var/www/backend/bot/cron_weekly_health_report.php >> /var/log/bot_health.log 2>&1
|
||||
|
||||
0 */3 * * * $DEX /var/www/backend/marketing_engine/telegram_scraper.php >> /var/log/mkt_telegram.log 2>&1
|
||||
0 */4 * * * $DEX /var/www/backend/marketing_engine/cron_insert_task.php >> /var/log/mkt_tasks.log 2>&1
|
||||
0 10 * * 0 $DEX /var/www/backend/marketing_engine/cron_weekly_report.php >> /var/log/mkt_weekly.log 2>&1
|
||||
|
||||
# ============================================================
|
||||
# انتقالي — يُحذف بعد التأكد من مسار worker.php
|
||||
# ============================================================
|
||||
0 * * * * $DEX /var/www/backend/bot/cron_empty_results_to_db.php >> /var/log/bot_drain.log 2>&1
|
||||
+129
-15
@@ -1,11 +1,16 @@
|
||||
# ============================================================
|
||||
# سيرو في حاويات — نسخة واحدة كاملة على سيرفر واحد
|
||||
# تربز في حاويات — نسخة واحدة كاملة على سيرفر واحد
|
||||
# ============================================================
|
||||
# المبدأ: التقسيم بالدور (nginx / fpm / سوكيتات / mysql / redis)
|
||||
# لا حاوية-واحدة-فيها-كل-شيء، ولا تفتيت microservices.
|
||||
# الأداء = نفس العمليات على نفس النواة؛ الفرق تشغيلي فقط.
|
||||
#
|
||||
# التشغيل: docker compose up -d --build (انظر README.md)
|
||||
#
|
||||
# البورتات: تربز تستضيف على نفس سيرفر نسخ أخرى (siro/intaleq)،
|
||||
# فكل منفذ هنا مخصص لتربز ولا يتصادم معها:
|
||||
# HTTP 8183 · driver 12022 · passenger 13033 · food 14042
|
||||
# mysql 33063 · phpmyadmin 8084 · coturn 3479 (UDP 49301–49400)
|
||||
# ============================================================
|
||||
|
||||
name: tripz-core
|
||||
@@ -23,6 +28,8 @@ services:
|
||||
- ../dashboard:/var/www/dashboard:ro
|
||||
depends_on:
|
||||
- php
|
||||
- php_transit
|
||||
- php_food
|
||||
mem_limit: 256m
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -30,8 +37,8 @@ services:
|
||||
# التقسيم لأبعد من هذا لا يضيف أداءً — نفس الصورة، نفس النواة.
|
||||
php:
|
||||
build:
|
||||
context: ./php
|
||||
dockerfile: Dockerfile.fpm
|
||||
context: ..
|
||||
dockerfile: docker/php/Dockerfile.fpm
|
||||
args:
|
||||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||||
volumes:
|
||||
@@ -39,6 +46,7 @@ services:
|
||||
- ../payment_server/v2:/var/www/v2
|
||||
- ../loction_server:/var/www/loction_server
|
||||
- ./php/opcache.ini:/usr/local/etc/php/conf.d/zz-opcache.ini:ro
|
||||
- ./php/php-prod.ini:/usr/local/etc/php/conf.d/zz-prod.ini:ro
|
||||
- ./php/www-pool.conf:/usr/local/etc/php-fpm.d/zz-pool.conf:ro
|
||||
- ./keys:/keys:ro
|
||||
env_file: .env
|
||||
@@ -48,6 +56,84 @@ services:
|
||||
mem_limit: 2g
|
||||
restart: unless-stopped
|
||||
|
||||
# php-fpm معزولة لتخدم المواصلات (transit) — حاوية مستقلة عن الباك إند الرئيسي.
|
||||
# المشترك الوحيد مع النظام الأساسي: JWT والمصادقة والرحلات الداخلية عبر backend/core
|
||||
# (نُركّبها read-only)، ونفس mysql/redis. لا صلة بـ backend الرئيسي ولا payment v2.
|
||||
php_transit:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: docker/php/Dockerfile.fpm.transit
|
||||
args:
|
||||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||||
volumes:
|
||||
- ../backend/core:/var/www/backend/core:ro
|
||||
- ../backend/functions.php:/var/www/backend/functions.php:ro
|
||||
# نفس سبب php_food: JwtService يحتاج Firebase\JWT من backend/vendor،
|
||||
# والصورة بلا composer. للقراءة فقط.
|
||||
- ../backend/vendor:/var/www/backend/vendor:ro
|
||||
- ../backend/transit:/var/www/backend/transit
|
||||
- ./php/opcache.ini:/usr/local/etc/php/conf.d/zz-opcache.ini:ro
|
||||
- ./php/php-prod.ini:/usr/local/etc/php/conf.d/zz-prod.ini:ro
|
||||
- ./php/www-pool.transit.conf:/usr/local/etc/php-fpm.d/zz-pool.conf:ro
|
||||
- ./keys:/keys:ro
|
||||
env_file: .env
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
mem_limit: 512m
|
||||
restart: unless-stopped
|
||||
|
||||
# php-fpm معزولة لوحدة طلبات الطعام — نفس منطق عزل php_transit.
|
||||
# المشترك الوحيد: JWT (backend/core) ونفس mysql/redis. قاعدة tripz_food منفصلة.
|
||||
php_food:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: docker/php/Dockerfile.fpm.transit
|
||||
args:
|
||||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||||
volumes:
|
||||
- ../backend/core:/var/www/backend/core:ro
|
||||
- ../backend/functions.php:/var/www/backend/functions.php:ro
|
||||
# core/bootstrap.php يحمّل backend/vendor/autoload.php، وJwtService
|
||||
# يحتاج Firebase\JWT. الصورة هنا بلا composer عمداً، ودون هذا التركيب
|
||||
# كانت كل نقطة طعام تسقط بـ Class "Firebase\JWT\JWT" not found.
|
||||
# للقراءة فقط: مكتبات مشتركة لا كود مشترك — العزل باقٍ.
|
||||
- ../backend/vendor:/var/www/backend/vendor:ro
|
||||
- ../backend/food:/var/www/backend/food
|
||||
- ./php/opcache.ini:/usr/local/etc/php/conf.d/zz-opcache.ini:ro
|
||||
- ./php/php-prod.ini:/usr/local/etc/php/conf.d/zz-prod.ini:ro
|
||||
- ./php/food-pool.conf:/usr/local/etc/php-fpm.d/zz-pool.conf:ro
|
||||
- ./keys:/keys:ro
|
||||
env_file: .env
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
mem_limit: 768m
|
||||
restart: unless-stopped
|
||||
|
||||
# سوكيت الطعام — WS بورت 4040 + HTTP داخلي 4041
|
||||
socket_food:
|
||||
build:
|
||||
context: ./php
|
||||
dockerfile: Dockerfile.socket
|
||||
args:
|
||||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||||
command: ["php", "food_socket.php", "start"]
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ../food_server:/app
|
||||
- ./keys:/keys:ro
|
||||
env_file: .env
|
||||
ports:
|
||||
# نفس منطق سوكيت السائقين: لا نفتح 4040 للعالم مباشرة — nginx على
|
||||
# المضيف يستمع 4040 بالشهادة ويمرّر إلى 14042 هنا. 4041 داخلي فقط
|
||||
# (الباك إند يناديه عبر http://socket_food:4041).
|
||||
- "127.0.0.1:${FOOD_SOCKET_PORT:-14042}:4040"
|
||||
depends_on:
|
||||
- redis
|
||||
mem_limit: 512m
|
||||
restart: unless-stopped
|
||||
|
||||
# سوكيت السائقين (Workerman + PHPSocketIO) — WS بورت 2020 + HTTP داخلي 2021
|
||||
# عملية دائمة، لا علاقة لها بـ fpm — حاوية مستقلة إجبارياً.
|
||||
socket_driver:
|
||||
@@ -63,12 +149,14 @@ services:
|
||||
- ./keys:/keys:ro
|
||||
env_file: .env
|
||||
ports:
|
||||
# لا نفتح 2020 للعالم مباشرة: Workerman يتكلم نصاً صريحاً، والتطبيق يطلب
|
||||
# TLS على هذا المنفذ (https://…:2020) فتتجمّد المصافحة وينتهي بـ timeout.
|
||||
# nginx على المضيف يستمع على 2020 بالشهادة ويمرّر إلى 12020 هنا.
|
||||
# انظر nginx/tripz-sockets-tls.conf
|
||||
- "127.0.0.1:12022:2020"
|
||||
# و2021 داخلي فقط: الباك إند يناديه عبر http://socket_driver:2021
|
||||
# لا نفتح 2020 للعالم مباشرة: Workerman يتكلم نصاً صريحاً، والتطبيق يطلب
|
||||
# TLS على هذا المنفذ فتتجمّد المصافحة وينتهي بـ timeout.
|
||||
# nginx على المضيف يستمع على 2020 بالشهادة ويمرّر إلى 12022 هنا.
|
||||
# انظر nginx/tripz-sockets-tls.conf
|
||||
# المنفذ قابل للضبط: على سيرفر تعمل عليه أكثر من نسخة (siro/tripz/intaleq)
|
||||
# لا يتصادم. اضبط DRIVER_SOCKET_PORT في .env.
|
||||
- "127.0.0.1:${DRIVER_SOCKET_PORT:-12022}:2020"
|
||||
# و2021 داخلي فقط: الباك إند يناسيه عبر http://socket_driver:2021
|
||||
depends_on:
|
||||
- redis
|
||||
mem_limit: 768m
|
||||
@@ -88,9 +176,10 @@ services:
|
||||
- ./keys:/keys:ro
|
||||
env_file: .env
|
||||
ports:
|
||||
# نفس منطق سوكيت السائقين: nginx على المضيف يستمع على 3030 بالشهادة
|
||||
# ويمرّر إلى 13032 هنا. و3031 داخلي فقط (http://socket_passenger:3031).
|
||||
- "127.0.0.1:13032:3030"
|
||||
# نفس منطق سوكيت السائقين: nginx على المضيف يستمع على 3030 بالشهادة
|
||||
# ويمرّر إلى 13033 هنا. و3031 داخلي فقط (http://socket_passenger:3031).
|
||||
# ⚠️ 13032 محجوزة من نسخة intaleq على السيرفر نفسه — لهذا استخدمنا 13033.
|
||||
- "127.0.0.1:${PASSENGER_SOCKET_PORT:-13033}:3030"
|
||||
depends_on:
|
||||
- redis
|
||||
mem_limit: 512m
|
||||
@@ -112,7 +201,9 @@ services:
|
||||
- --long-query-time=0.2
|
||||
- --slow-query-log-file=/var/lib/mysql/slow.log
|
||||
ports:
|
||||
- "127.0.0.1:33063:3306" # للإدارة من السيرفر نفسه فقط — ليس للعامة
|
||||
# للإدارة من السيرفر نفسه فقط — ليس للعامة.
|
||||
# 33061 يحتجزه intaleq-mysql-1 و33062 يحتجزه siro-mysql-1.
|
||||
- "127.0.0.1:33063:3306"
|
||||
mem_limit: 2560m
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -123,7 +214,9 @@ services:
|
||||
PMA_PORT: 3306
|
||||
UPLOAD_LIMIT: 300M
|
||||
ports:
|
||||
- "8084:80" # ادخل عليه عبر http://your-domain:8084 أو افتح بورت 8084 في CloudPanel
|
||||
# مقيّد على loopback عمداً — لا تكشفه للإنترنت بلا TLS.
|
||||
# الوصول عبر نفق SSH فقط: ssh -N -L 8084:127.0.0.1:8084 USER@SERVER
|
||||
- "127.0.0.1:8084:80"
|
||||
depends_on:
|
||||
- mysql
|
||||
mem_limit: 256m
|
||||
@@ -144,6 +237,27 @@ services:
|
||||
mem_limit: 512m
|
||||
restart: unless-stopped
|
||||
|
||||
# خادم TURN لمكالمات الصوت (رحلات + توصيل الطعام).
|
||||
# network_mode: host إجباري هنا لا تفضيلاً: coturn يضع عنوان الخادم داخل
|
||||
# حمولة ICE، ولو مرّ عبر جسر دوكر لأعلن عنواناً داخلياً (172.x) فيفشل
|
||||
# التمرير. ومع host يسري جدار الحماية عادةً بدل أن يلتفّ عليه docker-proxy.
|
||||
#
|
||||
# ⚠️ منفذ TURN مختلف عن نسخة سيرو (3478 محجوزة هناك): هنا 3479.
|
||||
coturn:
|
||||
image: coturn/coturn:4.6-alpine
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./coturn/turnserver.conf:/etc/coturn/turnserver.conf:ro
|
||||
command: >
|
||||
-c /etc/coturn/turnserver.conf
|
||||
--realm=${TURN_REALM:-api.tripz-egypt.com}
|
||||
--static-auth-secret=${TURN_STATIC_AUTH_SECRET:?TURN_STATIC_AUTH_SECRET is required}
|
||||
--external-ip=${TURN_EXTERNAL_IP:?TURN_EXTERNAL_IP is required}
|
||||
--listening-ip=${TURN_EXTERNAL_IP}
|
||||
--relay-ip=${TURN_EXTERNAL_IP}
|
||||
mem_limit: 256m
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mysql-data:
|
||||
redis-data:
|
||||
redis-data:
|
||||
@@ -0,0 +1,8 @@
|
||||
-- قاعدة وحدة طلبات الطعام لتربز — منفصلة عن باقي القواعد.
|
||||
CREATE DATABASE IF NOT EXISTS `tripz_food` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- ⚠️ كلمة المرور هنا يجب أن تطابق DB_FOOD_PASS في ملف .env وإلا فشل الاتصال.
|
||||
CREATE USER IF NOT EXISTS 'tripz_food'@'%' IDENTIFIED BY 'CHANGE_ME_STRONG_PASSWORD';
|
||||
GRANT ALL PRIVILEGES ON `tripz_food`.* TO 'tripz_food'@'%';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
+67
-17
@@ -1,7 +1,21 @@
|
||||
# نقطة واحدة لكل الخدمات الطلبية — التطبيق يغيّر الدومين فقط:
|
||||
# /backend/... → الباك إند الرئيسي (نفس شكل مسارات jordan-siro)
|
||||
# /backend/... → الباك إند الرئيسي
|
||||
# /v2/main/... → خادم المدفوعات
|
||||
# السوكيتات تُنشر مباشرة من حاوياتها (2020 / 3030) — لا تمر من هنا.
|
||||
# السوكيتات تُنشر مباشرة من حاوياتها (2020 / 3030 / 4040) — لا تمر من هنا.
|
||||
|
||||
# مُحلِّل أسماء دوكر المدمج. سببه عطل حقيقي دام أياماً:
|
||||
#
|
||||
# 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;
|
||||
@@ -10,17 +24,52 @@ server {
|
||||
index index.php index.html;
|
||||
client_max_body_size 25m;
|
||||
|
||||
# كان access_log off من اختبار ضغط قديم ونُسي مُطفأً، فصار تشخيص أي عطل
|
||||
# مستحيلاً: البحث في سجلّ الوصول يرجع صفراً دائماً فيبدو أن التطبيق لا
|
||||
# يستدعي المسار أصلاً، والحقيقة أن السجلّ فارغ لا الطلبات. أعِده مطفأً
|
||||
# مؤقتاً وقت اختبارات الضغط فقط، ولا تتركه هكذا.
|
||||
# وجهات 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). نمرّر
|
||||
# السلسلة إلى PHP ليقرأها عبر clientIp() في core/helpers.php.
|
||||
set $tripz_fwd $http_x_forwarded_for;
|
||||
if ($tripz_fwd = "") {
|
||||
set $tripz_fwd $remote_addr;
|
||||
}
|
||||
fastcgi_param HTTP_X_FORWARDED_FOR $tripz_fwd;
|
||||
fastcgi_param HTTP_X_REAL_IP $remote_addr;
|
||||
|
||||
access_log /dev/stdout;
|
||||
error_log /dev/stderr warn;
|
||||
|
||||
# المواصلات (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 ~ ^/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 php:9000;
|
||||
fastcgi_pass $upstream_php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_read_timeout 60s;
|
||||
fastcgi_buffers 16 16k;
|
||||
@@ -33,31 +82,32 @@ server {
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
include fastcgi_params;
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_pass $upstream_php;
|
||||
fastcgi_param SCRIPT_NAME /status;
|
||||
fastcgi_param SCRIPT_FILENAME /status;
|
||||
}
|
||||
|
||||
location /dashboard/siro-admin {
|
||||
alias /var/www/dashboard/siro-admin;
|
||||
# لوحات التحكم — الجديدة للتسمية المعتمدة، والقديمة للتوافق خلفها.
|
||||
location /dashboard/tripz-admin {
|
||||
alias /var/www/dashboard/tripz-admin;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /dashboard/siro-admin/index.html;
|
||||
try_files $uri $uri/ /dashboard/tripz-admin/index.html;
|
||||
}
|
||||
|
||||
location /dashboard/admin {
|
||||
alias /var/www/dashboard/siro-admin;
|
||||
alias /var/www/dashboard/tripz-admin;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /dashboard/admin/index.html;
|
||||
}
|
||||
|
||||
location /dashboard/siro-service {
|
||||
alias /var/www/dashboard/siro-service;
|
||||
location /dashboard/tripz-service {
|
||||
alias /var/www/dashboard/tripz-service;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /dashboard/siro-service/index.html;
|
||||
try_files $uri $uri/ /dashboard/tripz-service/index.html;
|
||||
}
|
||||
|
||||
location /dashboard/service {
|
||||
alias /var/www/dashboard/siro-service;
|
||||
alias /var/www/dashboard/tripz-service;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /dashboard/service/index.html;
|
||||
}
|
||||
@@ -65,4 +115,4 @@ server {
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,24 +4,25 @@
|
||||
# يُنسَخ على **المضيف** لا داخل الحاويات:
|
||||
# /etc/nginx/sites-enabled/tripz-sockets-tls.conf
|
||||
#
|
||||
# المشكلة التي يحلّها: حاويتا السوكيت تفتحان المنفذين نصاً صريحاً
|
||||
# (new SocketIO(2020) و new SocketIO(3030) بلا سياق SSL)، بينما
|
||||
# التطبيقان يطلبان https://api.tripz-egypt.com:2020 و :3030.
|
||||
# المشكلة التي يحلّها: حاويات السوكيت تفتح منافذها نصاً صريحاً
|
||||
# (new SocketIO(2020) / (3030) / (4040) بلا سياق SSL)، بينما
|
||||
# التطبيقات تطلب https://api.tripz-egypt.com:2020 و:3030 و:4040.
|
||||
# مصافحة TLS ضد منفذ لا يتكلم TLS تتجمّد حتى المهلة، فيظهر في اللوج:
|
||||
# Socket Connect Error: timeout
|
||||
#
|
||||
# الحل: الحاويتان تُنشران على 127.0.0.1 فقط (12020 / 13030 — انظر
|
||||
# docker-compose.yml)، و nginx هنا يستمع على 2020 / 3030 بشهادة الدومين
|
||||
# ويمرّر إليهما مع ترقية WebSocket. النتيجة: روابط التطبيقين تبقى كما هي
|
||||
# بلا أي بناء جديد، والـ JWT في الـ query string يبقى داخل نفق TLS.
|
||||
# الحل: الحاويات تُنشر على 127.0.0.1 فقط (12022 / 13033 / 14042)،
|
||||
# و nginx هنا يستمع على 2020 / 3030 / 4040 بشهادة الدومين ويمرّر
|
||||
# إليها مع ترقية WebSocket. النتيجة: روابط التطبيقات تبقى كما هي
|
||||
# وبلا أي بناء جديد، والـ JWT في الـ query string يبقى داخل نفق TLS.
|
||||
#
|
||||
# ⚠️ هذه الملفات الثلاثة تعيش على نفس السيرفر مع نسخ أخرى بمنافذ
|
||||
# خارجية مطابقة (2020/3030/4040) وبـ server_name مختلف — يفصل nginx
|
||||
# بينها حسب SNI، فلا يتعارض. إذا ظهر تعارض listen فتأكد كأن كل ملف
|
||||
# يُخصَّص server_name واحد فقط.
|
||||
# ══════════════════════════════════════════════════════════════════
|
||||
|
||||
# ملاحظة: لا نضع http2 إطلاقاً هنا. أولاً لأن ترقية WebSocket تعتمد على
|
||||
# ترويسة Upgrade في HTTP/1.1 ولا معنى لها في HTTP/2، وثانياً لأن http2 on;
|
||||
# لم يُضَف إلا في nginx 1.25.1 وnginx المضيف أقدم فيرفضه بـ:
|
||||
# nginx: [emerg] unknown directive "http2"
|
||||
# اسم مميّز يتفادى التضارب مع أي map باسم $connection_upgrade قد يكون
|
||||
# CloudPanel معرِّفه أصلاً في سياق http.
|
||||
# لا نضع http2 إطلاقاً هنا: ترقية WebSocket تعتمد على ترقدية
|
||||
# Upgrade في HTTP/1.1 ولا معنى لها في HTTP/2، وقد يرفضها nginx قديم.
|
||||
map $http_upgrade $tripz_connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
@@ -34,7 +35,7 @@ server {
|
||||
|
||||
server_name api.tripz-egypt.com;
|
||||
|
||||
# عدّل المسارين إن كانت شهادتك في مكان آخر — تحقّق بالأمر:
|
||||
# عدّل المسارين إن كانت شهادتك في مكان آخر:
|
||||
# grep -rh ssl_certificate /etc/nginx/sites-enabled/ | sort -u
|
||||
ssl_certificate /etc/nginx/ssl-certificates/api.tripz-egypt.com.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl-certificates/api.tripz-egypt.com.key;
|
||||
@@ -88,7 +89,9 @@ server {
|
||||
error_log /var/log/nginx/tripz-socket-passenger-error.log warn;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:13032;
|
||||
# ⚠️ 13033 وليس 13032: 13032 محجوزة من نسخة intaleq على
|
||||
# السيرفر نفسه وكان سوكيت الركاب في تربز متوفّقاً بها.
|
||||
proxy_pass http://127.0.0.1:13033;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
@@ -106,3 +109,45 @@ server {
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
|
||||
# ── سوكيت الطعام — طلبات التوصيل ─────────────────────────────────
|
||||
# الحاوية على 14042 (بورت مخصص لتربز؛ 14040 لنسخة سيرو).
|
||||
# الحاوية نفسها قد تكون سليمة بينما لا مستمع خارجياً على 4040 —
|
||||
# النتيجة `Socket Connect Error: timeout` في تطبيق السائق.
|
||||
server {
|
||||
listen 4040 ssl;
|
||||
listen [::]:4040 ssl;
|
||||
|
||||
server_name api.tripz-egypt.com;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl-certificates/api.tripz-egypt.com.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl-certificates/api.tripz-egypt.com.key;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_session_cache shared:TripzSock:10m;
|
||||
ssl_session_timeout 1d;
|
||||
|
||||
access_log off;
|
||||
error_log /var/log/nginx/tripz-socket-food-error.log warn;
|
||||
|
||||
location / {
|
||||
# FOOD_SOCKET_PORT في docker/.env — الافتراضي 14042.
|
||||
proxy_pass http://127.0.0.1:14042;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $tripz_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;
|
||||
|
||||
# وضع التوصيل يبقى مفتوحاً طوال مناوبة الكابتن — نفس مهل 2020.
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_read_timeout 3600s;
|
||||
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# صورة معزولة لخدمة Mawasalati (transit) — لا composer، لا vendor مشترك
|
||||
# نفس الامتدادات الأساسية فقط. لا صلة بـ backend الرئيسي أو payment v2.
|
||||
ARG PHP_VERSION=8.2
|
||||
FROM php:${PHP_VERSION}-fpm
|
||||
|
||||
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/install-php-extensions && \
|
||||
install-php-extensions mysqli pdo_mysql redis opcache gd
|
||||
|
||||
WORKDIR /var/www
|
||||
@@ -0,0 +1,16 @@
|
||||
; حوض fpm لوحدة الطعام — معزول عن حوض الرحلات الرئيسي
|
||||
[www]
|
||||
pm = dynamic
|
||||
pm.max_children = 24
|
||||
pm.start_servers = 4
|
||||
pm.min_spare_servers = 2
|
||||
pm.max_spare_servers = 8
|
||||
pm.max_requests = 1000
|
||||
pm.status_path = /status
|
||||
slowlog = /proc/self/fd/2
|
||||
request_slowlog_timeout = 3s
|
||||
|
||||
catch_workers_output = yes
|
||||
decorate_workers_output = no
|
||||
php_admin_value[error_log] = /proc/self/fd/2
|
||||
php_admin_flag[log_errors] = on
|
||||
@@ -0,0 +1,37 @@
|
||||
; ============================================================
|
||||
; إعدادات PHP للإنتاج — تُركَّب على كل حاويات fpm
|
||||
; ============================================================
|
||||
;
|
||||
; صورة php الرسمية لا تشحن php.ini إطلاقاً (تترك php.ini-production
|
||||
; و php.ini-development جانباً بلا تفعيل)، فتسري قيم PHP المدمجة:
|
||||
; display_errors مُفعّل. أي أن كل تحذير أو إشعار يُطبع **داخل جسم
|
||||
; الردّ** قبل الـ JSON.
|
||||
;
|
||||
; وهذا ليس تنظيراً: شاشة رصيد الكابتن كانت تسقط بـ
|
||||
; "FormatException: Unexpected character (at character 1) <br />"
|
||||
; لأن getAllPayment.php أخرج تحذيراً قبل الـ JSON فصار الردّ غير قابل
|
||||
; للتحليل. العطل يبدو في التطبيق بينما مصدره سطر تحذير في PHP.
|
||||
;
|
||||
; والأسوأ أمنياً: نص التحذير يحمل المسار المطلق للملف وأحياناً جزءاً من
|
||||
; الاستعلام — يُسلَّم للعميل مباشرة.
|
||||
;
|
||||
; القاعدة: تُسجَّل الأخطاء ولا تُعرض. www-pool.conf يوجّه error_log إلى
|
||||
; مخرج الحاوية، فتُقرأ بـ `docker compose logs php`.
|
||||
|
||||
display_errors = Off
|
||||
display_startup_errors = Off
|
||||
log_errors = On
|
||||
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
|
||||
|
||||
; لا تكشف نسخة PHP في ترويسة X-Powered-By.
|
||||
expose_php = Off
|
||||
|
||||
; رفع صور المستندات (رخصة، هوية) — متوافق مع client_max_body_size 25m
|
||||
; في nginx. تركهما على الافتراضي (2m) كان يقطع رفع صور الكاميرا بصمت.
|
||||
upload_max_filesize = 25M
|
||||
post_max_size = 25M
|
||||
|
||||
max_execution_time = 60
|
||||
memory_limit = 256M
|
||||
|
||||
date.timezone = UTC
|
||||
@@ -0,0 +1,17 @@
|
||||
; حوض fpm صغير — ترافيك Mawasalati أقل بكثير من الباك إند الرئيسي
|
||||
; حصة الحاوية 512m، ما في داعي لنفس حجم pool الرئيسي (48 عامل)
|
||||
[www]
|
||||
pm = dynamic
|
||||
pm.max_children = 16
|
||||
pm.start_servers = 3
|
||||
pm.min_spare_servers = 2
|
||||
pm.max_spare_servers = 6
|
||||
pm.max_requests = 1000
|
||||
pm.status_path = /status
|
||||
slowlog = /proc/self/fd/2
|
||||
request_slowlog_timeout = 3s
|
||||
|
||||
catch_workers_output = yes
|
||||
decorate_workers_output = no
|
||||
php_admin_value[error_log] = /proc/self/fd/2
|
||||
php_admin_flag[log_errors] = on
|
||||
Reference in New Issue
Block a user