Skip to content

Tailscale Serve:在 tailnet 內分享本機服務

使用 Tailscale Serve 在 tailnet 內以 HTTPS 分享本機 HTTP、TCP 服務與靜態檔案

Updated View as Markdown

本機跑了一個開發中的網站、後台或靜態檔案,想讓同一 tailnet 裡的其他裝置連進來,又不想開防火牆連接埠或上傳到公開主機,就用 Tailscale Serve。

本文以 Tailscale v1.102(2026 年 10 月)為準,指令為 v1.52 改版後的新語法:旗標在前、目標在後(例如 tailscale serve --bg 3000)。

Serve 是什麼

Tailscale Serve 會在你的裝置上啟一個 HTTPS(或 HTTP、TCP)服務,把流量轉給本機的服務。其他裝置用你的 MagicDNS 名稱連線,全程走 tailnet,不會暴露到網際網路。

一個 Serve 目標(target)可以是以下四種:

  • 本機服務:連接埠號碼(如 3000)、localhost:3000,或完整 URL。最常用來分享開發中的網站。注意反向代理永遠轉給 http://127.0.0.1,本機服務必須聽在 IPv4 迴路位址,只聽 [::1] 的會被拒絕(見範例一)。
  • 檔案或資料夾:絕對路徑(如 /home/alice/demo)。分享資料夾時會自動產生目錄列表。
  • 靜態文字:text:"...",適合放維護公告或快速測試。
  • TCP 轉發:--tcp 或 --tls-terminated-tcp,轉發 SSH、RDP 這類非 HTTP 的 TCP 服務。

預設走 HTTPS 443 連接埠,對外網址長這樣(443 以外會帶上連接埠號):

https://my-dev-machine.tailxxxxx.ts.net
https://my-dev-machine.tailxxxxx.ts.net:8443

Serve 收到 tailnet 來的請求時,會在轉給本機服務前加上身分標頭(Tailscale-User-Login、Tailscale-User-Name 等),後端可以用它識別是誰連進來的。例外:來自 tagged 裝置的請求不會帶這些標頭,只靠標頭做授權時要記得處理這個缺口。基於安全,後端服務建議只聽 127.0.0.1,避免有人繞過 Serve 直接偽造這些標頭。標頭的完整說明、剝除行為與 Grafana/Open WebUI/Dashy 範例,見 Serve 的身分標頭。

前置條件

  1. 裝置已加入 tailnet,且 MagicDNS 可以解析裝置名稱。
  2. 在管理後台啟用 HTTPS 憑證(Admin console → DNS → 啟用 HTTPS)。Serve 依賴 tailnet 自動配發的 TLS 憑證。
  3. 同一 tailnet 的存取控制(ACL)規則同樣適用於 Serve,而且是精確到連接埠的:對方能連你的裝置,不代表能連你的 Serve 網址。Serve 預設走 443,若 policy 只放行了特定連接埠(例如只開 22),對方能 SSH 但打不開你的 Serve 網址,需要額外放行 Serve 用的連接埠。
  4. Linux 上 tailscaled 預設只接受 root 管理:一般使用者執行 tailscale serve 若看到 Access denied,改用 sudo 執行,或先跑一次 sudo tailscale set --operator=$USER,之後即可免 sudo 操作 Tailscale。

如果你還沒啟用 HTTPS,直接跑 tailscale serve 即可,CLI 會給你一個 consent 網址,照著點開同意,Tailscale 會幫你把缺少的設定補上。

快速開始

假設本機 3000 連接埠跑著開發伺服器,在該裝置上執行:

tailscale serve 3000

第一次會看到類似輸出:

Available within your tailnet:
https://my-dev-machine.tailxxxxx.ts.net

|-- / proxy http://127.0.0.1:3000

Press Ctrl+C to exit.

接著在同一 tailnet 的另一台裝置上,用瀏覽器打開 https://my-dev-machine.tailxxxxx.ts.net 就能看到你的網站。不加旗標是前景執行,按 Ctrl+C 就停止分享。

常用指令

指令 用途
tailscale serve 3000 前景分享本機 3000 連接埠(預設 HTTPS 443)
tailscale serve --bg 3000 背景執行,重開機、tailscale down/up 後自動恢復
tailscale serve status 查看目前分享了哪些服務(加 --json 看 JSON 版)
tailscale serve --https=443 off 關掉 443 上的 HTTPS 分享(off 前要帶原本的旗標)
tailscale serve reset 清空本機所有 Serve 設定(含 Funnel 監聽)

幾個重點:

  • --bg 會把設定寫進節點的 serve config 並持續生效;沒加 --bg 的前景分享在重開機或 tailscale down/up 後要手動重跑。
  • 關閉單一分享時,off 指令的旗標要和當初啟用時一致。--bg 輸出的最後一行會直接告訴你該跑哪一行 off 指令,建議先跑 tailscale serve status 確認連接埠與路徑再關。
  • reset 不會印出任何訊息,跑完用 status 確認,會顯示 No serve config。注意它連 Funnel 的監聽設定也會一起清掉。

其他實用旗標:

# 換一個 HTTPS 連接埠(Serve 可用任意連接埠,不限 443 / 8443 / 10000)
tailscale serve --bg --https=8443 3000

# tailnet 內用純 HTTP(不需要憑證)
tailscale serve --bg --http=80 3000

# 同一台主機用路徑區分多個服務(前綴會被去掉,見範例一)
tailscale serve --bg 3000
tailscale serve --bg --set-path=/api http://127.0.0.1:8080/api

# 轉發本機 TCP 服務(例如 SSH)
tailscale serve --bg --tcp=2222 tcp://localhost:22

範例一:分享本機開發中的網站

以 Vite(預設 5173)為例。有兩個坑要先避開:Serve 永遠轉給 http://127.0.0.1,而 Vite 預設聽的 localhost 在 Node 17+ 常只綁到 IPv6 的 [::1],轉發會被拒絕;而且 Vite 6.0.9 / 5.4.12 之後預設擋掉非 localhost 的 Host(DNS rebinding 防護),Serve 轉發帶的是 *.ts.net 的 Host,不處理會看到「Blocked request」。兩個都在 vite.config.js 裡處理:

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  server: {
    // 明確聽在 127.0.0.1(仍是本機迴路,不會暴露到區網)
    host: "127.0.0.1",
    // 允許 tailnet 網址的 Host;開頭的 . 表示包含所有子網域
    allowedHosts: [".ts.net"],
  },
});
# 開發伺服器照常跑起來
npm run dev

# 另開一個終端機分享出去
tailscale serve --bg 5173

用 tailscale serve status 查到你的網址後,把 https://my-dev-machine.tailxxxxx.ts.net 貼給同事,對方在 tailnet 內就能直接預覽,不用把程式碼推上測試機。

想一次對照前後端時,加上 --set-path 把 API 掛在同一個主機名稱下:

tailscale serve --bg 5173
tailscale serve --bg --set-path=/api http://127.0.0.1:8080/api

這樣前端走 /,後端走 /api,共用同一個 HTTPS 網址。注意 --set-path 的前綴不會原樣轉給後端:請求 /api/users 時,Tailscale 會先去掉 /api 再轉發。上面把目標寫成含 /api 的完整 URL,就是為了把前綴補回去,讓路由註冊在 /api/* 的後端能正常運作。

範例二:分享一個資料夾

tailscale serve --bg /home/alice/demo

其他裝置打開你的 Serve 網址會看到目錄列表,點檔名即可下載。傳單一檔案就把路徑指到該檔案:

tailscale serve --bg /home/alice/demo/report.pdf

純文字公告最快,不用先建檔案:

tailscale serve --bg text:"網站維護中,09:00 UTC 回來"

macOS 有沙盒限制:從 Mac App Store 或 Standalone 版安裝的 Tailscale 只能分享連接埠,不能分享檔案或資料夾;要用檔案分享請改用開源版用戶端。

與 Funnel 的差異

Serve Funnel
看得到的人 只有同一 tailnet 內的裝置 整個網際網路都能連
典型用途 內部分享開發站、後台、檔案 公開 demo、webhook 接收、對外服務
連接埠限制 任意連接埠皆可 只能用 443、8443、10000
身分標頭 有(tagged 裝置的請求不帶) 沒有(公開流量不帶身分)

同一個連接埠不能同時是 Serve 又是 Funnel,以最後下的那道指令為準。如果你下了 Funnel 指令,該連接埠就變成公開的;要收回來就重下一次 serve。怎麼把服務公開到網際網路、要注意哪些限制與安全問題,見 Tailscale Funnel:把服務公開到網際網路。

如果想分享的對象是「一個邏輯服務」而不是「某一台裝置」——例如資料庫背後有多台後端、想要一個固定名稱與虛擬 IP、後端可以隨時增減——那是 Tailscale Services 的領域:它一樣用 tailscale serve 指令,只是多一個 --service 旗標,把服務和特定裝置解耦,同一台裝置也能同時當多個 Service 的後端。

常見問題

  • 跑 tailscale serve 被導去開網頁? 表示 HTTPS 或相關設定還沒啟用,照著 CLI 給的 consent 網址點開同意即可。
  • status 顯示 No serve config? 表示本機目前沒有任何分享,或剛跑完 reset。重下一道 serve 指令即可。
  • 確定在分享,對方卻連不上? 先檢查對方裝置是否在同一 tailnet,再檢查 ACL 是否放行了 Serve 用的連接埠(預設 443),最後用 tailscale serve status 確認網址、連接埠與路徑有沒有打錯。
  • Linux 上看到 Access denied? tailscaled 預設只接受 root 管理,改用 sudo tailscale serve ...,或先跑一次 sudo tailscale set --operator=$USER 之後免 sudo 操作。
  • 重開機後分享消失? 前景執行的分享不會自動回來,改用 tailscale serve --bg ... 即可持久化。

參考資料

Navigation

Type to search…

↑↓ navigate↵ selectEsc close