Headscale Self Hosted sebagai Alternatif Tailscale untuk Zero Trust Mesh Network

Ketika membangun infrastruktur yang terdistribusi, kebutuhan akan konektivitas yang aman, fleksibel, dan terpercaya menjadi prioritas utama. Headscale hadir sebagai solusi self-hosted yang memberikan kebebasan penuh untuk mengelola jaringan mesh private kita sendiri. Berbeda dengan Tailscale yang mengandalkan server terpusat milik vendor, Headscale memungkinkan kita untuk memiliki kontrol penuh, manajemen identitas, dan konfigurasi jaringan. Dalam artikel ini, kita akan mengeksplorasi bagaimana cara mengimplementasikan Headscale lengkap dengan Headplane sebagai web interface, sehingga kita dapat membangun ekosistem zero-trust networking yang aman dan efisien. Implementasi yang akan kita bahas mencakup instalasi di atas container (Docker Compose), konfigurasi SSL/TLS (dengan Caddy), integrasi OIDC (Google ID) untuk autentikasi yang robust, serta praktik operasional untuk mengelola nodes, routes, dan exit nodes. Dengan pendekatan hands-on, kita akan memahami setiap aspek teknis dari Headscale dan bagaimana menerapkannya di environment produksi.
Zero Trust Mesh Network
Zero trust networking adalah paradigma keamanan modern yang mengubah cara kita merancang infrastruktur jaringan. Berbeda dengan model tradisional yang membangun perimeter keamanan di sekitar jaringan internal, zero trust mengimplementasikan prinsip “never trust, always verify” untuk setiap komunikasi, baik dari internal maupun eksternal.
Mesh Network Architecture
Mesh network adalah topologi jaringan di mana setiap node dapat berkomunikasi langsung dengan node lain tanpa harus melalui satu titik pusat (central hub). Dalam konteks zero trust, mesh network memungkinkan:
- Direct Communication: Setiap perangkat dapat terhubung langsung dengan perangkat lain, mengeliminasi kebutuhan akan VPN concentrator tradisional.
- Distributed Resilience: Jika satu node offline, node lain tetap dapat berkomunikasi melalui rute alternatif.
- End-to-End Encryption: Semua komunikasi dienkripsi menggunakan WireGuard protocol, menjamin keamanan data dalam transit.
- Automatic Network Discovery: Nodes secara otomatis menemukan satu sama lain melalui control plane tanpa konfigurasi manual yang kompleks.
Headscale dan Tailscale
Tailscale adalah solusi VPN mesh network komersial yang dibangun di atas protokol WireGuard. Tailscale menyediakan layanan managed dengan server kontrol terpusat milik Tailscale Inc. Keuntungannya adalah kemudahan instalasi dan management, namun dengan trade-off: kita harus mempercayai Tailscale dengan metadata jaringan kita.
Headscale adalah implementasi open-source dari Tailscale yang memungkinkan kita untuk menjalankan control plane sendiri. Headscale kompatibel dengan klien Tailscale, artinya kita dapat menggunakan aplikasi klien Tailscale yang sudah familiar sambil menjalankan server kontrol milik sendiri. Ini memberikan keuntungan:
- Full Control: kita memiliki kontrol penuh atas data dan konfigurasi jaringan.
- Cost Efficient: Tidak perlu berlangganan layanan managed.
- Open Source: Kode tersedia untuk audit dan customization.
- Client Compatibility: Gunakan klien Tailscale resmi tanpa modifikasi.
Arsitektur
| |
Prerequisites
Sebelum memulai implementasi Headscale, pastikan beberapa prasyarat berikut terpenuhi.
- Docker dan Docker Compose sudah terinstall.
- Akses
sudountuk menjalankan commands administratif. - FQDN yang valid untuk server Headscale (contoh:
headscale.deployer.dpdns.org). A Record atau CNAME record yang mengarah ke IP server Headscale. DNS propagation sudah selesai dan resolving dengan benar. Dalam artikel ini saya menggunakan Cloudflare untuk DNS Management.
- OIDC provider seperti Google, Keycloak, Okta, atau penyedia OIDC lainnya. Dalam artikel ini saya menggunakan Google. Siapkan credentials OIDC (Client ID dan Client Secret) yang akan diintegrasikan dengan Headscale. Contoh redirect URI yang sesuai:
https://<FQDN-HEADSCALE>/oidc/callbackuntuk Headscale danhttps://<FQDN-HEADSCALE>/admin/oidc/callbackuntuk Headplane.

Instalasi & Konfigurasi Headscale
Pada bagian ini, kita akan mengimplementasikan Headscale beserta Headplane dalam environment Docker dengan SSL/TLS yang proper dan integrasi OIDC.
Struktur Direktori
Buat struktur direktori untuk Headscale dan konfigurasinya:
| |
Docker Secrets
Buat file secrets yang akan digunakan oleh Docker Secrets feature:
| |
Ganti <OIDC_CLIENT_SECRET> dengan Client Secret dari OIDC provider kita.
Environment File
Buat file .env untuk Docker Compose:
| |
Ganti <OIDC_CLIENT_ID> dengan Client ID dari OIDC provider kita.
Docker Compose Configuration
Buat docker-compose.yaml untuk Headscale dan Headplane:
| |
Konfigurasi Headscale
Buat file /opt/docker/headscale/config/config.yaml:
| |
Konfigurasi Headplane
Buat file /opt/docker/headscale/headplane/config/config.yaml:
| |
Caddy
Dalam artikel ini kita menggunakan Caddy untuk reverse proxy sesuai diagram arsitektur di atas.
Docker Compose Configuration
Buat docker-compose.yml untuk Caddy di /opt/docker/caddy/docker-compose.yml:
| |
Caddyfile Configuration
Buat Caddyfile untuk routing:
| |
Terkadang saya perlu menambahkan konfigurasi manual di /etc/hosts seperti berikut:
| |
Deployment
Buat network Docker terlebih dahulu:
| |
Start Caddy:
| |
Start Headscale dan Headplane:
| |
Verify Installation
Cek status containers:
| |
Cek logs untuk memastikan tidak ada error:
| |
Headscale Administration
Headscale API Key
Selanjutnya kita akan membuat API Key Headscale untuk keperluan administrasi, misalnya saya menggunakan --expiration 999d untuk jangka panjang:
| |
Catat dam simpan API Key ini, serta masukkan ke dalam Docker Secrets:
| |
Setup Headscale CLI
Sebelum menjalankan perintah Headscale, setup environment variables untuk CLI:
| |
Atau tambahkan ke ~/.bashrc:
| |
Membuat User
Setiap node harus tergabung dalam user. Buat user terlebih dahulu:
| |
Verifikasi user yang sudah dibuat:
| |
Menambahkan Node
Langkah selanjutnya adalah menambahkan perangkat (nodes) ke dalam jaringan. Headscale mendukung berbagai metode autentikasi: Pre-Authorization Key (Preauthkey), OIDC, dan ephemeral nodes.
Method 1: Pre-Authorization Key (Preauthkey) - Nodes Persisten
Preauthkey adalah cara termudah untuk menambahkan nodes yang tidak menggunakan OIDC. Preauthkey dapat dibuat sebagai reusable (dapat digunakan berkali-kali) atau single-use (hanya sekali).
Membuat Preauthkey
Untuk menambahkan nodes yang tidak memiliki Expiration, gunakan preauthkey reusable:
| |
Output akan menampilkan key, contoh: eed8cce8d0c9e5bda3f5e8d5e8c9d5c6
Catat key ini untuk digunakan saat setup klien.
Add Node Menggunakan Preauthkey (Linux/Ubuntu)
Install Tailscale Client
| |
Connect ke Headscale
| |
Ganti dengan IP yang sesuai untuk Ubuntu server. Verifikasi dari Headscale:
| |
Nodes baru akan muncul dalam daftar dengan IP dari prefix 100.64.0.0/10.
Add Node Menggunakan Preauthkey (Windows)
Install Tailscale Client
Download dan install dari https://tailscale.com/download/windows. Gunakan stable version.
Connect via Command Prompt (Admin)
| |
Atau Menggunakan GUI
- Klik Tailscale icon di system tray
- Klik “Login” atau “Sign in”
- Pilih “Use custom server” atau lihat opsi “Login Server”
- Masukkan URL Headscale:
https://headscale.deployer.dpdns.org - Paste preauthkey saat diminta
- Tunggu hingga connected
Method 2: OIDC - Nodes Ephemeral dengan Expiration
Nodes yang login menggunakan OIDC akan memiliki automatic expiration sesuai konfigurasi OIDC.
Add Node Menggunakan OIDC (Linux)
| |
Perintah ini akan membuka browser dengan OIDC login flow (Google OAuth dalam contoh ini). Setelah login berhasil, node akan secara otomatis ditambahkan ke user yang sesuai berdasarkan email OIDC. Jika berhasil akan muncul seperti berikut:

Add Node Menggunakan OIDC (Android)
- Unduh aplikasi “Tailscale” dari Google Play Store
- Buka aplikasi
- Tap “Sign in”
- Pilih “Use custom server”
- Masukkan URL:
https://headscale.deployer.dpdns.org - Lanjutkan dengan OIDC login (Google)
- Approve akses, dan node akan terhubung otomatis
Jika berhasil, akan tampil seperti berikut:
Verifikasi Nodes
Lihat semua nodes yang terhubung:
| |
Output akan menampilkan:
| |
Exit Node dan Subnet Routes
Headscale mendukung dua tipe route promotion: Exit Node dan Subnet Routes. Kedua fitur ini memungkinkan traffic dari nodes lain untuk melalui node tertentu.
Exit Node
Exit Node adalah node yang berperan sebagai gateway untuk seluruh traffic nodes lain. Semua traffic internet dari nodes yang menggunakan Exit Node akan diroute melalui Exit Node tersebut.
Use Case Exit Node
- Memberikan akses internet dengan IP yang sama
- Mengubah lokasi geografis traffic
- Centralized traffic filtering dan monitoring
- Backup connectivity jika node kehilangan akses internet langsung
Promote Node sebagai Exit Node
Dari daftar nodes di atas, ubuntu1 dan armbian dilabelkan untuk exit node. Untuk promote node sebagai exit node:
| |
Setelah di-promote, nodes lain dapat memilih untuk menempatkan traffic mereka melalui exit node ini.
Menggunakan Exit Node dari Klien
Linux/macOS
| |
Windows (via GUI)
- Klik Tailscale icon di system tray
- Settings → Exit node
- Pilih node yang ingin digunakan
- Traffic akan mulai diroute melalui exit node
Android/iOS
- Buka aplikasi Tailscale
- Settings / Gear icon
- Pilih “Exit nodes” atau “Route all traffic”
- Pilih exit node yang tersedia
Subnet Routes
Subnet Routes memungkinkan nodes untuk promote subnets tertentu sehingga nodes lain dapat mengakses resources di subnet tersebut. Berbeda dari exit node yang meroute semua traffic, subnet routes hanya meroute traffic untuk subnets spesifik.
Use Case Subnet Routes
- Share local subnets dengan nodes lain dalam mesh (contoh: LAN lokal)
- Access resources di private networks (contoh: internal servers, database)
- Multi-location connectivity untuk distributed infrastructure
- IoT devices discovery dan management
Promote Node sebagai Subnet Route
Dari contoh nodes, armbian mempromote dua subnets: 192.168.200.0/24 dan 192.168.254.0/24. Untuk promote subnets:
| |
Dari output headscale nodes list-routes, terlihat bahwa armbian (ID 3) mempromote:
- Approved & Available:
192.168.200.0/24,192.168.254.0/24 - Serving (Primary):
192.168.200.0/24,192.168.254.0/24
Ini berarti perangkat lain dalam mesh dapat mengakses resources di kedua subnet tersebut melalui node armbian.
Mengakses Resources via Subnet Routes
Setelah subnet routes di-enable, nodes lain dapat secara otomatis mengakses resources di subnets tersebut menggunakan IP address lokal:
| |
Klien Headscale secara otomatis mengupdate routing table untuk mengarahkan traffic ke subnet ke exit node yang appropriate. Tapi pada klien CLI, bisa jadi kita perlu menambahkan --accept-routes dengan perintah berikut:
| |
Testing Jaringan Headscale Mesh
Setelah semua nodes terhubung dan routes dikonfigurasi, langkah berikutnya adalah verifikasi bahwa jaringan mesh berfungsi dengan baik.
Verifikasi Node Connectivity
Ping antar Nodes
Dari node manapun dalam mesh, test ping ke node lain menggunakan IP Headscale mereka:
| |
Expected output: packets diterima dengan latency yang reasonable (tergantung network path).
Check Connectivity Status via CLI
| |
Test Direct Communication
SSH antar Nodes
| |
File Transfer
| |
Test Exit Node
Jika exit nodes sudah di-configure:
| |
Test Subnet Routes
Jika subnet routes sudah di-promote:
| |
Monitor Network Performance
Check Latency dan Packet Loss
| |
Monitor Headscale Metrics
Headscale expose Prometheus metrics di port 9090:
| |
Check Node Routes dan Policies
| |
Test dari Different OS
Untuk memastikan compatibility di berbagai OS, test dari:
- Linux desktop (Ubuntu, Fedora)
- Windows (desktop atau server)
- macOS (Intel atau Apple Silicon)
- Mobile (Android, iOS)
- ARM devices (Raspberry Pi, Armbian)
Long-running Stability Test
| |
Headplane
Headplane adalah web-based management interface untuk Headscale yang memudahkan administrasi jaringan melalui GUI daripada command-line interface. Headplane bertindak sebagai control plane user interface yang menyederhanakan manajemen Headscale.
Peran utama Headplane:
- User authentication via OIDC
- Node management (view, approve, remove nodes)
- Route management (enable/disable routes)
- API key management
- Monitoring dashboard
- Integration dengan Docker containers
Akses Headplane Web Interface
Headplane dapat diakses melalui URL:
| |
Login ke Headplane
Login via OIDC (Recommended)
- Buka
https://headscale.deployer.dpdns.org/admin - Klik “Sign in with OIDC” atau “Google” button
- Lakukan Google OAuth flow
- Setelah approved, akan redirect ke Headplane dashboard
- Session akan aktif untuk durasi yang dikonfigurasi (default: 24 jam)
Login via API Key
Jika OIDC tidak tersedia atau untuk akses programmatic:
- Dapatkan API key dari
/run/secrets/headscale_api_key - Pada login screen, masukkan API key sebagai credentials
- Sistem akan validate key dan grant access
Summary
Headscale memberikan alternatif yang powerful untuk Tailscale dengan memberikan kontrol penuh atas mesh network kita sendiri. Dengan implementasi yang telah dibahas dalam artikel ini, kita telah membangun infrastruktur yang:
- Secure: End-to-end encryption dengan WireGuard, authentication via OIDC
- Scalable: Support multiple nodes dari berbagai OS, dan database teroptimasi
- Manageable: Web interface via Headplane, kontrol penuh dari CLI
- Flexible: Custom routing, exit nodes, subnet routes
- Resilient: Distributed mesh architecture dengan redundancy
Implementasi Headscale cocok untuk berbagai use case:
- Remote Work: Secure access ke corporate resources
- Distributed Teams: Mesh connectivity antar lokasi yang berbeda
- IoT Management: Pengelolaan terpusat untuk IoT devices
- Hybrid Cloud: Seamless connectivity di multi-cloud environment
- Privacy-focused: Kontrol penuh tanpa ketergantungan pada third-party
Dengan monitoring, best practices, dan regular maintenance, Headscale dapat berjalan stabil dalam production environment dengan jumlah nodes dan user yang massif.
References
- https://headscale.net/
- https://github.com/tale/headplane
- https://tailscale.com/kb/1133/tailscale-architecture/
- https://www.wireguard.com/
- https://www.cloudflare.com/learning/security/glossary/what-is-zero-trust/
- https://docs.docker.com/
- https://letsencrypt.org/how-it-works/
- https://openid.net/connect/
- https://caddyserver.com/docs/
- https://tailscale.com/kb/




