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

پیشنیازهای دیپلوی 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

فعالسازی 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 قرار میدهد.




