Self-Hosting dari Rumah: Tunnel, Bug Delimiter, dan WireGuard
pujamalca.my.id saya jalankan dari rumah, bukan dari cloud. Masalahnya sederhana tapi klasik: koneksi rumahan gak punya IP publik statis, jadi gak bisa langsung terima trafik dari internet. Solusinya adalah pola reverse tunnel — sebuah klien tunnel ringan berbasis Java jalan di Mac Studio saya, membuka koneksi keluar terus-menerus ke sebuah VPS kecil. VPS itu yang menghadap publik: terima trafik, urus sertifikat HTTPS, lalu meneruskan semuanya lewat tunnel ke nginx di rumah. Efeknya, Mac di rumah gak perlu buka port apa pun ke internet, cukup satu koneksi keluar yang selalu hidup.
Bug yang Bikin Bingung Berhari-hari
Suatu waktu tunnel ini rusak dengan cara yang aneh: channel kontrolnya konek normal, status kelihatan sehat, tapi data gak pernah benar-benar lewat. Gak ada error yang muncul di log, jadi susah dilacak. Saya sempat curiga ke banyak hal — firewall, konfigurasi nginx, bahkan versi Java — sebelum akhirnya ketemu akar masalahnya.
Ternyata penyebabnya sepele tapi jahat. Protokol notifikasi koneksi di tunnel itu memisahkan pesan berdasarkan satu karakter pemisah (delimiter) tertentu. Kebetulan, kunci rahasia yang saya pakai untuk autentikasi juga mengandung karakter yang persis sama dengan delimiter itu. Akibatnya proses parsing pesan jadi salah tanpa ada exception atau error yang dilempar — pesannya cuma “terpotong” di tempat yang salah, dan tunnel diam-diam gagal meneruskan data.
Solusinya, dan Pelajarannya
Begitu kunci itu saya ganti dengan nilai yang gak mengandung karakter delimiter tadi, tunnel langsung jalan normal lagi. Pelajarannya jadi jelas: kalau sebuah protokol memakai delimiter karakter untuk parsing pesan, jangan pernah memasukkan karakter delimiter itu ke dalam value bebas seperti password atau kunci rahasia. Ini kelas bug yang gak akan ketahuan dari dokumentasi API, cuma ketahuan kalau kebetulan generate kunci acak dan apes kena karakter itu.
Mengunci Hop dengan WireGuard
Setelah tunnel-nya stabil, saya pikir trafik antara Mac dan VPS itu masih polos (belum ada enkripsi tambahan di level jaringan), jadi saya bungkus lagi hop itu dengan WireGuard. Hasilnya, trafik tunnel yang tadinya polos sekarang lewat terowongan terenkripsi tambahan sebelum sampai ke VPS.
Setup WireGuard di macOS ada dua jebakan yang berhubungan dengan launchd (sistem yang menjalankan proses background di macOS):
- Script resmi WireGuard butuh versi bash yang lebih baru dari bash bawaan macOS. Kalau launchd gak dipaksa memakai path bash yang benar, dia akan resolve ke bash bawaan itu dan gagal dengan error version mismatch.
- Proses WireGuard yang jalan di background sempat ikut mati beberapa detik setelah proses utamanya keluar. Ini karena launchd secara default membunuh seluruh grup proses begitu proses yang dipantau selesai. Untungnya ada satu opsi konfigurasi launchd yang bisa mencegah perilaku itu, sehingga proses background-nya tetap hidup.
Saat mendiagnosis ini di kondisi live, situs saya sempat down sekitar 3 menit sebelum saya menemukan fix-nya — cukup mendebarkan, tapi jadi pelajaran yang nempel.
Takeaway
Dua hal yang saya bawa dari pengalaman ini: pertama, hati-hati dengan protokol berbasis delimiter karakter — kunci atau value bebas apa pun bisa diam-diam bentrok dengannya tanpa error. Kedua, kalau menjalankan proses background lewat launchd di macOS, cek dua hal ini dulu: path bash yang dipakai, dan perilaku default launchd yang bisa mematikan seluruh grup proses.