Files
netbird-selfhosted/SUMMARY.md
timmy d026ce4ba9 docs: remove decorative emojis
Gitea's markdown renderer displays keycap emojis (1️⃣, 2️⃣) as broken
boxes. Strip all decorative emojis from doc files for cleaner rendering.
2026-04-18 09:30:18 +08:00

5.6 KiB
Raw Blame History

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 分鐘
手機 Appserver closed the stream without sending trailers 透過 NPM 對外公開時NPM 用 proxy_pass 而非 grpc_pass 轉 gRPC加上 Caddy :80 預設不支援 h2c NPM 加 advanced_configgRPC 路由)+ Caddy 全域啟用 protocols h1 h2 h2c;見 npm-grpc-fix.md

檔案位置

本機(/Users/timmy/dev/42_127/

├── README.md                         ← 專案總覽
├── QUICKSTART.md                     ← 快速部署步驟
├── SUMMARY.md                        ← 本檔(部署摘要)
├── netbird-selfhosted-setup.md       ← 完整安裝指南
└── npm-grpc-fix.md                   ← 經 NPM 對外公開時的 gRPC 修復

遠端伺服器192.168.42.127:/opt/netbird/

├── docker-compose.yml    ← 服務編排
├── Caddyfile             ← 反向代理路由
├── config.yaml           ← NetBird Server 設定
└── dashboard.env         ← Dashboard 環境變數

Docker Volume

  • netbird_netbird_dataNetBird SQLite 資料庫與 GeoIP 資料

後續維運

日常指令

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 指標

參考資料