Compare commits
3 Commits
ae9ce6fcc2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2808ed295a | |||
| c30abe2e83 | |||
| 7bfe4fcde6 |
62
CLAUDE.md
Normal file
62
CLAUDE.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## 倉庫性質
|
||||
|
||||
這是**純文件倉庫**(Markdown only),記錄 `192.168.42.127` 上 NetBird Self-Hosted 的部署、設定與營運經驗。沒有原始碼、沒有 build/test/lint 流程。實際的可執行設定檔(`docker-compose.yml`、`Caddyfile`、`config.yaml`、`dashboard.env`)住在**遠端主機** `192.168.42.127:/opt/netbird/`,本倉庫描述它們的內容與背後決策。
|
||||
|
||||
修改文件時的工作流程:
|
||||
1. 在本機編輯 Markdown
|
||||
2. 任何需要驗證的步驟透過 `ssh root@192.168.42.127` 在遠端跑
|
||||
3. `git diff` / `git log` 看歷史;`git commit` 走一般流程
|
||||
|
||||
## 部署上下文(寫文件時必須記住)
|
||||
|
||||
- **IP-only / HTTP-only**:無域名、無 TLS,僅供內網使用。所有 issuer / endpoint 都是 `http://192.168.42.127`
|
||||
- **Proxmox 非特權 LXC**:必須用 `crun`(不是 `runc`),原因是 `/proc/sys` 唯讀
|
||||
- **STUN port 是 `3479/udp`**(非標準),因為 `3478` 被同主機的 Headscale 佔用
|
||||
- **內建 IdP**:使用 NetBird Server 內建 Dex,不接外部 OIDC
|
||||
- **Dashboard 是 Next.js SSG**:`/nb-auth` 與 `/nb-silent-auth` 路徑在新版 image 不存在,Caddy 用 rewrite 把這兩個 path 改寫到 `/` 讓 client router 接手;`config.yaml` 的 `dashboardRedirectURIs` 仍保留完整 URI(OIDC 嚴格比對)
|
||||
|
||||
## 文件之間的關係(big picture)
|
||||
|
||||
文件**不是平行**的,有明確分層:
|
||||
|
||||
```
|
||||
README.md / QUICKSTART.md ← 入口、抄走能跑
|
||||
SUMMARY.md ← 部署決策與疑難排解總表
|
||||
netbird-selfhosted-setup.md ← 完整原理說明(QUICKSTART 的詳解版)
|
||||
|
||||
# 主題拆檔(在 README 表格中編目):
|
||||
npm-grpc-fix.md ← NPM 對外時的 gRPC 修復
|
||||
setup-keys-and-pat.md ← Setup Key / PAT;setup_keys.name 改 store.db 的繞道
|
||||
stun-port-conflict.md ← STUN 3478 → 3479 的原因
|
||||
client-troubleshooting.md ← Force Relay / bufferbloat
|
||||
peer-deployment-ops.md ← LXC Docker 部署 client、Tailscale iptables 衝突、daemon 重啟
|
||||
groups-and-policies.md ← Groups + Access Control Policies
|
||||
network-routes.md ← Subnet Router (home-lan) + Exit Nodes (exit-ct100, exit-virmach-lax)
|
||||
ssh-access.md ← 一般 SSH vs NetBird 內建 SSH 的混淆
|
||||
```
|
||||
|
||||
新增主題時:建獨立檔,更新 `README.md` 的表格與 `SUMMARY.md` 的疑難排解列。**不要**把細節塞回 README/SUMMARY。
|
||||
|
||||
## 寫作慣例(閱讀現有文件可見的模式)
|
||||
|
||||
- **語言**:繁體中文,台灣用語;技術名詞、CLI 指令、路徑、欄位名保留英文
|
||||
- **症狀 / 根因 / 解法**:疑難排解段固定走這三段;引言塊放實際 log 文字而不是改寫
|
||||
- **API 範例**:用 `curl` + `jq`,token 一律寫成 `TOKEN=<你的 PAT>` 變數,目標寫成 `https://netbird.timmy.us.kg/api/...`(從外部對外的網址,不是 `192.168.42.127`)
|
||||
- **本部署實例**:以「本部署的實例(YYYY-MM-DD)」段落記錄真實事件,便於日後回溯
|
||||
- **配置檔片段**:用 `cat > /opt/netbird/<file> << 'EOF'` 包起來,讓讀者能直接抄
|
||||
- **跨檔交叉引用**:用 markdown link 指到同目錄的 `.md`(例:`見 [npm-grpc-fix.md](./npm-grpc-fix.md)`)
|
||||
|
||||
## 既有的角色 / 命名(出現在多份文件,新文件要對齊)
|
||||
|
||||
- **Peers**:`mbp-13-pro`、`iphone-15-pro`、`CT100`(jump box / routing peer)、`CT101`、`CT124`、`virmach-lax`
|
||||
- **Groups**:`servers`(CT100、CT101)、`personal`(mbp、iphone)、預設 `All`(保留但 Default policy 已停用)
|
||||
- **Routes**:`home-lan`(CIDR `192.168.42.0/24`,via CT100)、`exit-ct100`、`exit-virmach-lax`(兩條 `0.0.0.0/0`)
|
||||
- **Tailscale 衝突**:CT100 是 userspace,CT124 是 kernel-mode(會踩 `iptables-legacy ts-input` 把 `100.64.0.0/10` drop 的雷)
|
||||
|
||||
## 提交訊息風格
|
||||
|
||||
`git log` 顯示偏好:`docs: <主題> — <一行原因/重點>`,必要時帶具體 case ID 或受影響的 peer 名稱(例:`docs: NetBird management DNS flap leaves daemon stuck (CT124 case)`)。
|
||||
@@ -23,6 +23,7 @@
|
||||
| [groups-and-policies.md](./groups-and-policies.md) | Groups 與 Access Control Policies 概念、設計、API 操作 |
|
||||
| [network-routes.md](./network-routes.md) | Subnet Router(`home-lan`)與 Exit Nodes(`exit-ct100`、`exit-virmach-lax`) |
|
||||
| [ssh-access.md](./ssh-access.md) | 一般 SSH vs NetBird 內建 SSH — 常見混淆點釐清 |
|
||||
| [caddy-netbird-diagram.html](./caddy-netbird-diagram.html) | Caddy 反向代理架構的視覺化示意圖(瀏覽器開啟) |
|
||||
| [SUMMARY.md](./SUMMARY.md) | 部署摘要與疑難排解記錄 |
|
||||
|
||||
## 快速開始
|
||||
@@ -37,6 +38,10 @@ netbird up --management-url http://192.168.42.127
|
||||
|
||||
## 架構
|
||||
|
||||

|
||||
|
||||
> 互動 / 動畫版:[caddy-netbird-diagram.html](./caddy-netbird-diagram.html)(用瀏覽器開)
|
||||
|
||||
```
|
||||
┌───────────────────────┐
|
||||
│ 192.168.42.127 │
|
||||
|
||||
331
caddy-netbird-diagram.html
Normal file
331
caddy-netbird-diagram.html
Normal file
@@ -0,0 +1,331 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-Hant">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Caddy 反向代理架構</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@500;700&family=Space+Grotesk:wght@500;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0f1419;
|
||||
--bg-2: #1a2129;
|
||||
--border: #2d3942;
|
||||
--text: #e6edf3;
|
||||
--text-muted: #8b98a5;
|
||||
--caddy: #1dd1a1;
|
||||
--yellow: #ffd166;
|
||||
--cyan: #5ec9d6;
|
||||
--purple: #a29bfe;
|
||||
--pink: #ff6b9d;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
background: radial-gradient(ellipse at top, #1a2129 0%, #0f1419 60%);
|
||||
color: var(--text);
|
||||
padding: 20px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.container { max-width: 1100px; margin: 0 auto; }
|
||||
|
||||
h1 {
|
||||
font-size: clamp(1.4rem, 4vw, 2rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.sub {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.sub .ip { color: var(--cyan); }
|
||||
|
||||
.diagram-wrap {
|
||||
background: var(--bg-2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.diagram-wrap::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image:
|
||||
linear-gradient(rgba(94,201,214,0.04) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(94,201,214,0.04) 1px, transparent 1px);
|
||||
background-size: 24px 24px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
svg { display: block; width: 100%; height: auto; position: relative; z-index: 1; }
|
||||
|
||||
.legend {
|
||||
display: flex;
|
||||
gap: 18px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 16px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px dashed var(--border);
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 0.78rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.legend-item { display: flex; align-items: center; gap: 6px; }
|
||||
.legend-dot { width: 10px; height: 10px; border-radius: 50%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Caddy 反向代理架構</h1>
|
||||
<div class="sub">host: <span class="ip">192.168.42.127</span></div>
|
||||
|
||||
<div class="diagram-wrap">
|
||||
<svg viewBox="0 0 1020 620" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<marker id="ar-y" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ffd166"/>
|
||||
</marker>
|
||||
<marker id="ar-c" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#5ec9d6"/>
|
||||
</marker>
|
||||
<marker id="ar-p" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#a29bfe"/>
|
||||
</marker>
|
||||
<marker id="ar-pk" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ff6b9d"/>
|
||||
</marker>
|
||||
|
||||
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2.5" result="blur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
|
||||
<linearGradient id="caddy-grad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#1dd1a1" stop-opacity="0.22"/>
|
||||
<stop offset="100%" stop-color="#1dd1a1" stop-opacity="0.06"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="host-grad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#2d3942"/>
|
||||
<stop offset="100%" stop-color="#1e2730"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="nb-title-grad" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#5ec9d6" stop-opacity="0.12"/>
|
||||
<stop offset="100%" stop-color="#5ec9d6" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- ===== Left port labels (with padding) ===== -->
|
||||
<g font-family="JetBrains Mono, monospace">
|
||||
<rect x="20" y="174" width="48" height="26" rx="5"
|
||||
fill="#0f1419" stroke="#ffd166" stroke-width="1.4"/>
|
||||
<text x="44" y="192" text-anchor="middle" font-size="12" font-weight="700" fill="#ffd166">:80</text>
|
||||
|
||||
<rect x="10" y="475" width="80" height="26" rx="5"
|
||||
fill="#0f1419" stroke="#ff6b9d" stroke-width="1.4"/>
|
||||
<text x="50" y="493" text-anchor="middle" font-size="11" font-weight="700" fill="#ff6b9d">:3478/udp</text>
|
||||
</g>
|
||||
|
||||
<!-- ===== HOST boundary ===== -->
|
||||
<rect x="110" y="60" width="560" height="520" rx="14"
|
||||
fill="url(#host-grad)" stroke="#3a4a58" stroke-width="1.5" stroke-dasharray="6 4"/>
|
||||
<text x="130" y="88" font-family="JetBrains Mono, monospace" font-size="13"
|
||||
fill="#5ec9d6" font-weight="700">host · 192.168.42.127</text>
|
||||
|
||||
<!-- ===== Caddy box ===== -->
|
||||
<g>
|
||||
<rect x="140" y="125" width="330" height="285" rx="10"
|
||||
fill="url(#caddy-grad)" stroke="#1dd1a1" stroke-width="1.8"/>
|
||||
<text x="160" y="153" font-family="Space Grotesk" font-size="15" font-weight="700" fill="#1dd1a1">Caddy</text>
|
||||
<text x="213" y="153" font-family="Space Grotesk" font-size="13" font-weight="500" fill="#8b98a5">反向代理</text>
|
||||
|
||||
<circle cx="285" cy="148" r="5" fill="#1dd1a1" opacity="0.8">
|
||||
<animate attributeName="r" values="5;11;5" dur="2s" repeatCount="indefinite"/>
|
||||
<animate attributeName="opacity" values="0.8;0;0.8" dur="2s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="285" cy="148" r="3.5" fill="#1dd1a1"/>
|
||||
|
||||
<g font-family="JetBrains Mono, monospace" font-size="12.5">
|
||||
<!-- / at y=186 (→ dashboard) -->
|
||||
<g>
|
||||
<rect x="160" y="170" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="191" fill="#ffd166" font-weight="700">/</text>
|
||||
<text x="438" y="191" text-anchor="end" fill="#8b98a5">→ dashboard</text>
|
||||
</g>
|
||||
|
||||
<!-- Dashed divider between dashboard routes and netbird routes -->
|
||||
<line x1="170" y1="222" x2="440" y2="222" stroke="#2d3942" stroke-width="1" stroke-dasharray="3 4"/>
|
||||
|
||||
<!-- /api/* at y=265 -->
|
||||
<g>
|
||||
<rect x="160" y="249" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="270" fill="#ffd166" font-weight="700">/api/*</text>
|
||||
<text x="438" y="270" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
<!-- /oauth2/* at y=303 -->
|
||||
<g>
|
||||
<rect x="160" y="287" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="308" fill="#ffd166" font-weight="700">/oauth2/*</text>
|
||||
<text x="438" y="308" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
<!-- /relay* at y=341 -->
|
||||
<g>
|
||||
<rect x="160" y="325" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="346" fill="#ffd166" font-weight="700">/relay*</text>
|
||||
<text x="438" y="346" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
<!-- gRPC at y=379 -->
|
||||
<g>
|
||||
<rect x="160" y="363" width="290" height="32" rx="6" fill="#0f1419" stroke="#a29bfe"/>
|
||||
<text x="176" y="384" fill="#a29bfe" font-weight="700">gRPC</text>
|
||||
<text x="438" y="384" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- ===== dashboard target ===== -->
|
||||
<g>
|
||||
<rect x="720" y="156" width="280" height="60" rx="10"
|
||||
fill="#1e2730" stroke="#ffd166" stroke-width="1.6"/>
|
||||
<!-- window icon -->
|
||||
<g transform="translate(740, 170)">
|
||||
<rect x="0" y="0" width="32" height="26" rx="3" fill="none" stroke="#ffd166" stroke-width="1.4"/>
|
||||
<line x1="0" y1="7" x2="32" y2="7" stroke="#ffd166" stroke-width="1.2"/>
|
||||
<circle cx="4" cy="3.5" r="1" fill="#ffd166"/>
|
||||
<circle cx="8" cy="3.5" r="1" fill="#ffd166"/>
|
||||
<circle cx="12" cy="3.5" r="1" fill="#ffd166"/>
|
||||
</g>
|
||||
<text x="790" y="182" font-family="Space Grotesk" font-size="14" font-weight="700" fill="#e6edf3">dashboard</text>
|
||||
<text x="790" y="202" font-family="JetBrains Mono, monospace" font-size="11" fill="#8b98a5">Web UI</text>
|
||||
</g>
|
||||
|
||||
<!-- ===== netbird-server target ===== -->
|
||||
<g>
|
||||
<!-- Outer box -->
|
||||
<rect x="720" y="222" width="280" height="248" rx="10"
|
||||
fill="#1e2730" stroke="#5ec9d6" stroke-width="1.6"/>
|
||||
|
||||
<!-- Title band at top (clearly separated from entries) -->
|
||||
<rect x="720" y="222" width="280" height="30" rx="10"
|
||||
fill="url(#nb-title-grad)"/>
|
||||
<!-- mask bottom corners of title bg so only top rounded -->
|
||||
<rect x="720" y="240" width="280" height="12" fill="url(#nb-title-grad)"/>
|
||||
|
||||
<!-- Server stack icon (small, inside title band) -->
|
||||
<g transform="translate(734, 230)" stroke="#5ec9d6" stroke-width="1.3" fill="none">
|
||||
<rect x="0" y="0" width="22" height="5" rx="1"/>
|
||||
<rect x="0" y="7" width="22" height="5" rx="1"/>
|
||||
<rect x="0" y="14" width="22" height="5" rx="1"/>
|
||||
<circle cx="3" cy="2.5" r="0.7" fill="#5ec9d6" stroke="none"/>
|
||||
<circle cx="3" cy="9.5" r="0.7" fill="#5ec9d6" stroke="none"/>
|
||||
<circle cx="3" cy="16.5" r="0.7" fill="#5ec9d6" stroke="none"/>
|
||||
</g>
|
||||
<text x="765" y="242" font-family="Space Grotesk" font-size="14" font-weight="700" fill="#e6edf3">netbird-server</text>
|
||||
|
||||
<!-- Divider under title -->
|
||||
<line x1="730" y1="254" x2="990" y2="254" stroke="#2d3942" stroke-width="1"/>
|
||||
|
||||
<!-- Entries (well below title, aligned with Caddy row centers) -->
|
||||
<g font-family="JetBrains Mono, monospace" font-size="11.5">
|
||||
<!-- HTTP API at y=265 -->
|
||||
<circle cx="730" cy="265" r="3" fill="#5ec9d6"/>
|
||||
<text x="742" y="269" fill="#8b98a5">HTTP API</text>
|
||||
|
||||
<!-- OAuth2 at y=303 -->
|
||||
<circle cx="730" cy="303" r="3" fill="#5ec9d6"/>
|
||||
<text x="742" y="307" fill="#8b98a5">OAuth2</text>
|
||||
|
||||
<!-- Relay at y=341 -->
|
||||
<circle cx="730" cy="341" r="3" fill="#5ec9d6"/>
|
||||
<text x="742" y="345" fill="#8b98a5">Relay</text>
|
||||
|
||||
<!-- gRPC at y=379 -->
|
||||
<circle cx="730" cy="379" r="3" fill="#a29bfe"/>
|
||||
<text x="742" y="383" fill="#8b98a5">gRPC</text>
|
||||
|
||||
<!-- STUN at y=440 -->
|
||||
<circle cx="730" cy="440" r="3" fill="#ff6b9d"/>
|
||||
<text x="742" y="444" fill="#ff6b9d" font-weight="700">STUN (:3478/udp)</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<!-- ===== Paths (all orthogonal) ===== -->
|
||||
<!-- :80 → Caddy -->
|
||||
<path id="p-in" d="M 68 187 L 140 187"
|
||||
stroke="#ffd166" stroke-width="2" fill="none" marker-end="url(#ar-y)"/>
|
||||
|
||||
<!-- / → dashboard (straight horizontal) -->
|
||||
<path id="p-dash" d="M 470 186 L 720 186"
|
||||
stroke="#ffd166" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-y)"/>
|
||||
|
||||
<!-- /api/* → HTTP API (straight) -->
|
||||
<path id="p-api" d="M 470 265 L 720 265"
|
||||
stroke="#5ec9d6" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-c)"/>
|
||||
|
||||
<!-- /oauth2/* → OAuth2 (straight) -->
|
||||
<path id="p-oauth" d="M 470 303 L 720 303"
|
||||
stroke="#5ec9d6" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-c)"/>
|
||||
|
||||
<!-- /relay* → Relay (straight) -->
|
||||
<path id="p-relay" d="M 470 341 L 720 341"
|
||||
stroke="#5ec9d6" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-c)"/>
|
||||
|
||||
<!-- gRPC → gRPC (straight) -->
|
||||
<path id="p-grpc" d="M 470 379 L 720 379"
|
||||
stroke="#a29bfe" stroke-width="1.8" fill="none" stroke-opacity="0.65" marker-end="url(#ar-p)"/>
|
||||
|
||||
<!-- :3478/udp → netbird STUN (L-shape) -->
|
||||
<path id="p-stun" d="M 90 488 L 690 488 L 690 440 L 720 440"
|
||||
stroke="#ff6b9d" stroke-width="2" fill="none" stroke-dasharray="6 4" marker-end="url(#ar-pk)"/>
|
||||
|
||||
<text x="360" y="512" font-family="JetBrains Mono, monospace" font-size="11"
|
||||
fill="#ff6b9d" font-weight="700">STUN · 直送,不經 Caddy</text>
|
||||
|
||||
<!-- ===== Flow dots ===== -->
|
||||
<circle r="4" fill="#ffd166" filter="url(#glow)">
|
||||
<animateMotion dur="1.4s" repeatCount="indefinite"><mpath href="#p-in"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#ffd166" filter="url(#glow)">
|
||||
<animateMotion dur="1.4s" begin="-0.7s" repeatCount="indefinite"><mpath href="#p-in"/></animateMotion>
|
||||
</circle>
|
||||
|
||||
<circle r="4" fill="#ffd166" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" repeatCount="indefinite"><mpath href="#p-dash"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#5ec9d6" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-0.3s" repeatCount="indefinite"><mpath href="#p-api"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#5ec9d6" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-0.6s" repeatCount="indefinite"><mpath href="#p-oauth"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#5ec9d6" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-0.9s" repeatCount="indefinite"><mpath href="#p-relay"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#a29bfe" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-1.2s" repeatCount="indefinite"><mpath href="#p-grpc"/></animateMotion>
|
||||
</circle>
|
||||
|
||||
<circle r="4" fill="#ff6b9d" filter="url(#glow)">
|
||||
<animateMotion dur="2.4s" repeatCount="indefinite"><mpath href="#p-stun"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#ff6b9d" filter="url(#glow)">
|
||||
<animateMotion dur="2.4s" begin="-1.2s" repeatCount="indefinite"><mpath href="#p-stun"/></animateMotion>
|
||||
</circle>
|
||||
</svg>
|
||||
|
||||
<div class="legend">
|
||||
<div class="legend-item"><span class="legend-dot" style="background:#ffd166"></span>HTTP (/) → dashboard</div>
|
||||
<div class="legend-item"><span class="legend-dot" style="background:#5ec9d6"></span>HTTP (/api, /oauth2, /relay) → netbird-server</div>
|
||||
<div class="legend-item"><span class="legend-dot" style="background:#a29bfe"></span>gRPC → netbird-server</div>
|
||||
<div class="legend-item"><span class="legend-dot" style="background:#ff6b9d"></span>UDP :3478 STUN(直送)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
208
caddy-netbird-diagram.svg
Normal file
208
caddy-netbird-diagram.svg
Normal file
@@ -0,0 +1,208 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1060 810" font-family="'Space Grotesk', 'Segoe UI', system-ui, sans-serif">
|
||||
<defs>
|
||||
<marker id="ar-y" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ffd166"/>
|
||||
</marker>
|
||||
<marker id="ar-c" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#5ec9d6"/>
|
||||
</marker>
|
||||
<marker id="ar-p" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#a29bfe"/>
|
||||
</marker>
|
||||
<marker id="ar-pk" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ff6b9d"/>
|
||||
</marker>
|
||||
|
||||
<linearGradient id="caddy-grad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#1dd1a1" stop-opacity="0.22"/>
|
||||
<stop offset="100%" stop-color="#1dd1a1" stop-opacity="0.06"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="host-grad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#2d3942"/>
|
||||
<stop offset="100%" stop-color="#1e2730"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="nb-title-grad" x1="0" y1="0" x2="1" y2="0">
|
||||
<stop offset="0%" stop-color="#5ec9d6" stop-opacity="0.12"/>
|
||||
<stop offset="100%" stop-color="#5ec9d6" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
|
||||
<pattern id="grid" width="24" height="24" patternUnits="userSpaceOnUse">
|
||||
<path d="M 24 0 L 0 0 0 24" fill="none" stroke="#5ec9d6" stroke-opacity="0.06" stroke-width="1"/>
|
||||
</pattern>
|
||||
|
||||
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2.5" result="blur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<rect width="1060" height="810" fill="#0f1419"/>
|
||||
|
||||
<text x="20" y="36" font-size="26" font-weight="700" fill="#e6edf3">Caddy 反向代理架構</text>
|
||||
<text x="20" y="60" font-family="'JetBrains Mono', 'Consolas', monospace" font-size="12" fill="#8b98a5">host: <tspan fill="#5ec9d6">192.168.42.127</tspan></text>
|
||||
|
||||
<rect x="10" y="80" width="1040" height="660" rx="16" fill="#1a2129" stroke="#2d3942" stroke-width="1"/>
|
||||
<rect x="10" y="80" width="1040" height="660" rx="16" fill="url(#grid)"/>
|
||||
|
||||
<g transform="translate(10, 100)">
|
||||
<g font-family="'JetBrains Mono', 'Consolas', monospace">
|
||||
<rect x="20" y="174" width="48" height="26" rx="5" fill="#0f1419" stroke="#ffd166" stroke-width="1.4"/>
|
||||
<text x="44" y="192" text-anchor="middle" font-size="12" font-weight="700" fill="#ffd166">:80</text>
|
||||
|
||||
<rect x="10" y="475" width="80" height="26" rx="5" fill="#0f1419" stroke="#ff6b9d" stroke-width="1.4"/>
|
||||
<text x="50" y="493" text-anchor="middle" font-size="11" font-weight="700" fill="#ff6b9d">:3478/udp</text>
|
||||
</g>
|
||||
|
||||
<rect x="110" y="60" width="560" height="520" rx="14" fill="url(#host-grad)" stroke="#3a4a58" stroke-width="1.5" stroke-dasharray="6 4"/>
|
||||
<text x="130" y="88" font-family="'JetBrains Mono', 'Consolas', monospace" font-size="13" fill="#5ec9d6" font-weight="700">host · 192.168.42.127</text>
|
||||
|
||||
<g>
|
||||
<rect x="140" y="125" width="330" height="285" rx="10" fill="url(#caddy-grad)" stroke="#1dd1a1" stroke-width="1.8"/>
|
||||
<text x="160" y="153" font-size="15" font-weight="700" fill="#1dd1a1">Caddy</text>
|
||||
<text x="213" y="153" font-size="13" font-weight="500" fill="#8b98a5">反向代理</text>
|
||||
|
||||
<circle cx="285" cy="148" r="5" fill="#1dd1a1" opacity="0.8">
|
||||
<animate attributeName="r" values="5;11;5" dur="2s" repeatCount="indefinite"/>
|
||||
<animate attributeName="opacity" values="0.8;0;0.8" dur="2s" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="285" cy="148" r="3.5" fill="#1dd1a1"/>
|
||||
|
||||
<g font-family="'JetBrains Mono', 'Consolas', monospace" font-size="12.5">
|
||||
<g>
|
||||
<rect x="160" y="170" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="191" fill="#ffd166" font-weight="700">/</text>
|
||||
<text x="438" y="191" text-anchor="end" fill="#8b98a5">→ dashboard</text>
|
||||
</g>
|
||||
|
||||
<line x1="170" y1="222" x2="440" y2="222" stroke="#2d3942" stroke-width="1" stroke-dasharray="3 4"/>
|
||||
|
||||
<g>
|
||||
<rect x="160" y="249" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="270" fill="#ffd166" font-weight="700">/api/*</text>
|
||||
<text x="438" y="270" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="160" y="287" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="308" fill="#ffd166" font-weight="700">/oauth2/*</text>
|
||||
<text x="438" y="308" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="160" y="325" width="290" height="32" rx="6" fill="#0f1419" stroke="#2d3942"/>
|
||||
<text x="176" y="346" fill="#ffd166" font-weight="700">/relay*</text>
|
||||
<text x="438" y="346" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="160" y="363" width="290" height="32" rx="6" fill="#0f1419" stroke="#a29bfe"/>
|
||||
<text x="176" y="384" fill="#a29bfe" font-weight="700">gRPC</text>
|
||||
<text x="438" y="384" text-anchor="end" fill="#8b98a5">→ netbird-server</text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<g>
|
||||
<rect x="720" y="156" width="280" height="60" rx="10" fill="#1e2730" stroke="#ffd166" stroke-width="1.6"/>
|
||||
<g transform="translate(740, 170)">
|
||||
<rect x="0" y="0" width="32" height="26" rx="3" fill="none" stroke="#ffd166" stroke-width="1.4"/>
|
||||
<line x1="0" y1="7" x2="32" y2="7" stroke="#ffd166" stroke-width="1.2"/>
|
||||
<circle cx="4" cy="3.5" r="1" fill="#ffd166"/>
|
||||
<circle cx="8" cy="3.5" r="1" fill="#ffd166"/>
|
||||
<circle cx="12" cy="3.5" r="1" fill="#ffd166"/>
|
||||
</g>
|
||||
<text x="790" y="182" font-size="14" font-weight="700" fill="#e6edf3">dashboard</text>
|
||||
<text x="790" y="202" font-family="'JetBrains Mono', 'Consolas', monospace" font-size="11" fill="#8b98a5">Web UI</text>
|
||||
</g>
|
||||
|
||||
<g>
|
||||
<rect x="720" y="222" width="280" height="248" rx="10" fill="#1e2730" stroke="#5ec9d6" stroke-width="1.6"/>
|
||||
<rect x="720" y="222" width="280" height="30" rx="10" fill="url(#nb-title-grad)"/>
|
||||
<rect x="720" y="240" width="280" height="12" fill="url(#nb-title-grad)"/>
|
||||
|
||||
<g transform="translate(734, 230)" stroke="#5ec9d6" stroke-width="1.3" fill="none">
|
||||
<rect x="0" y="0" width="22" height="5" rx="1"/>
|
||||
<rect x="0" y="7" width="22" height="5" rx="1"/>
|
||||
<rect x="0" y="14" width="22" height="5" rx="1"/>
|
||||
<circle cx="3" cy="2.5" r="0.7" fill="#5ec9d6" stroke="none"/>
|
||||
<circle cx="3" cy="9.5" r="0.7" fill="#5ec9d6" stroke="none"/>
|
||||
<circle cx="3" cy="16.5" r="0.7" fill="#5ec9d6" stroke="none"/>
|
||||
</g>
|
||||
<text x="765" y="242" font-size="14" font-weight="700" fill="#e6edf3">netbird-server</text>
|
||||
|
||||
<line x1="730" y1="254" x2="990" y2="254" stroke="#2d3942" stroke-width="1"/>
|
||||
|
||||
<g font-family="'JetBrains Mono', 'Consolas', monospace" font-size="11.5">
|
||||
<circle cx="730" cy="265" r="3" fill="#5ec9d6"/>
|
||||
<text x="742" y="269" fill="#8b98a5">HTTP API</text>
|
||||
|
||||
<circle cx="730" cy="303" r="3" fill="#5ec9d6"/>
|
||||
<text x="742" y="307" fill="#8b98a5">OAuth2</text>
|
||||
|
||||
<circle cx="730" cy="341" r="3" fill="#5ec9d6"/>
|
||||
<text x="742" y="345" fill="#8b98a5">Relay</text>
|
||||
|
||||
<circle cx="730" cy="379" r="3" fill="#a29bfe"/>
|
||||
<text x="742" y="383" fill="#8b98a5">gRPC</text>
|
||||
|
||||
<circle cx="730" cy="440" r="3" fill="#ff6b9d"/>
|
||||
<text x="742" y="444" fill="#ff6b9d" font-weight="700">STUN (:3478/udp)</text>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
<path id="p-in" d="M 68 187 L 140 187" stroke="#ffd166" stroke-width="2" fill="none" marker-end="url(#ar-y)"/>
|
||||
<path id="p-dash" d="M 470 186 L 720 186" stroke="#ffd166" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-y)"/>
|
||||
<path id="p-api" d="M 470 265 L 720 265" stroke="#5ec9d6" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-c)"/>
|
||||
<path id="p-oauth" d="M 470 303 L 720 303" stroke="#5ec9d6" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-c)"/>
|
||||
<path id="p-relay" d="M 470 341 L 720 341" stroke="#5ec9d6" stroke-width="1.8" fill="none" stroke-opacity="0.55" marker-end="url(#ar-c)"/>
|
||||
<path id="p-grpc" d="M 470 379 L 720 379" stroke="#a29bfe" stroke-width="1.8" fill="none" stroke-opacity="0.65" marker-end="url(#ar-p)"/>
|
||||
<path id="p-stun" d="M 90 488 L 690 488 L 690 440 L 720 440" stroke="#ff6b9d" stroke-width="2" fill="none" stroke-dasharray="6 4" marker-end="url(#ar-pk)"/>
|
||||
|
||||
<text x="360" y="512" font-family="'JetBrains Mono', 'Consolas', monospace" font-size="11" fill="#ff6b9d" font-weight="700">STUN · 直送,不經 Caddy</text>
|
||||
|
||||
<circle r="4" fill="#ffd166" filter="url(#glow)">
|
||||
<animateMotion dur="1.4s" repeatCount="indefinite"><mpath href="#p-in"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#ffd166" filter="url(#glow)">
|
||||
<animateMotion dur="1.4s" begin="-0.7s" repeatCount="indefinite"><mpath href="#p-in"/></animateMotion>
|
||||
</circle>
|
||||
|
||||
<circle r="4" fill="#ffd166" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" repeatCount="indefinite"><mpath href="#p-dash"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#5ec9d6" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-0.3s" repeatCount="indefinite"><mpath href="#p-api"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#5ec9d6" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-0.6s" repeatCount="indefinite"><mpath href="#p-oauth"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#5ec9d6" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-0.9s" repeatCount="indefinite"><mpath href="#p-relay"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#a29bfe" filter="url(#glow)">
|
||||
<animateMotion dur="1.8s" begin="-1.2s" repeatCount="indefinite"><mpath href="#p-grpc"/></animateMotion>
|
||||
</circle>
|
||||
|
||||
<circle r="4" fill="#ff6b9d" filter="url(#glow)">
|
||||
<animateMotion dur="2.4s" repeatCount="indefinite"><mpath href="#p-stun"/></animateMotion>
|
||||
</circle>
|
||||
<circle r="4" fill="#ff6b9d" filter="url(#glow)">
|
||||
<animateMotion dur="2.4s" begin="-1.2s" repeatCount="indefinite"><mpath href="#p-stun"/></animateMotion>
|
||||
</circle>
|
||||
</g>
|
||||
|
||||
<g font-family="'JetBrains Mono', 'Consolas', monospace" font-size="11" fill="#8b98a5">
|
||||
<circle cx="35" cy="775" r="5" fill="#ffd166"/>
|
||||
<text x="46" y="779">HTTP (/) → dashboard</text>
|
||||
|
||||
<circle cx="230" cy="775" r="5" fill="#5ec9d6"/>
|
||||
<text x="241" y="779">HTTP (/api, /oauth2, /relay) → netbird-server</text>
|
||||
|
||||
<circle cx="620" cy="775" r="5" fill="#a29bfe"/>
|
||||
<text x="631" y="779">gRPC → netbird-server</text>
|
||||
|
||||
<circle cx="820" cy="775" r="5" fill="#ff6b9d"/>
|
||||
<text x="831" y="779">UDP :3478 STUN(直送)</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
Reference in New Issue
Block a user