Bikin Image Host Murah Meriah Sendiri di Alibaba Cloud FC + OSS

image

Tiga hal dulu:

  1. Image host ini fiturnya sederhana, gampang dikonfigurasi, dan cukup aman. Kalau kurang buat Anda, serahkan source code-nya ke AI — nambah atau ngurangin fitur itu gampang.
  2. Semua AccessKey, password, domain, dan nama bucket di artikel ini adalah placeholder — ganti dengan punya Anda sendiri sebelum menyalin apa pun.
  3. Kodenya aplikasi Node.js satu file (sekitar 380 baris), dependensi disuntik lewat Layer FC, nol hardcoding di kode bisnis, dan semua konfigurasi dibaca dari environment variable.

Source code: https://github.com/ezzty/oss-upload


1. Kenapa bikin image host sendiri

Setiap blog statis pada dasarnya butuh image host. Banyak orang ngirit pakai image host gratis selamanya punya orang lain — tapi siapa sih dermawan yang nggak pernah tutup? Dan karena data Anda di tangan orang lain, Anda sama sekali nggak punya kendali, jadi selalu was-was.

Setelah cukup banyak kena pit, saya memutuskan bikin image host sendiri dengan biaya paling murah. Tujuan utamanya: hemat, tanpa batas kapasitas, dan tetap aman!

Kebanyakan setup image host self-hosted butuh server sendiri — puluhan yuan sebulan plus harus nambal sendiri — atau cuma jalan di klien lokal, jadi nggak bisa upload dari komputer lain. Akhirnya saya memutuskan bikin image host cloud serverless: upload di mana saja, kapan saja.

Alibaba Cloud Function Compute FC + OSS + CDN

FC bayar sesuai pemakaian (hampir ¥0 kalau trafiknya rendah) + tanpa database + zero ops, dengan paket deployment sekecil 6KB. Upload yang jarang praktis nggak makan biaya.

Penyimpanan gambar di OSS juga bayar sesuai pemakaian — puluhan GB gambar cuma beberapa yuan sebulan.

Tambah CDN di depannya, gambar loading-nya ngebut banget!

Image host pribadi bukan target serangan yang menggiurkan, tapi saya tetap pasang lapisan keamanan: PoW wajib buat nahan brute force, validasi magic number buat nahan file palsu, cek ukuran tiga kali buat nahan banjir payload, kuota harian buat nahan penyalahgunaan, dan token 2 jam buat nahan pencurian.

Setup ini nggak tanpa kekurangan: nggak ada multi-user, nggak ada manajemen album, nggak ada statistik pemakaian — bahkan nggak bisa hapus gambar tanpa masuk ke konsol OSS.

Tapi kecil, murah, dan lebih dari cukup buat pemakaian pribadi.


2. Arsitektur dan alur request

Browser upload.html
   │  ① POST /login   {user, pass}
   │  ← 200 {token} (valid 24h)
   │  ② POST /upload  Authorization: Bearer *** + image binary
   ▼
Alibaba Cloud Function Compute FC (Node.js 18, HTTP trigger)
   │  auth / rate limit / magic-number check / size check
   │  ③ ossClient.put(key, stream)
   ▼
OSS Bucket (private read/write, public read disabled)
   │  ④ CDN origin fetch (internal network, free)
   ▼
https://img.example.com/m/26j13/ab12cd.jpg   ← public access domain

Tiga trade-off desain:

  • Bucket diset private: nggak ada yang bisa baca langsung lewat direct link; gambar cuma bisa diakses lewat URL yang di-bind ke domain CDN. Begitu public read dinyalakan, bucket Anda jadi sumber daya bersama — orang lain bisa enumerasi dan nyedot trafik Anda.
  • Wajib login buat upload: kalau nggak, orang bakal nganggap domain API Anda image host gratis dan bikin tagihan serta penyimpanan Anda meledak nggak terkendali.
  • Kode bisnis nggak pernah menyentuh secret: AK/SK cuma ada di environment variable — nggak pernah kelihatan di kode atau repo.

3. Persiapan

3.1 Aktifkan produknya

Aktifkan Function Compute FC dan Object Storage OSS (dua-duanya bayar sesuai pemakaian, nggak perlu beli di muka).

3.2 Buat bucket

  • Nama: unik secara global, misalnya my-img
  • Region: pilih yang dekat dengan Anda/pengguna Anda, misalnya East China 1 (Hangzhou) → oss-cn-hangzhou
  • Kontrol akses: Private (penting)
  • Tipe penyimpanan: Standard — itu yang cocok buat gambar yang sering diakses. Jangan pilih Infrequent Access atau Archive; dua itu punya durasi penyimpanan minimum dan kalau dihapus lebih awal malah kena biaya.

3.3 Buat RAM user yang dibatasi ke satu bucket (sangat disarankan)

Banyak tutorial nyuruh pakai AccessKey akun root — jangan. AK root bocor berarti seluruh akun Alibaba Cloud Anda jatuh.

Konsol RAM → Policies → Create Policy → tab JSON:

{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "oss:GetObject",
        "oss:PutObject",
        "oss:DeleteObject",
        "oss:ListObjects",
        "oss:HeadObject"
      ],
      "Resource": [
        "acs:oss:*:*:my-img",
        "acs:oss:*:*:my-img/*"
      ]
    }
  ]
}

Beri nama policy-nya ImageHostSingleBucket. Lalu:

  1. RAM → Users → Create User, centang “Use permanent AccessKey for API call”
  2. Lampirkan hanya policy di atas ke user ini
  3. Generate AK/SK dan langsung simpan ke password manager lokal Anda

Beberapa trade-off yang disengaja:

  • Tanpa oss:ListBuckets — kalau bocor, penyerang bahkan nggak bisa lihat bucket apa saja yang Anda punya
  • Tanpa oss:CopyObject — image host nggak butuh izin copy; kasih sesedikit mungkin
  • Jangan lampirkan AliyunOSSFullAccess — itu bakal bikin AK image host Anda bisa baca semua data bucket yang Anda punya

4. Siapkan layer dependensi (Layer)

Kode bisnis cuma bergantung pada ali-oss. Taruh di Layer, paket kodenya tetap beberapa KB.

Opsi A: Unduh asset rilis langsung (disarankan)

Proyeknya sudah menerbitkan Release — layer.zip dan paket kode bisa diunduh langsung:

https://github.com/ezzty/oss-upload/releases/latest

Asset Ukuran Isi
layer.zip 3,25 MB ali-oss@6.23.0 dan dependensinya — total 2338 file
oss-upload-code.zip ~6 KB index.js + package.json, paket deployment fungsi

Keuntungannya: nggak perlu install Node.js, nggak perlu zip manual, dan nggak ada masalah “beda dengan yang sudah diverifikasi penulis” gara-gara npm install lokal Anda narik versi SDK yang lebih baru. Layer-nya cuma berisi source code paket npm, tanpa secret.

Opsi B: Build sendiri

Kalau Anda mau versi dependensi lain, atau nggak percaya paket yang sudah jadi:

mkdir -p layer-build/nodejs
cd layer-build
npm init -y
npm install ali-oss
# Direktori HARUS punya struktur ini:
#   nodejs/
#     node_modules/
#       ali-oss/
#       ...dependensi transitifnya
cd nodejs && zip -r ../layer.zip node_modules && cd ..

Upload

Konsol FC → Layer Management → Create Layer:

  • Nama: oss-upload-deps
  • Runtime: Node.js 18
  • Upload layer.zip

Layer cukup dibuat sekali. Kalau nanti mau upgrade ali-oss, pack versi baru, publish, lalu arahkan fungsi ke versi layer baru — kode bisnis nggak perlu diubah.


5. Deploy fungsinya

5.1 Ambil kode bisnisnya

Disarankan: pakai asset rilis langsung — unduh oss-upload-code.zip (~6 KB) dari https://github.com/ezzty/oss-upload/releases/latest; unzip dan Anda sudah punya paket deployment standar.

Kalau pack sendiri, root zip harus berisi hanya dua file ini (jangan ada folder pembungkus, kalau nggak Handler nggak bakal nemu index.handler):

code.zip
├── index.js        ← source bisnis
└── package.json    ← deklarasi dependensi (buat referensi; saat runtime sebenarnya dimuat dari layer)
zip code.zip index.js package.json

5.2 Buat fungsinya

  • Runtime: Node.js 18
  • Handler: index.handler
  • Spesifikasi: 0,05 vCPU / 128 MB memori / 512 MB disk (spesifikasi terkecil yang praktis jalan)
  • Konfigurasi Layer: bind layer oss-upload-deps yang baru Anda buat

Perhatikan setelan memori: kodenya membaca seluruh body ke memori (bodyBuf), dan decoding base64 bikin salinan lagi. 128 MB cukup buat gambar biasa, tapi kalau Anda naikkan batas upload ke 20 MB dan sering upload gambar mendekati batas, naikkan memorinya juga.

5.3 Environment variable (8 wajib — kurang satu aja nggak bakal start)

Environment variable fungsi ada 8 entri wajib — konfigurasikan seperti di gambar.

  • AUTH_USER admin — username login
  • AUTH_PASS <set password kuat> — password login; pakai string acak panjang
  • JWT_SECRET <string acak 32+ karakter> — secret penandatangan token
  • OSS_ACCESS_KEY_ID LTAIxxxxxxxxxxxxxxxx — AK user RAM
  • OSS_ACCESS_KEY_SECRET <AccessKey Secret Anda> — SK user RAM
  • OSS_BUCKET my-img — nama bucket
  • OSS_REGION oss-cn-hangzhou — region ID bucket
  • CDN_DOMAIN https://img.example.com — wajib menyertakan skema protokol; kalau nggak, langsung gagal start

1 opsional:

  • ALLOWED_ORIGINS example.com,myblog.net — sumber cross-origin yang diizinkan, dipisah koma. Fungsi tetap start tanpa ini; nilainya cuma dipakai kalau CORS level kode diaktifkan (defaultnya platform cuma mengembalikan Origin, jadi isValidOrigin nggak pernah dipanggil). Kalau Anda memang mengaktifkan CORS level kode, wajib diset, kalau nggak nilai fallback example.com bakal memblokir semua upload dari browser.

image

5.4 Bind domain kustom

Konsol FC → Domain Management → Add Domain, lalu ikuti petunjuk untuk konfigurasi CNAME dan sertifikat. Begitulah cara dapat alamat API seperti https://api.example.com.


6. Halaman frontend

upload.html adalah frontend satu file — tinggal taruh di direktori situs Anda.

Satu perubahan wajib — cari _FC_PARTS:

// Ganti ke domain kustom Function Compute Anda
const _FC_PARTS = ['https://', 'api.example.com'];

Batas ukuran harus sama dengan backend (dua-duanya default 20MB):

if (file.size > 20 * 1024 * 1024) { /* block */ }

Ada batas di masing-masing sisi — yang lebih kecil menang. Ubah cuma frontend, file besar bakal kena 413 di server; ubah cuma backend, pengguna diblokir di browser sebelum request-nya keluar.


7. Mau lebih dalam? Detail inti ada di README source

Itu alur lengkap buat menjalankan image host self-hosted. Kenapa kodenya ditulis begini, detail implementasi tiap lapisan proteksi, dan checklist acceptance lengkap semuanya ada di README repo source — rujuk saat butuh:

https://github.com/ezzty/oss-upload → “Core implementation (code level)” dan “Pre-launch acceptance” di README.md

Postingan blog ini cuma mau menjelaskan “kenapa self-host, gimana cara jalankannya, apa yang perlu diperhatikan”. Saat benar-benar deploy, README adalah dokumentasi teknis lengkapnya.


8. Biaya

Bayar sesuai pemakaian, tiga bagian:

Item Penagihan Skala
Komputasi FC Compute CU (vCPU + memori × durasi) + jumlah invokasi Ada kuota gratis; image host pribadi biasanya mendekati kuota itu
Penyimpanan OSS ¥/GB/bulan Standard storage sekitar ¥0,09–0,12/GB/bulan
Request OSS Per request Nggak signifikan
Trafik CDN ¥/GB Lihat di bawah

Trafik adalah porsi terbesar tagihan, dan paling gampang dioptimalkan:

  • Upload ke OSS: gratis
  • Jaringan internal OSS (FC ↔ OSS di region sama): gratis
  • Egress internet publik OSS: kena biaya (sekitar ¥0,5/GB, tergantung periode dan region)
  • Lewat CDN: origin fetch CDN pakai jaringan internal, jadi trafik origin gratis — Anda cuma bayar trafik CDN

Kesimpulan: selalu taruh CDN di depan image host — lebih cepat dan menghindari biaya egress OSS. Perhatikan juga FC dan OSS harus di region yang sama; lintas region lewat internet publik, lambat dan bisa kena biaya trafik tambahan.

Dari pengujian saya sendiri, upload beberapa puluh gambar sebulan biayanya sekitar ¥1 per bulan.


9. Maintenance dan update

Mengubah kode bisnis (misalnya format URL gambar):

  1. Edit index.js lokal
  2. zip code.zip index.js package.json
  3. Konsol → Code Deployment → Upload → Deploy
  4. Jalankan probe acceptance dari README buat memastikan versi baru sudah live

Mengubah frontend:

  1. Edit upload.html
  2. Upload ke situs Anda; pertimbangkan set Cache-Control: no-cache, kalau nggak pengguna bisa dapat versi lama

Upgrade dependensi:

  1. Jalankan ulang npm install ali-oss dan pack layer.zip
  2. Publish versi layer baru di konsol
  3. Ganti fungsi ke versi layer baru

Rotasi key (lakukan berkala):

  1. Generate AK/SK baru di RAM
  2. Update environment variable FC → deploy
  3. Setelah memastikan layanan sehat, nonaktifkan AK lama di konsol RAM

10. Referensi