Latar Belakang
Pernah dapat permintaan bikin aplikasi dari pengurus RT, yayasan, kelompok tani atau komunitas laen? Biasanya ceritanya begini: mereka butuh sistem pencatat kas, daftar hadir, atau portal warga, tapi pas ditanya soal hosting, jawabannya klasik: "Kita ga ada budgetnya mas." Disodorin dengan segala macem harga malah kemana, bilang mahal lah apalah, dibilang ga mau bantuin. But bro... nah, continue. (ga semuanya ya wkwk karena gua dapet juga emang yang mau bayar bahkan mereka aware langsung bilang berapa biayanya. bukan buat gua ini buat aplikasi bisa layak dipake wkwk)
Solusi paling umum yang sering disebut: pakai platform gratis. Tapi platform gratis punya masalah sendiri: instance mabok tidur ga mati ga hidup juga ga, bandwidth ga tau kemana, atau domain yang panjang dan susah diinget.
Gua punya setup yang sudah jalan di production: total biaya aktif setahun di bawah $1, bisa diakses dari mana saja, dengan domain yang proper. Artikel ini mendokumentasikan setup itu dari awal sampai bisa jalan.
Konsep Dasarnya
Idenya sederhana:
- Aplikasi jalan di server lokal (bisa laptop bekas, mini PC, atau bahkan Raspberry Pi)
- Cloudflare Tunnel membuka akses publik ke server itu tanpa IP publik statis
-
Domain
.my.iddipakai sebagai domain kustom, harganya sekitar Rp 15.000-16.000 per tahun Ga ada biaya VPS mahal. Ga ada biaya Cloudflare (plan Free sudah cukup). Satu-satunya biaya nyata adalah domain. (sama biaya yang ga keliatan, ntar dibahas di akhir)
Tech Stack yang Dipakai
- Cloudflare -- DNS, tunnel, dan SSL otomatis
- Cloudflared -- daemon tunnel yang jalan di server
- Nginx -- reverse proxy lokal; tiap aplikasi jalan di port berbeda
- Laravel -- framework aplikasi (bisa disesuaikan ke stack lain)
-
Domain
.my.id-- beli di registrar manapun (Niagahoster, Domainesia, dll)
Prerequisites
Sebelum mulai, pastikan lo punya:
- Akun Cloudflare (gratis)
- Domain aktif (contoh:
namaproject.my.id) - Server dengan akses root mau laptop bekas, mini PC, atau Raspberry Pi
- Aplikasi yang sudah jalan di port tertentu (contoh: port 8001, 8002, dst)
Spesifikasi yang dipakai
Buat gambaran aja gua pake laptop bekas dengan spek
- core i7 4558u - 2.8Ghz
- RAM 8GB
- Linux Mint
untuk koneksi internet gua pake indihome 75Mbps (sebulan 300rban)
Step 1: Daftarkan Domain ke Cloudflare
Setelah beli domain di registrar pihak ketiga, lo perlu pindahkan name server ke Cloudflare.
- Login ke Cloudflare Dashboard
- Klik Add a Site masukkan domain lo
- Pilih plan Free
- Cloudflare akan kasih dua nameserver, contoh: "ada.ns.cloudflare.com , bob.ns.cloudflare.com"
- Masuk ke panel registrar tempat lo beli domain, ganti nameserver ke milik Cloudflare
Lesson learned: Propagasi nameserver butuh waktu. Di pengalaman gua, sabar 24 jam dulu sebelum nge-test. Jangan panik kalau belum aktif setelah 1-2 jam pertama.
Step 2: Install Cloudflared di Server
# Download versi terbaru (sesuaikan arsitektur server lo)
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
Verifikasi:
cloudflared --version
Step 3: Login dan Buat Tunnel
cloudflared tunnel login
Perintah ini akan membuka browser untuk otorisasi. Setelah selesai, credentials tersimpan otomatis.
Buat tunnel baru:
cloudflared tunnel create nama-tunnel-lo
Catat Tunnel ID yang muncul, lo akan butuh ini di langkah berikutnya.
Step 4: Konfigurasi Tunnel
Buat file konfigurasi:
mkdir -p ~/.cloudflared
nano ~/.cloudflared/config.yml
Isi dengan:
tunnel: <TUNNEL_ID_LO>
credentials-file: /home/<user>/.cloudflared/<TUNNEL_ID_LO>.json
origincert: /home/<user>/.cloudflared/cert.pem
ingress:
- hostname: app1.namaproject.my.id
service: http://localhost:80
- hostname: app2.namaproject.my.id
service: http://localhost:80
- hostname: app3.namaproject.my.id
service: http://localhost:80
- service: http_status:404
Perhatiin bahwa semua domain diarahkan ke port 80, bukan ke port masing-masing aplikasi. Yang membedakan tiap aplikasi bukan di level tunnel, tapi di level Nginx lewat server_name. Jadi tunnel cuma bertugas buka akses dari luar ke port 80 di server lo, Nginx yang atur sisanya. Entry terakhir (http_status:404) wajib ada sebagai fallback.
Step 5: Routing DNS via Cloudflare
cloudflared tunnel route dns <TUNNEL_ID_LO> app1.namaproject.my.id
cloudflared tunnel route dns <TUNNEL_ID_LO> app2.namaproject.my.id
cloudflared tunnel route dns <TUNNEL_ID_LO> app3.namaproject.my.id
Perintah ini otomatis membuat DNS record bertipe CNAME yang mengarah ke tunnel lo di Cloudflare.
Catatan penting: Ini alasan kenapa Caprover tidak cocok untuk setup ini. Caprover butuh IP publik langsung untuk setup awalnya, ia tidak bisa bekerja di belakang CNAME tunnel. Kalau lo mau orkestrasi berbasis Docker, gunakan alternatif lain seperti Portainer atau setup manual Docker Compose.
Step 6: Setup Nginx sebagai Reverse Proxy Lokal
Nginx di setup ini bukan yang handle PHP-nya langsung, bukan PHP-FPM. Nginx di sini tugasnya satu: dengerin di port 80, lihat server_name-nya domain mana, lalu forward request ke php artisan serve yang jalan di port masing-masing aplikasi.
Jadi flow-nya:
Cloudflare Tunnel (port 80)
|
Nginx (routing by server_name)
|
php artisan serve app1 (port 8001)
php artisan serve app2 (port 8002)
php artisan serve app3 (port 8003)
Buat file konfigurasi Nginx untuk tiap aplikasi:
sudo nano /etc/nginx/sites-available/app1
Isi dengan:
server {
listen 80;
server_name app1.namaproject.my.id;
location / {
proxy_pass http://localhost:8001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Ulangi untuk tiap aplikasi, ganti server_name dan port proxy_pass-nya (8002, 8003, dst).
Aktifkan konfigurasi:
sudo ln -s /etc/nginx/sites-available/app1 /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Perintah ln -s ini wajib dijalankan supaya Nginx mau baca konfigurasinya. File yang ada di sites-available tidak otomatis aktif, harus di-symlink dulu ke sites-enabled.
Step 7: Jalankan Tunnel sebagai Service
Supaya tunnel otomatis jalan saat server restart:
sudo cloudflared service install
sudo systemctl start cloudflared
sudo systemctl enable cloudflared
Cek statusnya:
sudo systemctl status cloudflared
Step 8: Auto-Start php artisan serve saat Linux Hidup
Kalau aplikasi Laravel lo jalan pakai php artisan serve (bukan PHP-FPM), lo perlu pastiin perintah itu otomatis jalan saat server nyala, bukan cuma waktu lo login manual.
Caranya adalah bikin systemd service untuk tiap aplikasi. Ini jauh lebih proper daripada naruh perintah di .bashrc atau ngandalin screen/tmux yang gampang mati.
Buat file service untuk tiap aplikasi:
sudo nano /etc/systemd/system/laravel-app1.service
Isi dengan:
[Unit]
Description=Laravel App1 - php artisan serve
After=network.target
[Service]
User=<nama-user-lo>
WorkingDirectory=/home/<nama-user-lo>/path/ke/project-app1
ExecStart=/usr/bin/php artisan serve --host=0.0.0.0 --port=8001
Restart=always
[Install]
WantedBy=multi-user.target
Beberapa hal yang perlu diperhatikan:
-
Userisi dengan user Linux lo yang punya akses ke folder project, bukanrootdan bukanwww-datakalau project-nya ada di home directory lo sendiri -
WorkingDirectoryharus path absolut ke root project Laravel lo, yaitu folder yang ada fileartisan-nya -
--host=0.0.0.0supaya artisan serve bisa didengerin dari semua interface, karena Nginx yang forward request ke sini dari port 80 -
Restart=alwayssupaya service otomatis restart baik karena crash maupun setelah server reboot Aktifkan dan jalankan:
sudo systemctl daemon-reload
sudo systemctl enable laravel-app1
sudo systemctl start laravel-app1
Cek statusnya:
sudo systemctl status laravel-app1
Ulangi untuk tiap aplikasi, tinggal salin file service-nya dan ganti nama file, port, dan WorkingDirectory-nya.
# Contoh untuk app2
sudo cp /etc/systemd/system/laravel-app1.service /etc/systemd/system/laravel-app2.service
sudo nano /etc/systemd/system/laravel-app2.service
# ganti port ke 8002 dan WorkingDirectory ke path project app2
sudo systemctl daemon-reload
sudo systemctl enable laravel-app2
sudo systemctl start laravel-app2
Hasil Akhir
Setelah semua langkah selesai:
| Komponen | Biaya |
|---|---|
Domain .my.id
|
~Rp 15.000-16.000/tahun |
| Cloudflare (Free plan) | Rp 0 |
| Cloudflare Tunnel | Rp 0 |
| SSL/HTTPS otomatis | Rp 0 |
| Total | < Rp 20.000/tahun |
Semua subdomain otomatis dapat HTTPS dari Cloudflare tanpa konfigurasi tambahan. (peace of mind ga perlu mikirin SSL setting Let's Encrypt)
Lesson Learned
1. Sabar dengan propagasi DNS
Setelah ganti nameserver ke Cloudflare, tunggu sampai 24 jam. Jangan langsung panik kalau domain belum resolve dengan benar di beberapa jam pertama. Ini bukan bug, ini memang sifat DNS. Santuy dulu, tidur dulu, besok baru cek lagi.
2. Jangan pakai Caprover untuk setup ini
Caprover butuh IP publik langsung saat proses instalasinya, sementara Cloudflare Tunnel bekerja dengan CNAME, bukan IP statis. Dua hal ini tidak kompatibel. Gua sempat nyobain dan stuck cukup lama di situ. Kalau lo mau orkestrasi berbasis Docker, pakai alternatif cukup Docker Compose manual saja.
3. Satu tunnel, banyak aplikasi
Ga perlu buat tunnel baru untuk tiap aplikasi. Satu tunnel bisa handle banyak subdomain sekaligus lewat konfigurasi ingress. Tambah aplikasi baru? Tinggal tambah entry baru di config.yml dan route DNS-nya.
4. SSL gratis dan otomatis
Cloudflare handle SSL/HTTPS secara otomatis. Lo ga perlu setup Let's Encrypt atau certbot sama sekali. Semua subdomain langsung dapat HTTPS begitu DNS-nya aktif.
5. Urutan troubleshooting kalau tunnel ga jalan
Cek berurutan: status service cloudflared dulu (systemctl status cloudflared), lalu cek apakah aplikasi jalan di port yang benar (curl localhost:8001), baru terakhir cek DNS di Cloudflare dashboard. Jangan langsung panik ubah konfigurasi sebelum tahu masalahnya di layer mana. soalnya waktu itu pernah gangguan massal dari cloudflare nya
6. Pastikan APP_URL Laravel sesuai domain
Jangan lupa update .env di tiap project Laravel:
APP_URL=https://app1.namaproject.my.id
Kalo lupa ini, asset CSS/JS bisa tidak load karena URL-nya masih ngarah ke localhost.
7. Server harus selalu nyala
Konsekuensi dari setup self-hosted. Kalau server mati, semua aplikasi ikut down. Kalau lo pakai mesin rumahan, pastikan ada UPS atau setidaknya semua service diset auto-start.
Keamanan dan Keterbatasan: Jangan Tutup Mata
Setup ini gratis, tapi ada hal-hal yang perlu lo sadari sebelum deploy ke komunitas nyata.
Server bisa mati kapan saja
Ini realita self-hosted yang paling krusial. Server mati berarti semua aplikasi down seketika. Penyebabnya bisa macam-macam:
- Mati lampu (PLN lagi mood jelek)
- Internet rumah gangguan
- Lo pergi, ternyata selfhosted lu hang
- Worst case: kebakaran, banjir, atau bencana lainnya
Antisipasi yang bisa dilakukan:
- UPS (Uninterruptible Power Supply): Kasih waktu buffer saat mati lampu supaya server bisa shutdown bersih, atau cukup waktu buat lo restart layanan
-
Auto-start service: Pastikan semua service (Nginx, PHP-FPM atau artisan serve, Cloudflared) diset
systemctl enablesupaya otomatis jalan setelah server restart - Monitoring sederhana: Pakai Uptime Robot (gratis) untuk monitor URL dan kirim notifikasi ke email atau Telegram kalau aplikasi down
- Backup database rutin: Setup cron job backup database ke Google Drive atau storage eksternal. Data yang hilang jauh lebih buruk daripada sekadar downtime
# Contoh cron backup harian jam 2 pagi
0 2 * * * mysqldump -u root nama_db > /backup/db_$(date +\%F).sql
- Dokumentasi setup: Tulis semua konfigurasi di tempat yang bisa diakses dari luar (Notion, Google Docs). Kalau server kena musibah dan harus rebuild dari nol, lo perlu bisa rekonstruksi setup dalam waktu singkat Intinya: setup ini bukan untuk aplikasi yang harus 24/7 mission-critical. Untuk komunitas RT atau pencatat kas kelompok tani, downtime sesekali masih bisa ditoleransi. Tapi lo tetap harus transparan ke pengguna soal batasan ini.
Keamanan jaringan
Karena Cloudflare Tunnel ga butuh port terbuka di firewall, permukaan serangan sudah jauh lebih kecil dibanding VPS biasa. Tapi tetap lakukan ini:
- Aktifkan Cloudflare WAF (Web Application Firewall) di dashboard, sudah tersedia di free plan
- Set Cloudflare SSL/TLS mode ke Full (Strict)
- Jangan pernah expose port langsung ke internet; biarkan semua traffic lewat tunnel
- Pastikan
.envtidak pernah masuk ke Git repository
Kalau Udah Ada yang Mau Bayar (suggest mereka buat bayar sih), Upgrade ke VPS
Setup self-hosted ini bagus untuk awal atau untuk komunitas yang benar-benar nol budget (minta gratisan). Tapi kalau sudah mulai ada yang mau kontribusi, pertimbangkan untuk pindah ke VPS beneran.
Hitungannya masuk akal:
| Setup | Biaya |
|---|---|
| VPS DigitalOcean/Vultr/Hetzner (2GB RAM) | ~$5-6/bulan |
| Iuran per komunitas/klien | Rp 50.000-100.000/bulan |
| Break even di | 1-2 komunitas aja |
Kalau lo punya 10 komunitas atau klien yang masing-masing iuran Rp 50.000/bulan, lo sudah kumpulin Rp 500.000/bulan, sementara biaya VPS cuma sekitar Rp 80.000-100.000/bulan. Sisanya bisa buat domain, backup storage, atau masuk kantong lo sebagai maintenance fee.
Keuntungan pindah ke VPS:
- Uptime jauh lebih stabil, biasanya ada SLA 99.9%
- Ga tergantung kondisi internet dan listrik rumah lo
- Bisa tidur tenang
- Lebih tenang waktu pergi karena lo tinggal ga kepikiran macem-macem
- Irit listrik lo juga wkwk
- Lebih mudah di-scale kalau pengguna bertambah
Migrasi dari setup Cloudflare Tunnel ini ke VPS ga ribet: konfigurasi yang hampir sama bisa dipindah, bedanya servernya sekarang ada di cloud bukan di rumah.
Disclaimer Biaya (Serius wkwk)
Total biaya yang tercatat memang di bawah $1 per tahun. Tapi jujur, ini tidak termasuk:
- Tagihan listrik rumah yang ikut naik
- Domain my.id tahun berikutnya itu sekitar 50rban
- Biaya internet bulanan yang jadi "infrastruktur gratis"
- Waktu lo yang terpakai buat setup dan maintenance (ini yang mahal karena ide dan lo coding itu butuh mikirin flow dll yang tau ngadepin error hanya lo sendiri (lagi)) Tapi ya... anggap saja sedekah ilmu dan amal jariyah buat komunitas. Lumayan kan, sambil ngoding dapat pahala. Rezeki jangan ditolak, pahala jangan ditunda. 😄
Penutup
Setup ini cocok banget untuk:
- Aplikasi internal komunitas (RT, RW, perumahan)
- Portal yayasan atau sekolah kecil
- Aplikasi pencatat kas kelompok tani/pengajian/dll
- Proyek peliharaan lo / sampingan atau lagi ngeresearch / ngelab yang butuh domain proper tapi budget hampir nol Infrastrukturnya simple, maintenance-nya rendah, dan yang paling penting: semua orang bisa akses dari mana saja tanpa biaya macem-macem.
Top comments (0)