Files
headscale/OPERATIONS.md
2026-06-21 13:56:52 +08:00

10 KiB
Raw Permalink Blame History

Headscale 操作手冊

節點管理

查看節點狀態

# 列出所有節點
headscale nodes list

# JSON 格式輸出(含標籤)
headscale nodes list --output json | jq '.[] | {id, name, tags: .forced_tags}'

# 查看節點路由
headscale nodes list-routes

節點操作

# 重新命名節點
headscale nodes rename --identifier 2 iphone-15-pro-max
headscale nodes rename --identifier 4 ip-192-168-42-102

# 刪除節點
headscale nodes delete --identifier 6
headscale nodes delete --identifier 6 --force

命名規約:Linux 節點統一用 ip-<內網IP>(點改連字號),例如內網 192.168.42.105ip-192-168-42-105。改名只動 headscale 的 givenName(tailscale status 顯示的名字);節點自報的 name(hostname)不受影響。

用 HTTP API 改名(容器不在本機時)

當 headscale 容器不在當前機器、無法 docker exec 時,改用公開端點的 API。需要一把有效 API key(過期會回 401):

# 在 headscale 主機產生臨時 key
docker exec headscale headscale apikeys create --expiration 1h

# 查節點 ID(givenName 即顯示名)
curl -s -H "Authorization: Bearer <API_KEY>" \
  https://headscale.lotimmy.com/api/v1/node \
  | jq '.nodes[] | {id, givenName, name}'

# 改名:POST /api/v1/node/{id}/rename/{newName},成功回 HTTP 200
curl -s -X POST -H "Authorization: Bearer <API_KEY>" \
  https://headscale.lotimmy.com/api/v1/node/45/rename/ip-192-168-42-105

節點標籤管理

# 給節點加上 server 或 mobile 標籤
headscale nodes tag --identifier 4 --tags tag:server    # ct102
headscale nodes tag --identifier 9 --tags tag:server    # 15-macbook-pro
headscale nodes tag --identifier 12 --tags tag:server   # ip-192-168-88-82

headscale nodes tag --identifier 2 --tags tag:mobile    # iphone-15-pro-max
headscale nodes tag --identifier 5 --tags tag:mobile    # apple-tv-bedroom

# 移除所有標籤
headscale nodes tag --identifier 13 --tags ""

路由管理

# 批准路由(讓節點提供路由給其他節點)
headscale nodes approve-routes --identifier 4 --routes 0.0.0.0/0,192.168.42.0/24,::/0
headscale nodes approve-routes --identifier 5 --routes 192.168.42.0/24

金鑰管理

預授權金鑰Pre-auth Keys

# 產生 10 年期預授權金鑰
headscale preauthkeys create \
  --user 1 \
  --reusable \
  --ephemeral=false \
  --expiration 87600h

# 短期金鑰24 小時)
headscale preauthkeys create --user 1 --reusable --ephemeral=false --expiration 24h

# 列出預授權金鑰
headscale preauthkeys list --user 1

API 金鑰管理

# 列出 API 金鑰
headscale apikeys list

# 撤銷 API 金鑰
headscale apikeys revoke <KEY_ID>

# 使用腳本創建 API 金鑰
./create_headscale_api_key.sh

使用者管理

# 查看所有使用者
headscale users list

# 重新命名使用者namespace
headscale users rename --identifier 1 --new-name mainnet

ACL 政策管理

政策檔:config/policy.hujson(容器內 /etc/headscale/policy.hujson),由 config.yamlpolicy.mode: file + policy.path 啟用。

# 驗證語法(套用前務必先跑)
docker exec headscale headscale policy check --file /etc/headscale/policy.hujson

# 查看目前生效的政策
docker exec headscale headscale policy get

# 修改後套用file 模式於啟動時讀取,需重啟)
make restart

⚠️ 啟用 policy 後,acls 是唯一授權來源。policy.hujson 須保留 allow-allaccept * -> *:*)才能維持全互通,否則節點立即斷線。修改後務必確認 headscale nodes list 仍 online 且能 tailscale ping

Taildrive節點間檔案分享

權限由 policy 控制:nodeAttrs 授予 drive:share / drive:accessgrantstailscale.com/cap/drive 指定 share 範圍與讀寫權限(rw / ro)。需 headscale v0.29.0+。

# 分享端Linux/macOS/Windows
tailscale drive share <分享名稱> /要分享的/目錄
tailscale drive list
tailscale drive unshare <分享名稱>

# 存取端Linux 掛 WebDAV
#   http://100.100.100.100:8080/<tailnet>/<peer-name>/<分享名稱>

# 確認能力已下發到節點
docker exec tailscale tailscale debug netmap | grep -i drive

設備連接流程

完整流程

  1. 產生預授權金鑰
headscale preauthkeys create \
  --user 1 \
  --reusable \
  --ephemeral=false \
  --expiration 87600h
  1. 設備連接
tailscale up --login-server https://headscale.lotimmy.com --auth-key <金鑰>
  1. 註冊節點
headscale nodes register --user mainnet --key <設備返回的金鑰>
  1. 配置標籤和路由
# 添加標籤
headscale nodes tag --identifier <id> --tags tag:server

# 批准路由(如果需要)
headscale nodes approve-routes --identifier <id> --routes 0.0.0.0/0,::/0

Exit Node 配置

作為 Exit Node

tailscale up --reset \
  --login-server https://headscale.lotimmy.com \
  --advertise-exit-node \
  --advertise-routes=192.168.42.0/24 \
  --accept-routes=false

使用 Exit Node

# 指定 Exit Node
tailscale up --exit-node=<節點名稱或 IP>

# 使用特定節點的路由
tailscale up --exit-node=<節點名稱> --accept-routes

備份與還原

自動備份

# 執行自動備份
./headscale_backup_and_restore.sh

手動備份

# 停止服務
make down

# 建立備份
tar czvf headscale_backup_$(date +%Y%m%d_%H%M%S).tar.gz .

# 重新啟動服務
make up

備份驗證

備份腳本會自動:

  1. 停止服務
  2. 建立壓縮檔
  3. 計算資料庫 MD5 檢查碼
  4. 重啟服務
  5. 複製到遠端備份伺服器
  6. 驗證遠端備份完整性

日誌監控

服務日誌

# 查看 Tail 日誌
make logs

# 進入容器檢查
make exec

# 實時監控
make logs -f

API 健康檢查

# API 檢查腳本
./api_user_request.sh

# 手動檢查 API
curl -s https://headscale.lotimmy.com:8080/v1/metrics | head -n 10

系統監控

# 查看 Docker 事件
docker events --filter name=headscale

# 檢查容器資源使用
docker stats headscale

網路測試

內部連通性測試

# 測試內部節點連通性
tailscale ping 100.64.0.4
tailscale ping <節點名稱>

# 查看 tailnet 網路狀態
tailscale status

# 測試路由
tailscale ping <內網 IP>

DNS 測試

# 測試 MagicDNS
nslookup <節點名稱>.internal.lotimmy.com

# 測試自訂 DNS
dig @1.1.1.1 example.com

故障排除

常見問題

升級後容器無限重啟、所有節點離線(設定鍵被移除)

症狀:所有 tailscale/headscale 節點突然全部連不上;docker ps 顯示 headscale 一直 restartingRestartCount 持續飆高)。

原因:本服務使用 headscale/headscale:latest 並開啟 watchtower 自動更新,新版可能移除舊設定鍵,使容器一啟動就 FATAL 而陷入重啟迴圈。已知案例:

  • randomize_client_port(頂層)— FATAL,已移除,改到 policy 檔設定 "randomizeClientPort": true
  • ephemeral_node_inactivity_timeout — WARN改名為 node.ephemeral.inactivity_timeout

診斷

docker inspect headscale --format 'Status={{.State.Status}} RestartCount={{.RestartCount}}'
docker logs --tail 20 headscale   # 找 FATAL 那行,會指出是哪個設定鍵

修復:依日誌把被移除的鍵在 config/config.yaml 註解掉(或依新版語法遷移),再重建容器:

docker-compose up -d --force-recreate
docker inspect headscale --format '{{.State.Status}} {{.RestartCount}}'   # 應為 running / 0
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/health     # 應為 200

根治建議:把 image 釘到固定版本(如 headscale/headscale:v0.26.0),或移除 watchtower 標籤改為手動升級,避免破壞性更新自動套用(見「日常維護」)。

設備無法連接

  1. 檢查服務狀態
make ps
make logs
  1. 檢查預授權金鑰
headscale preauthkeys list --user 1
  1. 檢查防火牆
# 檢查端口
netstat -tlnp | grep 8080
netstat -tlnp | grep 9090
netstat -tlnp | grep 50443

節點顯示離線

  1. 檢查 WireGuard 連接
wg show
  1. 重啟節點
tailscale down
tailscale up
  1. 檢查系統日誌
journalctl -u tailscale -f

路由無法使用

  1. 確認節點標籤
headscale nodes list --output json | jq '.[] | {id, name, tags: .forced_tags}'
  1. 確認路由批准
headscale nodes list-routes
  1. 檢查 ACL 政策
headscale policy check

DNS 問題

  1. 檢查 MagicDNS
nslookup <節點名稱>.internal.lotimmy.com
  1. 檢查 DNS 伺服器
curl -s https://dns.nextdns.io/health
  1. 重啟 DNS 服務
systemctl restart systemd-resolved

緊急處理

服務無法啟動

# 檢查配置檔案
headscale config check

# 檢查 Docker 日誌
make logs

# 清理 Docker 資源
make clean
make up

資料庫損壞

  1. 停止服務
make down
  1. 從備份還原
# 恢復備份檔案
tar xzvf headscale_backup_xxxx.tar.gz

# 重新啟動
make up
  1. 驗證資料
headscale nodes list

日常維護

每日檢查清單

  • 檢查服務狀態:make ps
  • 查看日誌錯誤:make logs
  • 檢查連接節點數:headscale nodes list | wc -l
  • 執行 API 檢查:./api_user_request.sh
  • 檢查備份狀態(如果設定自動)

每週維護

  • 備份驗證測試
  • 檢查磁碟空間
  • 更新 Docker 映像:docker pull headscale/headscale:latest

    ⚠️ 升級前先看 CHANGELOG 的 BREAKING 段落,確認沒有被移除的設定鍵;建議釘版本而非用 :latest 自動更新(參見「故障排除 → 升級後容器無限重啟」)。

  • 檢查系統資源使用
  • 清理舊的日誌檔案

每月維護

  • 更新系統軟體
  • 重新審核 API 金鑰
  • 測試災難還原流程
  • 更新 ACL 政策
  • 檢查安全性設定