Tailscale 改寫了 mesh VPN 的使用體驗。三條指令裝完,所有裝置就會自動互通,NAT 穿越、金鑰輪替、子網路廣告全部不用煩。問題是這套魔法的另一面:整個網路的金鑰交換、節點目錄、ACL 規則、Magic DNS 都跑在 Tailscale 自家的控制伺服器上。對於跨多個 VPS、跨臺灣多個機房的內部網路而言,把整張拓撲圖交給美國的第三方並不總是合適。
Headscale 是 Juan Font 自 2020 年起獨立開發的 Tailscale 控制伺服器替代品,到 2026 年 4 月已經累積接近四萬顆星,並在 FOSDEM 2026 出現專題分享。它沒有重寫 Tailscale 的 client,而是反向工程出控制伺服器的 API,讓官方的 tailscale 指令、各平台 GUI 一律可以直接接到自家 VPS 上的 Headscale。
自己手動拼 WireGuard mesh 撐不到第十臺機器
WireGuard 本身只解決一件事:兩個 peer 之間的加密通道。每多一臺機器,所有既有節點的 [Peer] 區塊都得更新;金鑰外洩要重發;某個節點 IP 變了所有人都得改。三臺機器還能用 Ansible 模板硬撐,第十臺之後管理成本指數爆炸。
真正讓 mesh VPN 變難的不是加密,而是「誰知道誰存在、誰能連誰、用哪個位址連」這套控制平面。Tailscale 把這層做成一個雲端服務:每臺裝置開機後先去 control plane 報到拿到一份節點清單,再用 WireGuard 跟其他節點建立直接連線。資料平面還是純 WireGuard,但目錄與規則完全集中管理。
Headscale 接手的就是這層目錄。資料平面繼續使用 Tailscale client 內建的 WireGuard 引擎,加密與穿越邏輯完全不變。換句話說,自架 Headscale 不會犧牲 Tailscale 客戶端的體驗,換來的是金鑰、ACL、節點清單都留在自己 VPS 上。
最小可行部署其實只要一臺 VPS
官方文件刻意避開 reverse proxy 與複雜編排,預設情境就是單機 Docker。一臺 1 vCPU、1 GB RAM 的 VPS 對於數十個節點綽綽有餘,因為控制平面的流量只在節點加入、登出、變更時發生,平時幾乎沒有負載。
部署清單需要的東西不多:一個公開可解析的網域(例如 headscale.example.tw)、開放 TCP 443 給 client 註冊用、開放 UDP 3478 給內建 DERP 的 STUN 探測。Headscale 0.26 之後不再建議放在反向代理後面,原因是它需要直接終止 TLS 才能正確處理 client 的 noise 協議交握。
config.yaml 真正要動的欄位其實只有 server_url、listen_addr、IP prefix 與 DNS 設定。預設的資料庫是 SQLite,對小型節點數量完全夠用;超過幾百個節點才需要切到 PostgreSQL。資料目錄與 SQLite 檔案務必接到持久化 volume,每天 cron 備份一份到異地 S3——控制平面的金鑰一旦遺失,整張網路就要從零重建。
ACL 才是 Headscale 留得住人的理由
預設情況下 Headscale 對同一個 user 的所有節點開放全部 port,這在開發環境堪用,正式環境一定要設 ACL。語法跟 Tailscale 完全一樣,就是一份 HuJSON:
1 | { |
這份檔案用 headscale policy set 載入後即時生效。比起在每臺機器手動維護 iptables 規則,集中化 ACL 在審計與輪替時的價值會直接顯現。實務上建議至少切出三層:管理員、應用伺服器、開發者個人裝置,各自只開必要的 port,預設拒絕。
DERP 與 NAT 穿越決定了八成的連線品質
mesh VPN 真正的隱形成本在於 NAT 穿越失敗的那 10% 到 20% 連線。當兩端都在對稱式 NAT 或是企業防火牆後面,UDP hole punching 無法建立直連,Tailscale client 會自動 fallback 到 DERP relay 中繼。
Tailscale 官方在全球有 30 多個 DERP 節點,而 Headscale 的內建 DERP 只有一個——就是 Headscale 本身那臺。如果 Headscale 部署在臺北機房,臺北節點之間 fallback 走 DERP 沒問題,跨海節點就會吃到延遲。
實務做法是在不同地點再額外跑幾個 derper(Tailscale 開源的 DERP server),並寫進 Headscale 的 DERP map。一臺日本、一臺新加坡,跨區連線品質會明顯改善。對單一臺灣機房內的私有網路,內建 DERP 已經夠用,這部分先不用過早最佳化。
OIDC 接上之後再也不用手動發 pre-auth key
第一次部署完,把節點接入網路的方式是 headscale users create 產生 pre-auth key,再貼到 client 端執行 tailscale up --login-server=...。這套流程在三五個人的團隊還行,超過十人就會變成管理員每天最煩的雜事。
Headscale 0.26 對 OIDC 的支援已經成熟。把 issuer 指向自架的 Pocket ID、Authentik 或 Zitadel,使用者第一次連線時瀏覽器跳出登入頁,通過後 Headscale 自動建立對應的 user 與機器條目。離職時在 IdP 停用帳號,所有節點自動失效。
這個組合到 2026 年已經是自架社群的標配。同時自架 Pocket ID 處理 Passkey 登入,整個身分認證流程都不依賴外部 SaaS。
升級這件事真的不能跳版本
Headscale 在 0.x 階段每個 minor release 都可能改 config schema 或資料庫遷移腳本,官方明確警告升級時必須逐版本跳:0.23 → 0.24 → 0.25,不能直接從 0.23 跳到 0.28。社群 issue 區半數的「升完開不起來」回報都是因為這件事。
部署完之後固定 image tag,每次升級先在備援 VPS 跑一遍 dry run,確認 client 連得上、ACL 行為沒變再切流量。對要長期維運的網路而言,這比追新版功能重要得多。
結語
Headscale 不是要取代 Tailscale 的商業服務——對於不在意控制平面在哪、有預算買 Premium 的團隊,官方版仍然是阻力最小的選擇。但對於把基礎設施視為核心資產、需要把金鑰與拓撲留在臺灣機房的開發者與企業,Headscale 是完整、相容、可長期維護的替代方案。
把 Headscale 跑在一臺臺北的 VPS 上,再把 Pocket ID 與 Beszel 串起來,內部網路、身分認證、監控告警就完全握在自己手上。NCSE Network 的 VPS 位於臺灣是方電訊機房,搭配 Intel Gold CPU 與 NVMe SSD,跑控制平面與身分服務的反應速度與穩定度相當合適,需要部署自家 mesh 網路的團隊可以到 ncse.tw 看看適合的方案。