بلاگ/دیپلوی پروژه Laravel روی سرور اختصاصی و VPS: Nginx، PHP-FPM و Queue Worker با Supervisor
به‌روز شده

دیپلوی پروژه Laravel روی سرور اختصاصی و VPS: Nginx، PHP-FPM و Queue Worker با Supervisor

1405/07/126 بازدید
دیپلوی پروژه Laravel روی سرور اختصاصی و VPS: Nginx، PHP-FPM و Queue Worker با Supervisor

دیپلوی پروژه Laravel روی سرور اختصاصی و VPS: Nginx، PHP-FPM و Queue Worker با Supervisor

وقتی یک پروژه Laravel از مرحله توسعه به production می‌رسد، اجرای php artisan serve دیگر کافی نیست. باید یک وب‌سرور واقعی، یک پردازشگر PHP با تنظیمات production، و در بسیاری از پروژه‌ها یک صف پردازش پس‌زمینه (Queue) داشته باشید که همیشه در حال اجرا باشد. این راهنما دیپلوی لاراول روی سرور را از صفر تا اجرای پایدار Nginx، PHP-FPM و Supervisor پوشش می‌دهد — چه روی یک VPS باشد چه روی یک سرور اختصاصی.

دیپلوی پروژه Laravel روی سرور با Nginx و Supervisor

پیش‌نیازهای دیپلوی Laravel روی سرور

قبل از شروع، این موارد باید روی سرور آماده باشد:

  • دسترسی SSH با یک کاربر غیر root که دسترسی sudo دارد
  • PHP نسخه مناسب با پروژه (معمولاً 8.2 یا 8.3) به همراه extension‌های mbstring, xml, curl, zip, bcmath, pdo_mysql
  • Composer برای نصب dependency‌ها
  • یک دیتابیس (MySQL یا PostgreSQL) که یا روی همان سرور نصب شده یا به‌صورت مدیریت‌شده در دسترس است
  • Nginx به‌عنوان وب‌سرور جلویی
  • Supervisor برای نگه‌داشتن Queue Worker در حال اجرا

نصب این پکیج‌ها روی Ubuntu/Debian ساده است:

sudo apt update
sudo apt install -y nginx php8.3-fpm php8.3-cli php8.3-mbstring \
  php8.3-xml php8.3-curl php8.3-zip php8.3-bcmath php8.3-mysql \
  composer supervisor

انتخاب بین VPS و سرور اختصاصی برای Laravel

انتخاب بین VPS و سرور اختصاصی به ترافیک، بودجه و نیاز به کنترل سخت‌افزار بستگی دارد. برای اکثر پروژه‌های Laravel در مرحله راه‌اندازی یا رشد متوسط، یک VPS کافی است؛ وقتی بار پردازشی یا تعداد Queue Workerهای همزمان بالا می‌رود، سرور اختصاصی منابع پایدارتری می‌دهد.

ویژگیVPSسرور اختصاصی
هزینه شروعپایین، مقیاس‌پذیر ماهانهبالاتر، مناسب بار ثابت
راه‌اندازیچند دقیقه، آماده فورینیاز به تنظیم اولیه بیشتر
منابع (CPU/RAM)اشتراکی یا تضمین‌شده بسته به پلنکاملاً اختصاصی، بدون همسایه نویزی
مناسب برایپروژه‌های در حال رشد، استارتاپ‌هاترافیک بالا، چند Queue Worker موازی
مقیاس‌پذیریساده، ارتقای پلننیاز به تغییر سخت‌افزار یا خرید سرور جدید

برای اکثر تیم‌ها، شروع روی VPS و مهاجرت بعدی به سرور اختصاصی در صورت نیاز، مسیر منطقی‌تری نسبت به خرید اولیه سخت‌افزار اختصاصی است. اگر هنوز بین این دو مردد هستید، سوالات متداول خرید سرور مجازی می‌تواند به تصمیم‌گیری کمک کند.

انتقال کد و تنظیم فایل Environment

کد پروژه را از طریق Git به سرور منتقل کنید، نه آپلود مستقیم فایل:

cd /var/www
git clone <repo-url> myapp
cd myapp
composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate

در .env، حتماً APP_ENV=production و APP_DEBUG=false را تنظیم کنید؛ نگه‌داشتن APP_DEBUG=true روی سرور production یعنی خطاهای داخلی برنامه، شامل مسیر فایل‌ها و متغیرهای محیطی، مستقیم به بازدیدکننده نمایش داده می‌شود.

دسترسی نوشتن روی پوشه‌های لازم را بدهید:

sudo chown -R www-data:www-data /var/www/myapp
sudo chmod -R 775 /var/www/myapp/storage /var/www/myapp/bootstrap/cache

سپس Laravel را برای production کش کنید:

php artisan config:cache
php artisan route:cache
php artisan view:cache

نکته مهم: هر بار که .env را تغییر می‌دهید، باید php artisan config:cache را دوباره اجرا کنید؛ در غیر این صورت Laravel همچنان مقادیر کش‌شده قبلی را می‌خواند.

نصب و تنظیم Nginx برای Laravel

Nginx باید ریشه سایت را به پوشه public پروژه اشاره دهد، نه به ریشه پروژه. یک فایل جدید در /etc/nginx/sites-available/myapp بسازید:

server {
    listen 80;
    server_name example.com;
    root /var/www/myapp/public;

    add_header X-Frame-Options "SAMEORIGIN";
    index index.php;

    charset utf-8;

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

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

فعال‌سازی و تست کانفیگ:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

این کانفیگ پایه برای شروع کافی است؛ برای تنظیمات عمیق‌تر مثل gzip، کش فایل‌های استاتیک و محدودسازی نرخ درخواست، راهنمای بهینه‌سازی Nginx را ببینید.

تنظیم PHP-FPM برای Production

تنظیمات پیش‌فرض PHP-FPM برای یک سایت کم‌ترافیک کافی است، اما زیر بار واقعی باید pool را متناسب با RAM سرور تنظیم کنید. فایل /etc/php/8.3/fpm/pool.d/www.conf را ویرایش کنید:

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8

مقدار pm.max_children باید با فرمول تقریبی «RAM در دسترس تقسیم بر مصرف حافظه هر process PHP» تنظیم شود؛ عددی بیش از ظرفیت واقعی سرور باعث سواپ شدن حافظه و افت شدید سرعت پاسخ‌دهی می‌شود.

فعال کردن OPcache هم تأثیر مستقیم روی سرعت دارد؛ در php.ini:

opcache.enable=1
opcache.memory_consumption=128
opcache.validate_timestamps=0

نکته: opcache.validate_timestamps=0 یعنی PHP دیگر تغییرات فایل را چک نمی‌کند، بنابراین بعد از هر دیپلوی جدید باید PHP-FPM را reload کنید تا کد قدیمی از کش خارج شود:

sudo systemctl reload php8.3-fpm

اجرای Queue Worker با Supervisor

اگر پروژه از صف (Queue) برای ارسال ایمیل، پردازش فایل یا کارهای سنگین استفاده می‌کند، دستور php artisan queue:work باید دائم در حال اجرا باشد — صرف‌نظر از این‌که درایور صف شما database باشد یا Redis. اجرای آن در یک ترمینال ساده با بسته شدن سشن SSH متوقف می‌شود — راه‌حل درست Supervisor است.

فایل کانفیگ در /etc/supervisor/conf.d/myapp-worker.conf:

[program:myapp-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/myapp/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/myapp/storage/logs/worker.log
stopwaitsecs=3600

numprocs=2 یعنی دو پردازش Worker موازی اجرا می‌شود — روی سرور اختصاصی با CPU بیشتر، این عدد را افزایش دهید تا صف‌های سنگین سریع‌تر تخلیه شوند. مقدار --max-time=3600 باعث می‌شود Worker هر ساعت یک‌بار ری‌استارت شود تا memory leakهای احتمالی در طول زمان جمع نشوند.

فعال‌سازی:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start myapp-worker:*

برای بررسی وضعیت:

sudo supervisorctl status myapp-worker:*

اگر پروژه تسک‌های زمان‌بندی‌شده (php artisan schedule:run) هم دارد، یک cron job روی سطح سیستم اضافه کنید، نه Supervisor:

* * * * * php /var/www/myapp/artisan schedule:run >> /dev/null 2>&1

نمودار معماری دیپلوی Laravel: Nginx و PHP-FPM برای پردازش درخواست‌ها و Queue Worker تحت نظارت Supervisor برای پردازش صف

فعال‌سازی HTTPS با Let's Encrypt

بدون HTTPS، دیپلوی لاراول روی سرور کامل نیست — مرورگرها سایت بدون SSL را ناامن علامت می‌زنند و بسیاری از کوکی‌های Laravel (مثل session) در حالت secure نیاز به HTTPS دارند. Certbot ساده‌ترین راه برای گرفتن گواهی رایگان است:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com

Certbot به‌صورت خودکار بلاک server در Nginx را برای ریدایرکت HTTP به HTTPS به‌روزرسانی می‌کند و تمدید گواهی را هم با یک cron job داخلی خودش مدیریت می‌کند؛ کافی است هر چند ماه یک‌بار با sudo certbot renew --dry-run تمدید را تست کنید. اگر پروژه چند زیردامنه دارد و یک گواهی واحد برای همه آن‌ها نیاز است، راهنمای گواهی SSL وایلدکارد Let's Encrypt با Certbot را ببینید.

مانیتورینگ و نگهداری بعد از دیپلوی

بعد از این‌که سایت بالا آمد، چند نکته نگهداری را فراموش نکنید:

  • لاگ خطای Laravel در storage/logs/laravel.log و لاگ خطای Nginx در /var/log/nginx/error.log اولین جایی است که باید در صورت بروز مشکل چک کنید.
  • وضعیت PHP-FPM و Supervisor را با systemctl status php8.3-fpm و supervisorctl status به‌صورت دوره‌ای بررسی کنید.
  • قبل از هر دیپلوی جدید، php artisan down را برای فعال کردن حالت maintenance اجرا کنید و بعد از اتمام با php artisan up سایت را برگردانید.
  • بعد از هر git pull یا بروزرسانی کد، حتماً composer install --no-dev، کش‌های artisan و supervisorctl restart myapp-worker:* را دوباره اجرا کنید تا کد و Workerها هماهنگ بمانند.

جمع‌بندی

دیپلوی لاراول روی سرور — چه VPS و چه اختصاصی — یک فرآیند تکرارپذیر است: Nginx برای مسیر درخواست‌ها، PHP-FPM تنظیم‌شده برای بار واقعی، کش‌های artisan برای کاهش زمان پاسخ، Supervisor برای Queue Worker پایدار، و HTTPS برای امنیت. وقتی این تکه‌ها یک‌بار درست چیده شوند، دیپلوی‌های بعدی فقط چند دستور ساده‌اند.

اگر هنوز سرور مناسبی برای این پروژه ندارید، VPS ابری آریانت برای شروع و تست این تنظیمات گزینه مناسبی است، و برای پروژه‌هایی با ترافیک بالا و نیاز به منابع اختصاصی، سرور اختصاصی آریانت منابع پایدارتری در اختیار Queue Workerها و PHP-FPM قرار می‌دهد.