Deploy Laravel บน VPS Ubuntu ตั้งค่า Nginx + PHP + MySQL

Laravel เป็น PHP Framework ยอดนิยมที่ใช้งานกันอย่างแพร่หลายในไทย การ Deploy บน VPS ให้ถูกต้องต้องเตรียม Stack: Nginx + PHP-FPM + MySQL + Composer และตั้งค่า Permission, .env, Queue Worker อย่างถูกต้อง บทความนี้พาไปทีละขั้นตอนตั้งแต่ VPS เปล่าจนเว็บขึ้น Production

สเปค VPS แนะนำ: RAM 2 GB ขึ้นไป, SSD 30 GB+, Ubuntu 22.04 LTS สำหรับ Laravel แอปพลิเคชันขนาดกลาง

ทำความเข้าใจสถาปัตยกรรม Laravel บน VPS

ก่อนเริ่ม Deploy สิ่งสำคัญคือต้องเข้าใจว่า Laravel ทำงานร่วมกับ Stack ต่างๆ อย่างไร บน VPS ที่รัน Ubuntu 22.04 LTS นั้น ทุก Request จากผู้ใช้จะเดินทางผ่านชั้นต่างๆ ดังนี้

  1. Nginx รับ HTTP/HTTPS Request จากอินเทอร์เน็ต ทำหน้าที่เป็น Web Server และ Reverse Proxy
  2. PHP-FPM (FastCGI Process Manager) รับ Request จาก Nginx แล้วประมวลผล PHP Code ของ Laravel
  3. MySQL เก็บข้อมูลแอปพลิเคชัน เช่น ข้อมูลผู้ใช้ โพสต์ คำสั่งซื้อ ฯลฯ
  4. Laravel Application รับ Request ผ่าน public/index.php แล้วส่งต่อไปยัง Router, Controller, Model ตามลำดับ
  5. Queue Worker (ถ้ามี) ประมวลผลงานหนักในพื้นหลัง เช่น ส่งอีเมล, Resize รูป, Export ไฟล์

การเข้าใจโครงสร้างนี้ช่วยให้แก้ไขปัญหาได้รวดเร็วขึ้น ตัวอย่างเช่น ถ้าหน้าเว็บโหลดไม่ขึ้นให้ตรวจ Nginx Log ก่อน ถ้า PHP Error ให้ดูที่ PHP-FPM Log และถ้าข้อมูลไม่บันทึกให้ตรวจ MySQL

ทำไม VPS ดีกว่า Shared Hosting สำหรับ Laravel? Shared Hosting มักจำกัด PHP Extensions, ห้ามรัน Artisan Command ผ่าน Terminal, ไม่รองรับ Queue Worker และ Cron Job ที่ยืดหยุ่น ในขณะที่ VPS มีอิสระเต็มร้อย สามารถติดตั้ง Extension เพิ่ม ตั้งค่า php.ini เอง และรัน Process ได้ตลอด 24 ชั่วโมง

เตรียม VPS ให้ปลอดภัยก่อน Deploy Laravel

ก่อนที่จะติดตั้ง Stack ใดๆ ควรทำให้ VPS ปลอดภัยก่อน เพราะ VPS ที่เชื่อมต่ออินเทอร์เน็ตมักถูก Scan Port และ Brute Force อยู่ตลอดเวลา

ตั้งค่า UFW Firewall

# เปิดเฉพาะ Port ที่จำเป็น
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

สร้าง User ใหม่แทน Root

# สร้าง User ใหม่
sudo adduser deployer
sudo usermod -aG sudo deployer

# Copy SSH Key ไปยัง User ใหม่
sudo rsync --archive --chown=deployer:deployer ~/.ssh /home/deployer

ปิดการ Login ด้วย Password ผ่าน SSH

sudo nano /etc/ssh/sshd_config
# แก้ไขค่าต่อไปนี้:
PasswordAuthentication no
PermitRootLogin no

sudo systemctl restart sshd

การทำขั้นตอนเหล่านี้ก่อนจะช่วยลดความเสี่ยงได้มาก ควรทดสอบ Login ด้วย SSH Key ก่อนปิด Password Authentication เพื่อป้องกันการล็อกตัวเองออกจากระบบ

ขั้นที่ 1 — อัปเดตระบบและติดตั้ง Nginx

# อัปเดต package list
sudo apt update && sudo apt upgrade -y

# ติดตั้ง Nginx
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx

ขั้นที่ 2 — ติดตั้ง PHP 8.2 + Extensions ที่ Laravel ต้องการ

# เพิ่ม PHP PPA (Ubuntu 22.04)
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update

# ติดตั้ง PHP 8.2 และ Extensions ที่ Laravel ต้องการ
sudo apt install php8.2 php8.2-fpm php8.2-mysql php8.2-xml \
  php8.2-curl php8.2-mbstring php8.2-zip php8.2-bcmath \
  php8.2-tokenizer php8.2-gd php8.2-intl -y

# ตรวจสอบเวอร์ชัน
php -v

ขั้นที่ 3 — ติดตั้ง MySQL

sudo apt install mysql-server -y
sudo mysql_secure_installation

# สร้าง Database และ User สำหรับ Laravel
sudo mysql -u root -p
CREATE DATABASE laravel_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON laravel_db.* TO 'laravel_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

ขั้นที่ 4 — ติดตั้ง Composer

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer --version

ขั้นที่ 5 — Upload โปรเจกต์ Laravel

Upload ไฟล์โปรเจกต์ขึ้น VPS ด้วย Git หรือ SCP:

# ใช้ Git Clone (แนะนำ)
cd /var/www
sudo git clone https://github.com/yourusername/your-laravel-app.git myapp
sudo chown -R www-data:www-data /var/www/myapp

# ติดตั้ง Dependencies
cd /var/www/myapp
sudo -u www-data composer install --no-dev --optimize-autoloader

ขั้นที่ 6 — ตั้งค่า .env และ Application Key

cp .env.example .env
nano .env
# แก้ไขค่าต่อไปนี้:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=StrongPassword123!

# สร้าง Application Key
php artisan key:generate

# Run Migration
php artisan migrate --force

ขั้นที่ 7 — ตั้งค่า Storage Permission

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

# สร้าง Storage Link สำหรับ Public Assets
php artisan storage:link

ขั้นที่ 8 — ตั้งค่า Nginx Virtual Host

sudo nano /etc/nginx/sites-available/myapp

# เนื้อหาไฟล์ config:
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/myapp/public;
    index index.php;

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

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

    location ~ /\.ht { deny all; }
}

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

ขั้นที่ 9 — ติดตั้ง SSL ด้วย Certbot

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# ระบบจะตั้งค่า HTTPS และ Auto-renewal ให้อัตโนมัติ

ขั้นที่ 10 — ตั้งค่า Queue Worker (ถ้าใช้ Queue)

# สร้าง Supervisor config สำหรับ Queue Worker
sudo apt install supervisor -y
sudo nano /etc/supervisor/conf.d/laravel-worker.conf

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

# Reload Supervisor
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*

ขั้นที่ 11 — Optimize สำหรับ Production

# Cache Config, Routes, Views
php artisan config:cache
php artisan route:cache
php artisan view:cache

# Cache Composer Autoloader
composer dump-autoload --optimize

การตั้งค่า Cron Job สำหรับ Laravel Scheduler

Laravel มีระบบ Task Scheduling ในตัว (Laravel Scheduler) ที่ใช้ Cron Job เพียงหนึ่งบรรทัดเพื่อรัน Schedule ทั้งหมด ซึ่งสะดวกกว่าการสร้าง Cron Job แยกสำหรับแต่ละงาน

# เปิด Crontab ของ www-data user
sudo crontab -u www-data -e

# เพิ่มบรรทัดนี้ (รัน Laravel Scheduler ทุกนาที)
* * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1

เมื่อตั้งค่าแล้ว งาน Schedule ทั้งหมดที่กำหนดไว้ใน app/Console/Kernel.php หรือ Route Scheduler (Laravel 10+) จะทำงานตามเวลาที่กำหนดอัตโนมัติ ตัวอย่างงาน Schedule ที่พบบ่อย เช่น ส่ง Email Digest รายวัน, ลบ Log เก่า, Sync ข้อมูลจาก API ภายนอก

# ตัวอย่างการกำหนด Schedule ใน routes/console.php (Laravel 10+)
use Illuminate\Support\Facades\Schedule;

Schedule::command('emails:send-digest')->dailyAt('08:00');
Schedule::command('logs:clean')->weekly();
Schedule::command('cache:prune-stale-tags')->hourly();

การ Monitor และ Debug Laravel บน VPS

หลัง Deploy สิ่งสำคัญคือการ Monitor ให้แอปพลิเคชันทำงานได้อย่างมีเสถียรภาพ Laravel มีระบบ Logging ในตัวที่บันทึกข้อผิดพลาดทั้งหมดไว้ที่ storage/logs/laravel.log

ดู Log แบบ Real-time

tail -f /var/www/myapp/storage/logs/laravel.log

ตรวจ Nginx Access และ Error Log

sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

ตรวจสถานะ PHP-FPM

sudo systemctl status php8.2-fpm
sudo tail -f /var/log/php8.2-fpm.log

ปัญหาที่พบบ่อยและวิธีแก้

ปัญหา สาเหตุที่พบบ่อย วิธีแก้
500 Internal Server Error Permission ผิด หรือ .env ไม่ครบ ตรวจ storage/ permission และ .env
404 Not Found Nginx config ผิด หรือไม่มี try_files ตรวจ root path และ try_files ใน nginx.conf
502 Bad Gateway PHP-FPM ไม่ทำงาน sudo systemctl restart php8.2-fpm
Queue ไม่ทำงาน Supervisor หยุดทำงาน sudo supervisorctl start laravel-worker:*

การตั้งค่า Redis สำหรับ Cache และ Session ใน Laravel

Laravel รองรับ Redis เป็น Backend สำหรับ Cache, Session และ Queue ซึ่งช่วยให้แอปพลิเคชันทำงานได้เร็วขึ้นมากโดยลดการเข้าถึง Database ในการดึงข้อมูลที่ใช้บ่อยๆ การติดตั้ง Redis บน VPS Ubuntu นั้นง่ายมาก

# ติดตั้ง Redis
sudo apt install redis-server -y
sudo systemctl enable redis-server
sudo systemctl start redis-server

# ทดสอบว่า Redis ทำงาน
redis-cli ping

หลังติดตั้ง Redis แล้ว ให้ตั้งค่า Laravel ให้ใช้ Redis โดยแก้ไขไฟล์ .env ดังนี้

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

จากนั้นติดตั้ง Package ที่จำเป็น

composer require predis/predis

เมื่อตั้งค่าเสร็จแล้ว Laravel จะใช้ Redis แทน File System สำหรับ Cache และ Session ทำให้ Response Time ลดลงอย่างเห็นได้ชัด โดยเฉพาะหน้าที่ต้องดึงข้อมูลจำนวนมากจาก Database บ่อยๆ เช่น หน้าแรก หน้าสินค้า หรือ API Endpoint ที่ถูกเรียกบ่อย

การใช้งาน Cache ใน Laravel

// เก็บข้อมูลใน Cache นาน 60 นาที
Cache::put('popular_products', $products, 3600);

// ดึงข้อมูลจาก Cache ถ้าไม่มีค่อย Query Database
$products = Cache::remember('popular_products', 3600, function () {
    return Product::where('is_active', true)
                  ->orderBy('sales_count', 'desc')
                  ->limit(20)
                  ->get();
});

// ลบ Cache เมื่อข้อมูลเปลี่ยนแปลง
Cache::forget('popular_products');

การจัดการ Environment หลาย Environment บน VPS

โปรเจกต์ Laravel ที่ใช้งานจริงมักต้องแยก Environment อย่างน้อย 3 ระดับ ได้แก่ Local (เครื่อง Developer), Staging (สำหรับทดสอบ) และ Production (เซิร์ฟเวอร์จริง) การแยก Environment ให้ชัดเจนช่วยป้องกันไม่ให้ข้อมูลทดสอบปะปนกับข้อมูลจริง และช่วยให้ทีม QA ทดสอบระบบได้อย่างปลอดภัย

โครงสร้างไฟล์ .env แยก Environment

# สร้างไฟล์ .env แยกตาม Environment
.env              # ค่าหลัก (committed ไม่ได้ — อยู่ใน .gitignore)
.env.example      # Template สำหรับ Developer ใหม่ (committed ได้)
.env.staging      # ค่าสำหรับ Staging (ไม่ commit — ตั้งบน server เท่านั้น)
.env.production   # ค่าสำหรับ Production (ไม่ commit — ตั้งบน server เท่านั้น)

การใช้ dotenv-vault หรือ Secret Management

สำหรับโปรเจกต์ที่มีทีมงานหลายคน ควรพิจารณาใช้ Secret Management เพื่อแจกจ่าย Environment Variables อย่างปลอดภัย แทนการส่งไฟล์ .env ผ่าน Chat หรือ Email ซึ่งเสี่ยงต่อการรั่วไหล

# ใน .env.production ที่ถูกต้อง
APP_NAME="MyApp Production"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com
LOG_CHANNEL=daily
LOG_LEVEL=error

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_prod
DB_USERNAME=laravel_prod_user
DB_PASSWORD=VeryStrongProductionPassword!

MAIL_MAILER=smtp
MAIL_HOST=smtp.yourdomain.com
MAIL_PORT=587
[email protected]
MAIL_PASSWORD=YourMailPassword

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

กฎทอง: ไฟล์ .env ทุกตัวต้องอยู่ใน .gitignore เสมอ ยกเว้น .env.example ที่ไม่มีค่า Secret จริงๆ การรั่วไหลของ .env Production อาจทำให้ Database ถูก Compromise ได้ทันที

การตั้งค่า Laravel Horizon สำหรับ Monitor Queue บน VPS

Laravel Horizon เป็น Dashboard สำหรับ Monitor Queue Worker ที่สร้างโดยทีม Laravel อย่างเป็นทางการ ให้ข้อมูล Real-time เกี่ยวกับ Throughput ของ Job ระยะเวลาในการ Process และสถิติต่างๆ ของ Queue System ทำให้ Debug ปัญหา Queue ได้ง่ายขึ้นมาก

ติดตั้ง Laravel Horizon

composer require laravel/horizon
php artisan horizon:install

ตั้งค่า Horizon ใน config/horizon.php

// config/horizon.php — กำหนด Worker Process
'environments' => [
    'production' => [
        'supervisor-1' => [
            'maxProcesses' => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
        ],
    ],
    'local' => [
        'supervisor-1' => [
            'maxProcesses' => 3,
        ],
    ],
],

สร้าง Supervisor Config สำหรับ Horizon

sudo nano /etc/supervisor/conf.d/laravel-horizon.conf

[program:laravel-horizon]
process_name=%(program_name)s
command=php /var/www/myapp/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/myapp/storage/logs/horizon.log
stopwaitsecs=3600

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-horizon

ป้องกัน Horizon Dashboard ด้วย Gate

// app/Providers/HorizonServiceProvider.php
protected function gate(): void
{
    Gate::define('viewHorizon', function ($user) {
        return in_array($user->email, [
            '[email protected]',
        ]);
    });
}

หลังจากตั้งค่าแล้ว เข้าถึง Horizon Dashboard ได้ที่ https://yourdomain.com/horizon จะเห็นสถิติ Job ทั้งหมด เช่น จำนวน Job ที่รอ กำลังประมวลผล และ Failed พร้อม Option ให้ Retry Job ที่ล้มเหลวได้ทันทีจาก Dashboard โดยไม่ต้อง SSH เข้า Server

การทำ Laravel Rate Limiting และป้องกัน API Abuse บน VPS

เว็บแอปพลิเคชันบน Production ต้องมีกลไกป้องกัน Bot และการเรียก API มากเกินไปในเวลาสั้น Laravel มี Rate Limiting ในตัวผ่าน throttle Middleware ที่ใช้ Redis เป็น Backend เพื่อ Track จำนวนคำขอต่อ IP

ตั้งค่า Rate Limiting ใน routes/api.php

// ใน routes/api.php — ใช้ throttle Middleware
Route::middleware(['throttle:60,1'])->group(function () {
    Route::get('/products', [ProductController::class, 'index']);
    Route::post('/orders', [OrderController::class, 'store']);
});

// กำหนด Custom Throttle ใน RouteServiceProvider
RateLimiter::for('api', function (Request $request) {
    return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});

// สำหรับ Login Page — กำหนด Limit เข้มงวดขึ้น
RateLimiter::for('login', function (Request $request) {
    return [
        Limit::perMinute(5)->by($request->input('email')),
        Limit::perMinute(20)->by($request->ip()),
    ];
});
Middleware ค่า ใช้กับ
throttle:60,1 60 requests/นาที API ทั่วไป
throttle:5,1 5 requests/นาที Login/Register
throttle:1000,1 1000 requests/นาที Static/Public API
Nginx limit_req Layer 7 Rate Limit ป้องกัน DDoS ก่อนถึง PHP

เพิ่ม Rate Limiting บน Nginx ชั้นแรก

# เพิ่มใน /etc/nginx/nginx.conf ส่วน http block
limit_req_zone $binary_remote_addr zone=api:10m rate=60r/m;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

# เพิ่มใน server block ของ Laravel
location /api/ {
    limit_req zone=api burst=20 nodelay;
    limit_req_status 429;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
    include fastcgi_params;
}

location /login {
    limit_req zone=login burst=3 nodelay;
    limit_req_status 429;
    try_files $uri $uri/ /index.php?$query_string;
}

การใช้ Rate Limiting ทั้งบน Nginx และ Laravel พร้อมกัน (Defense in Depth) ช่วยลดภาระของ PHP Server ในกรณีที่มีการโจมตีขนาดใหญ่ เพราะ Nginx จะกรอง Request ที่เกิน Rate ออกก่อนที่จะส่งมาถึง PHP-FPM ช่วยประหยัด CPU และ RAM ของ VPS ได้อย่างมีนัยสำคัญ

การ Deploy Laravel ด้วย Git Hooks อัตโนมัติ

การ Deploy ด้วย Git Hooks ช่วยให้การอัปเดตโค้ดเป็นไปอย่างอัตโนมัติเมื่อ Push โค้ดขึ้น Remote Repository โดยไม่ต้อง SSH เข้าไปทำเองทุกครั้ง วิธีนี้เหมาะมากสำหรับโปรเจกต์ที่ Deploy บ่อยหรือทีมที่มีนักพัฒนาหลายคน

ตั้งค่า Bare Repository บน VPS

# สร้าง Bare Repository บน VPS
sudo mkdir -p /var/repo/myapp.git
cd /var/repo/myapp.git
sudo git init --bare
sudo chown -R deployer:deployer /var/repo/myapp.git

สร้าง Post-receive Hook

sudo nano /var/repo/myapp.git/hooks/post-receive
#!/bin/bash
TARGET="/var/www/myapp"
GIT_DIR="/var/repo/myapp.git"
BRANCH="main"

while read oldrev newrev ref; do
  BRANCH_NAME=$(git rev-parse --symbolic --abbrev-ref $ref)
  if [ "$BRANCH_NAME" = "$BRANCH" ]; then
    echo "Deploying branch: $BRANCH_NAME"
    git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
    cd $TARGET
    composer install --no-dev --optimize-autoloader
    php artisan migrate --force
    php artisan optimize:clear
    php artisan optimize
    sudo supervisorctl restart laravel-worker:*
    echo "Deploy complete"
  fi
done
sudo chmod +x /var/repo/myapp.git/hooks/post-receive

เพิ่ม Remote บนเครื่อง Developer

# บนเครื่อง Local ของ Developer
git remote add production deployer@YOUR_VPS_IP:/var/repo/myapp.git

# Deploy ด้วยคำสั่งเดียว
git push production main

เมื่อ Push โค้ดขึ้นไป Hook จะทำงานอัตโนมัติ ดึงโค้ดไปยัง /var/www/myapp Run Migration และ Restart Worker ทั้งหมดในครั้งเดียว ทำให้ Deploy เร็วและสม่ำเสมอทุกครั้ง ไม่ต้องกลัวลืมขั้นตอนใดขั้นตอนหนึ่ง

การอัปเดตโค้ด Laravel บน VPS (Zero-downtime Deployment)

เมื่อต้องการอัปเดตโค้ด ควรทำตามขั้นตอนที่ถูกต้องเพื่อไม่ให้ผู้ใช้งานพบข้อผิดพลาดระหว่าง Deploy

# 1. เข้าสู่โหมด Maintenance
php artisan down --retry=60

# 2. ดึงโค้ดล่าสุดจาก Git
git pull origin main

# 3. ติดตั้ง Dependencies ใหม่
composer install --no-dev --optimize-autoloader

# 4. Run Migration ถ้ามี
php artisan migrate --force

# 5. Clear Cache และ Re-cache
php artisan optimize:clear
php artisan optimize

# 6. Restart Queue Worker
sudo supervisorctl restart laravel-worker:*

# 7. ออกจาก Maintenance Mode
php artisan up

การใช้ php artisan down ก่อน Deploy ช่วยป้องกันไม่ให้ผู้ใช้พบ Database Error ระหว่างที่กำลัง Run Migration ซึ่งอาจทำให้ข้อมูลเสียหายได้ในกรณีที่ Migration มีการเปลี่ยนโครงสร้างตาราง

การเพิ่มประสิทธิภาพ Laravel ด้วย OPcache

PHP OPcache เป็น Extension ที่ช่วย Cache Bytecode ของ PHP ไว้ใน RAM ทำให้ PHP ไม่ต้องแปลง Source Code เป็น Bytecode ซ้ำในทุก Request ส่งผลให้ Response Time ลดลงอย่างมีนัยสำคัญ โดยเฉพาะ Laravel ที่มีไฟล์ PHP จำนวนมาก

sudo nano /etc/php/8.2/fpm/conf.d/10-opcache.ini
[opcache]
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.fast_shutdown=1
sudo systemctl restart php8.2-fpm

การตั้ง validate_timestamps=0 ทำให้ OPcache ไม่ตรวจสอบว่าไฟล์เปลี่ยนแปลงหรือเปล่าทุก Request ซึ่งเพิ่มประสิทธิภาพมาก แต่ต้องระวังว่าเมื่อ Deploy โค้ดใหม่จะต้อง Reload PHP-FPM เพื่อ Clear OPcache เสมอ มิฉะนั้น PHP จะยังรัน Code เก่าอยู่

# Clear OPcache หลัง Deploy
sudo systemctl reload php8.2-fpm

นอกจาก OPcache แล้ว ยังมีเทคนิคอื่นๆ ที่ช่วยเพิ่มประสิทธิภาพ Laravel บน VPS ได้ เช่น การใช้ Horizon สำหรับ Monitor Queue, การ Enable Gzip Compression บน Nginx, การตั้งค่า Keep-alive Connection เพื่อลด TCP Handshake และการใช้ CDN สำหรับ Static Assets เช่น รูปภาพ CSS และ JavaScript เพื่อลดภาระ VPS และเพิ่ม Response Time ให้ผู้ใช้ที่อยู่ห่างออกไป

ตรวจสอบและปรับ PHP-FPM Pool

PHP-FPM สามารถปรับ Pool Configuration เพื่อรองรับ Traffic ได้มากขึ้น โดยเฉพาะการตั้งค่า pm.max_children ซึ่งกำหนดจำนวน PHP Worker Process สูงสุด หลักการคือ RAM ที่เหลือหารด้วย RAM ที่ PHP Process หนึ่งใช้ (เฉลี่ย 30–50 MB) สำหรับ VPS RAM 2 GB ควรตั้งไว้ที่ประมาณ 20–30 process

sudo nano /etc/php/8.2/fpm/pool.d/www.conf

pm = dynamic
pm.max_children = 25
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10

sudo systemctl restart php8.2-fpm

เปิด Gzip Compression บน Nginx

# เพิ่มในไฟล์ /etc/nginx/nginx.conf ส่วน http block
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_disable "MSIE [1-6]\.";

sudo nginx -t && sudo systemctl reload nginx

Checklist ก่อน Go Live: APP_DEBUG=false ✓ → APP_ENV=production ✓ → SSL Active ✓ → Storage Permission ✓ → Queue Worker Running ✓ → Config Cache ✓ → Cron Job ตั้งแล้ว ✓ → OPcache เปิด ✓ → Gzip เปิด ✓ — พร้อม Production

⚠️ ความปลอดภัย: ห้าม Commit ไฟล์ .env ขึ้น Git เด็ดขาด ตั้งค่า Firewall ปิด Port ที่ไม่จำเป็น (UFW) และเปลี่ยน SSH Port เพื่อลด Brute Force

VPS Linux พร้อม Deploy Laravel ราคาเริ่มต้นไม่แพง

AsiaGB VPS ติดตั้ง Ubuntu 22.04 LTS ได้ทันที Root Access เต็มรูปแบบ SSD IP ไทย

ดูแพ็กเกจ VPS