Setup S3 Lokal yang Bisa Diakses Internet Pakai Cloudflare Tunnel (MinIO)

Setup S3 Lokal yang Bisa Diakses Internet Pakai Cloudflare Tunnel (MinIO)
Ilustrasi server lokal terhubung ke Cloudflare Tunnel dan bucket S3 MinIO secara aman melalui HTTPS.

Setup S3 Lokal yang Bisa Diakses Internet Pakai Cloudflare Tunnel (MinIO)

Use case: kamu pengen punya object storage model S3 di rumah/local server (buat upload file, backup, media, asset app), tapi tetap bisa diakses aman dari internet tanpa buka port router.

Artikel ini full step-by-step dari nol sampai bisa dipakai produksi skala kecil–menengah. Semua contoh pakai MinIO + Cloudflare Tunnel.


TL;DR

  • Jalankan MinIO di local (S3-compatible)
  • Pasang Cloudflare Tunnel untuk expose endpoint HTTPS
  • Kunci akses dengan credential kuat + policy bucket yang benar
  • Test pakai aws-cli endpoint custom

Arsitektur Sederhana

Internet Client
   ↓ HTTPS
Cloudflare Tunnel (cloudflared)
   ↓
MinIO (local/home server)
   ↓
Disk local (HDD/SSD)

Kelebihan model ini: - gak perlu port forwarding - dapat HTTPS domain publik - relatif aman kalau policy + auth beres


1) Prasyarat

  • Domain aktif di Cloudflare
  • Cloudflare account + Zero Trust aktif
  • Server lokal (Linux) dengan Docker/Compose
  • RAM minimal 1–2 GB untuk setup ringan

Contoh domain: - storage.terminalstory.my.id

Catatan: kalau kamu belum punya domain, bikin dulu di Cloudflare dan set nameserver ke Cloudflare.

2) Jalankan MinIO di Local (Docker Compose)

Bikin file docker-compose.yml:

services:
  minio:
    image: minio/minio:latest
    container_name: minio
    restart: unless-stopped
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: "ganti-user-root-yang-kuat"
      MINIO_ROOT_PASSWORD: "ganti-password-panjang-dan-random"
    volumes:
      - ./minio-data:/data
    ports:
      - "9000:9000"   # S3 API
      - "9001:9001"   # MinIO Console

Jalankan:

docker compose up -d

Cek:

docker ps
curl http://127.0.0.1:9000/minio/health/live

Kalau return OK, berarti MinIO up.


3) Bikin User S3 (Bukan Root)

Masuk ke MinIO Console: http://localhost:9001.

  1. Login pakai root user
  2. Users → Create User
  3. Buat user khusus (contoh: app-minio) + password kuat
  4. Policies → Create Policy
  5. misal: hanya read/write ke satu bucket tertentu

Contoh policy minimal:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::terminalstory-assets",
        "arn:aws:s3:::terminalstory-assets/*"
      ]
    }
  ]
}

4) Install cloudflared

Ubuntu/Debian (contoh):

# lihat docs resmi cloudflare untuk versi terbaru
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared stable main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update && sudo apt install cloudflared -y

Login cloudflared:

cloudflared tunnel login

5) Buat Tunnel + Route DNS

cloudflared tunnel create minio-tunnel
cloudflared tunnel route dns minio-tunnel storage.terminalstory.my.id

Buat config /etc/cloudflared/config.yml:

tunnel: minio-tunnel
credentials-file: /root/.cloudflared/<TUNNEL_ID>.json

ingress:
  - hostname: storage.terminalstory.my.id
    service: http://127.0.0.1:9000
  - service: http_status:404

Run service:

sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl restart cloudflared
sudo systemctl status cloudflared

6) Test Endpoint Publik

curl -I https://storage.terminalstory.my.id

Harus dapat response HTTPS aktif.


7) Integrasi AWS CLI (Endpoint Custom)

Install AWS CLI, lalu set profile khusus:

aws configure --profile minio-public
# isi access key + secret key dari MinIO user
# region: us-east-1 (atau bebas konsisten)
# output: json

List bucket:

aws --profile minio-public --endpoint-url https://storage.terminalstory.my.id s3 ls

Upload test:

echo "hello from terminalstory" > test.txt
aws --profile minio-public --endpoint-url https://storage.terminalstory.my.id s3 cp test.txt s3://terminalstory-assets/test.txt

8) Bikin Bucket Public (Opsional)

Kalau kamu butuh public assets (gambar/blog/media):

  1. Buat bucket public-assets
  2. Set policy public read

Contoh policy public read:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::public-assets/*"]
    }
  ]
}
Warning: jangan pakai public untuk bucket backup/private data.

9) Security Wajib (Jangan Diskip)

  1. Jangan pakai root credential untuk aplikasi
  2. bikin user policy terbatas (read/write bucket tertentu)
  3. Password wajib kuat
  4. panjang, random, unik
  5. Batasi bucket public
  6. default private
  7. Aktifkan versioning bucket
  8. bantu recovery kalau file ketimpa
  9. Tambahkan Cloudflare Access (opsional tapi recommended)
  10. khusus endpoint admin/console
  11. Pisahkan endpoint API vs console
  12. misal storage. untuk API, storage-admin. untuk console
  13. Backup rutin data MinIO
  14. local disk failure itu real

10) Problem Umum + Solusi

A) Upload gagal signature mismatch

  • pastikan endpoint benar
  • cek clock/time server sinkron (NTP)
  • cek akses key/secret key

B) URL bisa dibuka tapi gak bisa auth

  • cek policy user
  • cek bucket permission
  • pastikan app pakai endpoint HTTPS publik yang sama

C) Tunnel aktif tapi domain error

  • cek DNS route tunnel
  • cek service cloudflared status
  • cek file credential tunnel

11) Kapan Setup Ini Cocok?

Cocok kalau kamu: - punya home server/local VPS sendiri - pengen kontrol data storage sendiri - butuh endpoint S3-compatible buat app/backup - pengen expose aman tanpa buka port publik langsung

Kurang cocok kalau kamu: - gak mau maintain infra sama sekali - butuh SLA enterprise ketat dari hari pertama


Kesimpulan

Setup S3 lokal + Cloudflare Tunnel itu sweet spot buat creator/indie builder: - biaya relatif hemat - tetap punya endpoint internet-ready - kontrol data ada di tangan kamu

Yang paling penting: auth + policy + backup.
Kalau tiga itu beres, setup ini udah cukup kuat buat dipakai production skala kecil–menengah.