Initial commit: NetBird self-hosted deployment documentation
This commit is contained in:
245
QUICKSTART.md
Normal file
245
QUICKSTART.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# NetBird 快速部署指南
|
||||
|
||||
> 目標:在 Proxmox LXC (Ubuntu 24.04) 上部署 NetBird,使用 IP 直接存取(無域名、無 TLS)。
|
||||
|
||||
## 先決條件
|
||||
|
||||
- Proxmox LXC / Ubuntu 24.04
|
||||
- root 權限
|
||||
- 網際網路存取
|
||||
- 內網 IP (例:`192.168.42.127`)
|
||||
|
||||
> ⚠️ 以下步驟中的 `192.168.42.127` 請換成你的實際 IP。
|
||||
|
||||
---
|
||||
|
||||
## Step 1: 安裝前置套件
|
||||
|
||||
```bash
|
||||
apt-get update
|
||||
apt-get install -y curl jq ca-certificates gnupg openssl
|
||||
```
|
||||
|
||||
## Step 2: 安裝 Docker
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
systemctl start docker
|
||||
systemctl enable docker
|
||||
```
|
||||
|
||||
## Step 3: 安裝 crun(LXC 必須)
|
||||
|
||||
```bash
|
||||
curl -sL "https://github.com/containers/crun/releases/download/1.20/crun-1.20-linux-amd64" \
|
||||
-o /usr/local/bin/crun
|
||||
chmod +x /usr/local/bin/crun
|
||||
|
||||
cat > /etc/docker/daemon.json << 'EOF'
|
||||
{
|
||||
"runtimes": {
|
||||
"crun": {
|
||||
"path": "/usr/local/bin/crun"
|
||||
}
|
||||
},
|
||||
"default-runtime": "crun"
|
||||
}
|
||||
EOF
|
||||
|
||||
systemctl restart docker
|
||||
docker run --rm hello-world # 驗證
|
||||
```
|
||||
|
||||
## Step 4: 建立設定目錄與產生金鑰
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/netbird && cd /opt/netbird
|
||||
|
||||
RELAY_SECRET=$(openssl rand -base64 32 | sed 's/=//g')
|
||||
ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||
SERVER_IP=192.168.42.127 # 改成你的 IP
|
||||
```
|
||||
|
||||
## Step 5: 建立設定檔
|
||||
|
||||
### docker-compose.yml
|
||||
|
||||
```bash
|
||||
cat > /opt/netbird/docker-compose.yml << 'EOF'
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2
|
||||
container_name: netbird-caddy
|
||||
restart: unless-stopped
|
||||
networks: [netbird]
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
|
||||
dashboard:
|
||||
image: netbirdio/dashboard:latest
|
||||
container_name: netbird-dashboard
|
||||
restart: unless-stopped
|
||||
networks: [netbird]
|
||||
env_file:
|
||||
- ./dashboard.env
|
||||
|
||||
netbird-server:
|
||||
image: netbirdio/netbird-server:latest
|
||||
container_name: netbird-server
|
||||
restart: unless-stopped
|
||||
networks: [netbird]
|
||||
ports:
|
||||
- "3478:3478/udp"
|
||||
volumes:
|
||||
- netbird_data:/var/lib/netbird
|
||||
- ./config.yaml:/etc/netbird/config.yaml
|
||||
command: ["--config", "/etc/netbird/config.yaml"]
|
||||
|
||||
volumes:
|
||||
netbird_data:
|
||||
|
||||
networks:
|
||||
netbird:
|
||||
EOF
|
||||
```
|
||||
|
||||
### Caddyfile
|
||||
|
||||
```bash
|
||||
cat > /opt/netbird/Caddyfile << 'EOF'
|
||||
:80 {
|
||||
@grpc header Content-Type application/grpc*
|
||||
reverse_proxy @grpc h2c://netbird-server:80
|
||||
|
||||
@backend path /relay* /ws-proxy/* /api/* /oauth2/*
|
||||
reverse_proxy @backend netbird-server:80
|
||||
|
||||
reverse_proxy /* netbird-dashboard:80
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
### config.yaml
|
||||
|
||||
```bash
|
||||
cat > /opt/netbird/config.yaml << EOF
|
||||
server:
|
||||
listenAddress: ":80"
|
||||
exposedAddress: "http://${SERVER_IP}:80"
|
||||
stunPorts:
|
||||
- 3478
|
||||
metricsPort: 9090
|
||||
healthcheckAddress: ":9000"
|
||||
logLevel: "info"
|
||||
logFile: "console"
|
||||
|
||||
authSecret: "${RELAY_SECRET}"
|
||||
dataDir: "/var/lib/netbird"
|
||||
|
||||
auth:
|
||||
issuer: "http://${SERVER_IP}/oauth2"
|
||||
signKeyRefreshEnabled: true
|
||||
dashboardRedirectURIs:
|
||||
- "http://${SERVER_IP}/nb-auth"
|
||||
- "http://${SERVER_IP}/nb-silent-auth"
|
||||
cliRedirectURIs:
|
||||
- "http://localhost:53000/"
|
||||
|
||||
reverseProxy:
|
||||
trustedHTTPProxies:
|
||||
- "0.0.0.0/0"
|
||||
|
||||
store:
|
||||
engine: "sqlite"
|
||||
encryptionKey: "${ENCRYPTION_KEY}"
|
||||
EOF
|
||||
```
|
||||
|
||||
### dashboard.env
|
||||
|
||||
```bash
|
||||
cat > /opt/netbird/dashboard.env << EOF
|
||||
NETBIRD_MGMT_API_ENDPOINT=http://${SERVER_IP}
|
||||
NETBIRD_MGMT_GRPC_API_ENDPOINT=http://${SERVER_IP}
|
||||
AUTH_AUDIENCE=netbird-dashboard
|
||||
AUTH_CLIENT_ID=netbird-dashboard
|
||||
AUTH_CLIENT_SECRET=
|
||||
AUTH_AUTHORITY=http://${SERVER_IP}/oauth2
|
||||
USE_AUTH0=false
|
||||
AUTH_SUPPORTED_SCOPES=openid profile email groups
|
||||
AUTH_REDIRECT_URI=/nb-auth
|
||||
AUTH_SILENT_REDIRECT_URI=/nb-silent-auth
|
||||
NGINX_SSL_PORT=443
|
||||
LETSENCRYPT_DOMAIN=none
|
||||
EOF
|
||||
```
|
||||
|
||||
## Step 6: 啟動服務
|
||||
|
||||
```bash
|
||||
cd /opt/netbird
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
> ⏳ 首次啟動需等待約 2-5 分鐘下載 GeoLite2 地理資料庫(約 60MB)。
|
||||
|
||||
## Step 7: 驗證
|
||||
|
||||
```bash
|
||||
# 檢查容器狀態
|
||||
docker ps
|
||||
|
||||
# 測試 Dashboard
|
||||
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
|
||||
# 預期: 200
|
||||
|
||||
# 測試 OAuth2 端點(伺服器就緒的指標)
|
||||
curl -s http://127.0.0.1/oauth2/.well-known/openid-configuration | jq .issuer
|
||||
# 預期: "http://192.168.42.127/oauth2"
|
||||
```
|
||||
|
||||
## Step 8: 開始使用
|
||||
|
||||
### 1️⃣ Web 管理介面
|
||||
|
||||
瀏覽器開啟:**http://192.168.42.127**
|
||||
|
||||
首次登入會引導你建立管理員帳號。
|
||||
|
||||
### 2️⃣ 客戶端連線
|
||||
|
||||
安裝 NetBird 客戶端後執行:
|
||||
|
||||
```bash
|
||||
netbird up --management-url http://192.168.42.127
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 疑難排解
|
||||
|
||||
### Docker 容器啟動失敗
|
||||
|
||||
```
|
||||
OCI runtime create failed: runc create failed: ... permission denied
|
||||
```
|
||||
|
||||
**原因**:Proxmox LXC 容器 `/proc/sys` 限制。
|
||||
**解決**:確認已執行 Step 3 設定 crun。
|
||||
|
||||
### 伺服器啟動後無回應 (502 Bad Gateway)
|
||||
|
||||
**原因**:正在下載 GeoLite2 資料庫。
|
||||
**檢查**:`docker compose logs -f netbird-server`
|
||||
**處理**:耐心等待,視網速需 2-5 分鐘。
|
||||
|
||||
### 完全重置
|
||||
|
||||
```bash
|
||||
cd /opt/netbird
|
||||
docker compose down --volumes
|
||||
docker compose up -d
|
||||
```
|
||||
76
README.md
Normal file
76
README.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# NetBird Self-Hosted @ 192.168.42.127
|
||||
|
||||
在 Proxmox LXC (Ubuntu 24.04) 上自建 NetBird 的完整部署記錄與設定檔。
|
||||
|
||||
## 🎯 部署特色
|
||||
|
||||
- **IP-only 部署**:無需域名,純內網 LAN 使用
|
||||
- **HTTP 模式**:使用 Caddy 作為反向代理統一 port 80
|
||||
- **內建 IdP**:使用 NetBird Server 內建的 OAuth2(Dex),無需額外 IdP
|
||||
- **LXC 相容**:使用 crun 取代 runc 繞過 Proxmox 非特權容器限制
|
||||
|
||||
## 📁 文件說明
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| [QUICKSTART.md](./QUICKSTART.md) | 快速部署步驟(適合複製貼上執行) |
|
||||
| [netbird-selfhosted-setup.md](./netbird-selfhosted-setup.md) | 完整安裝指南(含原理說明) |
|
||||
| [SUMMARY.md](./SUMMARY.md) | 部署摘要與疑難排解記錄 |
|
||||
|
||||
## 🚀 快速開始
|
||||
|
||||
```bash
|
||||
# 瀏覽器開啟
|
||||
open http://192.168.42.127
|
||||
|
||||
# 客戶端連線
|
||||
netbird up --management-url http://192.168.42.127
|
||||
```
|
||||
|
||||
## 🏗️ 架構
|
||||
|
||||
```
|
||||
┌───────────────────────┐
|
||||
│ 192.168.42.127 │
|
||||
│ │
|
||||
:80 ────▶│ Caddy (反向代理) │
|
||||
│ ├── / ──▶│──▶ dashboard (Web UI)
|
||||
│ ├── /api/* ──▶│──▶ netbird-server
|
||||
│ ├── /oauth2/* ──▶│──▶ netbird-server
|
||||
│ ├── /relay* ──▶│──▶ netbird-server
|
||||
│ └── gRPC ──▶│──▶ netbird-server
|
||||
:3478/udp ────────────────────────│──▶ netbird-server (STUN)
|
||||
└───────────────────────┘
|
||||
```
|
||||
|
||||
## 🔧 環境
|
||||
|
||||
| 項目 | 值 |
|
||||
|------|-----|
|
||||
| 主機 | `192.168.42.127` |
|
||||
| 系統 | Ubuntu 24.04 LTS |
|
||||
| 容器類型 | Proxmox LXC (非特權) |
|
||||
| Docker | 29.4.0 |
|
||||
| OCI Runtime | crun 1.20 |
|
||||
| 設定目錄 | `/opt/netbird/` |
|
||||
|
||||
## 📦 服務清單
|
||||
|
||||
| 容器 | 映像 | 用途 |
|
||||
|------|------|------|
|
||||
| `netbird-caddy` | `caddy:2` | 反向代理 (:80) |
|
||||
| `netbird-dashboard` | `netbirdio/dashboard:latest` | Web 管理介面 |
|
||||
| `netbird-server` | `netbirdio/netbird-server:latest` | 管理 + Signal + Relay + STUN + IdP |
|
||||
|
||||
## ⚠️ 注意事項
|
||||
|
||||
- **無 TLS**:僅適合內網,勿暴露至公網
|
||||
- **無域名**:使用 IP 作為 issuer,若 IP 變更需重建
|
||||
- **LXC 限制**:必須使用 crun,不可使用預設 runc
|
||||
- **首次啟動慢**:需下載 GeoLite2 資料庫(約 60MB)
|
||||
|
||||
## 🔗 相關連結
|
||||
|
||||
- [NetBird 官方文件](https://docs.netbird.io/selfhosted/selfhosted-quickstart)
|
||||
- [NetBird GitHub](https://github.com/netbirdio/netbird)
|
||||
- [crun](https://github.com/containers/crun)
|
||||
142
SUMMARY.md
Normal file
142
SUMMARY.md
Normal 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.1(OCI 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 不支援叢集,需改用 PostgreSQL;Relay 可獨立部署
|
||||
- **監控**:已暴露 `metricsPort: 9090` 的 Prometheus 指標
|
||||
|
||||
## 參考資料
|
||||
|
||||
- 官方文件:https://docs.netbird.io/selfhosted/selfhosted-quickstart
|
||||
- Getting Started 腳本:https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh
|
||||
- crun release:https://github.com/containers/crun/releases
|
||||
- Proxmox LXC Docker 相容性:https://pve.proxmox.com/wiki/Linux_Container#_features
|
||||
302
netbird-selfhosted-setup.md
Normal file
302
netbird-selfhosted-setup.md
Normal file
@@ -0,0 +1,302 @@
|
||||
# NetBird Self-Hosted 安裝指南
|
||||
|
||||
> 環境:Proxmox LXC (CT127) / Ubuntu 24.04 / 內網 IP-only (無域名)
|
||||
|
||||
## 環境資訊
|
||||
|
||||
| 項目 | 值 |
|
||||
|------|-----|
|
||||
| 主機 | 192.168.42.127 |
|
||||
| 系統 | Ubuntu 24.04 LTS (Noble Numbat) |
|
||||
| 核心 | 6.8.12-16-pve (Proxmox VE) |
|
||||
| 容器類型 | LXC (非特權) |
|
||||
|
||||
## 1. 安裝前置套件
|
||||
|
||||
```bash
|
||||
apt-get update
|
||||
apt-get install -y curl jq ca-certificates gnupg openssl
|
||||
```
|
||||
|
||||
## 2. 安裝 Docker
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
systemctl start docker
|
||||
systemctl enable docker
|
||||
```
|
||||
|
||||
## 3. 解決 LXC 容器中 Docker 無法啟動的問題
|
||||
|
||||
Proxmox LXC 容器中 `/proc/sys` 被掛載為唯讀,導致 runc 1.3+ 嘗試存取 `net.ipv4.ip_unprivileged_port_start` sysctl 時失敗:
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
**解決方案:以 crun 取代 runc 作為 OCI runtime**
|
||||
|
||||
```bash
|
||||
# 下載 crun 1.20
|
||||
curl -sL "https://github.com/containers/crun/releases/download/1.20/crun-1.20-linux-amd64" \
|
||||
-o /usr/local/bin/crun
|
||||
chmod +x /usr/local/bin/crun
|
||||
|
||||
# 設定 Docker 使用 crun
|
||||
cat > /etc/docker/daemon.json << 'EOF'
|
||||
{
|
||||
"runtimes": {
|
||||
"crun": {
|
||||
"path": "/usr/local/bin/crun"
|
||||
}
|
||||
},
|
||||
"default-runtime": "crun"
|
||||
}
|
||||
EOF
|
||||
|
||||
systemctl restart docker
|
||||
|
||||
# 驗證
|
||||
docker run --rm hello-world
|
||||
```
|
||||
|
||||
## 4. 建立 NetBird 設定檔
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/netbird
|
||||
cd /opt/netbird
|
||||
```
|
||||
|
||||
### 4.1 產生金鑰
|
||||
|
||||
```bash
|
||||
RELAY_SECRET=$(openssl rand -base64 32 | sed 's/=//g')
|
||||
ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||
|
||||
echo "RELAY_SECRET=$RELAY_SECRET"
|
||||
echo "ENCRYPTION_KEY=$ENCRYPTION_KEY"
|
||||
```
|
||||
|
||||
> 記下這兩個值,下方設定檔需要用到。
|
||||
|
||||
### 4.2 docker-compose.yml
|
||||
|
||||
```yaml
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2
|
||||
container_name: netbird-caddy
|
||||
restart: unless-stopped
|
||||
networks: [netbird]
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "2"
|
||||
|
||||
dashboard:
|
||||
image: netbirdio/dashboard:latest
|
||||
container_name: netbird-dashboard
|
||||
restart: unless-stopped
|
||||
networks: [netbird]
|
||||
env_file:
|
||||
- ./dashboard.env
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "2"
|
||||
|
||||
netbird-server:
|
||||
image: netbirdio/netbird-server:latest
|
||||
container_name: netbird-server
|
||||
restart: unless-stopped
|
||||
networks: [netbird]
|
||||
ports:
|
||||
- "3478:3478/udp"
|
||||
volumes:
|
||||
- netbird_data:/var/lib/netbird
|
||||
- ./config.yaml:/etc/netbird/config.yaml
|
||||
command: ["--config", "/etc/netbird/config.yaml"]
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "2"
|
||||
|
||||
volumes:
|
||||
netbird_data:
|
||||
|
||||
networks:
|
||||
netbird:
|
||||
```
|
||||
|
||||
### 4.3 Caddyfile
|
||||
|
||||
Caddy 作為反向代理,將所有服務統一在 port 80:
|
||||
|
||||
```
|
||||
:80 {
|
||||
@grpc header Content-Type application/grpc*
|
||||
reverse_proxy @grpc h2c://netbird-server:80
|
||||
|
||||
@backend path /relay* /ws-proxy/* /api/* /oauth2/*
|
||||
reverse_proxy @backend netbird-server:80
|
||||
|
||||
reverse_proxy /* netbird-dashboard:80
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 config.yaml
|
||||
|
||||
將 `<RELAY_SECRET>` 和 `<ENCRYPTION_KEY>` 替換為步驟 4.1 產生的值:
|
||||
|
||||
```yaml
|
||||
server:
|
||||
listenAddress: ":80"
|
||||
exposedAddress: "http://192.168.42.127:80"
|
||||
stunPorts:
|
||||
- 3478
|
||||
metricsPort: 9090
|
||||
healthcheckAddress: ":9000"
|
||||
logLevel: "info"
|
||||
logFile: "console"
|
||||
|
||||
authSecret: "<RELAY_SECRET>"
|
||||
dataDir: "/var/lib/netbird"
|
||||
|
||||
auth:
|
||||
issuer: "http://192.168.42.127/oauth2"
|
||||
signKeyRefreshEnabled: true
|
||||
dashboardRedirectURIs:
|
||||
- "http://192.168.42.127/nb-auth"
|
||||
- "http://192.168.42.127/nb-silent-auth"
|
||||
cliRedirectURIs:
|
||||
- "http://localhost:53000/"
|
||||
|
||||
reverseProxy:
|
||||
trustedHTTPProxies:
|
||||
- "0.0.0.0/0"
|
||||
|
||||
store:
|
||||
engine: "sqlite"
|
||||
encryptionKey: "<ENCRYPTION_KEY>"
|
||||
```
|
||||
|
||||
### 4.5 dashboard.env
|
||||
|
||||
```env
|
||||
NETBIRD_MGMT_API_ENDPOINT=http://192.168.42.127
|
||||
NETBIRD_MGMT_GRPC_API_ENDPOINT=http://192.168.42.127
|
||||
AUTH_AUDIENCE=netbird-dashboard
|
||||
AUTH_CLIENT_ID=netbird-dashboard
|
||||
AUTH_CLIENT_SECRET=
|
||||
AUTH_AUTHORITY=http://192.168.42.127/oauth2
|
||||
USE_AUTH0=false
|
||||
AUTH_SUPPORTED_SCOPES=openid profile email groups
|
||||
AUTH_REDIRECT_URI=/nb-auth
|
||||
AUTH_SILENT_REDIRECT_URI=/nb-silent-auth
|
||||
NGINX_SSL_PORT=443
|
||||
LETSENCRYPT_DOMAIN=none
|
||||
```
|
||||
|
||||
## 5. 啟動服務
|
||||
|
||||
```bash
|
||||
cd /opt/netbird
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
首次啟動時 netbird-server 會下載 GeoLite2 地理位置資料庫(約 60MB),視網路速度可能需要數分鐘。
|
||||
|
||||
驗證所有容器正常運行:
|
||||
|
||||
```bash
|
||||
docker ps
|
||||
```
|
||||
|
||||
預期輸出三個容器皆為 `Up` 狀態:
|
||||
|
||||
```
|
||||
NAMES STATUS PORTS
|
||||
netbird-caddy Up 0.0.0.0:80->80/tcp
|
||||
netbird-dashboard Up 80/tcp, 443/tcp
|
||||
netbird-server Up 0.0.0.0:3478->3478/udp
|
||||
```
|
||||
|
||||
驗證 OAuth2 端點:
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1/oauth2/.well-known/openid-configuration | jq .issuer
|
||||
# 預期輸出: "http://192.168.42.127/oauth2"
|
||||
```
|
||||
|
||||
## 6. 使用方式
|
||||
|
||||
### Web 管理介面
|
||||
|
||||
瀏覽器打開 `http://192.168.42.127`,完成首次設定(建立管理員帳號)。
|
||||
|
||||
### 客戶端連線
|
||||
|
||||
```bash
|
||||
netbird up --management-url http://192.168.42.127
|
||||
```
|
||||
|
||||
## 服務架構
|
||||
|
||||
```
|
||||
Client Request (:80)
|
||||
|
|
||||
Caddy (反向代理)
|
||||
|
|
||||
+-- / --> netbird-dashboard (Web UI)
|
||||
+-- /api/* /oauth2/* --> netbird-server (管理 API + 內建 IdP)
|
||||
+-- /relay* /ws-proxy/* --> netbird-server (Relay + WebSocket)
|
||||
+-- gRPC (Content-Type 判斷) --> netbird-server (Signal + Management gRPC)
|
||||
|
||||
STUN (:3478/udp) --> netbird-server
|
||||
```
|
||||
|
||||
## 開放端口
|
||||
|
||||
| 端口 | 協定 | 用途 |
|
||||
|------|------|------|
|
||||
| 80 | TCP | Dashboard + API + Signal + Relay |
|
||||
| 3478 | UDP | STUN (NAT 穿透) |
|
||||
|
||||
## 常用維運指令
|
||||
|
||||
```bash
|
||||
cd /opt/netbird
|
||||
|
||||
# 查看日誌
|
||||
docker compose logs -f netbird-server
|
||||
docker compose logs -f --tail=50
|
||||
|
||||
# 重啟服務
|
||||
docker compose restart
|
||||
|
||||
# 停止服務
|
||||
docker compose down
|
||||
|
||||
# 更新映像
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
|
||||
# 完全重置(刪除所有資料)
|
||||
docker compose down --volumes
|
||||
```
|
||||
|
||||
## 注意事項
|
||||
|
||||
- 此為 HTTP-only 內網部署,無 TLS 加密,不適合暴露至公網
|
||||
- 如需公網存取,應配置域名並啟用 HTTPS(使用 Traefik + Let's Encrypt)
|
||||
- Proxmox LXC 容器需使用 crun 替代 runc,否則 Docker 容器無法啟動
|
||||
- 設定檔位於 `/opt/netbird/`,資料儲存在 Docker volume `netbird_netbird_data`
|
||||
Reference in New Issue
Block a user