Linux: مشروع التخرج — بناء خادم تطوير ويب من الصفر

هذا هو المشروع النهائي للدورة. ستجمع كل مهارات الدروس الخمسة والعشرين السابقة — بدءًا من آلة عارية لبناء خادم تطوير ويب يعمل بالكامل.

📋 المتطلبات المسبقة: يجب إكمال كل الدروس السابقة

1. ما ستتعلمه


2. تحدي شياو مينغ "الانطلاق غدًا"

(1) نقطة الألم: خادم جديد، يجب الانطلاق غدًا

شركة شياو مينغ اشترت خادمًا سحابيًا. المدير قال: "الانطلاق غدًا." أمام آلة عارية بIP وكلمة مرور root فقط، كان شياو مينغ يحتاج تطبيق كل ما تعلّمه.

(2) 10 خطوات من آلة عارية إلى الإنتاج

وضع شياو مينغ خطة:

BASH

1. دخول SSH           → 6. نشر تطبيق Node.js
2. إنشاء مستخدم + تعزيز SSH → 7. إعداد شهادة HTTPS
3. إعداد جدار الحماية     → 8. إعداد مدير العمليات PM2
4. تثبيت Nginx       → 9. نسخ احتياطي آلي
5. إعداد الوكيل العكسي → 10. فحص الصحة + التنبيه

(3) الفائدة: سلّم خلال 3 ساعات

بدأ شياو مينغ الساعة 2 ظهرًا، ونفّذ الخطة خطوة بخطوة، وأكمل النشر الكامل بحلول الساعة 5 مساءً. المدير اختبره ورد: "جيد، جاهز للانطلاق."


3. نقاط المعرفة

(1) قائمة تهيئة الخادم

BASH
□ دخول SSH (كلمة مرور root)
□ تحديث النظام (apt update && apt upgrade)
□ إنشاء مستخدم عادي (useradd -m -s /bin/bash)
□ إعداد sudo (usermod -aG sudo)
□ مصادقة مفاتيح SSH
□ تعطيل الجذر + الدخول بكلمة المرور
□ جدار الحماية (ufw: 22/80/443)
□ حماية fail2ban
□ تحديثات أمان تلقائية
⚠️ تحذير: قبل تعطيل الدخول بكلمة المرور، تأكد أن مفاتيح SSH مهيأة ومختبرة. وإلا ستُغلق خارج الخادم. الترتيب الموصى به: 1) هيّئ المفاتيح؛ 2) ادخل بنجاح بالمفاتيح؛ 3) تأكد أن كل شيء يعمل، ثم عطّل الدخول بكلمة المرور. أبقِ دائمًا جلسة SSH قائمة كشبكة أمان.

(2) رصة LEMP (Linux + Nginx + MySQL + PHP/Node.js/Python)

BASH
# Nginx
sudo apt install nginx
sudo systemctl enable --now nginx

# إذا كنت تستخدم MySQL
sudo apt install mysql-server
sudo mysql_secure_installation

# مقارنة نشر التطبيقات
الطريقة الأفضل لـ المميزات العيوب
خدمة systemd أي لغة أصلي، ناضج، مستقر إعداد معقد قليلًا
PM2 Node.js بدون إعداد، مراقبة مدمجة Node.js فقط
Gunicorn/uWSGI Python أداء جيد، معيار WSGI يحتاج Nginx
Docker Compose تطبيقات معقدة بيئة متسقة، سهل التوسع يتطلب معرفة Docker

(3) ▶ مثال: نشر تطبيق Node.js على Nginx

BASH
#!/bin/bash
# Deploy a Node.js app to production

# 1. إنشاء دليل التطبيق
sudo mkdir -p /opt/webapp
sudo chown -R alice:alice /opt/webapp

# 2. استنساخ ملفات التطبيق (بافتراض أنه مطوّر فعلًا)
git clone https://github.com/example/webapp.git /opt/webapp

# 3. تثبيت الاعتماديات والبناء
cd /opt/webapp
npm install
npm run build

# 4. إعداد PM2
npm install -g pm2
pm2 start server.js --name webapp -i max
pm2 save
pm2 startup

# 5. إعداد وكيل Nginx العكسي
sudo tee /etc/nginx/sites-available/webapp << 'EOF'
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        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;
    }

    location /static/ {
        alias /opt/webapp/public/;
        expires 30d;
    }
}
EOF

sudo ln -sf /etc/nginx/sites-available/webapp /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

الإخراج:

TEXT
npm WARN deprecated package@1.0.0
added 245 packages in 12s
Building production bundle...
[PM2] Process webapp started
┌────┬──────────┬─────────┬─────────┐
│ id │ name     │ status  │ cpu     │
├────┼──────────┼─────────┼─────────┤
│ 0  │ webapp   │ online  │ 0%      │
└────┴──────────┴─────────┴─────────┘
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

(4) ▶ مثال: HTTPS (Let's Encrypt + certbot)

💡 نصيحة: certbot يضيف تلقائيًا مؤقت systemd أو مهمة cron لتجديد الشهادات. بعد الإعداد، اختبر عملية التجديد بـsudo certbot renew --dry-run. من الحكمة أيضًا ضبط تذكير تقويمي للتحقق يدويًا من نجاح التجديد قبل حوالي 30 يومًا من الانتهاء (حوالي اليوم 60)، في حال كسر تغيير إعداد التجديد التلقائي.

BASH
# تثبيت certbot
sudo apt install certbot python3-certbot-nginx -y

# الحصول على شهادة (تعدّل إعدادات Nginx تلقائيًا)
sudo certbot --nginx -d example.com -d www.example.com

# عرض الشهادات
sudo certbot certificates

# التحقق من التجديد التلقائي
sudo certbot renew --dry-run

# الشهادة تتجدد تلقائيًا (certbot يضيف مؤقت systemd)
sudo systemctl list-timers | grep certbot

الإخراج:

TEXT
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem

Found the following certs:
  Certificate Name: example.com
    Expiry Date: 2026-10-05 10:23:45+00:00 (VALID: 89 days)

Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/example.com/fullchain.pem

certbot.timer  certbot.service  Sat 2026-07-08 00:00:00 UTC  13h left

(5) ▶ مثال: سكريبت فحص الصحة

BASH
#!/bin/bash
# health-check.sh - فحص صحة متعدد الخدمات

check_service() {
    local name="$1"
    local url="$2"
    local expect="${3:-200}"

    local status=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null)

    if [ "$status" = "$expect" ]; then
        echo "[OK] $name: $status (healthy)"
        return 0
    else
        echo "[FAIL] $name: $status (unhealthy)"
        return 1
    fi
}

echo "=== System Health Check ==="
echo "Time: $(date)"
echo ""

# موارد النظام
echo "CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}')%"
echo "Memory: $(free -h | grep Mem | awk '{print $3 "/" $2}')"
echo "Disk: $(df -h / | tail -1 | awk '{print $3 "/" $2 " (" $5 ")"}')"
echo ""

# خدمات الويب
check_service "Nginx" "http://localhost/nginx_status" 200
check_service "WebApp" "http://localhost:3000/health" 200
check_service "HTTPS" "https://example.com/" 200

echo ""
echo "=== Check Complete ==="

الإخراج:

TEXT
=== System Health Check ===
Time: Tue Jul  7 10:30:00 UTC 2026

CPU: 2.3%
Memory: 1.2Gi/3.9Gi
Disk: 12G/50G (24%)

[OK] Nginx: 200 (healthy)
[OK] WebApp: 200 (healthy)
[OK] HTTPS: 200 (healthy)

=== Check Complete ===

(6) ▶ مثال: سكريبت نشر كامل

⚠️ تحذير: نمط curl -fsSL URL | bash - ينفّذ سكريبتًا بعيدًا مباشرة على جهازك، مما يحمل خطر هجوم سلسلة التوريد — إذا خُترق المصدر أو اختُطف DNS، قد تُنفّذ كودًا خبيثًا. في الإنتاج، الأسلوب الأأمن هو تحميل السكريبت ومراجعته أولًا، ثم تنفيذه: curl -fsSL URL -o setup.sh && less setup.sh && bash setup.sh.

BASH
#!/bin/bash
# setup-server.sh - بناء خادم تطوير ويب من الصفر
# الاستخدام: sudo ./setup-server.sh example.com

set -euo pipefail

DOMAIN="${1:-example.com}"
APP_DIR="/opt/webapp"
APP_PORT=3000
ADMIN_USER="admin"

echo "========================================"
echo "    Build Web Dev Server from Scratch"
echo "    Domain: $DOMAIN"
echo "========================================"

# 1. تحديث النظام
echo ""
echo ">>> 1/10 Updating system..."
apt update && apt upgrade -y

# 2. إنشاء مستخدم عادي
echo ""
echo ">>> 2/10 Creating admin user..."
if ! id "$ADMIN_USER" &>/dev/null; then
    useradd -m -s /bin/bash "$ADMIN_USER"
    usermod -aG sudo "$ADMIN_USER"
    echo "Set password for $ADMIN_USER:"
    passwd "$ADMIN_USER"

    # ملاحظة: أضف مفتاح SSH العام يدويًا إلى /home/$ADMIN_USER/.ssh/authorized_keys
    mkdir -p /home/$ADMIN_USER/.ssh
    cp /root/.ssh/authorized_keys /home/$ADMIN_USER/.ssh/ 2>/dev/null || true
    chown -R $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.ssh
    chmod 700 /home/$ADMIN_USER/.ssh
    chmod 600 /home/$ADMIN_USER/.ssh/authorized_keys
fi

# 3. تعزيز SSH
echo ""
echo ">>> 3/10 Hardening SSH..."
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
systemctl restart sshd

# 4. جدار الحماية
echo ""
echo ">>> 4/10 Configuring firewall..."
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

# 5. fail2ban
echo ""
echo ">>> 5/10 Installing fail2ban..."
apt install -y fail2ban
cat > /etc/fail2ban/jail.d/sshd.conf << EOF
[sshd]
enabled = true
maxretry = 3
bantime = 86400
findtime = 600
EOF
systemctl enable --now fail2ban

# 6. تثبيت Nginx
echo ""
echo ">>> 6/10 Installing Nginx..."
apt install -y nginx
systemctl enable --now nginx

# 7. تثبيت Node.js
echo ""
echo ">>> 7/10 Installing Node.js..."
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
npm install -g pm2

# 8. إعداد وكيل Nginx العكسي
echo ""
echo ">>> 8/10 Configuring Nginx..."
cat > /etc/nginx/sites-available/$DOMAIN << EOF
server {
    listen 80;
    server_name $DOMAIN www.$DOMAIN;

    location / {
        proxy_pass http://127.0.0.1:$APP_PORT;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host \$host;
        proxy_cache_bypass \$http_upgrade;
        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;
    }
}
EOF

ln -sf /etc/nginx/sites-available/$DOMAIN /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx

# 9. شهادة HTTPS
echo ""
echo ">>> 9/10 Configuring HTTPS..."
apt install -y certbot python3-certbot-nginx
certbot --nginx --non-interactive --agree-tos \
    --email admin@$DOMAIN \
    -d $DOMAIN -d www.$DOMAIN \
    || echo "Warning: certbot failed, run manually: sudo certbot --nginx -d $DOMAIN"

# 10. سكريبت فحص الصحة
echo ""
echo ">>> 10/10 Setting up health check..."
mkdir -p /opt/scripts

cat > /opt/scripts/health-check.sh << 'EOF'
#!/bin/bash
WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK"

for svc in nginx sshd fail2ban; do
    if ! systemctl is-active --quiet "$svc"; then
        echo "[$(date)] FAIL: $svc is down" >> /var/log/health.log
    fi
done

DISK=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
[ "$DISK" -gt 85 ] && echo "[$(date)] WARNING: Disk usage ${DISK}%" >> /var/log/health.log
EOF

chmod +x /opt/scripts/health-check.sh

# إضافة إلى cron
(crontab -l 2>/dev/null; echo "*/10 * * * * /opt/scripts/health-check.sh > /dev/null 2>&1") | crontab -

echo ""
echo "========================================"
echo "Server setup complete!"
echo ""
echo "Deployment info:"
echo "  Admin user: $ADMIN_USER"
echo "  Nginx: http://$DOMAIN"
echo "  HTTPS: https://$DOMAIN (if certbot succeeded)"
echo "  Node.js: $(node --version)"
echo "  PM2: $(pm2 --version)"
echo ""
echo "Next steps:"
echo "  1. Deploy your app code to $APP_DIR"
echo "  2. Start the app: pm2 start $APP_DIR/server.js --name webapp"
echo "  3. Log in as $ADMIN_USER (root login is disabled)"
echo "========================================"

الإخراج:

TEXT
========================================
    Build Web Dev Server from Scratch
    Domain: example.com
========================================

>>> 1/10 Updating system...
...
========================================
Server setup complete!
Admin user: admin
Nginx: http://example.com
Node.js: v20.11.0
========================================

(7) ▶ مثال شامل: التحقق الكامل من النشر

BASH
#!/bin/bash
# verify-deploy.sh - التحقق من النشر

echo "========================================"
echo "    Deployment Verification"
echo "    Time: $(date)"
echo "========================================"
echo ""

errors=0

check() {
    local desc="$1"
    shift
    if "$@" &>/dev/null; then
        echo "  [OK] $desc"
    else
        echo "  [FAIL] $desc"
        errors=$((errors + 1))
    fi
}

echo "1. System Services"
echo "-----------"
check "Nginx running" systemctl is-active nginx
check "SSH running" systemctl is-active sshd
check "fail2ban running" systemctl is-active fail2ban
echo ""

echo "2. Network"
echo "--------"
check "Port 80 listening" bash -c "ss -tlnp | grep -q ':80 '"
check "Port 443 listening" bash -c "ss -tlnp | grep -q ':443 '"
check "ufw enabled" bash -c "ufw status | grep -q active"
echo ""

echo "3. HTTP Service"
echo "-------------"
check "Local Nginx responding" bash -c "curl -s -o /dev/null -w '%{http_code}' http://localhost | grep -q 200"
check "App process running" bash -c "pm2 list 2>/dev/null | grep -q 'online' || pgrep -f 'node server' > /dev/null"
echo ""

echo "4. Security"
echo "--------"
check "Root SSH disabled" bash -c "grep '^PermitRootLogin' /etc/ssh/sshd_config | grep -q 'no'"
check "Password login disabled" bash -c "grep '^PasswordAuthentication' /etc/ssh/sshd_config | grep -q 'no'"
echo ""

echo "5. Resources"
echo "--------"
echo "  CPU: $(top -bn1 | grep 'Cpu(s)' | awk '{print $2"%"}')"
echo "  Memory: $(free -h | grep Mem | awk '{print $3"/"$2}')"
echo "  Disk: $(df -h / | tail -1 | awk '{print $3"/"$2"("$5")"}')"
echo ""

echo "========================================"
if [ $errors -eq 0 ]; then
    echo "All verifications passed!"
else
    echo "$errors check(s) failed — please investigate"
fi
echo "========================================"

الإخراج:

TEXT
========================================
    Deployment Verification
    Time: Tue Jul  7 10:45:00 UTC 2026
========================================

1. System Services
-----------
  [OK] Nginx running
  [OK] SSH running
  [OK] fail2ban running

2. Network
--------
  [OK] Port 80 listening
  [OK] Port 443 listening
  [OK] ufw enabled

3. HTTP Service
-------------
  [OK] Local Nginx responding
  [OK] App process running

4. Security
--------
  [OK] Root SSH disabled
  [OK] Password login disabled

5. Resources
--------
  CPU: 2.3%
  Memory: 1.2Gi/3.9Gi
  Disk: 12G/50G(24%)

========================================
All verifications passed!
========================================

❓ أسئلة شائعة

س: ما أول شيء يجب فعله عند نشر خادم؟ ج: تحديث النظام (apt update && apt upgrade)، ثم إنشاء مستخدم عادي وإعداد مصادقة مفاتيح SSH. لا تعمل كجذر على المدى الطويل أبدًا.

س: ما العلاقة بين وكيل Nginx العكسي والتطبيق؟ ج: Nginx هو "الباب الأمامي" والتطبيق هو "الأشخاص بالداخل." المستخدمون يصلون إلى Nginx على المنفذ 80/443 ← Nginx يقرر أي تطبيق خلفي يحوّل الطلب إليه. Nginx يتعامل مع الملفات الثابتة، وإنهاء SSL، وموازنة الحمل؛ التطبيق يركز على المنطق التجاري.

س: هل شهادات HTTPS تحتاج تجديد دوري؟ ج: شهادات Let's Encrypt صالحة لـ90 يومًا. certbot يضيف تلقائيًا مؤقت systemd للتجديد. تحقق بـ: systemctl list-timers | grep certbot. تجديد يدوي: sudo certbot renew.

س: ما المقاييس التي يجب مراقبتها على خادم؟ ج: المقاييس الأساسية: استخدام المعالج، واستهلاك الذاكرة، ومساحة القرص (تنبيه عند أكثر من 80%)، وقرص I/O، وحركة الشبكة، وهل الخدمات تعمل، وانتهاء شهادة SSL.

س: كيف أتحقق من الأمان بعد النشر؟ ج: شغّل أدوات مسح أمني: 1) sudo ufw status لفحص المنافذ. 2) ss -tlnp لفحص عناوين استماع الخدمات. 3) grep "Failed password" /var/log/auth.log | wc -l لفحص حجم الهجمات. 4) استخدم https://www.ssllabs.com/ssltest/ لاختبار إعدادات SSL.


📖 ملخص


📝 تمارين

  1. أساسي (⭐): باستخدام آلة افتراضية أو خادم سحابي، نفّذ سكريبت setup-server.sh من الصفر، وانشر تطبيق ويب Node.js أو Python بسيط، وادخل عبر وكيل Nginx العكسي
  2. متوسط (⭐⭐): هيّئ شهادة Let's Encrypt HTTPS (استخدم --dry-run للاختبار)، واكتب وانشر سكريبت فحص صحة، وأعد التنبيه (بريد أو webhook)
  3. متقدم (⭐⭐⭐⭐⭐): هيّئ استراتيجية نسخ احتياطي كاملة (cron + rsync نسخ احتياطي بعيد) وتأكد أن النسخ الاحتياطية قابلة للاستعادة، ثم اكتب سكريبت تحقق نشر آلي يفحص كل حالات الخدمات وإعدادات الأمان ومقاييس الأداء، ويُخرج تقرير قبول منسّق
Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%