docs: Add Headscale setup guide and Custom Client documentation
- HEADSCALE_SETUP.md: Docker install, config, nginx reverse proxy, API reference - CUSTOM_CLIENT.md: All 25 modified files explained, build instructions (Win+Linux), MSI installer guide, tray app architecture, deployment guide
This commit is contained in:
@@ -0,0 +1,384 @@
|
|||||||
|
# Hướng dẫn Custom Tailscale Client
|
||||||
|
|
||||||
|
## Mục lục
|
||||||
|
1. [Tổng quan](#tổng-quan)
|
||||||
|
2. [Danh sách files đã thay đổi](#danh-sách-files-đã-thay-đổi)
|
||||||
|
3. [Chi tiết từng thay đổi](#chi-tiết-từng-thay-đổi)
|
||||||
|
4. [Build Windows Client](#build-windows-client)
|
||||||
|
5. [Build Linux Client](#build-linux-client)
|
||||||
|
6. [Tạo MSI Installer (Windows)](#tạo-msi-installer-windows)
|
||||||
|
7. [Tray App (Windows)](#tray-app-windows)
|
||||||
|
8. [Cách deploy lên máy mới](#cách-deploy-lên-máy-mới)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tổng quan
|
||||||
|
|
||||||
|
Custom Tailscale Client là bản fork từ Tailscale v1.97.0, được tuỳ chỉnh để:
|
||||||
|
- **Chạy song song** với Tailscale chính thức trên cùng 1 máy
|
||||||
|
- **Kết nối Headscale** tại `https://vpn.softs.business` (default)
|
||||||
|
- **Không xung đột** service name, named pipe, registry, TUN adapter, thư mục dữ liệu
|
||||||
|
|
||||||
|
### Namespace isolation (tránh xung đột)
|
||||||
|
|
||||||
|
| Thành phần | Tailscale gốc | Tailscale-Custom |
|
||||||
|
|------------|---------------|------------------|
|
||||||
|
| Service name | `Tailscale` | `Tailscale-Custom` |
|
||||||
|
| Named pipe | `Tailscale\tailscaled` | `Tailscale-Custom\tailscaled` |
|
||||||
|
| Registry | `SOFTWARE\Tailscale IPN` | `SOFTWARE\Tailscale-Custom IPN` |
|
||||||
|
| Policy registry | `Policies\Tailscale` | `Policies\Tailscale-Custom` |
|
||||||
|
| ProgramData | `C:\ProgramData\Tailscale` | `C:\ProgramData\Tailscale-Custom` |
|
||||||
|
| LocalAppData | `...\Tailscale` | `...\Tailscale-Custom` |
|
||||||
|
| TUN adapter | `Tailscale` | `Tailscale-Custom` |
|
||||||
|
| TUN GUID | `{37217669-...}` | `{47317669-...}` |
|
||||||
|
| Control URL | `https://controlplane.tailscale.com` | `https://vpn.softs.business` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Danh sách files đã thay đổi
|
||||||
|
|
||||||
|
### Nhóm 1: Đổi tên service / đường dẫn (Coexistence)
|
||||||
|
|
||||||
|
| File | Thay đổi |
|
||||||
|
|------|----------|
|
||||||
|
| `cmd/tailscaled/tailscaled_windows.go` | `serviceName = "Tailscale-Custom"` |
|
||||||
|
| `cmd/tailscaled/tailscaled.go` | `defaultTunName() = "Tailscale-Custom"` |
|
||||||
|
| `paths/paths.go` | Named pipe path, state file path |
|
||||||
|
| `paths/paths_windows.go` | ACL directory check |
|
||||||
|
| `util/winutil/winutil_windows.go` | Registry keys |
|
||||||
|
| `util/syspolicy/source/policy_store_windows.go` | Policy registry paths |
|
||||||
|
| `net/tstun/tun_windows.go` | WintunTunnelType + GUID |
|
||||||
|
| `logpolicy/logpolicy.go` | Log directories |
|
||||||
|
| `log/filelogger/log.go` | Log file path |
|
||||||
|
| `clientupdate/clientupdate_windows.go` | Update cache path |
|
||||||
|
| `envknob/envknob.go` | Env file path |
|
||||||
|
| `ipn/auditlog/store.go` | Audit log path |
|
||||||
|
|
||||||
|
### Nhóm 2: Đổi Control URL
|
||||||
|
|
||||||
|
| File | Thay đổi |
|
||||||
|
|------|----------|
|
||||||
|
| `ipn/prefs.go` | `DefaultControlURL = "https://vpn.softs.business"` |
|
||||||
|
| `ipn/conf.go` | Default URL trong comment |
|
||||||
|
| `control/controlclient/direct.go` | Server URL references |
|
||||||
|
| `cmd/tailscale/cli/debug.go` | Debug command default |
|
||||||
|
| `cmd/tailscaled/debug.go` | Debug URL |
|
||||||
|
| `net/netmon/state.go` | Login endpoint |
|
||||||
|
| `net/captivedetection/endpoints.go` | Captive portal check |
|
||||||
|
| `util/winutil/policy/policy_windows.go` | Policy default URL |
|
||||||
|
| `util/syspolicy/syspolicy.go` | System policy default |
|
||||||
|
|
||||||
|
### Nhóm 3: Thêm mới
|
||||||
|
|
||||||
|
| File | Mô tả |
|
||||||
|
|------|-------|
|
||||||
|
| `cmd/tailscale-tray/main.go` | Windows system tray app |
|
||||||
|
| `cmd/tailscale-tray/icon.go` | Icon generation |
|
||||||
|
| `installer/TailscaleCustom.wxs` | WiX v5 MSI installer |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Chi tiết từng thay đổi
|
||||||
|
|
||||||
|
### 1. `ipn/prefs.go` - Control URL mặc định
|
||||||
|
```go
|
||||||
|
// TRƯỚC:
|
||||||
|
const DefaultControlURL = "https://controlplane.tailscale.com"
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
const DefaultControlURL = "https://vpn.softs.business"
|
||||||
|
```
|
||||||
|
|
||||||
|
Thêm `vpn.softs.business` vào `IsLoginServerSynonym()` để Tailscale nhận diện đây là server hợp lệ.
|
||||||
|
|
||||||
|
### 2. `cmd/tailscaled/tailscaled_windows.go` - Service name
|
||||||
|
```go
|
||||||
|
// TRƯỚC:
|
||||||
|
const serviceName = "Tailscale"
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
const serviceName = "Tailscale-Custom"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. `cmd/tailscaled/tailscaled.go` - TUN device name
|
||||||
|
```go
|
||||||
|
// TRƯỚC (trong defaultTunName()):
|
||||||
|
case "windows": return "Tailscale"
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
case "windows": return "Tailscale-Custom"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. `paths/paths.go` - Named pipe & state paths
|
||||||
|
```go
|
||||||
|
// TRƯỚC:
|
||||||
|
DefaultTailscaledSocket = `\\.\pipe\ProtectedPrefix\Administrators\Tailscale\tailscaled`
|
||||||
|
stateFileInProgramData = `Tailscale\server-state.conf`
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
DefaultTailscaledSocket = `\\.\pipe\ProtectedPrefix\Administrators\Tailscale-Custom\tailscaled`
|
||||||
|
stateFileInProgramData = `Tailscale-Custom\server-state.conf`
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. `net/tstun/tun_windows.go` - TUN adapter
|
||||||
|
```go
|
||||||
|
// TRƯỚC:
|
||||||
|
tun.WintunTunnelType = "Tailscale"
|
||||||
|
guid, _ := windows.GUIDFromString("{37217669-42da-4657-a55b-0d995d328250}")
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
tun.WintunTunnelType = "Tailscale-Custom"
|
||||||
|
guid, _ := windows.GUIDFromString("{47317669-42da-4657-a55b-0d995d328250}")
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Quan trọng**: GUID phải khác để 2 TUN adapter cùng tồn tại.
|
||||||
|
|
||||||
|
### 6. `util/winutil/winutil_windows.go` - Registry
|
||||||
|
```go
|
||||||
|
// TRƯỚC:
|
||||||
|
regBase = `SOFTWARE\Tailscale IPN`
|
||||||
|
regPolicyBase = `SOFTWARE\Policies\Tailscale`
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
regBase = `SOFTWARE\Tailscale-Custom IPN`
|
||||||
|
regPolicyBase = `SOFTWARE\Policies\Tailscale-Custom`
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. `control/controlclient/direct.go` - Server validation
|
||||||
|
Cập nhật các URL reference từ `controlplane.tailscale.com` sang `vpn.softs.business`.
|
||||||
|
|
||||||
|
### 8. `logpolicy/logpolicy.go` - Log paths
|
||||||
|
```go
|
||||||
|
// TRƯỚC:
|
||||||
|
dir = filepath.Join(os.Getenv("ProgramData"), "Tailscale", "Logs")
|
||||||
|
|
||||||
|
// SAU:
|
||||||
|
dir = filepath.Join(os.Getenv("ProgramData"), "Tailscale-Custom", "Logs")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Windows Client
|
||||||
|
|
||||||
|
### Yêu cầu
|
||||||
|
- Go 1.26+ (hoặc dùng `.\tool\go.exe` trong repo)
|
||||||
|
- GCC/MinGW (cho CGO, cần cho tray app)
|
||||||
|
|
||||||
|
### Build CLI + Daemon
|
||||||
|
```powershell
|
||||||
|
cd <repo_root>
|
||||||
|
|
||||||
|
# Build tailscale.exe (CLI)
|
||||||
|
.\tool\go.exe build -o .\dist\tailscale.exe `
|
||||||
|
-ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" `
|
||||||
|
tailscale.com/cmd/tailscale
|
||||||
|
|
||||||
|
# Build tailscaled.exe (daemon/service)
|
||||||
|
.\tool\go.exe build -o .\dist\tailscaled.exe `
|
||||||
|
-ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" `
|
||||||
|
tailscale.com/cmd/tailscaled
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Tray App
|
||||||
|
```powershell
|
||||||
|
# Cần CGO_ENABLED=1 (cho systray) và -H=windowsgui (ẩn console)
|
||||||
|
$env:CGO_ENABLED="1"
|
||||||
|
.\tool\go.exe build -o .\dist\tailscale-tray.exe `
|
||||||
|
-ldflags "-H=windowsgui" `
|
||||||
|
tailscale.com/cmd/tailscale-tray
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cần thêm `wintun.dll`
|
||||||
|
Copy `wintun.dll` từ:
|
||||||
|
- https://www.wintun.net/ (tải chính thức)
|
||||||
|
- Hoặc từ `C:\Program Files\Tailscale\wintun.dll` nếu đã cài Tailscale gốc
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Copy-Item "C:\Program Files\Tailscale\wintun.dll" .\dist\
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Linux Client
|
||||||
|
|
||||||
|
### Build CLI + Daemon
|
||||||
|
```bash
|
||||||
|
cd <repo_root>
|
||||||
|
|
||||||
|
# Lấy Go toolchain
|
||||||
|
./tool/go build -o ./dist/tailscale \
|
||||||
|
-ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" \
|
||||||
|
tailscale.com/cmd/tailscale
|
||||||
|
|
||||||
|
./tool/go build -o ./dist/tailscaled \
|
||||||
|
-ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" \
|
||||||
|
tailscale.com/cmd/tailscaled
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cài đặt trên Linux
|
||||||
|
```bash
|
||||||
|
# Copy binaries
|
||||||
|
sudo cp dist/tailscale /usr/local/bin/
|
||||||
|
sudo cp dist/tailscaled /usr/local/bin/
|
||||||
|
|
||||||
|
# Tạo systemd service
|
||||||
|
sudo cat > /etc/systemd/system/tailscale-custom.service << 'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=Tailscale-Custom VPN daemon
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/local/bin/tailscaled --state=/var/lib/tailscale-custom/tailscaled.state --socket=/var/run/tailscale-custom/tailscaled.sock
|
||||||
|
Restart=on-failure
|
||||||
|
RuntimeDirectory=tailscale-custom
|
||||||
|
StateDirectory=tailscale-custom
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now tailscale-custom
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kết nối
|
||||||
|
```bash
|
||||||
|
sudo tailscale up --login-server https://vpn.softs.business --accept-dns=false \
|
||||||
|
--socket /var/run/tailscale-custom/tailscaled.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Lưu ý Linux**: Trên Linux, custom Tailscale dùng `--socket` và `--state` khác path để tránh xung đột với Tailscale gốc. Không cần đổi tên service vì Linux dùng socket file thay vì named pipe.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tạo MSI Installer (Windows)
|
||||||
|
|
||||||
|
### Yêu cầu
|
||||||
|
- .NET SDK
|
||||||
|
- WiX Toolset v5: `dotnet tool install --global wix`
|
||||||
|
- WiX Util extension: `wix extension add WixToolset.Util.wixext`
|
||||||
|
|
||||||
|
### Cấu trúc thư mục installer
|
||||||
|
```
|
||||||
|
dist/
|
||||||
|
├── tailscale.exe # CLI
|
||||||
|
├── tailscaled.exe # Daemon/service
|
||||||
|
├── tailscale-tray.exe # System tray app
|
||||||
|
└── wintun.dll # TUN driver
|
||||||
|
|
||||||
|
installer/
|
||||||
|
└── TailscaleCustom.wxs # WiX definition
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build MSI
|
||||||
|
```powershell
|
||||||
|
wix build -o .\dist\TailscaleCustom.msi `
|
||||||
|
-ext WixToolset.Util.wixext `
|
||||||
|
.\installer\TailscaleCustom.wxs
|
||||||
|
```
|
||||||
|
|
||||||
|
### MSI bao gồm:
|
||||||
|
- Cài `tailscaled.exe` làm Windows Service (auto-start)
|
||||||
|
- Cài `tailscale.exe` (CLI) và thêm vào PATH
|
||||||
|
- Cài `tailscale-tray.exe` với auto-start qua Registry
|
||||||
|
- Cài `wintun.dll` (TUN driver)
|
||||||
|
- Shortcuts trên Desktop và Start Menu
|
||||||
|
- UpgradeCode riêng: `E1F2A3B4-C5D6-4E7F-8A9B-0C1D2E3F4A5B`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tray App (Windows)
|
||||||
|
|
||||||
|
### Tính năng
|
||||||
|
- **System tray icon**: Xanh = kết nối, xám = ngắt kết nối
|
||||||
|
- **Status**: Hiển thị trạng thái, IP, hostname
|
||||||
|
- **Connect / Disconnect**: Bật/tắt VPN
|
||||||
|
- **Account**: Submenu hiển thị tất cả profiles, chuyển đổi giữa các server
|
||||||
|
- **Add Server**: Dialog nhập URL server mới → tạo profile mới → mở trình duyệt login
|
||||||
|
- **Single instance**: Chỉ cho chạy 1 instance qua Windows Mutex
|
||||||
|
|
||||||
|
### Kiến trúc code
|
||||||
|
```
|
||||||
|
cmd/tailscale-tray/
|
||||||
|
├── main.go # App logic, systray menu, Win32 dialogs
|
||||||
|
└── icon.go # ICO generation (16x16, green/gray)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pattern**: Dùng per-item `onClick` goroutine (giống official Tailscale systray):
|
||||||
|
```go
|
||||||
|
func onClick(ctx context.Context, item *systray.MenuItem, fn func()) {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done(): return
|
||||||
|
case <-item.ClickedCh: fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependency
|
||||||
|
- `fyne.io/systray` - Cross-platform system tray
|
||||||
|
- `golang.org/x/sys/windows` - Win32 API
|
||||||
|
- `tailscale.com/client/local` - IPC client đến tailscaled
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cách deploy lên máy mới
|
||||||
|
|
||||||
|
### Windows - MSI Installer
|
||||||
|
```powershell
|
||||||
|
# Cài đặt (silent)
|
||||||
|
msiexec /i TailscaleCustom.msi /qn
|
||||||
|
|
||||||
|
# Kết nối (mở cmd/powershell)
|
||||||
|
tailscale up --login-server https://vpn.softs.business --accept-dns=false
|
||||||
|
|
||||||
|
# Hoặc dùng pre-auth key (tự động, không cần approve trên server)
|
||||||
|
tailscale up --login-server https://vpn.softs.business --accept-dns=false --authkey <KEY>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux - Manual install
|
||||||
|
```bash
|
||||||
|
# Copy binaries
|
||||||
|
sudo cp tailscale tailscaled /usr/local/bin/
|
||||||
|
|
||||||
|
# Tạo service (xem phần Build Linux ở trên)
|
||||||
|
sudo systemctl enable --now tailscale-custom
|
||||||
|
|
||||||
|
# Kết nối
|
||||||
|
sudo tailscale up --login-server https://vpn.softs.business --accept-dns=false \
|
||||||
|
--socket /var/run/tailscale-custom/tailscaled.sock
|
||||||
|
|
||||||
|
# Hoặc dùng pre-auth key
|
||||||
|
sudo tailscale up --login-server https://vpn.softs.business --accept-dns=false \
|
||||||
|
--authkey <KEY> --socket /var/run/tailscale-custom/tailscaled.sock
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quan trọng: `--accept-dns=false`
|
||||||
|
Luôn dùng flag này để tránh Tailscale ghi đè DNS config của máy, gây mất mạng internet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TODO cho phiên bản tiếp theo
|
||||||
|
|
||||||
|
### Web Admin App (Docker)
|
||||||
|
- [ ] Dashboard: tổng nodes, online/offline
|
||||||
|
- [ ] Nodes list: approve/reject/delete
|
||||||
|
- [ ] Users management: CRUD
|
||||||
|
- [ ] Pre-auth keys: tạo/quản lý
|
||||||
|
- [ ] Dùng Headscale REST API (xem `HEADSCALE_SETUP.md`)
|
||||||
|
|
||||||
|
### Hoàn thiện Linux Client
|
||||||
|
- [ ] Build script cho Linux (amd64, arm64)
|
||||||
|
- [ ] Tạo `.deb` / `.rpm` package
|
||||||
|
- [ ] Systemd service file đóng gói sẵn
|
||||||
|
- [ ] Test coexistence với Tailscale gốc trên Linux
|
||||||
|
|
||||||
|
### Hoàn thiện Windows Client
|
||||||
|
- [ ] Code signing cho exe/msi
|
||||||
|
- [ ] Auto-update mechanism
|
||||||
|
- [ ] Tray app: hiển thị danh sách peers
|
||||||
|
- [ ] Tray app: copy IP khi click
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
# Hướng dẫn cài đặt Headscale Server
|
||||||
|
|
||||||
|
## Mục lục
|
||||||
|
1. [Tổng quan](#tổng-quan)
|
||||||
|
2. [Yêu cầu hệ thống](#yêu-cầu-hệ-thống)
|
||||||
|
3. [Cài đặt Headscale bằng Docker](#cài-đặt-headscale-bằng-docker)
|
||||||
|
4. [Cấu hình domain & reverse proxy](#cấu-hình-domain--reverse-proxy)
|
||||||
|
5. [Quản lý users & nodes](#quản-lý-users--nodes)
|
||||||
|
6. [API Reference cho Web Admin](#api-reference-cho-web-admin)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tổng quan
|
||||||
|
|
||||||
|
Headscale là bản self-hosted của control server Tailscale. Nó cho phép:
|
||||||
|
- Tạo mạng riêng ảo (VPN mesh) giữa các máy
|
||||||
|
- Không phụ thuộc vào server của Tailscale
|
||||||
|
- Toàn quyền quản lý users, nodes, ACL
|
||||||
|
|
||||||
|
**Kiến trúc:**
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||||
|
│ Client Windows │────▶│ Headscale │◀────│ Client Linux │
|
||||||
|
│ (Tailscale- │ │ (vpn.softs. │ │ (Tailscale- │
|
||||||
|
│ Custom) │ │ business) │ │ Custom) │
|
||||||
|
└─────────────────┘ │ Port: 443 │ └─────────────────┘
|
||||||
|
│ gRPC + HTTPS │
|
||||||
|
└──────────────────┘
|
||||||
|
▲
|
||||||
|
│
|
||||||
|
┌──────────────────┐
|
||||||
|
│ Web Admin App │
|
||||||
|
│ (quản lý nodes) │
|
||||||
|
└──────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Yêu cầu hệ thống
|
||||||
|
|
||||||
|
- VPS Linux (Ubuntu 22.04+ hoặc Debian 12+)
|
||||||
|
- Docker + Docker Compose
|
||||||
|
- Domain trỏ về VPS (ví dụ: `vpn.softs.business`)
|
||||||
|
- Port 443 (HTTPS) mở
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cài đặt Headscale bằng Docker
|
||||||
|
|
||||||
|
### 1. Tạo thư mục cấu hình
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/headscale/config /opt/headscale/data
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Tạo file cấu hình `/opt/headscale/config/config.yaml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
server_url: https://vpn.softs.business
|
||||||
|
listen_addr: 0.0.0.0:8080
|
||||||
|
metrics_listen_addr: 0.0.0.0:9090
|
||||||
|
|
||||||
|
# gRPC cho Tailscale client
|
||||||
|
grpc_listen_addr: 0.0.0.0:50443
|
||||||
|
grpc_allow_insecure: false
|
||||||
|
|
||||||
|
# Database
|
||||||
|
database:
|
||||||
|
type: sqlite
|
||||||
|
sqlite:
|
||||||
|
path: /var/lib/headscale/db.sqlite
|
||||||
|
|
||||||
|
# Khoảng IP cấp cho các node
|
||||||
|
prefixes:
|
||||||
|
v4: 100.64.0.0/10
|
||||||
|
v6: fd7a:115c:a1e0::/48
|
||||||
|
|
||||||
|
# DERP (relay khi P2P không được)
|
||||||
|
derp:
|
||||||
|
server:
|
||||||
|
enabled: true
|
||||||
|
region_id: 999
|
||||||
|
region_code: custom
|
||||||
|
region_name: "Custom DERP"
|
||||||
|
stun_listen_addr: 0.0.0.0:3478
|
||||||
|
|
||||||
|
urls: []
|
||||||
|
paths: []
|
||||||
|
auto_update_enabled: true
|
||||||
|
update_frequency: 24h
|
||||||
|
|
||||||
|
# DNS - KHÔNG bật MagicDNS để tránh xung đột
|
||||||
|
dns:
|
||||||
|
magic_dns: false
|
||||||
|
base_domain: vpn.local
|
||||||
|
nameservers:
|
||||||
|
global: []
|
||||||
|
|
||||||
|
# Thời gian hiệu lực node key
|
||||||
|
node_key_expiry: 0 # không hết hạn
|
||||||
|
|
||||||
|
# Bật API (quan trọng cho Web Admin)
|
||||||
|
# API key tạo bằng: headscale apikeys create
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Tạo `docker-compose.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "3.9"
|
||||||
|
services:
|
||||||
|
headscale:
|
||||||
|
image: headscale/headscale:latest
|
||||||
|
container_name: headscale
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- /opt/headscale/config:/etc/headscale
|
||||||
|
- /opt/headscale/data:/var/lib/headscale
|
||||||
|
ports:
|
||||||
|
- "8080:8080" # HTTP API
|
||||||
|
- "9090:9090" # Metrics
|
||||||
|
- "3478:3478/udp" # STUN
|
||||||
|
command: serve
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Ho_Chi_Minh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Reverse proxy (Nginx)
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name vpn.softs.business;
|
||||||
|
|
||||||
|
ssl_certificate /etc/ssl/certs/vpn.softs.business.crt;
|
||||||
|
ssl_certificate_key /etc/ssl/private/vpn.softs.business.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_read_timeout 86400s;
|
||||||
|
proxy_send_timeout 86400s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Khởi động
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/headscale
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Tạo user đầu tiên
|
||||||
|
docker exec headscale headscale users create default
|
||||||
|
|
||||||
|
# Tạo API key (dùng cho Web Admin)
|
||||||
|
docker exec headscale headscale apikeys create --expiration 365d
|
||||||
|
# Lưu lại key này!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quản lý users & nodes
|
||||||
|
|
||||||
|
### Tạo user
|
||||||
|
```bash
|
||||||
|
docker exec headscale headscale users create <username>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Đăng ký node (sau khi client login)
|
||||||
|
```bash
|
||||||
|
docker exec headscale headscale nodes register --key <NODE_KEY> --user <username>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Liệt kê nodes
|
||||||
|
```bash
|
||||||
|
docker exec headscale headscale nodes list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Xóa node
|
||||||
|
```bash
|
||||||
|
docker exec headscale headscale nodes delete --identifier <node_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tạo pre-auth key (để client tự đăng ký, không cần approve thủ công)
|
||||||
|
```bash
|
||||||
|
docker exec headscale headscale preauthkeys create --user <username> --reusable --expiration 24h
|
||||||
|
```
|
||||||
|
|
||||||
|
Client dùng pre-auth key:
|
||||||
|
```bash
|
||||||
|
tailscale up --login-server https://vpn.softs.business --authkey <PREAUTH_KEY>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Reference cho Web Admin
|
||||||
|
|
||||||
|
Headscale có REST API đầy đủ. Web Admin app sẽ dùng các endpoint này:
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
Mọi request cần header:
|
||||||
|
```
|
||||||
|
Authorization: Bearer <API_KEY>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Endpoints chính
|
||||||
|
|
||||||
|
| Method | Endpoint | Mô tả |
|
||||||
|
|--------|----------|-------|
|
||||||
|
| `GET` | `/api/v1/user` | Danh sách users |
|
||||||
|
| `POST` | `/api/v1/user` | Tạo user mới |
|
||||||
|
| `DELETE` | `/api/v1/user/{name}` | Xóa user |
|
||||||
|
| `GET` | `/api/v1/node` | Danh sách tất cả nodes |
|
||||||
|
| `GET` | `/api/v1/node/{nodeId}` | Chi tiết 1 node |
|
||||||
|
| `DELETE` | `/api/v1/node/{nodeId}` | Xóa node |
|
||||||
|
| `POST` | `/api/v1/node/{nodeId}/expire` | Expire node |
|
||||||
|
| `POST` | `/api/v1/node/register` | Đăng ký node mới |
|
||||||
|
| `GET` | `/api/v1/node/{nodeId}/routes` | Routes của node |
|
||||||
|
| `POST` | `/api/v1/routes/{routeId}/enable` | Bật route |
|
||||||
|
| `POST` | `/api/v1/routes/{routeId}/disable` | Tắt route |
|
||||||
|
| `GET` | `/api/v1/preauthkey` | Danh sách pre-auth keys |
|
||||||
|
| `POST` | `/api/v1/preauthkey` | Tạo pre-auth key |
|
||||||
|
| `POST` | `/api/v1/preauthkey/expire` | Expire key |
|
||||||
|
| `GET` | `/api/v1/apikey` | Danh sách API keys |
|
||||||
|
| `POST` | `/api/v1/apikey` | Tạo API key |
|
||||||
|
|
||||||
|
### Ví dụ: Lấy danh sách nodes
|
||||||
|
```bash
|
||||||
|
curl -s -H "Authorization: Bearer <API_KEY>" \
|
||||||
|
https://vpn.softs.business/api/v1/node | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"machineKey": "mkey:...",
|
||||||
|
"nodeKey": "nodekey:...",
|
||||||
|
"name": "thinkpad",
|
||||||
|
"user": { "id": "1", "name": "huanld" },
|
||||||
|
"ipAddresses": ["100.64.0.1", "fd7a:115c:a1e0::1"],
|
||||||
|
"online": true,
|
||||||
|
"lastSeen": "2026-04-10T16:52:30Z",
|
||||||
|
"createdAt": "2026-04-10T16:55:04Z",
|
||||||
|
"registerMethod": "REGISTER_METHOD_CLI"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ví dụ: Approve node mới (thay vì chạy lệnh thủ công)
|
||||||
|
```bash
|
||||||
|
# Lấy danh sách nodes chờ approve
|
||||||
|
curl -s -H "Authorization: Bearer <API_KEY>" \
|
||||||
|
https://vpn.softs.business/api/v1/node
|
||||||
|
|
||||||
|
# Register node bằng key
|
||||||
|
curl -X POST -H "Authorization: Bearer <API_KEY>" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"key": "<NODE_KEY>", "user": "huanld"}' \
|
||||||
|
https://vpn.softs.business/api/v1/node/register
|
||||||
|
```
|
||||||
|
|
||||||
|
### Web Admin cần hiển thị:
|
||||||
|
1. **Dashboard**: Tổng nodes, online/offline, users
|
||||||
|
2. **Nodes list**: Tên, IP, user, trạng thái online, last seen
|
||||||
|
3. **Approve**: Nút approve cho nodes mới (gọi register API)
|
||||||
|
4. **Users**: CRUD users
|
||||||
|
5. **Pre-auth Keys**: Tạo/quản lý keys để client tự đăng ký
|
||||||
Reference in New Issue
Block a user