Table of contents
Mencari cara upload Laravel ke cPanel sering jadi tantangan ketika hosting tidak menyediakan akses SSH atau Node.js. Kondisi ini cukup umum, terutama di shared hosting dasar. Tanpa terminal, proses seperti composer install atau build asset harus dilakukan secara manual.
Artikel ini membahas langkah praktis yang bisa langsung diterapkan, mulai dari persiapan hingga deployment, dengan pendekatan yang realistis dan aman agar aplikasi Laravel tetap berjalan optimal di lingkungan terbatas.
Persiapan Sebelum Upload Laravel ke cPanel (Checklist Singkat)
Sebelum mulai upload, pastikan beberapa hal berikut sudah siap agar proses tidak terhenti di tengah jalan:
- Sudah memiliki akun hosting dengan akses cPanel
- Laravel sudah terinstall (via Softaculous atau dari localhost)
- Project Laravel sudah berjalan normal di localhost (tidak error)
- Asset frontend sudah di-build di lokal (karena tidak ada Node.js di server)
- Sudah menyiapkan:
- File project Laravel
- Database (.sql) jika menggunakan database
- Sudah membuat database, user, dan password di cPanel
Penyesuaian Struktur (Wajib)
Agar aman di shared hosting:
- Buat folder baru: Core (atau bebas)
- Pindahkan semua file Laravel kecuali folder public ke dalam folder tersebut
Hasil akhirnya:
- public_html/Core → berisi core Laravel
- public_html/ → nantinya berisi isi folder public
Ini penting untuk mencegah file sensitif Laravel bisa diakses langsung dari browser.
Langkah-langkah Upload Laravel ke cPanel (Detail Teknis)
Bagian ini adalah inti dari proses deployment. Ikuti secara berurutan karena setiap langkah saling berkaitan.
Tahap 1: Upload dan Setup Awal
#1. Kompres Project Laravel
Dari localhost, kompres project menjadi .zip atau .tar.gz.
- Klik kanan project Laravel
- Kompres menjadi .zip atau .tar.gz

Langkah ini bertujuan agar proses upload lebih cepat dan menghindari kegagalan upload file dalam jumlah besar. Selain itu, struktur file tetap utuh saat dipindahkan ke server.
#2. Login ke cPanel & Set PHP
Masuk ke cPanel, lalu buka MultiPHP Manager atau PHP Selector.

- Buka MultiPHP Manager / PHP Selector
- Sesuaikan versi PHP dengan Laravel (misalnya PHP 8.x untuk Laravel terbaru)

Contoh:
- Laravel terbaru → PHP 8.x
Ini krusial. Jika versi tidak sesuai, biasanya akan muncul error seperti blank page atau fatal error.
#3. Setup Database
Buka MySQL Database Wizard untuk membuat database, user, dan password.
- Buka MySQL Database Wizard

- Buat:
- Nama database
- User database
- Password
- Assign user ke database
Setelah itu, gunakan phpMyAdmin untuk mengimpor file .sql.

- Masuk ke phpMyAdmin
- Import file .sql

Langkah ini memastikan aplikasi Laravel bisa langsung terhubung ke database saat dijalankan.
#4. Upload File Laravel
- Buka File Manager

- Masuk ke public_html
- Buat folder baru: Core

- Upload file zip ke dalam folder tersebut
- Klik kanan → Extract

Setelah ekstrak, seluruh file Laravel ada di:
public_html/Core
Penempatan di folder khusus ini bertujuan agar file inti Laravel tidak langsung terekspos ke publik.
#5. Konfigurasi File .env
Edit file .env di dalam folder Core dengan mengaktifkan hidden files.
Caranya, masuk ke folder Core → aktifkan Show Hidden Files

Edit .env,ubah pada bagian APP_ENV , APP_DEBUG, APP_URL menjadi:
APP_ENV=production
APP_DEBUG=true
APP_URL=https://namadomainmu.com
Lalu untuk DB_DATABASE, DB_USERNAME, DB_PASSWORD isi dengan nama database, user database dan password database yang sudah dibuat sebelumnya.

Simpan file .env tersebut bila sudah selesai.
Penyesuaian ini penting agar:
- Laravel tahu domain production
- Koneksi database berjalan normal
Tahap 2: Konfigurasi Public & Routing
Di tahap ini, Laravel mulai “disambungkan” ke domain utama. Tahap ini adalah bagian paling penting karena menentukan apakah Laravel bisa diakses dari browser.
Berikut ini checklistnya:
- Membuat symlink storage di dalam public_html/Core/public
- Memindahkan isi di dalam public_html/Core/public ke public_html/
- Melakukan edit path dan penambahan pada file index.php yang sudah dipindah ke public_html/
- Membuat file .htaccess di dalam folder public_html/Core untuk memblokir akses langsung dari luar
Ada dua cara yang bisa dilakukan. Cara pertama adalah manual dan aman untuk pemula, dan cara kedua menggunakan script tapi lebih cepat.
Cara Pertama (Manual & Lebih Aman untuk Pemula)
#1. Membuat Symlink Storage
Masuk ke:
public_html/Core/public
Buat file link.php:
<?php
$target = dirname(__DIR__) . '/storage/app/public';
$link = dirname(__FILE__) . '/storage';
if (!file_exists($link)){
symlink($target, $link);
echo "Symlink $target dibuat di $link" ;
}
else {
echo "Gagal! symlink/folder sudah ada di $link" ;
}
Akses di browser:
http://namadomainmu.com/Core/public/link.php

Jika berhasil:
- Folder storage akan muncul di dalam public
Lalu hapus file link.php (penting untuk keamanan).
#2. Pindahkan Folder Public
Masuk ke:
public_html/Core/public
Pindahkan semua file ke:
public_html/

Perubahan ini memberi tahu Laravel lokasi file inti setelah struktur direktori diubah.
Tambahkan juga:
$app->usePublicPath(__DIR__);
Kode ini memastikan asset seperti CSS/JS tetap bisa diakses dari root domain.
#3. Edit File index.php
Buka file index.php dan ubah bagian path sebelumnya:
dari:
'/../storage/framework/maintenance.php'
'/../vendor/autoload.php'
'/../bootstrap/app.php'
menjadi:
public_html/index.php
Ubah path:
Dari:
'/../vendor/autoload.php'
Menjadi:
'/Core/storage/framework/maintenance.php'
'/Core/vendor/autoload.php'
'/Core/bootstrap/app.php'
Lalu edit juga pada bagian sebelum $app->handleRequest(Request::capture());
$app->usePublicPath(__DIR__);
Kode ini memastikan asset seperti CSS/JS tetap bisa diakses dari root domain. Nantinya file assetts di folder public_html menjadi:

#4. Proteksi Folder Core
Masuk ke:
public_html/Core
Buat file .htaccess:
Options -Indexes
Deny from all

Tujuannya untuk memblokir akses langsung ke file inti Laravel demi keamanan.
#5. Testing Website
Akses domain:
- Cek homepage
- Coba login
- Pastikan gambar & asset muncul

Pastikan halaman tampil normal, login berjalan, dan asset tidak error. Jika ada masalah, biasanya terkait path atau symlink.
Cara Kedua (Otomatis dengan Script)
Untuk mempercepat proses, gunakan script otomatis.
Buat file:
public_html/Core/laravel.php
Isi dengan script:
<?php
/**
* Script Otomatisasi Laravel Super (Full Auto)
* 1. Symlink Storage
* 2. Move Public Files (1 tingkat ke atas)
* 3. Proteksi .htaccess di folder core
* 4. Auto-Edit index.php (Update path & PublicPath)
* 5. Logging proses ke file .txt
*
/// — KONFIGURASI —$
basePath = __DIR__; // Folder 'Core' saat ini
$coreFolderName = basename($basePath); // Nama folder core otomatis (misal: 'Core')
$destinationParent = dirname($basePath, 1); // Folder root (public_html / domain root)
$logFile = $basePath . '/automation_log.txt';
// Fungsi bantuan untuk logging
function writeLog($message, $logFile) {
$timestamp = date('Y-m-d H:i:s');
$content = "[$timestamp] $message\n";
file_put_contents($logFile, $content, FILE_APPEND);
echo $content;
}
echo "<pre>";writeLog("— MEMULAI PROSES OTOMATISASI —"
, $logFile);
// — 1. PROSES SYMLINK STORAGE —$
targetStorage = $basePath . '/storage/app/public';
$shortcutStorage = $basePath . '/public/storage';
if (!is_link($shortcutStorage)) {
if (is_dir($targetStorage)) {
if (symlink($targetStorage, $shortcutStorage)) {
writeLog("[SUCCESS] Symlink storage dibuat: $shortcutStorage", $logFile);
} else {
writeLog("[ERROR] Gagal membuat symlink storage.", $logFile);
}
} else {
writeLog("[ERROR] Folder target storage tidak ditemukan.", $logFile);
}
} else {
writeLog("[INFO] Symlink storage sudah ada.", $logFile);
}
// — 2. PINDAHKAN ISI FOLDER PUBLIC KE 1 TINGKAT DI ATAS —$
publicPath = $basePath . '/public';
if (is_dir($publicPath)) {
$files = scandir($publicPath);
foreach ($files as $file) {
if ($file == '.' || $file == '..') continue;
$source = $publicPath . '/' . $file;
$dest = $destinationParent . '/' . $file;
if (rename($source, $dest)) {
writeLog("[SUCCESS] Pindah: $file -> $destinationParent", $logFile);
} else {
writeLog("[ERROR] Gagal memindahkan: $file", $logFile);
}
}
} else {
writeLog("[ERROR] Folder /public tidak ditemukan.", $logFile);
}
// — 3. EDIT INDEX.PHP SECARA OTOMATIS —$
newIndexFile = $destinationParent . '/index.php';
if (file_exists($newIndexFile)) {
$content = file_get_contents($newIndexFile);
// Update path autoload & app.php
// Mencari pattern: __DIR__.'/../
// Diganti menjadi: __DIR__.'/{nama_folder_core}/
$content = str_replace("__DIR__.'/../", "__DIR__.'/" . $coreFolderName . "/", $content);
// Tambahkan usePublicPath(__DIR__) setelah loading app
// Mencari baris capture request untuk menyisipkan kode sebelumnya
$publicPathCode = "\n// Set public path ke folder root saat ini\n\$app->usePublicPath(__DIR__);\n\n";
if (strpos($content, 'usePublicPath') === false) {
$content = str_replace('$app = require_once', '$app = require_once', $content);
// Sisipkan sebelum $app->handleRequest
$content = str_replace('$app->handleRequest', $publicPathCode . '$app->handleRequest', $content);
if (file_put_contents($newIndexFile, $content)) {
writeLog("[SUCCESS] index.php telah diperbarui otomatis dengan path '$coreFolderName' dan usePublicPath.", $logFile);
} else {
writeLog("[ERROR] Gagal menulis perubahan ke index.php.", $logFile);
}
} else {
writeLog("[INFO] index.php sepertinya sudah memiliki konfigurasi usePublicPath.", $logFile);
}
} else {
writeLog("[ERROR] File index.php tidak ditemukan di tujuan pindah.", $logFile);
}
// — 4. BUAT .HTACCESS UNTUK PROTEKSI FOLDER CORE —$
htaccessContent = "Options -Indexes\nDeny from all";
$htaccessFile = $basePath . '/.htaccess';
if (!file_exists($htaccessFile)) {
if (file_put_contents($htaccessFile, $htaccessContent)) {
writeLog("[SUCCESS] .htaccess dibuat di folder $coreFolderName untuk proteksi.", $logFile);
} else {
writeLog("[ERROR] Gagal membuat .htaccess.", $logFile);
}
} else {
writeLog("[INFO] .htaccess sudah ada.", $logFile);
}
// — 5. BUAT SYMLINK LOG KE ROOT (OPSIONAL) —$
logShortcut = $destinationParent . '/install_log.txt';
if (!is_link($logShortcut)) {
@symlink($logFile, $logShortcut);
writeLog("[INFO] Log shortcut dibuat di root: install_log.txt", $logFile);
}writeLog("— PROSES SELESAI —"
, $logFile);
echo "</pre>";
Script ini dirancang untuk menggantikan proses manual seperti membuat symlink storage, edit index.php dan .htaccess di dalam folder Core dan seluruh file di dalam public akan dipindahkan ke public_html
Akses:
http://namadomainmu.com/Core/laravel.php
Jika berhasil:
- Semua proses manual akan dilakukan otomatis

Cocok jika ingin menghindari human error.
Selanjutnya, akses kembali website, pastikan sudah sesuai. Di tahap ini, proses upload Laravel di hosting sudah selesai.

Alternatif: Memindahkan Core ke Luar public_html
Jika folder Core dipindah ke /home/user/Core, maka perlu penyesuaian path.
Edit file index.php beriku ini dan script symlink agar mengarah ke lokasi baru. Cara ini lebih aman karena file inti benar-benar berada di luar akses publik.
<?php
$target = dirname(__DIR__) . '/storage/app/public';
$link = dirname(__FILE__) . '/storage';
if (!file_exists($link)){
symlink($target, $link);
echo "Symlink $target dibuat di $link" ;
}
else {
echo "Gagal! symlink/folder sudah ada di $link" ;
}
lalu ubah pada bagian:
$target = dirname(__DIR__) . '/storage/app/public';
menjadi:
$target = dirname(__DIR__) . '/Core/storage/app/public';
Simpan lalu jalankan file link.php
Tahap 3: Upload ke Subdomain / Addon Domain
Setelah seluruh file laravel telah di upload dan di ekstrak ke dalam home directory subdomain atau addon domainnya (dalam contoh sudah diupload ke /laravel.ramasukakal.my.id) dilanjutkan dengan mengubah Document Root subdomain atau addon domainnya supaya mengarah ke folder public laravel.
#1. Ubah Document Root
Masuk ke menu Domains, lalu klik Manage pada subdomain.


Ubah Document Root ke folder /public Laravel agar tidak perlu memindahkan file manual.

#2. Buat Symlink Storage
Buat kembali file link.php di dalam folder public subdomain.Langkah ini sama seperti sebelumnya, yaitu agar file storage bisa diakses dari browser.
<?php
$target = dirname(__DIR__) . '/storage/app/public';
$link = dirname(__FILE__) . '/storage';
if (!file_exists($link)){
symlink($target, $link);
echo "Symlink $target dibuat di $link" ;
}
else {
echo "Gagal! symlink/folder sudah ada di $link" ;
}
#3. Testing Subdomain
Akses subdomain dan pastikan aplikasi berjalan normal.Biasanya metode ini lebih sederhana karena struktur Laravel tetap utuh tanpa modifikasi besar.

Kelebihan Laravel
Laravel tetap menjadi salah satu framework PHP paling populer karena menawarkan kombinasi kemudahan, fleksibilitas, dan ekosistem yang matang.
Expressive
Laravel dirancang dengan sintaks yang intuitif dan mudah dibaca. Bahkan tanpa dokumentasi mendalam, banyak bagian kode bisa langsung dipahami dari penamaannya.
Hal ini membantu mempercepat proses development sekaligus memudahkan saat maintenance atau kolaborasi tim, terutama pada project yang skalanya terus berkembang.
Simple
Banyak proses yang biasanya kompleks menjadi lebih ringkas di Laravel. Misalnya untuk mengambil data dari database, cukup menggunakan Eloquent ORM seperti $all_user = User::all(); tanpa query panjang.
Struktur ini membuat kode lebih bersih, konsisten, dan mudah dikelola dalam jangka panjang.
Accessible
Laravel memiliki dokumentasi resmi yang sangat lengkap dan selalu diperbarui. Selain itu, komunitasnya besar sehingga mudah menemukan solusi saat menemui kendala. Update fitur juga rutin dirilis, sehingga developer bisa terus mengikuti perkembangan teknologi tanpa harus berpindah framework.
Kesimpulan
Upload Laravel ke cPanel tanpa SSH dan Node.js memang bukan skenario ideal, tapi tetap bisa dilakukan dengan pendekatan manual seperti di atas.
Kunci utamanya ada di penyesuaian struktur folder, konfigurasi path, dan memastikan semua dependency sudah disiapkan dari localhost.
Kalau proses ini terasa cukup kompleks atau berisiko error, kamu bisa mempertimbangkan bantuan dari tim teknis IDwebhost agar proses deployment lebih aman dan efisien.
Selain itu, tersedia juga paket Hosting khusus Laravel dari IDwebhost yang sudah mendukung Terminal/SSH, Composer, dan environment yang kompatibel penuh dengan Laravel.
Dengan setup tersebut, kamu tidak perlu lagi repot melakukan upload manual seperti ini, karena proses deployment bisa dilakukan jauh lebih praktis.