شهادات SSL
يدعم FORGE استراتيجيات متعددة لشهادات SSL/TLS حسب طريقة نشرك ومتطلباتك. كل طريقة نشر -- Docker Compose أو Kubernetes أو SSH -- تتضمن إعدادات SSL مدمجة لضمان تقديم تطبيقك عبر HTTPS في الإنتاج.
نظرة سريعة على خيارات SSL
| الطريقة | التكلفة | التجديد التلقائي | الأفضل لـ |
|---|---|---|---|
| Let's Encrypt | مجاني | نعم (شهادات 90 يوماً) | معظم عمليات النشر |
| Cloudflare Proxy | مجاني | نعم (Cloudflare يُدير) | حماية DDoS و CDN |
| شهادة مخصصة | متفاوت | يدوي | المؤسسات، شهادات EV، wildcards |
توصية
لمعظم التطبيقات، Let's Encrypt هو الخيار الأفضل. إنه مجاني ومؤتمت بالكامل وموثوق من جميع المتصفحات. استخدم Cloudflare Proxy إذا كنت تحتاج أيضاً حماية DDoS وقدرات CDN.
Let's Encrypt
Let's Encrypt يوفر شهادات TLS مجانية ومؤتمتة موثوقة من جميع المتصفحات الرئيسية. الشهادات صالحة لـ 90 يوماً وتُجدد تلقائياً قبل انتهاء الصلاحية.
المتطلبات
قبل الحصول على شهادة Let's Encrypt، تأكد من:
- سجل DNS A لنطاقك يُشير إلى عنوان IP خادمك
- المنفذ 80 متاح من الإنترنت (للتحقق بتحدي HTTP-01)
- لديك عنوان بريد إلكتروني صالح لإشعارات انتهاء الصلاحية
مع Kubernetes (cert-manager)
cert-manager هو متحكم إدارة شهادات أصلي لـ Kubernetes يُؤتمت الإصدار والتجديد.
الخطوة 1: تثبيت cert-manager
# Install cert-manager in the cluster
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.yaml
# Verify installation
kubectl wait --for=condition=ready pod \
-l app.kubernetes.io/instance=cert-manager \
-n cert-manager --timeout=120sالخطوة 2: توليد manifests مع Let's Encrypt
forge deploy:k8s --ssl=letsencrypt --email=admin@myapp.comالخطوة 3: تطبيق ClusterIssuer
ملف cluster-issuer.yaml المُولّد يُعدّ Let's Encrypt:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: admin@myapp.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-account-key
solvers:
- http01:
ingress:
class: nginxkubectl apply -f k8s/cert-manager/cluster-issuer.yamlالخطوة 4: تطبيق Ingress مع TLS
Ingress المُولّد يُشير إلى ClusterIssuer عبر annotation:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- myapp.com
- admin.myapp.com
- api.myapp.com
secretName: myapp-tls
rules:
# ... قواعد التوجيهkubectl apply -f k8s/ingress.yamlالخطوة 5: التحقق من إصدار الشهادة
# Check certificate status
kubectl get certificate -n myapp
# View certificate details
kubectl describe certificate myapp-tls -n myapp
# Check certificate request
kubectl get certificaterequest -n myapp
kubectl get order -n myappاستخدم staging أولاً
للاختبار، استخدم خادم staging لـ Let's Encrypt لتجنب الوصول لحدود المعدل:
# In cluster-issuer.yaml, change:
server: https://acme-staging-v02.api.letsencrypt.org/directoryانتقل لخادم الإنتاج بمجرد التأكد من أن كل شيء يعمل.
مع Docker Compose (Caddy)
Caddy يتعامل مع Let's Encrypt تلقائياً بدون أي إعدادات. عندما يرى Caddy اسم نطاق حقيقي في إعداداته، يحصل على شهادات TLS ويُجددها بدون أي إعداد يدوي.
الخطوة 1: توليد ملف Compose للإنتاج
forge deploy:compose --env=production --ssl=letsencryptالخطوة 2: إعداد Caddy
ملف Caddyfile المُولّد:
{
email admin@myapp.com
}
myapp.com {
reverse_proxy web:3000
encode gzip
}
admin.myapp.com {
reverse_proxy admin:3001
encode gzip
}
api.myapp.com {
reverse_proxy api:8080
encode gzip
}الخطوة 3: بدء الـ stack
docker compose -f docker-compose.prod.yaml up -dCaddy سيقوم تلقائياً بـ:
- الحصول على شهادات من Let's Encrypt
- إعداد HTTPS على المنفذ 443
- إعادة توجيه HTTP إلى HTTPS
- تجديد الشهادات قبل انتهاء صلاحيتها
- تفعيل OCSP stapling
تخزين شهادات Caddy
Caddy يُخزّن الشهادات في Docker volume باسم caddy_data. هذا الـ volume يستمر عبر إعادة تشغيل الحاويات، لذا لا تُطلب الشهادات من جديد بدون داعٍ.
مع SSH (certbot)
لعمليات النشر التقليدية على الخادم بدون حاويات، استخدم certbot للحصول على شهادات Let's Encrypt وإدارتها.
الخطوة 1: توليد سكربت إعداد SSL
forge deploy:ssl --method=certbot --domain=myapp.com --email=admin@myapp.comالخطوة 2: تشغيل السكربت المُولّد على خادمك
ssh deploy@myapp.com 'bash -s' < deploy/ssl/setup-certbot.shالسكربت يُنفّذ:
#!/bin/bash
set -euo pipefail
# Install certbot
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
# Obtain certificates for all domains
sudo certbot certonly --nginx \
-d myapp.com \
-d admin.myapp.com \
-d api.myapp.com \
--email admin@myapp.com \
--agree-tos \
--non-interactive
# Certificates are stored in:
# /etc/letsencrypt/live/myapp.com/fullchain.pem
# /etc/letsencrypt/live/myapp.com/privkey.pemالخطوة 3: إعداد التجديد التلقائي
certbot يُعدّ systemd timer للتجديد التلقائي. تحقق أنه نشط:
# Check renewal timer
sudo systemctl status certbot.timer
# Test renewal (dry run)
sudo certbot renew --dry-runالخطوة 4: إعداد Nginx لاستخدام الشهادات
server {
listen 443 ssl http2;
server_name myapp.com;
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;
# Recommended SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://localhost:3000;
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;
}
}
server {
listen 80;
server_name myapp.com admin.myapp.com api.myapp.com;
return 301 https://$host$request_uri;
}Cloudflare Proxy
Cloudflare يوفر SSL/TLS مجاني عند توجيه حركة المرور عبر شبكتهم. هذا يضيف أيضاً حماية DDoS و CDN وقدرات Web Application Firewall (WAF).
الإعداد
الخطوة 1: أضف نطاقك إلى Cloudflare
- أنشئ حساب Cloudflare مجاني على cloudflare.com
- أضف نطاقك واتبع تعليمات إعداد DNS
- حدّث nameservers نطاقك للإشارة إلى Cloudflare
الخطوة 2: إعداد وضع SSL
في Cloudflare Dashboard > SSL/TLS:
| الوضع | الوصف | التوصية |
|---|---|---|
| Off | بدون تشفير | لا تستخدم أبداً |
| Flexible | يُشفّر من المتصفح إلى Cloudflare فقط | غير موصى به |
| Full | تشفير من طرف لطرف، يقبل self-signed على الخادم | مقبول |
| Full (Strict) | تشفير من طرف لطرف، يتطلب شهادة صالحة على الخادم | موصى به |
استخدم وضع Full (Strict)
استخدم دائماً وضع Full (Strict). هذا يتطلب شهادة صالحة على خادم الأصل (استخدم Cloudflare Origin Certificate أو Let's Encrypt). وضع Flexible يترك حركة المرور بين Cloudflare وخادمك بدون تشفير.
الخطوة 3: تثبيت Cloudflare Origin Certificate
Origin Certificates هي شهادات مجانية تُصدرها Cloudflare لتشفير حركة المرور بين Cloudflare وخادمك:
- اذهب إلى Cloudflare Dashboard > SSL/TLS > Origin Server
- اضغط "Create Certificate"
- اختر أسماء المضيفين (مثل
*.myapp.com،myapp.com) - اختر فترة الصلاحية (حتى 15 سنة)
- حمّل الشهادة والمفتاح الخاص
ثبّت على خادمك:
# Save certificate files
sudo mkdir -p /etc/ssl/cloudflare
sudo nano /etc/ssl/cloudflare/myapp.com.pem # Paste certificate
sudo nano /etc/ssl/cloudflare/myapp.com-key.pem # Paste private key
# Set permissions
sudo chmod 600 /etc/ssl/cloudflare/myapp.com-key.pemأعدّ Nginx لاستخدام Origin Certificate:
server {
listen 443 ssl http2;
server_name myapp.com;
ssl_certificate /etc/ssl/cloudflare/myapp.com.pem;
ssl_certificate_key /etc/ssl/cloudflare/myapp.com-key.pem;
location / {
proxy_pass http://localhost:3000;
}
}الخطوة 4: تفعيل ميزات الأمان الإضافية
في Cloudflare Dashboard، فعّل:
- Always Use HTTPS -- يُعيد توجيه كل حركة HTTP إلى HTTPS
- Automatic HTTPS Rewrites -- يُصلح مشاكل المحتوى المختلط
- Minimum TLS Version -- عيّن إلى TLS 1.2
- HSTS -- فعّل HTTP Strict Transport Security
الشهادات المخصصة
لمتطلبات المؤسسات مثل شهادات Extended Validation (EV) أو شهادات wildcard من CAs محددة أو شهادات organization-validated.
الإعداد
الخطوة 1: الحصول على شهادة من CA الخاص بك
أنشئ Certificate Signing Request (CSR):
# Generate private key and CSR
openssl req -new -newkey rsa:2048 -nodes \
-keyout myapp.com.key \
-out myapp.com.csr \
-subj "/C=US/ST=State/L=City/O=MyOrg/CN=myapp.com"أرسل CSR إلى Certificate Authority (DigiCert أو Sectigo أو غيرها) وحمّل الشهادة الصادرة.
الخطوة 2: التثبيت على خادمك
# Create certificate directory
sudo mkdir -p /etc/ssl/custom
# Copy certificate files
sudo cp myapp.com.crt /etc/ssl/custom/
sudo cp myapp.com.key /etc/ssl/custom/
sudo cp ca-bundle.crt /etc/ssl/custom/
# Create full chain
cat /etc/ssl/custom/myapp.com.crt /etc/ssl/custom/ca-bundle.crt \
> /etc/ssl/custom/myapp.com-fullchain.crt
# Set permissions
sudo chmod 600 /etc/ssl/custom/myapp.com.keyالخطوة 3: إعداد خادم الويب
server {
listen 443 ssl http2;
server_name myapp.com;
ssl_certificate /etc/ssl/custom/myapp.com-fullchain.crt;
ssl_certificate_key /etc/ssl/custom/myapp.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
}# Create TLS secret from certificate files
kubectl create secret tls myapp-tls \
--cert=myapp.com-fullchain.crt \
--key=myapp.com.key \
-n myappmyapp.com {
tls /etc/ssl/custom/myapp.com-fullchain.crt /etc/ssl/custom/myapp.com.key
reverse_proxy web:3000
}تجديد الشهادة
الشهادات المخصصة لا تُجدد تلقائياً. عيّن تذكيراً في التقويم للتجديد قبل انتهاء الصلاحية. معظم الشهادات صالحة لسنة واحدة.
مقارنة خيارات SSL
| الميزة | Let's Encrypt | Cloudflare Proxy | شهادة مخصصة |
|---|---|---|---|
| التكلفة | مجاني | مجاني (مع CF) | $10 - $500+/سنة |
| التجديد التلقائي | نعم (دورة 90 يوماً) | نعم (CF يُدير) | لا (يدوي) |
| جهد الإعداد | منخفض | متوسط | عالي |
| حماية DDoS | لا | نعم (مُضمّنة) | لا |
| CDN | لا | نعم (مُضمّنة) | لا |
| أنواع الشهادات | DV فقط | DV (proxy)، OV/EV (origin) | DV، OV، EV |
| دعم Wildcard | نعم (DNS-01) | نعم | نعم |
| ثقة المتصفحات | جميع المتصفحات | جميع المتصفحات | جميع المتصفحات |
| Kubernetes | cert-manager | وضع Proxy | Secret يدوي |
| Docker Compose | Caddy (تلقائي) | وضع Proxy | Volume يدوي |
| SSH / Bare Metal | certbot | وضع Proxy | تثبيت يدوي |
أوامر FORGE SSL
يوفر FORGE أوامر CLI لكل طريقة نشر:
# Kubernetes مع Let's Encrypt
forge deploy:k8s --ssl=letsencrypt --email=admin@myapp.com
# Docker Compose مع Caddy (Let's Encrypt تلقائي)
forge deploy:compose --ssl=letsencrypt --email=admin@myapp.com
# خادم SSH مع certbot
forge deploy:ssl --method=certbot --domain=myapp.com --email=admin@myapp.com
# توليد سكربتات إعداد SSL بدون تنفيذ
forge deploy:ssl --method=certbot --domain=myapp.com --output=./deploy/ssl/التحقق من إعدادات SSL
بعد النشر، تحقق من إعداد SSL:
# Check certificate details
openssl s_client -connect myapp.com:443 -servername myapp.com 2>/dev/null | \
openssl x509 -noout -subject -dates -issuer
# Test with curl
curl -vI https://myapp.com 2>&1 | grep -E "SSL|issuer|expire"
# Check all subdomains
for domain in myapp.com admin.myapp.com api.myapp.com; do
echo "--- $domain ---"
curl -sI "https://$domain" | head -1
doneأدوات عبر الإنترنت للاختبار الشامل:
- SSL Labs Server Test -- تحليل التقييم والإعدادات المُفصّل
- Security Headers -- التحقق من رؤوس أمان HTTP
استكشاف الأخطاء
الشهادة لا تُصدر
# cert-manager: Check certificate request status
kubectl describe certificaterequest -n myapp
kubectl describe order -n myapp
kubectl describe challenge -n myapp
# Common reasons:
# - DNS not pointing to server
# - Port 80 blocked by firewall
# - Rate limit exceeded (use staging server)الشهادة انتهت صلاحيتها
# certbot: Force renewal
sudo certbot renew --force-renewal
# cert-manager: Delete and recreate
kubectl delete certificate myapp-tls -n myapp
kubectl apply -f k8s/cert-manager/certificate.yamlتحذيرات المحتوى المختلط
تأكد أن جميع الموارد تُحمّل عبر HTTPS. تحقق من عناوين URL المُثبّتة بـ http:// في إعدادات تطبيقك والقوالب.
الخطوات التالية
- النشر باستخدام Docker Compose -- النشر مع HTTPS تلقائي
- النشر على Kubernetes -- التوسع مع cert-manager
- النشر عبر SSH -- إعداد الخادم التقليدي