أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

أتمتة مراقبة انتهاء شهادات SSL والدومين بـ GitHub Actions قبل ما الموقع يطير

📅 ٢٠ أبريل ٢٠٢٦⏱ 6 دقائق قراءة
أتمتة مراقبة انتهاء شهادات SSL والدومين بـ GitHub Actions قبل ما الموقع يطير

لو شهادة SSL خلصت يوم جمعة الساعة 3 الفجر، موقعك بيرجع للزوار برسالة NET::ERR_CERT_DATE_INVALID لحد الاتنين الصبح — و Google مش هيستنى، و SEO بيتأثر في 24 ساعة. الـ workflow اللي هنا بيمسك المشكلة دي قبل ما تحصل، بتكلفة صفر دولار.

المشكلة باختصار

كتير من الفرق بتعتمد على إن Let's Encrypt أو cert-manager "هيعمل renew لوحده". ده صحيح 95% من الوقت. المشكلة في الـ 5% الباقيين: DNS اتغير، rate limit من Let's Encrypt، webhook لـ cert-manager وقع، الشهادة اتجدّدت بس nginx مـعـملش reload. في حادثة Microsoft Teams يوم 3 فبراير 2020 شهادة انتهت وأوقفت الخدمة ساعات — وده فريق معاه موارد ضخمة. ركز: الأتمتة لوحدها مش كفاية، لازم verifier تاني بيتأكد إن الأتمتة شغالة فعلاً.

قفل رقمي فوق كود يرمز لشهادة SSL ومراقبة انتهاء صلاحيتها

ليه auto-renew بتاع Let's Encrypt مش كفاية لوحده

Let's Encrypt بيبعت إيميل قبل انتهاء الشهادة بـ 20 و 10 و 1 يوم — بس على الإيميل المسجّل وقت إصدار الشهادة. لو المطوّر ده ساب الشركة من سنتين، الإيميل بيتوه. كمان ACME v2 بيفرض rate limit قدره 50 شهادة/أسبوع لكل registered domain، فلو الـ renew فشل مرتين بسبب DNS propagation، ممكن توصل للـ limit وتفضل أسبوع كامل بدون شهادة.

والأهم: بدءًا من 2026 الصناعة بتتجه لشهادات عمرها 47 يوم بدل 398 يوم. يعني كل شهر تقريبًا في renew. لو واحد منهم فشل ومفيش monitor خارجي، الموقع بيطير.

الحل: GitHub Actions يفحص كل 12 ساعة ويبعت Slack

المبدأ بسيط: GitHub Actions بيشغّل openssl s_client على كل دومين، يحسب كام يوم فاضل، ويبعت Slack webhook على ثلاث مراحل — 30 يوم، 15 يوم، 7 أيام (قاعدة 30-15-7 المتعارف عليها في الصناعة).

ليه GitHub Actions مش سيرفرك؟ لأن الـ monitor المفروض يكون خارج البنية اللي بيراقبها. لو السيرفر وقع، cron المحلي مش هيبعت تنبيه. GitHub Actions ده SLA تاني مختلف تمامًا.

الخطوات

  1. اعمل repo جديد (خاص أو عام مش فارق) اسمه ssl-monitor.
  2. ضيف Slack Incoming Webhook في Settings → Secrets → Actions باسم SLACK_WEBHOOK.
  3. احفظ الملف اللي تحت في .github/workflows/ssl-check.yml.
  4. حدّث مصفوفة DOMAINS بدومينات موقعك.
  5. شغّل workflow_dispatch يدويًا مرة علشان تتأكد إن الـ Slack بيوصل.

الـ workflow كامل (انسخه وشغّله)

YAML
name: SSL & Domain Expiry Monitor

on:
  schedule:
    - cron: '0 */12 * * *'   # كل 12 ساعة
  workflow_dispatch:

jobs:
  check-ssl:
    runs-on: ubuntu-latest
    steps:
      - name: Install whois
        run: sudo apt-get update && sudo apt-get install -y whois

      - name: Check SSL and domain expiry
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        run: |
          DOMAINS=("ahmedhaies.com" "lms.ahmedhaies.com" "api.ahmedhaies.com")
          THRESHOLDS=(30 15 7)

          notify() {
            local msg="$1"
            curl -sS -X POST "$SLACK_WEBHOOK" \
              -H 'Content-type: application/json' \
              -d "{\"text\": \"$msg\"}"
          }

          for d in "${DOMAINS[@]}"; do
            # 1) SSL expiry
            EXP=$(echo | openssl s_client -servername "$d" -connect "$d:443" 2>/dev/null \
                 | openssl x509 -noout -enddate | cut -d= -f2)
            EXP_TS=$(date -d "$EXP" +%s)
            NOW_TS=$(date +%s)
            DAYS=$(( (EXP_TS - NOW_TS) / 86400 ))
            echo "SSL $d -> $DAYS days"

            for t in "${THRESHOLDS[@]}"; do
              if [ "$DAYS" -eq "$t" ]; then
                notify ":lock: SSL for *$d* expires in *$DAYS days* ($EXP)"
              fi
            done

            # 2) Domain (whois) expiry
            WEXP=$(whois "$d" | grep -iE 'Registry Expiry Date|Expiration Date' \
                   | head -1 | awk -F': ' '{print $2}')
            if [ -n "$WEXP" ]; then
              WEXP_TS=$(date -d "$WEXP" +%s)
              WDAYS=$(( (WEXP_TS - NOW_TS) / 86400 ))
              echo "Domain $d -> $WDAYS days"
              if [ "$WDAYS" -lt 60 ]; then
                notify ":earth_africa: Domain *$d* expires in *$WDAYS days*"
              fi
            fi
          done

الـ workflow ده بيشتغل على الـ ubuntu-latest runner المجاني، كل تشغيلة بتاخد حوالي 15 ثانية. لو عندك 10 دومينات و بتتشغّل كل 12 ساعة، ده ≈ 600 ثانية شهريًا من الـ 2000 دقيقة المجانية. يعني فعلاً بصفر دولار.

شاشة تعرض لوجات GitHub Actions أثناء فحص شهادات SSL عبر openssl

مثال واقعي: فريق صغير معاه 12 دومين

فرضية: شركة SaaS فيها 12 دومين/subdomain، كلهم على Let's Encrypt مع cert-manager في Kubernetes. آخر 6 شهور حصل عندهم موقفين: مرة api-staging.x.com الشهادة فشلت renew بسبب DNS record اتشال بالغلط، ومرة status.x.com الشهادة اتجدّدت بس nginx-ingress مـعـمـلـش reload. المرتين الفريق اكتشف الموقف من Twitter.

بعد ما حطوا الـ workflow ده، بقى في تنبيه Slack يوم 30 قبل الانتهاء. الـ ROI الحقيقي مش في توفير الوقت — الـ ROI إنهم عرفوا يلحقوا قبل ما العميل يبلّغهم.

مفهوم سريع: ليه openssl s_client ده بالظبط

لو المفهوم جديد عليك، خليني أوضّح بمثال: تخيل إنك بتدق الباب على الموقع وتقول "ورّيني البطاقة الشخصية بتاعتك". الـ openssl s_client -connect host:443 بيفتح connection حقيقي TLS ويطلب الشهادة، و openssl x509 -enddate بيقرأ حقل "تاريخ الانتهاء" من الشهادة دي. ده أدق بكتير من إنك تسأل خدمة خارجية، لأنه بيحاكي نفس اللي المتصفح بيعمله. تقنيًا: الأمر ده بيعمل TLS handshake، بياخد الـ X.509 certificate chain، ويطبع الحقل notAfter.

trade-offs: GitHub Actions vs الأدوات التانية

  • مقابل Uptime Kuma (self-hosted): Kuma أقوى في الـ UI ودعم أنواع فحوصات أكتر، بس محتاج سيرفر، RAM، ونسخ احتياطي. GitHub Actions: صفر صيانة، صفر سيرفر، بس UI محدود لـ logs الـ workflow.
  • مقابل Better Uptime / BetterStack: بيدّيك dashboard احترافي وتنبيهات SMS، بس الـ free tier بيقف عند 10 monitors ومش بيغطي whois. بتكسب UI، بتخسر ~30$/شهر للـ tier الجاي.
  • مقابل cert-manager alerts داخل k8s: cert-manager بيبعت Prometheus metrics، بس لو الـ Prometheus نفسه في نفس الكلاستر ووقع، مش هتعرف. الـ monitor الخارجي بيحل المشكلة دي.
  • الـ trade-off الحقيقي هنا: بتكسب صفر تكلفة وصفر صيانة، بتخسر الـ rich alerting (SMS، call، PagerDuty integration). لو موقعك mission-critical ومحتاج SLA < 5 دقايق على الـ alert، كمّل معاه أداة مدفوعة كمان.

أخطاء شائعة لازم تتجنبها

  • whois rate limit: registrars كتير بيحطّوا rate limit على whois. لو عندك > 20 دومين، اعمل الفحص ده مرة يوميًا بس مش كل 12 ساعة.
  • SNI: لازم -servername موجود في أمر openssl، وإلا هتجيب default cert بتاع السيرفر مش اللي للـ domain المطلوب.
  • self-hosted runners: متشغّلش الـ workflow ده على runner جوا نفس البنية اللي بتراقبها. ده بيلغي قيمة "monitor خارجي".
  • notify threshold == exactly N: الكود فوق بيبعت Slack لما الأيام تساوي 30 أو 15 أو 7. لو الـ workflow فات اليوم ده لأي سبب، مش هتعرف. بديل أأمن: استخدم -le مع ملف state محفوظ في artifact علشان متكررش الـ alert.

متى لا تستخدم هذه الطريقة

الـ workflow ده مش مناسب في 3 حالات:

  • عندك أكتر من 200 دومين — GitHub Actions minutes هتبدأ تكلّف، وبرضو بتوصل حدود whois. استخدم أداة متخصصة زي SSLMate Cert Spotter أو Prometheus blackbox exporter.
  • محتاج SLA على الـ monitoring نفسه < 15 دقيقة — GitHub Actions فيه delays في الـ scheduled cron أحيانًا بتوصل 20–40 دقيقة وقت الزحمة.
  • عندك Datadog أو New Relic أصلاً — فيهم SSL check جاهز، متعملش شغل مكرر.

الخطوة التالية

افتح repo جديد دلوقتي، الصق الـ workflow فوق، حط 3 دومينات بس في البداية، وشغّل workflow_dispatch يدوي. لو الـ Slack وصل في أول دقيقة، إنت خلاص مغطّى. لو ما وصلش، افحص قيمة SLACK_WEBHOOK في الـ secrets وجرّب تبعت curl من تيرمنالك مباشرة علشان تعزل السبب.

مصادر

  • Let's Encrypt — Rate Limits (ACME v2)
  • GitHub Actions — Scheduled workflows & secrets
  • OpenSSL s_client manual
  • Microsoft Teams outage — expired certificate (Feb 2020)
  • Dotcom-Monitor — SSL Certificate Expiration Guide 2026
  • UptimeObserver — 47-Day SSL Validity Era

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة