# Peer 部署與維運操作 記錄新增 peer、改名、daemon 維運等實際操作的 know-how。 ## 在 LXC/VM 裡透過 Docker 部署 NetBird 客戶端 適合 headless 伺服器(沒有 GUI、沒有真人 SSO 登入流程)。本 NetBird 部署已在 `CT100`、`CT101` 用此方法上線。 ### 前置 - 目標主機已裝 Docker - 有可用的 PAT(見 `setup-keys-and-pat.md`) - 對目標 NetBird management server 可連線 ### 步驟 #### 1. 為這台機器建一把 one-off setup key ```bash TOKEN=<你的 PAT> curl -sf -X POST -H "Authorization: Token $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "CT100-SSH-JumpBox", "type": "one-off", "expires_in": 86400, "revoked": false, "auto_groups": [], "usage_limit": 1, "ephemeral": false }' \ https://netbird.timmy.us.kg/api/setup-keys | jq ``` 命名慣例:`<主機名>-<用途>`(例 `CT100-SSH-JumpBox`、`CT101-RustDesk`),Dashboard 上一眼看得出這把 key 給誰。 - `type: one-off` + `usage_limit: 1` — 用一次就失效,最小攻擊面 - `expires_in: 86400` — 24 小時內沒用就過期 - `ephemeral: false` — 此 peer 離線後不自動清除(伺服器要持續存在) 把回傳的 `key` 欄位(UUID)存起來,下一步要用。 #### 2. 在目標主機寫 docker-compose.yml ```yaml services: netbird: image: netbirdio/netbird:latest container_name: netbird restart: unless-stopped network_mode: host cap_add: - NET_ADMIN - SYS_RESOURCE environment: - NB_SETUP_KEY=<上一步拿到的 key UUID> - NB_MANAGEMENT_URL=https://netbird.timmy.us.kg:443 - NB_HOSTNAME=<主機名,例 CT100> volumes: - /opt/netbird/data:/var/lib/netbird labels: - com.centurylinklabs.watchtower.enable=true ``` 放在 `/opt/netbird/docker-compose.yml`(跟 NetBird server 部署在 `.127` 的路徑一致,維運直覺)。 關鍵設定: - `network_mode: host` — NetBird 需要能直接看到 host 的網路介面來做 ICE - `cap_add: [NET_ADMIN, SYS_RESOURCE]` — 建 WireGuard 介面必要 - `NB_HOSTNAME` — peer 註冊後的顯示名稱(日後可用 API 再改) - Watchtower label — 讓 Watchtower 自動跟 upstream 更新 #### 3. 啟動 ```bash cd /opt/netbird docker compose pull docker compose up -d # 驗證 sleep 10 docker exec netbird netbird status ``` 正常輸出應該有 `Management: Connected`、`Relays: 2/2 Available`、`Peers count: N/N Connected`。 ### LXC 容器內的 TUN 問題 **理論上**:NetBird 需要 `/dev/net/tun` 來建立 WireGuard kernel 介面。 **實際上**:在非特權 LXC 容器(如 Proxmox 的 `unprivileged: 1`)`/dev/net/tun` 不存在,但 NetBird client 容器透過 `network_mode: host` + `cap_add: NET_ADMIN` 能跑起來,並顯示 `Interface type: Kernel`(推測是透過 host namespace 繞過)。 如果未來遇到 TUN 不可用的情境: - 選項 A:在 PVE CT config 加 `lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file,optional 0 0`(需重啟 CT) - 選項 B:切 userspace WireGuard(參考 Tailscale 的 `--tun=userspace-networking` 作法,但 NetBird 沒有這個開關,需要手動 patch) ## Peer 改名(API 做得到,setup key 做不到) ### 對比: | 資源 | API PUT `name` | 其他方式 | |------|--------------|---------| | setup_keys | **不生效**(見 `setup-keys-and-pat.md`) | 改 `store.db` + 重啟 server | | peers | **生效**,連 FQDN / dns_label 都自動同步 | — | ### 用法 ```bash TOKEN=<你的 PAT> # 列出 peer IDs curl -sf -H "Authorization: Token $TOKEN" \ https://netbird.timmy.us.kg/api/peers | jq '.[] | {id, name, hostname, ip}' # 改名 curl -X PUT -H "Authorization: Token $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "mbp-13-pro", "ssh_enabled": false, "login_expiration_enabled": false, "inactivity_expiration_enabled": false, "approval_required": false }' \ https://netbird.timmy.us.kg/api/peers/ ``` **注意**:PUT 需要帶完整的 peer 設定(不只 name),`ssh_enabled` 等欄位若不帶會用預設值覆蓋。先 GET 看看這個 peer 現況,再帶相同值 + 新的 name。 ### 命名慣例 改名後的 `dns_label` 會是 `.netbird.selfhosted`,建議: - 全小寫、英數與連字號、不用空格/中文 - 語意清楚:`mbp-13-pro`、`iphone-15-pro`、`ct100`、`ct101` - 避免 `.local` 等 mDNS 後綴(macOS 預設 hostname 會自動帶,改掉) ## Mac daemon 卡住:launchctl 重啟 ### 症狀 `netbird status` 顯示 `Management: Disconnected, reason: rpc error: context canceled` 或類似 RPC 錯誤。Signal 可能還是 Connected,但 peers count 歸零。 UI 上 Disconnect → Connect 通常可以恢復,但 daemon 真的卡死時 UI 也不回應。 ### 解法 直接重啟 launchd service: ```bash sudo launchctl kickstart -k system/netbird ``` ⚠️ 服務名稱是 **`netbird`**,**不是** `io.netbird.client`、`com.netbird.daemon` 等常見猜測。 確認方式: ```bash ls /Library/LaunchDaemons/ | grep -i netbird # → netbird.plist cat /Library/LaunchDaemons/netbird.plist | grep -A 1 'Label' # → netbird ``` launchd 語法 `system/