VPS Murah Nevacloud

Cara Deploy Laravel 13 di VPS: Nginx, PHP 8.5, Tanpa Forge

Laravel 13 butuh PHP minimal 8.3, dan Ubuntu 26.04 LTS sudah membawa PHP 8.5 di repositori bawaannya. Artinya, untuk pertama kali dalam beberapa tahun, kita bisa deploy Laravel 13 di VPS tanpa menambah PPA pihak ketiga sama sekali. Cukup apt install, satu server block Nginx, lalu beberapa perintah artisan.

Oke, lanjuutt.. Kita bahas urutannya dari server kosong sampai aplikasi menjawab HTTP 200, termasuk dua hal yang paling sering terlupa: permission folder dan queue worker yang ikut mati saat VPS reboot.

Kenapa Laravel 13 Layak Dipasang Sendiri di VPS

Laravel 13 dirilis 17 Maret 2026 dan masih menerima perbaikan bug sampai kuartal ketiga 2027, dengan dukungan keamanan sampai 17 Maret 2028. Siklus sepanjang itu membuatnya masuk akal untuk proyek yang tidak ingin repot migrasi tiap tahun.

Yang berubah dibanding Laravel 12: PHP 8.3 jadi batas minimum (8.2 tidak lagi didukung), dan dokumentasi resmi menyebut tiga hal yang sekarang jadi jalur utama deployment: konfigurasi Nginx standar, php artisan optimize, serta perintah php artisan reload untuk memuat ulang queue worker dan proses panjang lain setelah rilis baru.

Poin terakhir itu penting. Dulu kita harus mengingat-ingat php artisan queue:restart; sekarang reload menangani proses yang bisa dimuat ulang, dan sisanya diurus process monitor.

Prasyarat yang Perlu Disiapkan

  • VPS Ubuntu 26.04 LTS (24.04 juga bisa, hanya PHP bawaannya 8.3)
  • Akses sudo dan nama domain yang A record-nya sudah menunjuk ke IP VPS
  • Database MariaDB/MySQL yang sudah terpasang
  • Repositori aplikasi (Git) yang siap di-clone

Kalau domain belum diarahkan, tunda dulu langkah Certbot. Urutan yang benar: DNS dulu, sertifikat belakangan.

Langkah 1: Pasang PHP 8.5 dan Ekstensi yang Diminta Laravel

Dokumentasi deployment Laravel 13 mencantumkan daftar ekstensi wajib: Ctype, cURL, DOM, Fileinfo, Filter, Hash, Mbstring, OpenSSL, PCRE, PDO, Session, Tokenizer, dan XML. Di Ubuntu, sebagian besar sudah ikut dalam paket dasar, tapi lebih aman dipasang eksplisit.


sudo apt update
sudo apt install -y php8.5 php8.5-fpm php8.5-cli php8.5-mysql \
  php8.5-curl php8.5-mbstring php8.5-xml php8.5-zip php8.5-gd php8.5-intl

Pastikan versi yang benar-benar terpasang:


php -v
systemctl status php8.5-fpm --no-pager
ls -l /run/php/php8.5-fpm.sock

Kalau php-fpm di Ubuntu 26.04 sudah menunjuk ke 8.5, memakai paket tanpa nomor versi juga sah. Yang tidak boleh ditebak adalah nama socket-nya, karena di situ Nginx akan diarahkan.

Langkah 2: Siapkan Aplikasi dan Permission


sudo mkdir -p /srv/app && sudo chown $USER:www-data /srv/app
git clone <repo-url> /srv/app
cd /srv/app
composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate

Isi .env untuk produksi: kredensial database, APP_URL dengan HTTPS, dan yang paling sering terlewat:


APP_ENV=production
APP_DEBUG=false

Dokumentasi Laravel tegas soal ini: APP_DEBUG=true di produksi bisa membocorkan nilai konfigurasi sensitif ke pengunjung. Setelah .env benar, jalankan migrasi:


php artisan migrate --force

Bendera --force wajib karena Laravel menolak migrasi di lingkungan produksi tanpa konfirmasi eksplisit.

Sekarang bagian yang bikin error 500 padahal semua sudah “benar”: permission. Laravel perlu menulis ke storage dan bootstrap/cache.


sudo chown -R www-data:www-data storage bootstrap/cache
sudo find storage bootstrap/cache -type d -exec chmod 775 {} \;
sudo find storage bootstrap/cache -type f -exec chmod 664 {} \;

Jangan tergoda chmod -R 777. Itu bukan solusi permission, itu cara mengundang masalah lain.

Langkah 3: Server Block Nginx untuk Laravel

Dokumentasi resmi Laravel 13 menyediakan contoh yang bisa langsung dipakai, dengan satu penyesuaian: ganti path socket ke versi PHP yang kita pasang.


server {
    listen 80;
    listen [::]:80;
    server_name app.contoh.com;
    root /srv/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 ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/run/php/php8.5-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_buffer_size 32k;
        fastcgi_buffers 8 32k;
        fastcgi_busy_buffers_size 64k;
        fastcgi_hide_header X-Powered-By;
    }

    location ~ \.php$ {
        return 404;
    }

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

Blok location ~ \.php$ { return 404; } bukan hiasan: tanpa itu, berkas PHP di luar public/ bisa dipanggil langsung lewat URL dan dieksekusi FPM. Ini bagian dari konfigurasi resmi Laravel, dan sering terlewat saat orang menyalin hanya bagian location /.

Tiga detail yang menentukan:

  • root harus menunjuk ke folder public, bukan root proyek. Menyajikan dari root proyek membuka .env ke publik.
  • **Blok location ~ /\.(?!well-known).* { deny all; }** menutup akses ke seluruh file berawalan titik, termasuk .env, .git, dan file konfigurasi lain. Jangan dihapus karena “tidak dipakai”.
  • fastcgi_pass pakai socket, bukan 127.0.0.1:9000, kecuali kita memang mengubah listen FPM.

Aktifkan dan uji konfigurasi:


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

Langkah 4: Cache Konfigurasi dengan php artisan optimize

Ini langkah yang membedakan deploy rapi dan deploy sekadar “jalan”. Laravel 13 menyediakan satu perintah yang merangkum config:cache, event:cache, route:cache, dan view:cache:


php artisan optimize

Efeknya nyata: konfigurasi tidak lagi dibaca dari .env per request, route dan Blade view sudah terkompilasi. Satu peringatan penting — setelah config:cache, fungsi env() di luar file config/ akan mengembalikan null. Jadi pastikan semua akses .env lewat config/.

Kalau perlu membatalkan semuanya saat debugging:


php artisan optimize:clear

Langkah 5: Queue Worker yang Hidup Lagi Setelah Reboot

Kalau aplikasi memakai queue (email, ekspor CSV, sinkronisasi), worker harus jalan terus. php artisan queue:work adalah proses panjang, jadi butuh supervisor. systemd sudah tersedia tanpa paket tambahan:


[Unit]
Description=Laravel queue worker
After=network.target mariadb.service

[Service]
User=www-data
Group=www-data
Restart=always
RestartSec=5
WorkingDirectory=/srv/app
ExecStart=/usr/bin/php8.5 /srv/app/artisan queue:work --sleep=3 --tries=3 --max-time=3600

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl enable --now laravel-worker
systemctl status laravel-worker --no-pager

--max-time=3600 membuat worker berhenti sendiri tiap satu jam lalu dihidupkan ulang systemd. Ini praktik yang aman untuk menghindari kebocoran memori pada proses yang hidup berbulan-bulan.

Setiap kali ada rilis baru, muat ulang proses panjangnya:


php artisan reload

Langkah 6: Verifikasi, Jangan Cuma Percaya “Sepertinya Jalan”

Laravel 13 punya health route bawaan di /up yang membalas 200 kalau aplikasi berhasil boot, dan 500 kalau ada exception saat bootstrap.


curl -sI https://app.contoh.com/up | head -1
curl -sI https://app.contoh.com | head -1
ss -lntp | grep nginx
sudo tail -n 30 /var/log/nginx/error.log

Kalau muncul 502, hampir selalu penyebabnya salah satu dari tiga: socket FPM tidak cocok, permission storage belum benar, atau APP_KEY kosong. Periksa /var/log/nginx/error.log dulu sebelum mengubah konfigurasi apa pun.

Setelah HTTPS aktif lewat Certbot, jangan lupa set APP_URL ke https:// dan jalankan php artisan optimize sekali lagi supaya URL yang di-cache ikut berubah.

Kesimpulan

Deploy Laravel 13 di VPS sekarang tidak lagi butuh panel berbayar atau PPA tambahan: PHP 8.5 sudah ada di Ubuntu 26.04, konfigurasi Nginx-nya resmi dari dokumentasi, dan php artisan optimize menutup sebagian besar selisih performa. Yang benar-benar menentukan adalah tiga hal kecil: root menunjuk ke public, permission storage benar, dan queue worker punya supervisor.

Sisakan satu jam untuk menuliskan keenam langkah ini ke sebuah skrip atau playbook, karena deploy kedua akan terasa jauh lebih cepat daripada yang pertama. Kalau nanti macet di 502, ingat urutannya: log Nginx dulu, socket kedua, permission ketiga.

Baca juga

Nevacloud VPS Indonesia

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *