Cara Koneksi Laravel dengan MinIO sebagai Storage
Pengantar
Dalam membangun aplikasi web, kita sering berhadapan dengan kebutuhan penyimpanan file: mulai dari foto profil, dokumen PDF, hingga video. Biasanya kita menyimpan file di server langsung, tapi cara ini cepat penuh, sulit diskalakan, dan rawan kalau server bermasalah. Di sinilah object storage hadir sebagai solusi. Salah satu teknologi yang populer adalah MinIO. MinIO adalah software penyimpanan objek (object storage) open-source yang sepenuhnya kompatibel dengan Amazon S3 API. Artinya, aplikasi yang biasanya menyimpan file ke Amazon S3 bisa dengan mudah diarahkan ke MinIO tanpa banyak perubahan kode.
Kelebihan MinIO:
- Self-hosted → bisa jalan di VPS milik kita sendiri.
- Cepat dan ringan → dirancang untuk performa tinggi.
- Kompatibel dengan S3 → integrasi mudah dengan banyak framework, termasuk Laravel.
- Mendukung skala besar → bisa dipakai untuk data pribadi sampai enterprise.
- Jadi, dengan MinIO kita bisa punya “S3 versi pribadi” di server sendiri, lebih hemat biaya, tapi tetap powerful.
Persyaratan
- VPS Linux (Ubuntu 22.04/24.04 oke) dengan akses root/SSH.
- Domain/subdomain untuk MinIO (opsional tapi direkomendasikan): misalnya minio.example.com.
- Laravel 9/10/11 berjalan di lokal (Windows/Mac/Linux).
- PHP 8.1+ di lokal.
- Composer di lokal.
- Akses firewall / reverse proxy (Nginx) untuk buka 80/443.
Setup MinIO di VPS
- Login ke Console
Buka https://console.minio.example.com (atau http://IP:9001 bila belum SSL).
Login memakai kredensial awal (jika belum pernah set, MinIO akan meminta membuat root user & password saat pertama run melalui env MINIO_ROOT_USER/MINIO_ROOT_PASSWORD. - Buat Bucket
Masuk menu Buckets → Create Bucket, beri nama: mis. laravelbucket.
Setup Laravel
- Pasang dependensi S3 Flysystem
Gunakan perintah berikut
composer require league/flysystem-aws-s3-v3:^3.0 aws/aws-sdk-php:^3.0
- Konfigurasi config/filesystems.php
return [ 'default' => env('FILESYSTEM_DISK', 'local'), 'disks' => [ 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'bucket' => env('AWS_BUCKET', 'laravelbucket'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_PATH_STYLE_ENDPOINT', true), 'throw' => false, ], ], ];
- Isi variabel di .env
FILESYSTEM_DISK=s3 AWS_ACCESS_KEY_ID=username minio AWS_SECRET_ACCESS_KEY=password minio AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET=laravel-media # Jika pakai domain + SSL (via reverse proxy) AWS_ENDPOINT=https://minio.example.com # WAJIB untuk MinIO AWS_PATH_STYLE_ENDPOINT=true
Jika belum pakai domain dan akses IP: AWS_ENDPOINT=http://IP_VPS:9000
Ujicoba Koneksi dari Laravel Menggunakan php artisan tinker
Gunakan perintah berikut di cmd
php artisan tinker
>>> use Illuminate\Support\Facades\Storage;
>>> Storage::disk('s3')->put('test/hello.txt', 'Halo dari Laravel!');
Jika hasilnya =>true berarti laravel anda sudah terhubung dengan minio dan file akan muncul di bucket MinIO.
Buat Form di Laravel
- Controller
Buka terminal dan buat file ini MediaController lalu isi seperti di bawah:
validate([ 'file' => ['required', 'file', 'max:10240'], // 10MB ]); // Simpan privat (default). Folder 'uploads' bisa anda ganti. $path = $request->file('file')->store('uploads', 's3'); // Presigned URL (aman, expired 15 menit) $url = Storage::disk('s3')->temporaryUrl($path, now()->addMinutes(15)); return back()->with([ 'ok' => "Upload OK: {$path}", 'url' => $url, ]); } // Generate presigned URL untuk path tertentu (opsional) public function sign(Request $request) { $request->validate([ 'path' => ['required', 'string'], 'ttl' => ['nullable', 'integer', 'min:1', 'max:1440'], // menit ]); $path = $request->string('path'); abort_unless(Storage::disk('s3')->exists($path), Response::HTTP_NOT_FOUND); $minutes = (int) ($request->ttl ?? 10); $url = Storage::disk('s3')->temporaryUrl( $path, now()->addMinutes($minutes), ['ResponseCacheControl' => 'private, max-age=300'] ); return response()->json(['url' => $url]); } // Proxy download tanpa mengekspos domain MinIO (opsional) public function download(string $path) { abort_unless(Storage::disk('s3')->exists($path), 404); $mime = Storage::disk('s3')->mimeType($path) ?? 'application/octet-stream'; $filename = basename($path); return new StreamedResponse(function () use ($path) { $stream = Storage::disk('s3')->readStream($path); fpassthru($stream); if (is_resource($stream)) { fclose($stream); } }, 200, [ 'Content-Type' => $mime, 'Content-Disposition' => "inline; filename=\"{$filename}\"", 'Cache-Control' => 'private, max-age=300', ]); } }
- Route
Buka routes/web.php dan tambahkan kode seperti dibawah
use App\Http\Controllers\MediaController; Route::get('/media/form', [MediaController::class, 'uploadForm'])->name('media.form'); Route::post('/media/upload',[MediaController::class, 'upload'])->name('media.upload'); Route::get('/media/sign', [MediaController::class, 'sign'])->name('media.sign'); Route::get('/media/d/{path}', [MediaController::class, 'download']) ->where('path', '.*') ->name('media.download');
- Buka kembali terminal dan jalankan perintah berikut
php artisan serve
- Buka browser dan akses halaman berikut
127.0.0.1:8000/media/form
- Klik Choose File, kemudian klik Upload
- Jika berhasil maka file akan tersimpan di MinIO
Kesimpulan
Dengan MinIO, kita bisa memiliki object storage privat yang powerful seperti Amazon S3, tapi berjalan di VPS milik kita sendiri. Integrasi dengan Laravel pun mudah karena sudah ada driver S3 bawaan.
Beberapa hal penting:
- Gunakan Service Account khusus, jangan root user MinIO.
- Set .env Laravel dengan AWS_USE_PATH_STYLE_ENDPOINT=true.
- Karena bucket private, gunakan temporaryUrl() atau proxy route untuk akses file.
- Pastikan VPS sudah diamankan dengan reverse proxy + SSL.
Hasil akhirnya aplikasi Laravel lokal bisa menyimpan, membaca, dan membagikan file dari MinIO di VPS dengan cara yang aman, efisien, dan hemat biaya