لماذا تشغيل Symfony على VPS بدلاً من الاستضافة المشتركة؟
تفرض الاستضافة المشتركة إصدار PHP المثبت على الخادم، وتعطّل امتدادات عدة، وتمنع تشغيل العمليات الدائمة في الخلفية. يتطلب Symfony 7 كحد أدنى PHP 8.2 — وهو شرط لا توفره كثير من بيئات الاستضافة المشتركة حتى الآن. على خادم VPS تختار PHP 8.3 منذ اليوم الأول وتثبّت ext-redis وext-intl وما تحتاج إليه.
تحتاج Symfony Messenger إلى عمليات Worker دائمة يديرها Supervisor أو systemd، وهذا مستحيل على الاستضافة المشتركة. على VPS تبدأ بأمر واحد وتُعاد تلقائياً بعد أي توقف.
ما يتيحه VPS لـ Symfony
- وصول root كامل — ثبّت أي امتداد PHP وعدّل OPcache سطراً بسطر دون فتح تذكرة دعم
- PHP 8.3 أصيل — استفد من typed class constants وتحسينات JIT دون انتظار ترقية الخادم المشترك
- Supervisor وعمال دائمون — شغّل
messenger:consume باستمرار مع إعادة تشغيل تلقائية لمعالجة الطوابير - Redis محلي — ثبّت Redis على نفس الخادم للجلسات وذاكرة التخزين المؤقت لـDoctrine وبروتوكولات Messenger
- PHP متعدد الإصدارات عبر ondrej/php — أبقِ PHP 8.1 لتطبيق قديم وPHP 8.3 لتطبيق جديد على نفس المضيف
- Xdebug والتنميط في التدريج — فعّل Blackfire أو Xdebug على بيئة المراجعة دون المساس بالإنتاج، وأضف الأداة للإنتاج وقت الحاجة فقط
- نشر ذري مع Deployer — صفر وقت توقف عبر الروابط الرمزية والرجوع بأمر واحد
المتطلبات المحددة — الموارد والبرامج
نظام التشغيل: Ubuntu 24.04 LTS أو Debian 12.
PHP: 8.3 موصى به (الحد الأدنى 8.2 لـSymfony 7). الامتدادات المطلوبة: php8.3-cli وphp8.3-fpm وphp8.3-mbstring وphp8.3-xml وphp8.3-curl وphp8.3-opcache.
Composer: الإصدار 2.x إلزامي.
قاعدة البيانات: MySQL 8.0+ أو PostgreSQL 16+.
الحد الأدنى من الذاكرة RAM:
- 1 GB: التطوير أو التطبيقات الخفيفة بدون طوابير
- 2 GB: الإنتاج مع Symfony Messenger وبروتوكول Redis واحد
- 4 GB: عمال متعددون وRedis وجلسات عالية التردد
المنافذ المطلوبة: 80 و443 و22. أغلق كل شيء آخر.
تثبيت PHP 8.3 و Symfony CLI على Ubuntu VPS
تحديث النظام وتثبيت المتطلبات الأساسية
apt update && apt upgrade -y && apt install -y curl git unzip software-properties-commonإضافة مستودع `ondrej/php`
add-apt-repository ppa:ondrej/php && apt updateتثبيت PHP 8.3-FPM والامتدادات المطلوبة
apt install -y php8.3-fpm php8.3-cli php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip php8.3-intl php8.3-opcache php8.3-redis php8.3-mysqlالتحقق من الإصدار المثبت وحالة الخدمة
php --version && systemctl status php8.3-fpmتثبيت Composer 2.x عالمياً
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composerتثبيت Symfony CLI
curl -1sLf 'https://dl.cloudsmith.io/public/symfony/stable/setup.deb.sh' | bash && apt install -y symfony-cliالتحقق من استيفاء جميع متطلبات Symfony
symfony check:requirementsتثبيت nginx وRedis
apt install -y nginx redis-server && systemctl enable --now nginx redis-server
نشر تطبيق Symfony للإنتاج باستخدام Deployer PHP
في مشروع Symfony المحلي، أضف Deployer كاعتمادية تطوير
composer require deployer/deployer --devتهيئة إعدادات Deployer (اختر وصفة `symfony`)
./vendor/bin/dep initتعديل `deploy.php` في جذر المشروع
require 'recipe/symfony.php';
set('repository', '[email protected]:your-org/your-app.git');
host('your-vps.example.com')
->set('remote_user', 'deploy')
->set('deploy_path', '/var/www/symfony-app');على الخادم، إنشاء مستخدم النشر
useradd -m -s /bin/bash deploy && usermod -aG www-data deployتشغيل أول عملية نشر من الجهاز المحلي
./vendor/bin/dep deploy productionالتحقق من الرابط الرمزي `current/`
ls -la /var/www/symfony-app/عند الحاجة، الرجوع فوراً للإصدار السابق
./vendor/bin/dep rollback production
إعداد nginx لـ Symfony
أنشئ /etc/nginx/sites-available/symfony-app بهذا الكتلة الأساسية:
server {
listen 80;
server_name your-domain.com;
root /var/www/symfony-app/current/public;
index index.php;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
}
location ~ /\.ht {
deny all;
}
}فعّل الموقع واختبر الإعدادات قبل إعادة تحميل nginx:ln -s /etc/nginx/sites-available/symfony-app /etc/nginx/sites-enabled/ && nginx -t && systemctl reload nginx
متغيرات البيئة والأمان
يقرأ Symfony ملف .env ثم .env.local ثم .env.prod.local. في الإنتاج، يجب وضع جميع القيم الحساسة في .env.local — لا تلتزم بها في git أبداً.
المتغيرات الأساسية في الإنتاج:
APP_ENV=prod
APP_DEBUG=false
APP_SECRET=<64-chars-hex-random>
DATABASE_URL="mysql://dbuser:[email protected]:3306/symfony_prod"
MAILER_DSN=smtp://user:[email protected]:587
MESSENGER_TRANSPORT_DSN=redis://127.0.0.1:6379/messagesأنشئ APP_SECRET عشوائياً: openssl rand -hex 32. لا تعيد استخدام القيمة الافتراضية للمشروع.
APP_DEBUG=false حاسم: في وضع debug يكشف Symfony تتبعات المكدس الكاملة واستعلامات SQL في المتصفح — تسريب خطير في الإنتاج.
الطوابير غير المتزامنة مع Symfony Messenger و Supervisor
يؤخّر Symfony Messenger المهام الثقيلة (إرسال البريد، توليد PDF، الـwebhooks) إلى طابور معالجة غير متزامن. على الخادم يضمن Supervisor استمرار تشغيل العامل وإعادة تشغيله بعد أي توقف.
ثبّت Supervisor:apt install -y supervisor
أنشئ /etc/supervisor/conf.d/symfony-messenger.conf:
[program:symfony-messenger]
command=/var/www/symfony-app/current/bin/console messenger:consume async --time-limit=3600
user=deploy
autostart=true
autorestart=true
startretries=3
redirect_stderr=true
stdout_logfile=/var/log/supervisor/symfony-messenger.logشغّل العامل:supervisorctl reread && supervisorctl update && supervisorctl start symfony-messenger
تعزيز الأمان بثلاث أوامر. احجب الوصول إلى .git/ في nginx (أضف location ~ /\.git { deny all; }). ثبّت fail2ban: apt install -y fail2ban. قيّد صلاحيات مجلد النشر: chmod 750 /var/www/symfony-app && chown -R deploy:www-data /var/www/symfony-app. أعدّ OPcache مع opcache.validate_timestamps=0 في الإنتاج للأداء الأقصى.
استكشاف الأخطاء — أكثر 4 مشكلات شيوعاً
1. The environment variable "APP_SECRET" is not set.
APP_SECRET غائب من .env.local على الخادم. تحقق من وجود الملف في {{deploy_path}}/shared/.
2. خطأ 500 صامت — سجلات فارغة
مع APP_DEBUG=false يكتب Symfony في var/log/prod.log. اقرأ هذا الملف: tail -f /var/www/symfony-app/current/var/log/prod.log. في الغالب هي مشكلة صلاحيات — صحّحها بـ chown -R deploy:www-data var/.
3. Connection refused على قاعدة البيانات
DATABASE_URL تشير إلى 127.0.0.1 لكن MySQL يستمع على localhost (Unix socket) — أو العكس. اختبر مباشرة: mysql -u dbuser -p -h 127.0.0.1 symfony_db.
4. لا توجد أوامر في نطاق "cache"
Symfony لا يستطيع الكتابة في var/cache/. الحل: chmod -R 775 var/cache var/log && chown -R deploy:www-data var/.
النشر من Marketplace ServOrbit
إذا كنت تفضل تجنب ساعات الإعداد اليدوي، يثبّت قالب symfony-stack في Marketplace ServOrbit ويعدّ تلقائياً كل البنية الموصوفة في هذا الدليل: PHP 8.3-FPM وComposer وnginx المحسّن لـSymfony وRedis وSupervisor والصلاحيات الصحيحة. الخادم جاهز في أقل من 5 دقائق مع وصول فوري عبر SSH.
تحتفظ بالتحكم الكامل: الخادم ملكك ولا يوجد أي ربط تجاري، ويمكنك استخدام Deployer PHP تماماً كما هو موضح أعلاه من أول اتصال SSH.