Memindahkan aplikasi Laravel dari lingkungan lokal atau shared hosting ke Virtual Private Server (VPS) memberikan kontrol penuh atas performa, keamanan, dan konfigurasi server. Namun, mengelola server sendiri menuntut pemahaman alur instalasi stack yang tepat serta pengaturan hak akses folder yang aman. Jika alur deployment dilakukan secara manual dengan perintah copy-paste berulang kali, risiko kesalahan manusia (human error) saat merilis fitur baru menjadi sangat tinggi.
Solusi terbaik untuk masalah ini adalah membangun alur deployment otomatis berbasis CI/CD (Continuous Integration / Continuous Deployment) menggunakan GitHub Actions. Setiap kali kode baru di-push ke repository, GitHub Actions akan terhubung ke VPS melalui SSH dan mengeksekusi script deployment secara konsisten. Jika kamu ingin mendalami pengelolaan alur kerja repository Git yang rapi sebelum memasang CI/CD, pelajari juga panduan workflow Git Laravel.
Artikel ini membahas panduan komprehensif mulai dari persiapan awal VPS Ubuntu (22.04 / 24.04 LTS), konfigurasi stack Nginx dan PHP-FPM, deployment manual pertama kali, hingga otomatisasi penuh menggunakan GitHub Actions.
1. Persiapan Environment Server VPS (Ubuntu Stack Setup)
Langkah awal adalah menyiapkan server VPS yang masih bersih (fresh install). OS yang direkomendasikan adalah Ubuntu 22.04 LTS atau 24.04 LTS karena stabilitas dan dukungan paket perangkat lunaknya yang luas.
1.1 Update Perangkat Lunak & Keamanan Dasar SSH
Sebelum menginstal stack web server, perbarui indeks paket sistem terlebih dahulu.
sudo apt update && sudo apt upgrade -y
Sangat tidak disarankan menggunakan user root untuk kebutuhan operasional sehari-hari dan deployment. Buat user baru dengan akses sudo (misalnya user deployer):
sudo adduser deployer
sudo usermod -aG sudo deployer
Pindah ke user deployer dan buat folder .ssh untuk mendaftarkan public key SSH komputer kamu:
su - deployer
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Setelah meletakkan public key di file authorized_keys, uji koneksi SSH dari terminal lokal tanpa kata sandi. Jika berhasil, matikan autentikasi kata sandi dan otorisasi root pada file /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
Restart layanan SSH setelah mengubah konfigurasi:
sudo systemctl restart ssh
1.2 Instalasi Web Server (Nginx) & PHP-FPM
Aplikasi Laravel membutuhkan web server seperti Nginx dan runtime PHP beserta beberapa ekstensi spesifik. Install Nginx dan PHP versi 8.3 (atau 8.2 sesuai kebutuhan proyek) dengan perintah berikut:
sudo apt install -y nginx php8.3-fpm php8.3-cli php8.3-mbstring \
php8.3-xml php8.3-bcmath php8.3-curl php8.3-mysql php8.3-sqlite3 \
php8.3-zip php8.3-gd php8.3-intl unzip git
Pastikan layanan Nginx dan PHP-FPM sudah berjalan aktif di latar belakang:
sudo systemctl status nginx
sudo systemctl status php8.3-fpm
1.3 Instalasi Composer & Node.js
Composer diperlukan untuk mengelola dependensi PHP, sedangkan Node.js dan NPM digunakan untuk mengompilasi asset frontend (Vite / Tailwind CSS).
Instal Composer secara global ke direktori /usr/local/bin:
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer
Untuk menginstal Node.js versi LTS terbaru (misal Node.js 20), gunakan script dari NodeSource:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
Verifikasi versi yang terinstal:
composer --version
node -v
npm -v
1.4 Instalasi & Konfigurasi Database (MySQL)
Install MySQL Server pada VPS:
sudo apt install -y mysql-server
sudo mysql_secure_installation
Masuk ke CLI MySQL untuk membuat database dan user khusus aplikasi Laravel:
CREATE DATABASE laravel_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'PasswordSangatRahas1a!';
GRANT ALL PRIVILEGES ON laravel_db.* TO 'laravel_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
1.5 Instalasi Supervisor & Setup Laravel Scheduler
Laravel menggunakan queue untuk memproses task latar belakang (seperti pengiriman email atau pemrosesan gambar). Supervisor bertugas memastikan queue worker Laravel terus berjalan dan otomatis melakukan restart jika terjadi crash.
Install Supervisor:
sudo apt install -y supervisor
Buat file konfigurasi worker baru di /etc/supervisor/conf.d/laravel-worker.conf:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/my-laravel-app/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=deployer
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/my-laravel-app/storage/logs/worker.log
stopwaitsecs=3600
Informasikan Supervisor untuk membaca konfigurasi baru dan memulainya:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
Untuk task scheduling (Laravel Scheduler), tambahkan baris cron job menggunakan perintah crontab -e pada user deployer:
* * * * * cd /var/www/my-laravel-app && php artisan schedule:run >> /dev/null 2>&1
2. Deployment Manual Pertama Kali (Initial Setup)
Sebelum mengkonfigurasi otomatisasi CI/CD, lakukan deployment manual terlebih dahulu untuk memastikan struktur direktori, izin akses, file .env, dan server block Nginx berfungsi dengan benar.
2.1 Mendaftarkan SSH Deploy Key di GitHub
Agar server VPS dapat menarik kode (pull) dari repository private GitHub tanpa mengetik kata sandi, buat pasangan SSH Deploy Key khusus pada VPS:
ssh-keygen -t ed25519 -C "vps-deploy-key" -f ~/.ssh/id_ed25519_github -N ""
Tampilkan public key yang dihasilkan:
cat ~/.ssh/id_ed25519_github.pub
Salin teks public key tersebut, lalu buka repository proyek kamu di GitHub:
- Masuk ke Settings > Deploy keys.
- Klik Add deploy key.
- Berikan judul (misal:
VPS Production Server). - Tempelkan isi public key dan simpan (centang Allow write access jika dibutuhkan, namun untuk deploy key biasanya akses read-only sudah cukup).
Tambahkan konfigurasi SSH client pada VPS di ~/.ssh/config agar perintah Git otomatis menggunakan private key tersebut:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
IdentitiesOnly yes
Uji koneksi SSH ke GitHub:
ssh -T git@github.com
2.2 Clone Repository & Konfigurasi File Environment
Buat direktori tujuan di /var/www/my-laravel-app dan sesuaikan kepemilikan direktori awal:
sudo mkdir -p /var/www/my-laravel-app
sudo chown -R deployer:www-data /var/www/my-laravel-app
Clone repository GitHub ke direktori tersebut:
git clone git@github.com:username/repository-name.git /var/www/my-laravel-app
cd /var/www/my-laravel-app
Salin file contoh konfigurasi .env.example menjadi .env:
cp .env.example .env
nano .env
Buka file .env dan sesuaikan parameter utama untuk lingkungan produksi:
APP_NAME="Laravel Pro"
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://example.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=PasswordSangatRahas1a!
2.3 Hak Akses & Kepemilikan Direktori (Folder Permissions)
Salah satu penyebab paling umum terjadinya kesalahan HTTP 500 saat deploy Laravel adalah salah konfigurasi hak akses folder. Web server Nginx berjalan di bawah user/group www-data, sedangkan kita mengelola kode dengan user deployer.
Tambahkan user deployer ke dalam grup www-data:
sudo usermod -aG www-data deployer
Atur kepemilikan folder ke deployer:www-data:
sudo chown -R deployer:www-data /var/www/my-laravel-app
Berikan akses baca dan tulis bagi grup pada folder storage dan bootstrap/cache:
sudo find /var/www/my-laravel-app -type f -exec chmod 644 {} \;
sudo find /var/www/my-laravel-app -type d -exec chmod 755 {} \;
sudo chmod -R 775 /var/www/my-laravel-app/storage
sudo chmod -R 775 /var/www/my-laravel-app/bootstrap/cache
2.4 Instalasi Dependensi, Migrasi, & Optimasi Cache
Jalankan instalasi dependensi Composer tanpa paket development:
composer install --no-dev --optimize-autoloader
Generate kunci aplikasi (application key):
php artisan key:generate
Jalankan migrasi database dengan flag --force (flag ini wajib digunakan di lingkungan produksi agar artisan tidak meminta konfirmasi interaktif):
php artisan migrate --force
Buat symbolic link untuk direktori penyimpanan media publik:
php artisan storage:link
Install dependensi Node.js dan build asset frontend:
npm ci
npm run build
Lakukan optimasi performa Laravel dengan memuat konfigurasi, route, dan view ke dalam memori cache:
php artisan config:cache
php artisan route:cache
php artisan view:cache
2.5 Konfigurasi Server Block Nginx
Buat file konfigurasi Nginx baru di /etc/nginx/sites-available/my-laravel-app:
sudo nano /etc/nginx/sites-available/my-laravel-app
Masukkan konfigurasi baku Nginx untuk Laravel berikut:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/my-laravel-app/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
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:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Aktifkan konfigurasi situs dengan membuat symlink ke folder sites-enabled:
sudo ln -s /etc/nginx/sites-available/my-laravel-app /etc/nginx/sites-enabled/
Uji sintaks Nginx dan lakukan reload:
sudo nginx -t
sudo systemctl reload nginx
2.6 Aktivasi SSL HTTPS dengan Certbot (Let's Encrypt)
Gunakan Certbot untuk memasang sertifikat SSL gratis secara otomatis:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
Certbot akan otomatis memperbarui file konfigurasi Nginx kamu untuk mengalihkan seluruh lalu lintas HTTP ke HTTPS secara aman.
3. Membuat Script Deployment Otomatis (deploy.sh)
Melakukan rilis kode baru secara manual memerlukan banyak langkah berurutan. Jika ada satu langkah yang terlewat (misalnya lupa menjalankan php artisan queue:restart), aplikasi bisa mengalami perilaku yang membingungkan.
Buat sebuah script bash pembantu bernama deploy.sh di dalam folder proyek /var/www/my-laravel-app/deploy.sh:
nano /var/www/my-laravel-app/deploy.sh
Isi file deploy.sh dengan baris perintah berikut:
#!/bin/bash
set -e
echo "=== Memulai Proses Deployment ==="
# 1. Pastikan berada di direktori proyek
cd /var/www/my-laravel-app
# 2. Ambil perubahan kode terbaru dari branch main
echo "Mengunduh kode terbaru dari Git..."
git pull origin main
# 3. Install/Update dependensi PHP
echo "Menginstal dependensi Composer..."
composer install --no-dev --optimize-autoloader
# 4. Jalankan migrasi database
echo "Menjalankan migrasi database..."
php artisan migrate --force
# 5. Build asset frontend (Opsional jika dilakukan di server)
echo "Mengompilasi asset frontend..."
npm ci
npm run build
# 6. Rebuild cache aplikasi
echo "Memperbarui cache konfigurasi, route, dan view..."
php artisan config:cache
php artisan route:cache
php artisan view:cache
# 7. Restart queue worker agar membaca kode baru
echo "Merestart Laravel Queue Worker..."
php artisan queue:restart
echo "=== Deployment Berhasil Selesai! ==="
Berikan hak akses eksekusi pada script tersebut:
chmod +x /var/www/my-laravel-app/deploy.sh
Uji eksekusi script secara langsung dari terminal VPS untuk memastikan tidak ada perintah yang error:
/var/www/my-laravel-app/deploy.sh
4. Otomatisasi CI/CD dengan GitHub Actions
Dengan script deploy.sh yang sudah siap di VPS, kini kamu bisa mengkonfigurasi GitHub Actions agar mengeksekusi script tersebut secara otomatis setiap kali ada penambahan kode (push) ke branch main. Penataan pipeline ini melengkapi panduan workflow Git Laravel dalam siklus pengolahan kode yang modern.
4.1 Menyiapkan SSH Key Khusus GitHub Actions
GitHub Actions membutuhkan private key SSH untuk masuk ke VPS sebagai user deployer.
Buat pasangan kunci SSH baru di komputer lokal atau VPS khusus untuk GitHub Actions:
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions_vps -N ""
Tambahkan isi dari github_actions_vps.pub ke file ~/.ssh/authorized_keys milik user deployer di VPS:
cat ~/.ssh/github_actions_vps.pub >> ~/.ssh/authorized_keys
4.2 Menambahkan GitHub Encrypted Secrets
Buka repository proyek kamu di GitHub:
- Navigasi ke Settings > Secrets and variables > Actions.
- Klik tombol New repository secret.
- Daftarkan 4 variabel rahasia berikut:
| Nama Secret | Nilai / Isi |
|---|---|
VPS_HOST | IP Public server VPS kamu (contoh: 103.170.xx.xx atau example.com) |
VPS_USERNAME | Username SSH di VPS (deployer) |
VPS_SSH_KEY | Isi lengkap dari private key github_actions_vps (termasuk baris -----BEGIN OPENSSH PRIVATE KEY-----) |
VPS_PORT | Port SSH server kamu (default: 22) |
4.3 Membuat File Workflow GitHub Actions (.github/workflows/deploy.yml)
Di dalam proyek Laravel lokal kamu, buat direktori .github/workflows dan buat file deploy.yml:
name: Deploy Laravel to VPS
on:
push:
branches:
- main
jobs:
deploy:
name: Execute Remote Deployment Script
runs-on: ubuntu-latest
steps:
- name: Trigger Remote Deploy Script via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USERNAME }}
key: ${{ secrets.VPS_SSH_KEY }}
port: ${{ secrets.VPS_PORT }}
script: |
cd /var/www/my-laravel-app
./deploy.sh
Commit file deploy.yml dan lakukan push ke GitHub:
git add .github/workflows/deploy.yml
git commit -m "ci: add github actions vps deployment workflow"
git push origin main
Buka tab Actions di repository GitHub kamu. Kamu akan melihat workflow baru berjalan secara otomatis, terhubung ke VPS melalui SSH, dan mengeksekusi script deploy.sh.
5. Optimasi Spesifikasi Rendah (Vite Build di GitHub Actions Runner)
Jika VPS kamu memiliki spesifikasi RAM terbatas (misalnya 1GB tanpa SWAP), menjalankan perintah npm run build di dalam server VPS sering kali menyebabkan kegagalan akibat masalah Out of Memory (OOM).
Solusi terbaiknya adalah mengompilasi asset frontend langsung di dalam runner gratis milik GitHub Actions, kemudian mengunggah folder hasil kompilasi (public/build) ke VPS menggunakan rsync atau scp.
Berikut adalah alternatif konfigurasi .github/workflows/deploy.yml untuk skenario build asset di runner:
name: Deploy Laravel to VPS (Build Asset on Runner)
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Node.js Environment
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install Frontend Dependencies & Build Assets
run: |
npm ci
npm run build
- name: Copy Built Assets to VPS via Rsync
uses: Burnett01/rsync-deployments@v7.0.1
with:
switches: -avzr --delete
path: public/build/
remote_path: /var/www/my-laravel-app/public/build/
remote_host: ${{ secrets.VPS_HOST }}
remote_port: ${{ secrets.VPS_PORT }}
remote_user: ${{ secrets.VPS_USERNAME }}
remote_key: ${{ secrets.VPS_SSH_KEY }}
- name: Execute Server Deployment Commands
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USERNAME }}
key: ${{ secrets.VPS_SSH_KEY }}
port: ${{ secrets.VPS_PORT }}
script: |
cd /var/www/my-laravel-app
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan queue:restart
Dengan metode ini, beban kompilasi CSS dan JS dipindahkan penuh ke infrastruktur GitHub Actions, sehingga server VPS tetap dingin dan hemat memori.
6. Practical Pitfalls & Cara Mengatasinya
Dalam rilis aplikasi Laravel di lingkungan nyata, ada beberapa kendala teknis yang sering ditemui. Berikut adalah perincian masalah dan langkah pemecahannya:
6.1 Permisi File & Kesalahan HTTP 500 (Permission Denied)
Jika aplikasi menampilkan halaman kosong atau error 500 setelah deploy, penyebab utamanya hampir selalu berkaitan dengan izin akses folder storage dan bootstrap/cache.
Ketika proses git pull dilakukan oleh user deployer, file baru yang ditarik mungkin tidak bisa ditulis oleh Nginx (www-data).
Solusi:
Pastikan umask user deployer dikonfigurasi agar membuat file dengan izin grup yang dapat ditulis. Atau pastikan script deploy.sh menyertakan penyesuaian izin akses jika diperlukan:
sudo chown -R deployer:www-data /var/www/my-laravel-app/storage /var/www/my-laravel-app/bootstrap/cache
sudo chmod -R 775 /var/www/my-laravel-app/storage /var/www/my-laravel-app/bootstrap/cache
6.2 Prompt Konfirmasi Migrasi Database di Produksi
Secara bawaan, perintah php artisan migrate di lingkungan APP_ENV=production akan menghentikan eksekusi dan meminta konfirmasi interaktif: Application In Production! Do you really wish to run command?.
Dalam alur CI/CD otomatis tanpa terminal interaktif, hal ini membuat proses deploy menggantung (hang) hingga waktu eksekusi runner habis (timeout).
Solusi:
Wajib menggunakan flag --force pada perintah migrasi di script deployment:
php artisan migrate --force
6.3 Queue Worker Masih Menggunakan Kode Lama
Laravel memuat seluruh kode aplikasi ke dalam memori (RAM) saat proses queue:work dinyalakan. Jika kamu memperbarui kode logika di Controller atau Job lalu melakukan git pull, worker Supervisor tidak akan otomatis menyadari perubahan tersebut dan tetap mengeksekusi logika lama.
Solusi:
Selalu sertakan perintah php artisan queue:restart di akhir alur deployment. Perintah ini memberi instruksi halus (graceful signal) kepada worker untuk berhenti setelah menyelesaikan tugas berjalan, dan Supervisor akan otomatis menyalakan instance worker baru dengan kode aplikasi paling mutakhir.
6.4 Error Host Key Verification Failed pada SSH Action
Jika job GitHub Actions gagal pada tahap SSH dengan pesan kesalahan Host key verification failed, artinya runner tidak mengenali fingerprint server VPS kamu.
Solusi:
Action appleboy/ssh-action sebenarnya menangani hal ini secara otomatis. Namun jika kamu menggunakan perintah SSH native dalam runner, pastikan kamu menambahkan fingerprint VPS menggunakan ssh-keyscan:
- name: Scan SSH Host Keys
run: |
mkdir -p ~/.ssh
ssh-keyscan -H ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts
7. Penutup
Mengonfigurasi server VPS Ubuntu dari awal dan mengintegrasikannya dengan GitHub Actions memberikan alur deployment yang stabil, cepat, dan terhindar dari human error. Langkah utama yang telah diselesaikan meliputi:
- Menyiapkan stack web server (Nginx, PHP 8.3-FPM, MySQL, Composer, Supervisor).
- Mengatur skema perizinan direktori yang aman antara user
deployerdan grupwww-data. - Menyusun script deployment (
deploy.sh) yang menangani migrasi, pembersihan cache, dan restart worker. - Mengotomatiskan eksekusi rilis menggunakan GitHub Actions via SSH Secrets.
Rekomendasi Langkah Selanjutnya
Untuk skala proyek yang lebih besar atau sistem dengan transaksi tinggi, kamu dapat mempertimbangkan beberapa peningkatan infrastruktur berikut:
- Zero-Downtime Deployment: Implementasikan alat rilis berbasis release directory symlinks seperti Deployer.php atau Laravel Envoyer. Metode ini menyiapkan rilis baru di folder terpisah sebelum memindahkan symlink web server, sehingga aplikasi tidak mengalami downtime sama sekali saat proses rilis berlangsung.
- Error & Log Monitoring: Pasang alat pemantau error otomatis seperti Sentry, Bugsnag, atau Laravel Pulse/Telescope di produksi agar setiap kesalahan runtime setelah deployment dapat terdeteksi secara real-time.
Fitur komentar belum diaktifkan oleh administrator.