لماذا تضع Traefik في واجهة خادم VPS الخاص بك؟
عندما تشغّل عدة تطبيقات محوّلة إلى حاويات على خادم VPS نفسه، تصبح إدارة المضيفات الافتراضية (virtual hosts) في Nginx يدويًا وتجديد كل شهادة أمرًا غير قابل للإدارة بسرعة. يحل Traefik هذه المشكلة بقراءة علامات حاويات Docker الخاصة بك مباشرةً: تعلن عن مسار عند تنفيذ docker run أو في ملف docker-compose.yml، فيهيّئه Traefik أثناء التشغيل، ويولّد شهادة Let's Encrypt، ويعرضه عبر HTTPS. لا ملف تهيئة لتحريره، ولا إعادة تحميل: كل شيء ديناميكي.
يبقى Nginx خادم HTTP ممتازًا، لكن تهيئته ثابتة: كل خدمة جديدة تتطلب ملف vhost، وأمر nginx -s reload، وأداة ACME منفصلة (certbot ومهمة التجديد الخاصة به). صُمّم Traefik لبنية تتغير باستمرار، وهذه بالضبط حال خادم VPS تُضاف إليه الحاويات وتُحدَّث وتُزال كل أسبوع. وقد ثبّت الفرع v3، الصادر في أبريل 2024، دعم HTTP/3 وتصدير التتبع عبر OpenTelemetry، وشدّد صياغة قواعد التوجيه.
ما يقدّمه Traefik عمليًا على خادم VPS
- اكتشاف تلقائي لحاويات Docker عبر مزوّد Docker (تظهر المسارات دون إعادة تشغيل)
- شهادات SSL من Let's Encrypt تُولَّد وتُجدَّد تلقائيًا (تحديات HTTP-01 أو TLS-ALPN-01 أو DNS-01)، ويبدأ تجديدها افتراضيًا قبل 30 يومًا من انتهاء صلاحيتها
- توجيه حسب النطاق أو المسار أو الترويسة، يُدار بالكامل عبر علامات Docker
- لوحة تحكم ويب مدمجة لعرض الموجّهات (routers) والخدمات والبرمجيات الوسيطة (middlewares) في الوقت الحقيقي
- برمجيات وسيطة جاهزة للاستخدام: إعادة توجيه HTTPS، والمصادقة الأساسية (basic auth)، وتحديد معدل الطلبات، وترويسات الأمان، والضغط
- موازنة أحمال تلقائية عند توسيع خدمة إلى عدة نسخ (replicas)
- تفعيل HTTP/3 (QUIC) على نقطة دخول بخيار واحد
- مزوّدات أخرى غير Docker (Swarm وKubernetes وNomad والملفات) إذا توسّعت بنيتك التحتية
المتطلبات
Traefik نفسه خفيف جدًا: معالج vCPU واحد و1 غيغابايت من RAM يكفيان بوفرة للوكيل وحده، والتكلفة الإضافية تأتي من تطبيقاتك خلفه. جهّز خادم VPS يعمل بنظام Debian 12 أو Ubuntu 22.04/24.04 مع Docker Engine وإضافة Docker Compose v2 مثبَّتة (الأمر docker compose دون شرطة)، واسم نطاق تشير سجلّاته A/AAAA إلى عنوان IP الخاص بخادم VPS قبل التشغيل الأول (وإلا فلن تتمكن Let's Encrypt من التحقق من النطاق)، والمنفذين 80 و443 مفتوحين للاتصالات الواردة عبر TCP في جدار الحماية (UFW)، إضافةً إلى المنفذ 443 عبر UDP إن فعّلت HTTP/3. احتفظ بعنوان بريد إلكتروني صالح لحساب ACME. للحصول على شهادات wildcard، ستحتاج أيضًا إلى وصول API إلى مزوّد DNS الخاص بك.
انشر Traefik باستخدام Docker Compose
أنشئ الشبكة والبنية الشجرية
أنشئ شبكة Docker مشتركة سيستخدمها Traefik وتطبيقاتك، ثم مجلدًا مخصصًا يحتوي على الملف
acme.json(مخزن الشهادات ومفاتيحها الخاصة):docker network create proxy mkdir -p /opt/traefik && cd /opt/traefik touch acme.json && chmod 600 acme.jsonأنشئ الملف قبل التشغيل الأول: إذا لم يكن المسار المربوط موجودًا، يُنشئ Docker مجلدًا مكانه ولا يعود Traefik قادرًا على الكتابة فيه. الصلاحيات 600 إلزامية: يرفض Traefik ملفًا يستطيع مستخدمون آخرون قراءته.
هيّئ نقاط الدخول (entrypoints) ومحلّل ACME
ضع هذا الملف في
/opt/traefik/docker-compose.yml. يعلن نقطتَي دخول (webعلى :80، وwebsecureعلى :443)، وcertificateResolver من Let's Encrypt يُتحقَّق منه عبر تحدي HTTP، واكتشاف الحاويات عبر مقبس Docker المربوط للقراءة فقط، ولوحة التحكم:services: traefik: image: traefik:v3.7 container_name: traefik restart: unless-stopped ports: - "80:80" - "443:443" - "443:443/udp" command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.network=proxy" - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entrypoint.to=websecure" - "--entrypoints.web.http.redirections.entrypoint.scheme=https" - "--entrypoints.websecure.address=:443" - "--entrypoints.websecure.http3=true" - "[email protected]" - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json" - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web" - "--api.dashboard=true" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./acme.json:/acme.json" networks: - proxy labels: - "traefik.enable=true" - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)" - "traefik.http.routers.dashboard.entrypoints=websecure" - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt" - "traefik.http.routers.dashboard.service=api@internal" - "traefik.http.routers.dashboard.middlewares=dashboard-auth" - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$05$$REMPLACER_PAR_LE_HASH" networks: proxy: external: trueالخيار
exposedbydefault=falseأساسي: من دونه تُنشر كل حاوية على الخادم، بما فيها قاعدة بياناتك. ثبّت الفرع (v3.7) بدلًا منlatest، وتابع الإصدارات قبل الانتقال إلى إصدار فرعي جديد.افرض إعادة التوجيه من HTTP إلى HTTPS
تُعلَن إعادة التوجيه مباشرةً على نقطة الدخول
web، بالخيارين--entrypoints.web.http.redirections.entrypoint.to=websecureو...entrypoint.scheme=httpsالموجودين أصلًا في الملف أعلاه. هذا أبسط وأكثر أمانًا من موجّه «catch-all» مع برمجية وسيطة: تُحوَّل كل حركة المرور غير المشفّرة إلى HTTPS بإعادة توجيه دائمة، دون علامة تُكرَّر على كل خدمة، ويواصل تحدي HTTP الخاص بـ Let's Encrypt المرور عبر المنفذ 80.أمّن لوحة التحكم
تُعرض لوحة التحكم على
traefik.example.comخلف البرمجية الوسيطةbasicauthالمسمّاةdashboard-auth. ولّد تجزئة bcrypt (الحزمةapache2-utilsعلى Debian/Ubuntu) مع مضاعفة علامات$، كما تشترط قيمة علامة داخل ملف Compose:apt install -y apache2-utils htpasswd -nB admin | sed -e 's/\$/\$\$/g'الصق النتيجة مكان
admin:$$2y$$05$$REMPLACER_PAR_LE_HASH. التجزئة الملصقة بعلامات$مفردة يقرؤها Compose كمتغيرات فتتعطل المصادقة. لا تترك أبدًا الراية--api.insecure=trueفي الإنتاج: فهي تنشر لوحة التحكم دون مصادقة.شغّل Traefik
ابدأ المكدّس وتابع السجلّات:
cd /opt/traefik docker compose up -d docker compose logs -f traefikيُفترض أن ترى مزوّد Docker يبدأ، ثم الموجّه
dashboardيرتبط، دون أي خطأ ACME. أثناء التجارب، أضِف مؤقتًا--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory: يصدر خادم staging من Let's Encrypt شهادات لا تثق بها المتصفحات، لكنه يحميك من حد المعدل (rate limit) في بيئة الإنتاج إذا فشلت تهيئة ما مرارًا. احذف الخيار وأفرغacme.jsonقبل الانتقال إلى الإنتاج.اربط تطبيقًا
يعيش كل تطبيق في ملف
docker-compose.ymlخاص به، مربوطًا بشبكةproxyوموصوفًا بعلاماته:services: app: image: ghcr.io/example/app:1.0.0 restart: unless-stopped networks: - proxy labels: - "traefik.enable=true" - "traefik.http.routers.app.rule=Host(`app.example.com`)" - "traefik.http.routers.app.entrypoints=websecure" - "traefik.http.routers.app.tls.certresolver=letsencrypt" - "traefik.http.services.app.loadbalancer.server.port=3000" networks: proxy: external: trueعند تنفيذ
docker compose up -d، يكتشف Traefik الحاوية ويحصل على الشهادة ويفعّل المسار في ثوانٍ، دون المساس بتهيئته الخاصة. تحدد العلامةloadbalancer.server.portالمنفذ الداخلي للتطبيق، وتصبح ضرورية حين تعرض الصورة أكثر من منفذ. يجب أن يكون اسم الموجّه (appهنا) فريدًا على مستوى الخادم كله.تحقّق من الشهادة وإعادة التوجيه
تحقّق من جهاز خارج خادم VPS:
curl -I http://app.example.com curl -I https://app.example.com dig +short app.example.comيجب أن يعيد الطلب الأول إعادة توجيه دائمة نحو
https://، والثاني الرمز200(أو رمز تطبيقك) مع شهادة Let's Encrypt صالحة، ويجب أن يعرضdigعنوان IP الخاص بالخادم. تسرد لوحة التحكم أيضًا كل موجّه مع محلّل شهادته. المنفذ 80 الذي يرفض الاتصال يشير في الغالب إلى جدار الحماية.
برمجيات وسيطة مفيدة في الإنتاج
تُعلَن البرمجية الوسيطة في Traefik عبر علامة، مرة واحدة، ثم تُربط بموجّه أو أكثر عبر traefik.http.routers.<router>.middlewares=<name1>,<name2>. لذا تعرّفها على الخدمة المعنية دون المساس بالتهيئة المركزية لـ Traefik. إليك تلك التي تفيد على كل خادم VPS تقريبًا.
خمس برمجيات وسيطة يجب معرفتها
- BasicAuth على أداة إدارة (Adminer وFlower…):
traefik.http.middlewares.adminauth.basicauth.users=admin:$$2y$$05$$...، ثمtraefik.http.routers.myadmin.middlewares=adminauth. القاعدة نفسها لمضاعفة$كما في لوحة التحكم. - تحديد معدل الطلبات أمام واجهة API أو نموذج:
traefik.http.middlewares.ratelimit.ratelimit.average=100و...ratelimit.period=1sو...ratelimit.burst=200تسمح بـ 100 طلب في الثانية في المتوسط، مع دفعات تصل إلى 200. دونaverageيكون الحد معطّلًا. - ترويسات الأمان: تضع البرمجية الوسيطة
headersترويسة HSTS (stsSeconds=31536000وstsIncludeSubdomains=true)، وX-Frame-Options: DENY(frameDeny=true)، وX-Content-Type-Options: nosniff(contentTypeNosniff=true)، دون ملف تهيئة منفصل. - إعادة توجيه www إلى النطاق المجرد:
redirectregexمعregex=^https://www\.(.+)وreplacement=https://$${1}وpermanent=true. لا تنسَ إعلان المضيفين معًا في قاعدة الموجّه حتى تغطي الشهادةwww. - الضغط: يفعّل
traefik.http.middlewares.compress.compress=trueكلًّا من gzip وBrotli وZstandard بحسب ما يقبله المتصفح، دون أي إعداد في جهة التطبيق.
للحصول على شهادة wildcard (*.example.com) وتجنّب عرض كل نطاق فرعي، انتقل من httpChallenge إلى dnsChallenge: فهو التحدي الوحيد الذي يصدر شهادة wildcard. مع Cloudflare، أعلن --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare ومرّر إلى Traefik المتغير CF_DNS_API_TOKEN، وهو رمز API مقيَّد بالصلاحيتين Zone / DNS / Edit وZone / Zone / Read. يعمل الزوج القديم CF_API_EMAIL + CF_API_KEY أيضًا، لكنه يتطلب مفتاح API العام الذي يفتح الحساب كله: فضّل الرمز. يُثبت Traefik عندها ملكية النطاق عبر سجل TXT، وهو ما يعمل حتى للخدمات غير المعروضة علنًا.
فعّل HTTP/3 (QUIC)
يفعّله ملف Compose أعلاه أصلًا: --entrypoints.websecure.http3=true على نقطة دخول TLS، ونشر المنفذ 443:443/udp. يستمع Traefik عندها عبر UDP على المنفذ نفسه الذي تستخدمه نقطة دخول TCP؛ يبدأ الاتصال دائمًا عبر TCP ثم ينتقل المتصفح إلى QUIC في الجولة التالية. شرطان: لا تُخدَم عبر HTTP/3 إلا الموجّهات المفعَّل فيها TLS، ويجب أن يسمح جدار الحماية بمرور المنفذ 443 عبر UDP (ufw allow 443/udp). إذا نشرت منفذ UDP مختلفًا عن منفذ نقطة الدخول، يعلن الخيار http3.advertisedPort المنفذ الصحيح. للتحقق، استخدم curl مبنيًّا بدعم HTTP/3: curl --http3 -I https://app.example.com.
القادم من Traefik v2: ما الذي يتعطل
يحافظ الإصدار v3 على توافق تهيئة التوجيه في v2، لكنه يغيّر الصياغة الافتراضية للقواعد ويرفض الإقلاع مع عدة خيارات أُزيلت. للترحيل دون إعادة كتابة كل شيء دفعة واحدة، أضِف --core.defaultRuleSyntax=v2 إلى تهيئة التثبيت: تستمر قواعدك القديمة في العمل، وتنقل الموجّهات واحدًا تلو الآخر إلى صياغة v3، ثم تحذف الخيار. تنبّه سجلّات Traefik إلى كل خيار مُهمَل ما زال مستخدمًا: اقرأها بعد التشغيل الأول. التغييرات التي توقع المستخدمين أكثر من غيرها:
التغييرات الكاسرة في v3
- Swarm: لم يعد الخيار
swarmModeفي مزوّد Docker موجودًا، وهو يمنع الإقلاع. أصبح لـ Docker Swarm مزوّد خاص به (--providers.swarm). - قواعد التوجيه: يصبح
HeadersوHeadersRegexpعلى التواليHeaderوHeaderRegexp، ويختفيHostHeaderلصالحHost، ولم تعد معظم أدوات المطابقة تقبل إلا قيمة واحدة. - المسارات: لم يعد
PathوPathPrefixيقرآن تعبيرًا نمطيًا ولا عنصرًا نائبًا مثل{id}، فلا يطابق مسار كهذا أي شيء بعد الآن. انتقل إلىPathRegexpالذي يتبع صياغة regexp في Go، مثلHostRegexp. - برمجيات وسيطة أُعيدت تسميتها أو خُفّفت: يصبح
IPWhiteListباسمIPAllowList(بالخيارات نفسها)، وتفقد البرمجية الوسيطةheadersالخياراتsslRedirectوsslTemporaryRedirectوsslHostوsslForceHostوfeaturePolicy. - Content-Type: لم يعد Traefik يخمّن نوع استجابة لم يحدد الخادم الخلفي نوعها؛ أضِف البرمجية الوسيطة
ContentTypeإن كان تطبيق ما يعتمد على ذلك. - مزوّدات وأدوات مراقبة أُزيلت: تمنع Marathon وRancher v1 وTraefik Pilot ومقاييس InfluxDB v1 الإقلاع؛ ويمر التتبع (tracing) عبر OpenTelemetry وحده (لا تصدير مباشر بعد الآن إلى Jaeger أو Zipkin أو Datadog).
Traefik v3 أم Nginx أم Caddy أمام حاوياتك
مرّر الجدول أفقيًا
| المعيار | Traefik v3 | Nginx | Caddy 2 |
|---|---|---|---|
| التهيئة | علامات Docker أو YAML أو TOML، تُطبَّق أثناء التشغيل | ملفات vhost ثابتة، و`nginx -s reload` عند كل تغيير | Caddyfile أو واجهة JSON، وإعادة تحميل دون انقطاع |
| HTTPS تلقائي | مدمج (ACME: HTTP-01 وTLS-ALPN-01 وDNS-01) | أداة خارجية (certbot) ومهمة تجديد | مدمج ومفعَّل افتراضيًا |
| اكتشاف الحاويات | أصيل، عبر مقبس Docker | غائب: أداة خارجية أو تحرير يدوي | عبر الوحدة المجتمعية caddy-docker-proxy |
| HTTP/3 | مستقر منذ v3.0 (أبريل 2024)، بخيار واحد لكل نقطة دخول | تجريبي منذ nginx 1.25.0 (مايو 2023)، بتهيئة مخصصة | مفعَّل افتراضيًا منذ Caddy 2.6 (سبتمبر 2022) |
| سهولة التعلّم | متوسطة: موجّهات وخدمات وبرمجيات وسيطة يجب استيعابها | معروف للجميع، لكن HTTPS مع Docker يتطلبان أدوات إضافية | الأسرع لبضعة مواقع |
استكشاف الأعطال: الأخطاء الأكثر شيوعًا
تأتي معظم أعطال Traefik من أربعة مصادر: DNS أو جدار حماية يمنعان تحقق Let's Encrypt، والملف acme.json، وشبكة Docker ناقصة، وعلامات مكتوبة بشكل خاطئ. إليك الأعراض وطرق إصلاحها:
الأعراض وطرق الإصلاح
- لم يُحصل على الشهادة، وخطأ ACME من نوع
unauthorizedأو403في السجلّات: لا تستطيع Let's Encrypt الوصول إلى نطاقك. تحقّق من الخارج أن المنفذ 80 يستجيب (curl -I http://app.example.com) وأن DNS يشير إلى الخادم (dig +short app.example.com). خلف شبكة CDN في وضع الوكيل، فضّلdnsChallenge. permissions 644 for /acme.json are too open, please use 600: يرفض المحلّل الملف. أصلح ذلك بـchmod 600 /opt/traefik/acme.jsonثم أعد تشغيل Traefik؛ يحمي هذا الفحص المفاتيح الخاصة المخزنة فيه.- المسار ظاهر في لوحة التحكم لكن مع
502 Bad Gateway: الحاوية ليست على شبكةproxy، أو المنفذ الداخلي خاطئ. تحقّق بـdocker inspect <container>(قسمNetworks)، وأضِف الشبكة أو العلامةloadbalancer.server.port، ثم أعد إنشاء الحاوية. على حاوية مرتبطة بعدة شبكات، تزيل العلامةtraefik.docker.network=proxyالالتباس. - علامات متجاهَلة ومسار غائب عن لوحة التحكم: تنقص العلامة
traefik.enable=true(إلزامية معexposedbydefault=false)، أو تعلن خدمتان اسم الموجّه نفسه. تشير سجلّات Traefik حينها إلى التعارض. - BasicAuth يرفض كلمة مرور صحيحة: علامات
$في التجزئة غير مضاعفة في ملفdocker-compose.yml. في ملف Compose تصبح كل$علامتين$$؛ أما في ملف تهيئة ديناميكية بصيغة YAML أو TOML فتُلصق التجزئة كما هي.
الخطوة التالية: تقوية المكدّس
يتولى Traefik التوجيه وTLS، لكن المكدّس الجاهز للإنتاج يتطلب أكثر من ذلك: فحوص الصحة (healthchecks)، وسياسة إعادة التشغيل، وتدوير السجلّات، وإبقاء الأسرار خارج ملف Compose، ونسخ الأحجام احتياطيًا (بما فيها acme.json). تتناول قائمة التحقق لـ Docker Compose في الإنتاج هذه النقاط واحدة تلو الأخرى. وإن كنت ما زلت مترددًا في اختيار الأداة، تساعدك مقارنة Caddy وTraefik وNginx Proxy Manager على الحسم بحسب عدد الخدمات والحاجة إلى الاكتشاف التلقائي.