MinIO di VPS: Storage S3 Self-Host untuk Backup dan File Aplikasi

 


Backup aplikasi sering gagal bukan karena skripnya salah, melainkan karena tempat menampungnya tidak jelas. File cadangan menumpuk di disk yang sama dengan aplikasi, lalu ikut hilang saat disk itu bermasalah. Atau sebaliknya: Anda memakai layanan object storage berbayar untuk kebutuhan yang sebenarnya kecil, dan tagihannya terasa tidak sebanding dengan file yang disimpan.

MinIO menyelesaikan persoalan itu dengan cara yang lugas. Ia adalah server object storage yang kompatibel dengan API S3, dan bisa Anda jalankan sendiri di VPS. Aplikasi yang sudah bisa bicara ke S3 — mulai dari skrip backup sampai CMS dan aplikasi web — umumnya bisa diarahkan ke MinIO tanpa diubah total. Bedanya, data Anda tinggal di server Anda sendiri, dan biaya bulanannya adalah VPS yang memang sudah Anda bayar.

Artikel ini membawa Anda dari nol sampai MinIO bisa dipakai sebagai target backup: instalasi lewat Docker Compose, pembuatan bucket dan access key, pengujian upload dan unduh, lalu satu contoh nyata mengirim backup ke sana. Di ujungnya ada peringatan keamanan yang tidak boleh dilewati: console MinIO tidak boleh dibiarkan terbuka ke internet tanpa pelindung.

Prasyarat yang perlu Anda siapkan

Anda butuh VPS dengan Docker dan Docker Compose yang sudah terpasang, plus akses SSH sebagai root atau pengguna dengan hak sudo. Untuk satu node MinIO, RAM 2 GB dan ruang kosong beberapa GB sudah cukup untuk memulai, tapi jangan pakai MinIO satu node sebagai satu-satunya salinan backup penting. Prinsipnya tetap sama: backup yang hanya ada di satu tempat bukan backup yang aman. Nanti, di bagian akhir, Anda akan melihat cara memadukannya dengan salinan kedua.

Siapkan juga satu domain atau subdomain bila Anda berencana membuka console lewat HTTPS, misalnya minio.domainanda.com untuk console dan s3.domainanda.com untuk API. Untuk tahap instalasi di artikel ini, keduanya belum wajib — Anda bisa mengakses lewat SSH tunnel atau IP lokal dulu, lalu menambahkan reverse proxy setelahnya.

Langkah 1: Siapkan folder dan file Docker Compose

Buat folder khusus agar konfigurasi MinIO tidak bercampur dengan proyek lain:

sudo mkdir -p /opt/minio
cd /opt/minio

Selanjutnya buat file /opt/minio/docker-compose.yml dengan isi berikut:

services:
  minio:
    image: minio/minio:latest
    container_name: minio
    restart: unless-stopped
    command: server /data --console-address ":9001"
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:9001:9001"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    volumes:
      - minio_data:/data

volumes:
  minio_data:

Ada beberapa keputusan di file ini yang sengaja dibuat begitu:

  • Perintah server /data --console-address ":9001" memberi tahu MinIO untuk menyimpan objek di /data dan menjalankan console web di port 9001. Port 9000 adalah API S3-nya, tempat aplikasi dan CLI mengirim file.
  • Port di-bind ke 127.0.0.1, bukan ke semua interface. Artinya MinIO hanya bisa diakses dari dalam VPS itu sendiri sampai Anda memasang reverse proxy. Ini sengaja: langkah paling gampang untuk membobol MinIO adalah membiarkan console-nya terekspos langsung ke internet.
  • Kredensial root tidak ditulis langsung di file Compose, melainkan diambil dari file .env. File ini harus dibuat terpisah.

Buat file /opt/minio/.env dengan isi seperti ini, lalu ganti nilainya dengan kredensial kuat buatan Anda sendiri:

MINIO_ROOT_USER=admin-minio-anda
MINIO_ROOT_PASSWORD=ganti-dengan-password-panjang-dan-acak

Password root MinIO minimal 8 karakter, tapi untuk akun root, pakailah yang jauh lebih panjang dari itu — gabungan huruf, angka, dan simbol, dan simpan di password manager. Setelah itu kunci izin file-nya:

sudo chmod 600 /opt/minio/.env

Hasil yang diharapkan: dua file sudah ada di /opt/minio, yaitu docker-compose.yml dan .env, dan file .env tidak bisa dibaca pengguna lain di server.

Langkah 2: Jalankan dan periksa MinIO

Jalankan dari folder yang sama:

cd /opt/minio
sudo docker compose up -d
sudo docker compose ps

Keluaran ps yang sehat menunjukkan container minio berstatus Up atau running. Bila statusnya terus Restarting, jangan langsung menebak — baca lognya:

sudo docker compose logs --tail 50 minio

Dua penyebab yang paling sering muncul: password root kurang dari 8 karakter, atau port 9000/9001 sudah dipakai layanan lain. Pesan error di log biasanya menyebut keduanya dengan jelas. Perbaiki penyebabnya, lalu jalankan sudo docker compose up -d lagi.

Untuk memastikan API-nya menjawab, jalankan dari dalam VPS:

curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9000/minio/health/live

Hasil yang diharapkan: kode 200. Itu berarti API S3 MinIO sudah hidup dan siap menerima koneksi.


Langkah 3: Buat bucket dan access key khusus aplikasi

Masuk ke console lewat SSH tunnel agar tidak membuka port ke publik. Dari komputer Anda, jalankan:

ssh -L 9001:127.0.0.1:9001 root@IP-VPS-ANDA

Lalu buka http://127.0.0.1:9001 di browser dan login dengan MINIO_ROOT_USER dan MINIO_ROOT_PASSWORD dari file .env. Setelah masuk, buat bucket baru, misalnya backup-aplikasi. Nama bucket hanya boleh berisi huruf kecil, angka, titik, dan strip — hindari huruf besar dan spasi.

Jangan berhenti di akun root. Akun root itu kunci utama: kalau bocor, seluruh server ikut terbuka. Untuk aplikasi atau skrip backup, buat pengguna terpisah dengan hak yang lebih sempit. Di console, buka menu Identity, lalu Users, dan buat pengguna baru, misalnya backup-writer, dengan password panjangnya sendiri. Kemudian pasang policy yang membatasi pengguna itu hanya ke bucket backup, misalnya policy bawaan readWrite yang dipersempit, atau policy kustom yang hanya mengizinkan tulis ke bucket backup-aplikasi.

Alur yang sama bisa dilakukan lewat CLI MinIO (mc), dan ini justru lebih enak diulang. Instal mc di VPS:

curl https://dl.min.io/client/mc/release/linux-amd64/mc \
  --create-dirs -o $HOME/minio-binaries/mc
chmod +x $HOME/minio-binaries/mc
export PATH=$PATH:$HOME/minio-binaries/

Tambahkan baris export PATH itu ke ~/.bashrc bila Anda ingin mc tetap tersedia di sesi berikutnya. Lalu daftarkan server Anda sebagai alias:

mc alias set lokal http://127.0.0.1:9000 MINIO_ROOT_USER MINIO_ROOT_PASSWORD

Ganti MINIO_ROOT_USER dan MINIO_ROOT_PASSWORD dengan nilai dari .env. Hasil yang diharapkan: pesan Added 'lokal' successfully. Setelah itu buat bucket dan pengguna dari terminal:

mc mb lokal/backup-aplikasi
mc admin user add lokal backup-writer PASSWORD-PANJANG-UNTUK-BACKUP-WRITER
mc admin info lokal

Perintah mc admin info menampilkan informasi server bila koneksi dan kredensial benar. Bila muncul error akses ditolak, hampir selalu penyebabnya salah ketik kredensial atau alias menunjuk ke port yang salah — periksa kembali port 9000 untuk API, bukan 9001.

Langkah 4: Uji upload, unduh, dan hapus dengan mc

Sebelum MinIO dipakai backup sungguhan, uji dulu tiga operasi dasarnya. Buat satu file percobaan:

echo "uji backup MinIO" > /tmp/uji-minio.txt
mc cp /tmp/uji-minio.txt lokal/backup-aplikasi/
mc ls lokal/backup-aplikasi/

Keluaran mc ls yang diharapkan menampilkan uji-minio.txt di dalam bucket. Lanjutkan dengan unduh dan bandingkan isinya:

mc cp lokal/backup-aplikasi/uji-minio.txt /tmp/uji-minio-unduhan.txt
cat /tmp/uji-minio-unduhan.txt

Isinya harus sama persis: uji backup MinIO. Bila unduhan gagal tapi upload berhasil, periksa policy pengguna yang Anda pakai — pengguna itu mungkin hanya diberi izin tulis tanpa izin baca. Terakhir, bersihkan file percobaan:

mc rm lokal/backup-aplikasi/uji-minio.txt
rm /tmp/uji-minio.txt /tmp/uji-minio-unduhan.txt

Langkah 5: Uji dengan AWS CLI sebagai klien S3 kedua

Kenapa perlu klien kedua? Karena tujuan MinIO adalah kompatibel dengan S3. Kalau hanya mc yang bisa bicara dengannya, Anda belum membuktikan kompatibilitas itu. AWS CLI adalah pembuktian yang murah dan cepat.

Pastikan AWS CLI sudah terpasang, lalu jalankan perintah berikut dengan endpoint mengarah ke MinIO Anda:

aws --endpoint-url http://127.0.0.1:9000 s3 ls s3://backup-aplikasi

Bila bucket masih kosong setelah file percobaan dihapus, keluarannya memang kosong — itu normal, bukan error. Untuk uji tulis lewat AWS CLI:

echo "uji lewat aws cli" > /tmp/uji-aws.txt
aws --endpoint-url http://127.0.0.1:9000 s3 cp /tmp/uji-aws.txt s3://backup-aplikasi/
aws --endpoint-url http://127.0.0.1:9000 s3 ls s3://backup-aplikasi
rm /tmp/uji-aws.txt
aws --endpoint-url http://127.0.0.1:9000 s3 rm s3://backup-aplikasi/uji-aws.txt

Catatan penting: saat memakai AWS CLI terhadap MinIO lokal tanpa HTTPS, Anda mungkin perlu mengatur variabel AWS_ACCESS_KEY_ID dan AWS_SECRET_ACCESS_KEY ke access key pengguna backup Anda, atau menambahkan --no-sign-request hanya untuk percobaan baca publik — jangan pakai opsi tanpa tanda tangan untuk data backup yang privat. Bila muncul error soal sertifikat atau signature, periksa dulu apakah endpoint yang Anda pakai HTTP atau HTTPS, karena keduanya harus konsisten antara perintah dan konfigurasi server.

Langkah 6: Pakai MinIO sebagai target backup nyata

Sekarang hubungkan ke skrip backup yang sudah ada. Polanya sama untuk database maupun file: buat arsip, kirim ke bucket, verifikasi, lalu hapus arsip lokal bila perlu.

Contoh untuk backup database dan folder aplikasi dalam satu arsip terkompresi:

mysqldump -u USER_DB -p NAMA_DB > /tmp/backup-db.sql
tar -czf /tmp/backup-aplikasi.tar.gz /tmp/backup-db.sql /var/www/aplikasi-anda
mc cp /tmp/backup-aplikasi.tar.gz lokal/backup-aplikasi/$(date +%F)/
mc ls lokal/backup-aplikasi/$(date +%F)/
rm /tmp/backup-db.sql /tmp/backup-aplikasi.tar.gz

Ganti USER_DB, NAMA_DB, dan /var/www/aplikasi-anda dengan nilai Anda sendiri. Folder bertanggal $(date +%F) membuat setiap backup harian terpisah, sehingga Anda tidak menimpa backup kemarin dengan backup hari ini tanpa sadar.

Untuk backup otomatis, simpan perintah itu sebagai skrip, misalnya /opt/minio/backup-ke-minio.sh, beri izin eksekusi dengan chmod +x, lalu jadwalkan lewat cron. Satu hal yang sering terlewat: skrip cron berjalan dengan PATH yang minimal, jadi tuliskan path lengkap untuk mc (misalnya $HOME/minio-binaries/mc) atau definisikan PATH di awal skrip. Bila cron diam-diam gagal, hampir selalu penyebabnya adalah perintah yang tidak ditemukan karena PATH.

Jangan lupa menguji restore, bukan hanya backup. Backup yang belum pernah dicoba dikembalikan nilainya belum terbukti. Ambil satu arsip dari bucket, ekstrak di folder sementara, dan periksa isinya bisa dibuka:

mc cp lokal/backup-aplikasi/2026-10-26/backup-aplikasi.tar.gz /tmp/restore-test/
tar -tzf /tmp/restore-test/backup-aplikasi.tar.gz | head

Bila daftar isi arsip tampil, jalur backup-ke-restore Anda sudah utuh dari ujung ke ujung.

Peringatan keamanan: jangan buka console ke publik begitu saja

Ini bagian yang paling sering diremehkan, dan paling mahal akibatnya. Console MinIO di port 9001 adalah panel admin. Kalau port itu terbuka ke internet tanpa HTTPS dan tanpa pembatasan, siapa pun bisa mencoba login, dan serangan brute force hanya soal waktu.

Aturan praktisnya:

  • Selama belum ada reverse proxy, biarkan port 9000 dan 9001 hanya di 127.0.0.1, seperti konfigurasi di artikel ini, dan akses console lewat SSH tunnel.
  • Bila sudah waktunya dibuka lewat domain, pasang Nginx sebagai reverse proxy dengan HTTPS (Let's Encrypt), arahkan satu subdomain ke port 9001 untuk console dan subdomain lain ke port 9000 untuk API, dan aktifkan pembatasan akses bila memungkinkan.
  • Jangan pernah memakai password root bawaan atau password pendek. Ganti segera bila Anda pernah login dengan kredensial contoh dari tutorial mana pun.
  • Buat access key terpisah per aplikasi, dan cabut key yang sudah tidak dipakai lewat console atau mc admin user remove.
  • Untuk bucket backup, jangan aktifkan akses publik. Bucket backup harus privat; akses publik hanya masuk akal untuk aset yang memang dirancang dibagikan, seperti file statis situs.

Satu node MinIO di satu VPS juga bukan jawaban untuk semua risiko. Bila VPS itu sendiri hilang, bucket di dalamnya ikut hilang. Untuk data yang benar-benar penting, salin juga bucket itu ke lokasi kedua — bisa dengan mc mirror ke server MinIO lain, atau dengan menyinkronkan arsip backup ke penyimpanan di luar VPS. Artikel ini memberi Anda fondasi yang bisa dipakai; lapisan kedua itu yang mengubahnya dari sekadar tempat simpan menjadi strategi backup.

Tabel ringkasan

KomponenKeterangan
Image Dockerminio/minio:latest
API S3Port 9000, dipakai aplikasi, mc, dan AWS CLI
Console webPort 9001, dipakai untuk administrasi lewat browser
Direktori data/data di dalam container, volume minio_data
File konfigurasi/opt/minio/docker-compose.yml dan /opt/minio/.env
Kredensial rootMINIO_ROOT_USER dan MINIO_ROOT_PASSWORD di .env
Bucket contohbackup-aplikasi
Uji dasarmc cp, mc ls, unduh dan bandingkan isi, lalu mc rm
Uji S3 keduaaws --endpoint-url http://127.0.0.1:9000 s3 ls dan s3 cp
Akses amanBind 127.0.0.1, SSH tunnel, lalu reverse proxy + HTTPS

Checklist akhir

  • Container MinIO berstatus Up dan endpoint /minio/health/live menjawab 200
  • Bucket backup-aplikasi sudah dibuat
  • Pengguna khusus backup sudah dibuat, bukan memakai akun root untuk skrip
  • Upload, unduh, dan hapus file percobaan berhasil lewat mc
  • AWS CLI bisa membaca dan menulis ke bucket yang sama
  • Satu backup nyata sudah dikirim dan berhasil diuji restore dari folder sementara
  • Console tidak terbuka langsung ke internet tanpa reverse proxy dan HTTPS
  • File .env berizin 600 dan kredensial tersimpan di password manager

Satu hal yang patut Anda putuskan setelah instalasi ini: aplikasi apa yang pertama kali Anda arahkan ke MinIO — backup database, file upload pengguna, atau arsip log? Ceritakan pilihan Anda di komentar, dan kendala apa yang Anda temui saat menghubungkannya.

Baca juga: Docker Compose untuk Self-Hosting dari Nol untuk fondasi Compose yang dipakai di sini, Docker Volume dan Backup: Jangan Sampai Data Hilang agar volume minio_data Anda tidak hilang saat container dihapus, Backup VPS Otomatis dan Terenkripsi ke Cloud untuk lapisan salinan kedua di luar VPS, dan Satu VPS Banyak Layanan dengan Nginx Reverse Proxy saat Anda siap membuka MinIO lewat domain dengan HTTPS.

Komentar