Files
netbird-selfhosted/SUMMARY.md
timmy aaece30ca6 docs: add peer deployment ops guide
Document the operational patterns established while adding CT100 and
CT101 as peers via Docker, plus incidental fixes:

- Docker compose template for headless peer containers
- One-off setup key naming convention and API creation
- Peer rename via API PUT (works, unlike setup keys)
- Mac daemon kickstart via 'sudo launchctl kickstart -k system/netbird'
  (service name is 'netbird', not 'io.netbird.client')
- UPNP auto-port-mapping discovery in NetBird client
- CT100 PermitRootLogin drop-in override (first-match-wins sshd quirk)
2026-04-18 15:22:33 +08:00

155 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NetBird 部署摘要
## 部署結果
**NetBird Self-Hosted 已部署於 `192.168.42.127`**
- 部署日期2026-04-17
- 存取方式:`http://192.168.42.127`
- 部署模式HTTP-only無 TLS、IP-only無域名
## 部署時的關鍵決策
### 1. 為何不用官方 `getting-started.sh` 腳本?
官方腳本是互動式的(讀取 `/dev/tty`),且預設選項需要公網域名與 Let's Encrypt。本次為內網 IP 部署,手動產生設定檔更直接。
腳本原始碼中支援 `NETBIRD_DOMAIN=use-ip` 模式line 308會自動偵測 IP 並切換為 HTTP、port 80、`rel://` relay 協定。本次部署採用了相同的邏輯但以手動設定檔實現。
### 2. 為何選 Caddy 而非 Traefik 作為反向代理?
- Traefik 內建 Let's Encrypt ACME但無域名時會反覆嘗試失敗
- Caddy 設定檔更精簡(約 10 行),純 HTTP 路由對本場景足夠
- 兩者都能正確處理 gRPC (h2c) 後端
### 3. 為何需要 crun 取代 runc
**遇到的錯誤**
```
OCI runtime create failed: runc create failed: unable to start container process:
error during container init: open sysctl net.ipv4.ip_unprivileged_port_start file:
reopen fd 8: permission denied
```
**根因分析**
- Proxmox 非特權 LXC 將 `/proc/sys` 掛載為唯讀(`ro`
- runc 1.2+ 為防止 TOCTOU 攻擊會用「reopen fd」機制存取 sysctl 檔案
- 此機制在 LXC 的 `/proc` mount namespace 限制下失敗
**嘗試但無效的方法**
- `--privileged` flag
- `--security-opt apparmor=unconfined --security-opt seccomp=unconfined`
- `mount -o remount,rw /proc/sys`
- apt 安裝的 crun 1.14.1OCI spec 太舊Docker 不接受)
**最終解法**
下載 GitHub 最新 crun binary (1.20),並設為 Docker 預設 runtime。
## 安裝步驟摘要
```
1. apt 安裝前置套件 (curl, jq, openssl) ← 約 1 分鐘
2. 安裝 Docker Engine ← 約 2 分鐘(網速慢)
3. 下載 crun binary設定為 Docker 預設 runtime ← 約 30 秒
4. 建立 /opt/netbird/ 下四個設定檔 ← 約 30 秒
5. docker compose pull + up -d ← 約 1 分鐘
6. 等待 netbird-server 下載 GeoLite2 資料庫 ← 約 2-5 分鐘
```
總耗時約 10 分鐘(含 GeoIP 下載)。
## 服務驗證
所有服務已驗證正常運作:
| 端點 | 狀態 | 說明 |
|------|------|------|
| `http://192.168.42.127/` | 200 | Dashboard Web UI |
| `http://192.168.42.127/oauth2/.well-known/openid-configuration` | 200 | OIDC Discovery |
| STUN `:3478/udp` | | NAT 穿透 |
| 內部 gRPC (Signal + Management) | | h2c via Caddy |
## 疑難排解記錄
| 問題 | 原因 | 解法 |
|------|------|------|
| 初次 apt install 卡住 | 背景執行的 apt 行程未結束就被觸發第二個,導致 lock 競爭 | 清除 `/var/lib/dpkg/lock*``/var/lib/apt/lists/lock`,重啟 apt |
| `curl: command not found` | apt 仍在安裝中 | 等待安裝完成 |
| 所有 Docker 容器啟動失敗 | LXC `/proc/sys` 唯讀 + runc 1.3 的 reopen fd 機制 | 改用 crun 1.20 |
| Docker Compose `crun` runtime 未知 | `/etc/docker/daemon.json` 設定未生效 | `systemctl restart docker` |
| apt 的 crun 1.14.1 報 `unknown version specified` | crun 的 OCI spec 1.0.0 與 Docker 29.4 不相容 | 從 GitHub 下載 crun 1.20 |
| 502 Bad Gateway所有 API 端點) | netbird-server 下載 GeoLite2 中,尚未開始監聽 port 80 | 等待 2-5 分鐘 |
| 手機 App`server closed the stream without sending trailers` | 透過 NPM 對外公開時NPM 用 `proxy_pass` 而非 `grpc_pass` 轉 gRPC加上 Caddy `:80` 預設不支援 h2c | NPM 加 `advanced_config`gRPC 路由)+ Caddy 全域啟用 `protocols h1 h2 h2c`;見 [npm-grpc-fix.md](./npm-grpc-fix.md) |
| `PUT /api/setup-keys/{id}` 回 200 但 `name` 沒改 | NetBird API 只更新 `auto_groups``revoked``name` 是 read-only | 改 `store.db``setup_keys.name` → 重啟 `netbird-server`;見 [setup-keys-and-pat.md](./setup-keys-and-pat.md) |
| peer 之間一直走 Relay`[stun:...:3478] is Checking...` | STUN port 3478 被 Headscale (`.126`) 搶先佔用 DNAT | NetBird 改用 3479/udpserver config + OpenWrt DNAT見 [stun-port-conflict.md](./stun-port-conflict.md) |
| STUN 都通了,仍然 `Connection type: Relayed``ICE candidate: -/-` | 客戶端 **Force Relay Connection** 開關被打開,跳過 ICE gathering | App Settings → Advanced → 關掉 Force Relay見 [client-troubleshooting.md](./client-troubleshooting.md) |
| ping RTT 尖峰到 2-4 秒 | 當下 WiFi/ISP 有 bufferbloat | 用 `networkQuality -v` 確認(看 RPM與 NetBird 無關 |
| Mac `netbird status` 卡在 `Management: Disconnected, rpc error` | daemon 本身卡死,`netbird up`/`down` 救不回 | `sudo launchctl kickstart -k system/netbird`(服務名是 `netbird` 而非 `io.netbird.client`);見 [peer-deployment-ops.md](./peer-deployment-ops.md) |
| LXC CT100 SSH root 密碼被擋(`Permission denied` | sshd_config 內有 `PermitRootLogin prohibit-password``yes` 先出現first-match-wins | 加 `/etc/ssh/sshd_config.d/99-allow-root.conf` 覆蓋socket activation 不需重啟 sshd |
## 檔案位置
### 本機(/Users/timmy/dev/42_127/
```
├── README.md ← 專案總覽
├── QUICKSTART.md ← 快速部署步驟
├── SUMMARY.md ← 本檔(部署摘要)
├── netbird-selfhosted-setup.md ← 完整安裝指南
├── npm-grpc-fix.md ← 經 NPM 對外公開時的 gRPC 修復
├── setup-keys-and-pat.md ← Setup Keys / PAT 操作與 API 限制繞道
├── stun-port-conflict.md ← STUN 改用 3479 (3478 被 Headscale 佔用)
├── client-troubleshooting.md ← 客戶端 Force Relay / bufferbloat 排錯
└── peer-deployment-ops.md ← Docker 部署客戶端、改名、Mac daemon 重啟
```
### 遠端伺服器192.168.42.127:/opt/netbird/
```
├── docker-compose.yml ← 服務編排
├── Caddyfile ← 反向代理路由
├── config.yaml ← NetBird Server 設定
└── dashboard.env ← Dashboard 環境變數
```
### Docker Volume
- `netbird_netbird_data`NetBird SQLite 資料庫與 GeoIP 資料
## 後續維運
### 日常指令
```bash
ssh root@192.168.42.127
cd /opt/netbird
# 查看日誌
docker compose logs -f
# 重啟
docker compose restart
# 更新映像
docker compose pull && docker compose up -d
# 備份資料庫
docker compose exec netbird-server sqlite3 /var/lib/netbird/store.db ".backup /tmp/backup.db"
docker cp netbird-server:/tmp/backup.db ./backup-$(date +%F).db
```
### 可能的擴展
- **加上 TLS**:若之後取得域名,可切換為 Traefik + Let's Encrypt或本機自簽憑證
- **外部 IdP**:需支援 OIDC 的 IdP如 Authentik、Keycloak、Google可取代內建 Dex
- **高可用性**SQLite 不支援叢集,需改用 PostgreSQLRelay 可獨立部署
- **監控**:已暴露 `metricsPort: 9090` 的 Prometheus 指標
## 參考資料
- 官方文件https://docs.netbird.io/selfhosted/selfhosted-quickstart
- Getting Started 腳本https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh
- crun releasehttps://github.com/containers/crun/releases
- Proxmox LXC Docker 相容性https://pve.proxmox.com/wiki/Linux_Container#_features