عندك ثلاث خدمات تعمل على عناوين خاصة، ووسيط عكسي جاهز. بقي أن يصل إليها الناس بأسماء يحفظونها: wp.example.com وn8n.example.com وapi.example.com.
في هذا الجزء نربط الاسم بالخدمة من الطرفين: سجل في نظام الأسماء يشير إلى عنوانك العام، وقاعدة في الوسيط تشير إلى العنوان الخاص. ثم نعالج المشكلة التي تظهر بعدها دائماً: التطبيق لا يعرف أنه خلف وسيط.
كل ما في هذه السلسلة مُنفَّذ فعلاً. بنينا المختبر على سيرفر Proxmox VE 9.2 بعنوان عام واحد، وأنشأنا عليه شبكة خاصة 10.10.10.0/24 وأربع حاويات، ونشرنا ثلاثة نطاقات فرعية حقيقية بشهادات Let's Encrypt. كل لقطة وكل مخرج أمر في هذه المقالات من ذلك المختبر — والعناوين في الصور حقيقية وقت التنفيذ.
القاعدة الذهبية
كل نطاقاتك الفرعية تشير إلى العنوان العام نفسه. الوسيط وحده يعرف العناوين الخاصة.
هذا يعني أن جدول نطاقاتك يبدو هكذا — ولاحظ تكرار العنوان:
| النوع | الاسم | القيمة | الخدمة الفعلية (سرّ الوسيط) |
|---|---|---|---|
| A | wp | 82.39.115.50 | 10.10.10.11:80 |
| A | n8n | 82.39.115.50 | 10.10.10.12:5678 |
| A | api | 82.39.115.50 | 10.10.10.13:3000 |
| A | cloud | 82.39.115.50 | 10.10.10.14:80 |
متى A ومتى CNAME؟
- A يربط اسماً بعنوان مباشرة. استعمله لكل نطاقاتك الفرعية.
- CNAME يربط اسماً باسم آخر. مفيد حين تريد أن يتبع نطاق فرعي نطاقاً آخر تلقائياً، فإذا تغيّر العنوان عدّلت سجلاً واحداً.
# الطريقة المباشرة
wp A 82.39.115.50
n8n A 82.39.115.50
# طريقة السجل الواحد
srv A 82.39.115.50
wp CNAME srv.example.com
n8n CNAME srv.example.com
الثانية أنظف إن كنت تتوقّع تغيّر العنوان. الأولى أبسط وأسرع في الحلّ بجزء مجهري.
التنفيذ: من الطرفية
إن كان نطاقك على Cloudflare تستطيع إنشاء السجل بأمر واحد:
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"wp","content":"82.39.115.50","ttl":120,"proxied":false}'
ثم تحقّق من الانتشار قبل أن تكمل:
dig +short wp.example.com
# يجب أن يعيد: 82.39.115.50
لا تطلب الشهادة قبل أن ينتشر السجل. إن طلبتها وDNS لم ينتشر بعد، ستفشل — وتكرار المحاولة يستهلك حصّتك عند Let's Encrypt (خمس محاولات فاشلة لكل نطاق في الساعة). انتظر حتى يعيد dig العنوان الصحيح، ثم اطلبها.
المشكلة التي ستواجهها حتماً
ربطت النطاق، وفتح الموقع، لكن شيئاً غريباً يحدث: الروابط داخل الموقع تشير إلى http بدل https، أو إلى العنوان الداخلي، أو تدخل في حلقة تحويل لا تنتهي.
السبب واحد: التطبيق لا يعلم أنه خلف وسيط. هو يرى اتصالاً عادياً غير مشفّر قادماً من 10.10.10.10، فيبني روابطه على هذا الأساس.
الحل: ترويستان
الوسيط يرسل مع كل طلب:
X-Forwarded-Proto: https— «الزائر جاء عبر HTTPS»X-Forwarded-For: 185.x.x.x— «عنوان الزائر الحقيقي»
Nginx Proxy Manager يرسلهما تلقائياً. الناقص هو أن يثق بهما تطبيقك.
ووردبريس
في wp-config.php، قبل سطر /* That's all, stop editing! */:
define( 'WP_HOME', 'https://wp.example.com' );
define( 'WP_SITEURL', 'https://wp.example.com' );
if ( isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
$_SERVER['HTTPS'] = 'on';
}
هذه الأسطر الستّة تحلّ حلقة التحويل ومشكلة الروابط المكسورة معاً. وهي بالضبط ما استعملناه في مختبرنا:
n8n
environment:
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- N8N_SECURE_COOKIE=false
ولا تنسَ تفعيل Websockets Support في الوسيط — بدونه تفتح الواجهة ثم تتجمّد بلا رسالة خطأ.
تطبيقات Node وExpress
app.set('trust proxy', true);
// الآن req.ip يعطي عنوان الزائر الحقيقي لا عنوان الوسيط
في مختبرنا كتبنا واجهة برمجية صغيرة تعرض ما تراه، وهي أوضح دليل على أن السلسلة تعمل:
هيكل نطاقات مقترح
| النطاق الفرعي | الخدمة | يُنشر؟ |
|---|---|---|
| www / الجذر | الموقع التعريفي | نعم |
| app | التطبيق الرئيسي | نعم |
| api | الواجهة البرمجية | نعم |
| cloud | سحابة الملفات | نعم |
| git | مستودعات الكود | نعم، مع تقييد الدخول |
| panel / admin | لوحات الإدارة | لا — عبر VPN أو نفق |
| db | قواعد البيانات | لا — لا تُنشر إطلاقاً |
قاعدة بسيطة تحميك: إذا لم يكن للخدمة زائر خارجي، فلا تعطها نطاقاً. لوحات الإدارة وقواعد البيانات وأدوات المراقبة تبقى داخلية، ويصل إليها فريقك عبر نفق أو VPN.
أخطاء شائعة وحلولها
| العَرَض | السبب | الحل |
|---|---|---|
| حلقة تحويل لا تنتهي | التطبيق يظنّ أنه على HTTP فيحوّل إلى HTTPS بلا نهاية | ثق بترويسة X-Forwarded-Proto |
| روابط الصور مكسورة | siteurl ما زال العنوان الداخلي | اضبط WP_HOME وWP_SITEURL |
| كل الزوّار بعنوان واحد في السجلات | التطبيق لا يقرأ X-Forwarded-For | trust proxy أو ما يعادله |
| الواجهة تفتح ثم تتجمّد | WebSocket غير مفعّل | فعّله للمضيف في الوسيط |
| DNS لا يستجيب بعد الإنشاء | الكاش المحلي | اختبر بـdig @1.1.1.1 لا بالمتصفح |
| النطاق يفتح موقعاً آخر | لا يوجد مضيف مطابق فيُعرض الافتراضي | أضف المضيف، أو اضبط رداً افتراضياً بـ404 |
أسئلة شائعة
كم نطاقاً فرعياً أستطيع إنشاءه؟
بلا حدّ عملي، ومجاناً. النطاقات الفرعية لا تُشترى — تُنشأ من نطاقك الأصلي.
هل أحتاج شهادة لكل نطاق فرعي؟
نعم، لكن Let's Encrypt تعطيك إياها مجاناً والوسيط يديرها. أو شهادة شاملة واحدة *.example.com بتحدّي DNS.
ما قيمة TTL المناسبة؟
120 ثانية أثناء الإعداد لتتمكّن من التغيير بسرعة، ثم ارفعها إلى 3600 بعد الاستقرار.
هل أستطيع استعمال نطاقات من مزوّدين مختلفين؟
نعم. الوسيط لا يعرف ولا يهمّه من يستضيف نطاقك — يكفي أن يشير إلى عنوانك.
وماذا عن النطاق الجذر بلا www؟
يعمل تماماً: أنشئ سجل A للجذر (@) وأضفه في الوسيط مع www في المضيف نفسه.
الخطوة التالية
نطاقاتك تعمل. في الجزء الثامن نضع Cloudflare أمام كل شيء: حماية وكاش وإخفاء لعنوان سيرفرك — ونحلّ المشكلة التي تنشأ مع الشهادات عند تفعيل السحابة البرتقالية.
هذه المقالة جزء من سلسلة «من IP واحد إلى عشرات الخدمات» — عشرة أجزاء بُنيت كلها على سيرفر Proxmox حقيقي: ١. لماذا يكفي عنوان واحد · ٢. الشبكة الخاصة · ٣. إعداد NAT · ٤. تمرير المنافذ · ٥. الـReverse Proxy · ٦. Nginx Proxy Manager · ٧. النطاقات الفرعية · ٨. Cloudflare والشهادات · ٩. مقارنة الحلول · ١٠. سحابة صغيرة كاملة