المدوّنة · الخوادم ولينكس

«404 Not Found» على Nginx: الروابط الدائمة وملف الإعداد

· 6 دقائق قراءة

«404 Not Found» على Nginx: الروابط الدائمة وملف الإعداد

المشهد الأكثر تكراراً بعد نقل موقع أو تثبيت ووردبريس جديد على خادم Nginx هو: الصفحة الرئيسية تفتح بسلاسة وأناقة، ولكن بمجرد النقر على أي مقال أو صفحة داخلية تظهر شاشة بيضاء جافة تحمل عبارة «404 Not Found - nginx». هذا الموقف يصيب الكثيرين بالذعر ظناً منهم أن المقالات وقاعدة البيانات قد حُذفت، بينما الحقيقة التقنية البسيطة هي أن خادم الويب لم يتعلم بعد كيف يوجّه عناوين الروابط الافتراضية إلى ملف التشغيل الرئيسي.

يرجع ذلك إلى اختلاف معماري جوهري بين خادمي Apache وNginx؛ فبينما يعتمد أباتشي على ملف .htaccess الموزع في كل مجلد لقراءة قواعد إعادة التوجيه تلقائياً، يتجاهل Nginx ملفات .htaccess تماماً بدافع التصميم والأداء الفائق؛ حيث يعتمد محرك Nginx على بنية معالجة أحداث خفيفة (Event-driven Architecture عبر تقنية epoll) ترفض فحص القرص الصلب عند كل طلب بحثاً عن ملفات إعدادات محلية، وتشترط كتابة قواعد إعادة كتابة الروابط (URL Rewriting) مركزياً داخل ملف إعداد النطاق (Virtual Host).

لقطة شاشة لصفحة خطأ 404 Not Found الافتراضية في المتصفح الصادرة من خادم Nginx
شاشة خطأ 404 الصادرة عن Nginx: الخادم بحث عن مجلد أو ملف فعلي يطابق الرابط على القرص ولم يجده.

عندما تطلب عنواناً مخصصاً مثل https://example.com/my-first-post/، فإن هذا العنوان ليس ملفاً فيزيائياً حقيقياً مستقراً على القرص الصلب للسيرفر، بل هو مسار ظاهري جمالي (Pretty Permalink). مهمة خادم الويب هنا أن يتحقق بالترتيب: هل يوجد ملف بهذا الاسم؟ إذا كان الجواب لا، هل يوجد مجلد بهذا الاسم؟ إذا كان الجواب لا، عليه ألا يُظهر خطأ 404 في وجه الزائر فوراً، بل يجب أن يسلّم الطلب كاملاً إلى ملف التشغيل index.php مع الاحتفاظ بعنوان الرابط المطلوب عبر معايير الاستعلام (Arguments)، ليتولى سكربت الموقع قراءة الرابط واستخراج المقال المطابق من قاعدة البيانات.

الحل الجذري: إضافة توجيه try_files إلى إعدادات Nginx#

يعد توجيه try_files السلاح السحري في Nginx لمعالجة مسارات الروابط الدائمة لكافة المنصات الحديثة (WordPress, Laravel, Drupal, Ghost):

  1. سجّل الدخول إلى السيرفر عبر منفذ الأوامر SSH بصلاحيات sudo:
    ssh user@your-server-ip
  2. افتح ملف الإعداد الخاص بموقعك، والموجود عادة في المسار /etc/nginx/sites-available/:
    sudo nano /etc/nginx/sites-available/example.com
  3. ابحث عن كتلة الموقع الرئيسية location / { ... }. إذا لم تكن موجودة، أضفها داخل كتلة server { ... }:
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
  4. تأكد كذلك من وجود كتلة معالجة ملفات PHP مع تعريف ملف الفهرس index.php في سطر index بالأعلى:
    index index.php index.html index.htm;
    
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
  5. احفظ التعديل بالضغط على Ctrl + O ثم Enter، واخرج بالضغط على Ctrl + X.

شرح الآلية الهندسية لسطر try_files $uri $uri/ /index.php?$args;#

  • $uri: يفحص الخادم أولاً هل الطلب هو ملف حقيقي على القرص (مثل صورة logo.png أو ملف تنسيق style.css أو ملف جافا سكريبت)؟ إذا وجده يعرضه مباشرة للزائر دون استدعاء معالج PHP، مما يوفر موارد السيرفر.
  • $uri/: إذا لم يكن ملفاً مستقلاً، يفحص هل هو مجلد حقيقي موجود على القرص الصلب؟ إذا وجده يعرض محتواه أو ملف الفهرس التابع له.
  • /index.php?$args: إذا لم يكن ملفاً ولا مجلداً حقيقياً (وهي حالة كافة المقالات والتصنيفات والصفحات في ووردبريس)، يحوّل Nginx الطلب فوراً وبشكل داخلي إلى index.php مع تمرير نص الرابط والمتغيرات (Arguments) دون أي تعديل على عنوان المتصفح الظاهر للمستخدم.

حالات خاصة شائعة لخطأ 404 في خوادم Nginx#

1. الموقع مثبت داخل مجلد فرعي (Subdirectory)#

إذا كان موقعك أو مدونتك مثبتة داخل مسار فرعي مثل https://example.com/blog/، فإن توجيه الجذر لن يخدم هذا المجلد بمفرده ويجب إنشاء كتلة مخصصة للمسار:

location /blog/ {
    try_files $uri $uri/ /blog/index.php?$args;
}

2. شبكات ووردبريس متعددة المواقع (WordPress Multisite)#

في شبكات ووردبريس متعددة المواقع بنظام المجلدات الفرعية (Subdirectories)، تختلف مسارات الملفات المرفوعة ولوحات التحكم، ويتطلب Nginx قواعد مخصصة لمنع ظهور 404 على لوحات المواقع الفرعية:

# توجيه شبكة ووردبريس متعددة المواقع
if (!-e $request_filename) {
    rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;
    rewrite ^/[_0-9a-zA-Z-]+.*(/wp-admin/.*\.php)$ $1 last;
    rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last;
}

3. خطأ في مسار المجلد الجذري (root Directive)#

إذا كان سطر root داخل ملف إعداد النطاق يشير إلى مسار خاطئ أو مجلد قديم قبل نقل الملفات، فلن يتمكن Nginx من العثور حتى على ملف index.php الأساسي:

# تأكد من تطابق المسار بدقة متناهية مع مكان وجود ملفاتك
root /var/www/example.com/public_html;

4. أذونات وصلاحيات القراءة لملفات ومجلدات النظام#

إذا كانت صلاحيات ملفات موقعك تمنع مستخدم خادم الويب (عادة www-data في أوبونتو وديبيان، أو nginx في أنظمة RHEL) من قراءة المجلدات، فستظهر أخطاء 404 أو 403:

# تعيين الملكية الصحيحة لمستخدم خادم الويب
sudo chown -R www-data:www-data /var/www/example.com/public_html

# تعيين الصلاحيات القياسية للمجلدات والملفات
sudo find /var/www/example.com/public_html -type d -exec chmod 755 {} \;
sudo find /var/www/example.com/public_html -type f -exec chmod 644 {} \;

مقارنة معمارية معالجة الروابط: Nginx مقابل Apache#

المعيار الهندسي خادم Apache HTTP Server خادم Nginx High-Performance
طريقة قراءة الروابط يعتمد على ملفات .htaccess في كل مجلد يعتمد حصراً على ملف الإعداد المركزي للنطاق
استهلاك القرص والذاكرة يفحص القرص عند كل طلب بحثاً عن الملفات يقدم أداءً فائقاً لقراءة القواعد من الذاكرة اللحظية
صيغة التوجيه الأساسية RewriteRule ^index\.php$ - [L] try_files $uri $uri/ /index.php?$args;
إمكانية التعديل للمستخدم العادي سهلة ومباشرة من لوحة cPanel أو FTP تتطلب وصولاً متميزاً للسيرفر عبر SSH وSudo

كيف تتأكد أن الخطوة نجحت تماماً؟#

قبل إعادة تشغيل السيرفر وتفادي تعطل المواقع الأخرى، نفذ أمر الفحص المخبري الدقيق:

  1. اختبر صحة صياغة وتراكيب ملف إعدادات Nginx:
    sudo nginx -t
    يجب أن ترى رسالة التأكيد الخضراء: syntax is ok متبوعة بـ test is successful.
  2. أعد تحميل إعدادات Nginx دون قطع أي اتصال مباشر للزوار:
    sudo systemctl reload nginx
  3. جرّب تصفح أي مقال فرعي في متصفحك أو عبر أداة curl في الطرفية:
    curl -I https://example.com/sample-post/
    يجب أن تتلقى استجابة HTTP/2 200 OK بدلاً من كود 404 المزعج.
  4. إذا كان الموقع يعمل بووردبريس، ادخل إلى الإعدادات > الروابط الدائمة في لوحة الإدارة واضغط على حفظ التغييرات لتحديث بنية الروابط الداخلية المخزنة.

المشاكل الشائعة وحلولها#

تظهر مشكلة تنزيل الملف بدلاً من فتحه (Browser downloads index.php)
هذا يعني أن Nginx أعاد توجيه الرابط لملف PHP بنجاح لكنه لم يمرره لمعالج FastCGI لتنفيذه برمجياً. تأكد من سلامة كتلة location ~ \.php$ وتأكد أن خدمة php-fpm تعمل بكفاءة عبر sudo systemctl status php8.2-fpm.
تظهر أخطاء 404 على الصور وملفات التنسيق فقط
تحقق من مسار root المعرف في ملف Nginx؛ وإذا كانت هناك كتلة مخصصة للملفات الثابتة مثل location ~* \.(jpg|jpeg|png|css|js)$، تأكد من عدم احتوائها على مسار root خاطئ أو قواعد مانعة تحجب القراءة.
عدم تطبيق التعديلات رغم إعادة تشغيل Nginx
تأكد من أن ملف الإعداد موجود داخل مجلد sites-enabled ومربوط برابط رمزي صحيح:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

المصادر#

التعليقات

كن أول من يشارك رأيه أو تجربته.

أضف تعليقاً أو سؤالاً

سجّل الدخول لتعجب بالتعليقات المفيدة وترفعها لأعلى النقاش. سجّل الدخول

لا يُنشر، ولا نرسل إليه شيئاً.

يظهر التعليق بعد مراجعته. الروابط لا تُفعَّل.

تبني موقعاً عربياً؟

سكربتات وقوالب وإضافات وخوادم — مصمّمة للمواقع العربية.

تصفّح المنتجات