Initial commit: NetBird self-hosted deployment documentation

This commit is contained in:
2026-04-17 08:41:50 +08:00
commit 6e956f7334
4 changed files with 765 additions and 0 deletions

142
SUMMARY.md Normal file
View File

@@ -0,0 +1,142 @@
# 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 分鐘 |
## 檔案位置
### 本機(/Users/timmy/dev/42_127/
```
├── README.md ← 專案總覽
├── QUICKSTART.md ← 快速部署步驟
├── SUMMARY.md ← 本檔(部署摘要)
└── netbird-selfhosted-setup.md ← 完整安裝指南
```
### 遠端伺服器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