دليل مفصّل خطوة بخطوة مع شرح كل سطر وإعدادات احترافية جاهزة للإنتاج
apt update يجلب قائمة الحزم المحدّثة من الإنترنت دون تثبيت شيء بعد. ثم apt upgrade -y يثبّت التحديثات المتاحة مباشرة دون طلب تأكيد. الـ && تعني "نفّذ الثاني فقط إذا نجح الأول".
curl وwget لتحميل الملفات. git لاستنساخ المشاريع. unzip/zip لفك الضغط. software-properties-common يسمح لنا بإضافة مستودعات خارجية مثل مستودع PHP لاحقاً.
# تحديث قائمة الحزم وترقية النظام
apt update && apt upgrade -y
# تثبيت الأدوات الأساسية
apt install -y curl wget git unzip zip software-properties-common
-y للموافقة التلقائية.
php8.3-mysql للتواصل مع قاعدة البيانات ← php8.3-mbstring لدعم Unicode والعربية ← php8.3-xml لمعالجة XML ← php8.3-bcmath للعمليات الحسابية الدقيقة (مهم للمدفوعات) ← php8.3-curl لإرسال HTTP requests ← php8.3-zip للضغط وفك الضغط ← php8.3-gd لمعالجة الصور ← php8.3-opcache لتسريع PHP بشكل كبير.
# إضافة مستودع PHP الرسمي
add-apt-repository ppa:ondrej/php -y
apt update
# تثبيت PHP 8.3 مع جميع الإضافات المطلوبة لـ Laravel
apt install -y php8.3 php8.3-fpm php8.3-cli \
php8.3-mysql php8.3-pgsql php8.3-sqlite3 \
php8.3-mbstring php8.3-xml php8.3-bcmath \
php8.3-curl php8.3-zip php8.3-gd php8.3-intl \
php8.3-redis php8.3-imagick php8.3-opcache \
php8.3-tokenizer php8.3-fileinfo
# التحقق من نجاح التثبيت
php -v
php-fpm8.3 -v
nano /etc/php/8.3/fpm/php.ini
; ===== الأداء والذاكرة =====
memory_limit = 256M ; حد الذاكرة لكل طلب
max_execution_time = 120 ; أقصى وقت تنفيذ بالثواني
max_input_time = 60 ; وقت قراءة البيانات المدخلة
; ===== رفع الملفات =====
upload_max_filesize = 64M ; أقصى حجم ملف مرفوع
post_max_size = 64M ; يجب أن يكون مساوياً أو أكبر من السابق
max_file_uploads = 20 ; أقصى عدد ملفات في طلب واحد
; ===== الأمان =====
expose_php = Off ; إخفاء إصدار PHP من الـ headers
display_errors = Off ; لا تعرض الأخطاء للمستخدم
log_errors = On ; سجّل الأخطاء في الملف
error_log = /var/log/php8.3-error.log
; ===== OPcache - تسريع PHP =====
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2
opcache.fast_shutdown = 1
nano /etc/php/8.3/fpm/pool.d/www.conf
[www]
user = www-data ; المستخدم الذي يشغّل PHP-FPM
group = www-data ; المجموعة - نفس مستخدم Nginx
listen = /run/php/php8.3-fpm.sock ; مسار ملف Socket
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; إدارة العمليات - dynamic أفضل للـ VPS
pm = dynamic ; يتكيّف مع الحمل تلقائياً
pm.max_children = 20 ; أقصى عدد عمليات متزامنة
pm.start_servers = 4 ; عدد العمليات عند البدء
pm.min_spare_servers = 2 ; الحد الأدنى للعمليات الخاملة
pm.max_spare_servers = 6 ; الحد الأقصى للعمليات الخاملة
pm.max_requests = 500 ; إعادة تشغيل العملية بعد 500 طلب لمنع تسريب الذاكرة
request_terminate_timeout = 120 ; إنهاء الطلب بعد 120 ثانية
systemctl restart php8.3-fpm
systemctl enable php8.3-fpm ; يعمل تلقائياً عند إعادة تشغيل السيرفر
utf8mb4 هو الترميز الصحيح الذي يدعم العربية والإيموجي. الـ utf8 القديم لا يدعم كل Unicode. unicode_ci يعني المقارنة غير حساسة لحالة الأحرف.
# تثبيت MySQL
apt install -y mysql-server mysql-client
systemctl start mysql
systemctl enable mysql
# تشغيل أداة التأمين التفاعلية
mysql_secure_installation
-- الدخول لـ MySQL
-- في terminal اكتب أولاً: mysql -u root -p
-- إنشاء قاعدة البيانات مع الترميز الصحيح للعربية
CREATE DATABASE laravel_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- إنشاء مستخدم مخصص للمشروع (لا تستخدم root أبداً)
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'StrongPassword@2024';
-- منح الصلاحيات لقاعدة البيانات فقط
GRANT ALL PRIVILEGES ON laravel_db.* TO 'laravel_user'@'localhost';
-- تحديث جدول الصلاحيات فوراً
FLUSH PRIVILEGES;
EXIT;
gzip_comp_level 6 هو توازن جيد بين الضغط واستهلاك المعالج.
rate=30r/s تعني 30 طلب في الثانية. هذا يحمي من هجمات DDoS وbrute force. الـ 10m هو حجم الذاكرة المخصصة لتتبع الـ IPs (10MB تتسع لـ 160,000 IP).
# تثبيت Nginx
apt install -y nginx
systemctl start nginx
systemctl enable nginx
# فتح ملف الإعداد الرئيسي
nano /etc/nginx/nginx.conf
user www-data; # المستخدم الذي يشغّل Nginx
worker_processes auto; # عملية لكل CPU core تلقائياً
worker_rlimit_nofile 65535; # أقصى ملفات مفتوحة = أقصى اتصالات
pid /run/nginx.pid;
events {
worker_connections 1024; # اتصالات لكل عملية
multi_accept on; # قبول عدة اتصالات في وقت واحد
use epoll; # أفضل آلية للـ Linux
}
http {
# الأساسيات
sendfile on; # إرسال الملفات مباشرة من kernel
tcp_nopush on; # تجميع البيانات قبل الإرسال
tcp_nodelay on; # إرسال فوري للبيانات الصغيرة
keepalive_timeout 65; # إبقاء الاتصال مفتوحاً 65 ثانية
server_tokens off; # إخفاء إصدار Nginx - أمان
include /etc/nginx/mime.types;
default_type application/octet-stream;
# ===== الضغط - يقلل حجم الاستجابة 60-80% =====
gzip on;
gzip_vary on; # يخبر الـ CDN أن الاستجابة مضغوطة
gzip_proxied any;
gzip_comp_level 6; # مستوى الضغط 1-9 (6 = توازن مثالي)
gzip_min_length 1024; # لا تضغط الملفات الصغيرة جداً
gzip_types
text/plain text/css text/xml text/javascript
application/json application/javascript
application/xml+rss image/svg+xml;
# ===== Logs =====
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# ===== حجم الطلبات =====
client_max_body_size 64M; # أقصى حجم للـ request body
client_body_buffer_size 128k;
# ===== Rate Limiting - حماية من DDoS والـ brute force =====
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
index.php ليعالجه Laravel. هذا ما يجعل الـ routes تعمل.
.env و.git و.htaccess. هذا أمان حرج — ملف .env يحتوي كلمات مرور قاعدة البيانات.
nano /etc/nginx/sites-available/laravel
server {
listen 80;
listen [::]:80; # يدعم IPv6 أيضاً
server_name yourdomain.com www.yourdomain.com;
# مجلد public فقط هو المكشوف - أمان مهم
root /var/www/laravel/public;
index index.php index.html;
# ملفات log مستقلة لكل موقع
access_log /var/log/nginx/laravel_access.log;
error_log /var/log/nginx/laravel_error.log;
# قلب إعداد Laravel - يوجّه كل الطلبات لـ index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# معالجة ملفات PHP عبر PHP-FPM
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
# Timeouts للطلبات الثقيلة
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 120s;
fastcgi_read_timeout 120s;
fastcgi_buffer_size 64k;
fastcgi_buffers 8 64k;
}
# الملفات الثابتة - Cache سنة كاملة لتسريع التحميل
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off; # لا نسجّل طلبات الصور لتوفير مساحة
}
# حظر الوصول لملفات .env و .git وغيرها - أمان حرج
location ~ /\. {
deny all;
access_log off;
}
# حظر الوصول للملفات الحساسة مباشرة
location ~ /(\.env|composer\.(json|lock)|package\.json|artisan) {
deny all;
}
# Rate Limiting - 50 طلب burst لكل IP
limit_req zone=general burst=50 nodelay;
limit_conn addr 20; # أقصى 20 اتصال متزامن لكل IP
# Security Headers - يحمي من هجمات XSS وClickjacking
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
# ربط الملف في sites-enabled
ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
# حذف الموقع الافتراضي
rm /etc/nginx/sites-enabled/default
# اختبار صحة الإعدادات قبل التطبيق
nginx -t
# تطبيق الإعدادات بدون إيقاف السيرفر
systemctl reload nginx
/usr/local/bin حتى يمكن استدعاؤه بكتابة composer فقط من أي مجلد بدلاً من php composer.phar الطويلة.
# تحميل Composer من الموقع الرسمي
curl -sS https://getcomposer.org/installer | php
# نقله لمسار عام ليكون متاحاً من أي مكان
mv composer.phar /usr/local/bin/composer
# إعطاؤه صلاحية التنفيذ
chmod +x /usr/local/bin/composer
# التحقق من التثبيت
composer --version
config:cache يجمع كل ملفات الإعداد في ملف واحد محسوب مسبقاً. route:cache يجمع كل الـ routes في ملف PHP واحد بدلاً من قراءتها كل طلب. view:cache يُجمِّع قوالب Blade مسبقاً. كل هذا يقلل وقت الاستجابة.
public/storage إلى storage/app/public حتى يمكن عرض الملفات المرفوعة (الصور وغيرها) في المتصفح مباشرة.
# إنشاء المجلد
mkdir -p /var/www/laravel
# خيار 1: استنساخ مشروع موجود من Git
git clone https://github.com/yourusername/your-project.git /var/www/laravel
# خيار 2: إنشاء مشروع Laravel جديد
composer create-project laravel/laravel /var/www/laravel
# الانتقال للمجلد
cd /var/www/laravel
# إذا كان مشروع موجود من Git، ثبّت الحزم
composer install --no-dev --optimize-autoloader
# نسخ ملف البيئة
cp .env.example .env
nano .env
APP_NAME="اسم مشروعك"
APP_ENV=production # وضع الإنتاج - مهم
APP_KEY= # سيُملأ تلقائياً بأمر key:generate
APP_DEBUG=false # أطفئ Debug في الإنتاج - أمان
APP_URL=https://yourdomain.com
LOG_CHANNEL=stack
LOG_LEVEL=error # سجّل الأخطاء فقط لتوفير المساحة
# ===== قاعدة البيانات =====
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=StrongPassword@2024
# ===== Cache والـ Session =====
CACHE_DRIVER=file # غيّره لـ redis إذا ثبّتت Redis
SESSION_DRIVER=file # غيّره لـ redis إذا ثبّتت Redis
QUEUE_CONNECTION=sync # غيّره لـ database أو redis للـ queues
# توليد مفتاح التشفير - ضروري
php artisan key:generate
# تشغيل الـ migrations لإنشاء جداول قاعدة البيانات
php artisan migrate --force
# ===== تحسين الأداء للإنتاج =====
php artisan config:cache # تجميع ملفات الإعداد في ملف واحد
php artisan route:cache # تجميع الـ routes في ملف واحد
php artisan view:cache # تجميع قوالب Blade مسبقاً
php artisan event:cache # تجميع الـ events والـ listeners
# إنشاء رابط Storage لعرض الملفات المرفوعة
php artisan storage:link
www-data. إذا كان مالك الملفات شخصاً آخر، ستحصل على أخطاء "Permission denied". هذا يجعل PHP قادراً على قراءة كل الملفات.
644 تعني: المالك يقرأ ويكتب، الجميع يقرأ فقط. 755 للمجلدات تضيف صلاحية الدخول للمجلد (x). هذا الحد الأدنى الآمن.
775 تعني المالك والمجموعة يكتبان، الآخرون يقرؤون فقط.
# جعل www-data مالك كل الملفات
chown -R www-data:www-data /var/www/laravel
# الصلاحيات الأساسية الآمنة
find /var/www/laravel -type f -exec chmod 644 {} \;
find /var/www/laravel -type d -exec chmod 755 {} \;
# هذين المجلدين فقط يحتاجان صلاحية كتابة
chmod -R 775 /var/www/laravel/storage
chmod -R 775 /var/www/laravel/bootstrap/cache
# تثبيت Certbot مع plugin الـ Nginx
apt install -y certbot python3-certbot-nginx
# الحصول على الشهادة وإعداد HTTPS تلقائياً
# استبدل yourdomain.com بدومينك الفعلي
certbot --nginx -d yourdomain.com -d www.yourdomain.com
# اختبار التجديد التلقائي
certbot renew --dry-run
# التحقق من أن timer التجديد يعمل
systemctl status certbot.timer
Nginx Full هو اسم مختصر يفتح كلا الـ port 80 (HTTP) والـ port 443 (HTTPS) دفعة واحدة. يمكنك التحقق من هذه الـ profiles بأمر ufw app list.
# السماح بـ SSH أولاً - لا تنسَ هذا!
ufw allow OpenSSH
# السماح بـ HTTP (80) و HTTPS (443) معاً
ufw allow 'Nginx Full'
# تفعيل الـ Firewall
ufw enable
# التحقق من القواعد المفعّلة
ufw status
# تثبيت Redis
apt install -y redis-server
# فتح ملف الإعدادات
nano /etc/redis/redis.conf
# ابحث عن: supervised no
# وغيّرها إلى:
supervised systemd # يجعل systemd يدير Redis
# إعادة التشغيل بعد التعديل
systemctl restart redis-server
systemctl enable redis-server
# اختبار Redis - يجب أن يرد: PONG
redis-cli ping
.env:CACHE_DRIVER=redis # Cache في الذاكرة بدلاً من الملفات
SESSION_DRIVER=redis # Sessions في الذاكرة - أسرع
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
# تثبيت Supervisor
apt install -y supervisor
# إنشاء ملف إعداد الـ worker
nano /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d ; اسم العملية مع رقمها
command=php /var/www/laravel/artisan queue:work --sleep=3 --tries=3 --max-time=3600
; --sleep=3: انتظر 3 ثواني إذا ما في مهام
; --tries=3: حاول 3 مرات قبل تمييز المهمة كفاشلة
; --max-time=3600: أعد التشغيل كل ساعة
autostart=true ; يبدأ تلقائياً مع Supervisor
autorestart=true ; يُعيد التشغيل إذا توقف
stopasgroup=true
killasgroup=true
user=www-data ; يشتغل بنفس مستخدم Laravel
numprocs=2 ; عمليتان متوازيتان
redirect_stderr=true
stdout_logfile=/var/www/laravel/storage/logs/worker.log
stopwaitsecs=3600
# قراءة الإعدادات الجديدة
supervisorctl reread
# تطبيق التغييرات
supervisorctl update
# تشغيل الـ workers
supervisorctl start laravel-worker:*
# التحقق من حالتهم
supervisorctl status
# فحص حالة جميع الخدمات - يجب أن تكون active (running)
systemctl status nginx
systemctl status php8.3-fpm
systemctl status mysql
systemctl status redis-server
systemctl status supervisor
# أو كلها دفعة واحدة
systemctl status nginx php8.3-fpm mysql redis-server supervisor
# اختبار صحة إعدادات Nginx
nginx -t
# اختبار صحة إعدادات PHP-FPM
php-fpm8.3 -t
# متابعة أخطاء Nginx الآن
tail -f /var/log/nginx/laravel_error.log
# متابعة أخطاء Laravel الآن
tail -f /var/www/laravel/storage/logs/laravel.log
.env أو أي ملف إعداد لاحقاً، شغّل دائماً: php artisan config:cache لتطبيق التغييرات في وضع الإنتاج.