Initial commit: Tailscale Docker deployment with Headscale

Docker Compose 部署 Tailscale 連線至自架 Headscale 控制伺服器,
包含子網路由、出口節點、iptables NAT 設定及完整中文文件。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 09:17:12 +08:00
commit 2ffa06ac80
15 changed files with 399 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
.omc/

42
CLAUDE.md Normal file
View File

@@ -0,0 +1,42 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
Docker-based Tailscale deployment using a self-hosted Headscale control server (`https://headscale.lotimmy.com`). Runs a `tailscale/tailscale:latest` container in host network mode with subnet routing (192.168.88.0/24) and exit node capability.
## Commands
```bash
# Start the Tailscale container
./run.sh # docker-compose up -d
# Stop the container
./stop.sh # docker-compose down
# Connect to Headscale (advertise subnet routes + exit node)
./docker_exec_tailscale_up.sh
# Check status / get IP
./docker_exec_tailscale_status.sh
./docker_exec_tailscale_ip.sh
# Run arbitrary tailscale commands inside the container
./tailscale <args> # wrapper for: docker exec -i tailscale tailscale "$@"
# Reset iptables and configure NAT/forwarding for Tailscale routing (run on host)
./iptables_reset_and_configure.sh
```
## Architecture
- **docker-compose.yml** - Single service (`tailscale`) running `tailscale/tailscale:latest` with `NET_ADMIN`/`SYS_MODULE` caps, host networking, TUN device mount, and persistent state at `/opt/tailscale`.
- **`.env`** - Contains `TS_AUTHKEY` for pre-authenticated registration with Headscale.
- **iptables_reset_and_configure.sh** - Configures host firewall: allows SSH/HTTP/HTTPS/ICMP, sets up MASQUERADE NAT for Tailscale CGNAT range (100.64.0.0/10) via eth0, and enables forwarding between `tailscale0` and `eth0`.
- Watchtower auto-update is enabled via container label.
## Notes
- Documentation (`README`) is in Traditional Chinese.
- Hostname convention: `ip-192-168-88-XX` matching the host's LAN IP.

93
OPERATIONS.md Normal file
View File

@@ -0,0 +1,93 @@
# Operations Guide
## 日常操作
### 啟動服務
```bash
./run.sh
```
啟動 Tailscale Docker 容器(背景執行)。
### 停止服務
```bash
./stop.sh
```
停止並移除容器。
### 連線至 Headscale
```bash
./docker_exec_tailscale_up.sh
```
使用預設的 Auth Key 連線至 `https://headscale.lotimmy.com`,並:
- 廣播子網路 `192.168.88.0/24`
- 啟用出口節點Exit Node
- 接受其他節點的路由
### 檢查狀態
```bash
./docker_exec_tailscale_status.sh # 查看連線狀態
./docker_exec_tailscale_ip.sh # 查詢 Tailscale IP
```
### 執行任意 Tailscale 指令
```bash
./tailscale status
./tailscale ping <peer>
./tailscale netcheck
```
`./tailscale``docker exec -i tailscale tailscale` 的包裝腳本。
## 防火牆與路由設定
在主機上執行:
```bash
sudo ./iptables_reset_and_configure.sh
```
此腳本會:
1. 清除所有現有 iptables 規則
2. 允許 SSH (22)、HTTP (80)、HTTPS (443)、ICMP
3. 設定 Tailscale CGNAT 範圍 (100.64.0.0/10) 的 NAT MASQUERADE
4. 啟用 `tailscale0``eth0` 之間的封包轉送
5. 將規則儲存至 `/etc/iptables/rules.v4`
## 環境變數
| 變數 | 說明 | 位置 |
|------|------|------|
| `TS_AUTHKEY` | Headscale 預認證金鑰 | `.env` |
## 持久化資料
- Tailscale 狀態檔案:主機的 `/opt/tailscale` 掛載至容器的 `/var/lib/tailscale`
- iptables 規則:`/etc/iptables/rules.v4`
## 故障排除
```bash
# 確認容器正在執行
docker ps | grep tailscale
# 查看容器日誌
docker logs tailscale
# 確認 TUN 裝置存在
ls -la /dev/net/tun
# 確認 IP 轉送已啟用
cat /proc/sys/net/ipv4/ip_forward
# 登出並重新連線
./tailscale logout
./docker_exec_tailscale_up.sh
```

44
QUICKSTART.md Normal file
View File

@@ -0,0 +1,44 @@
# Quick Start
## 前置需求
- Docker 與 Docker Compose
- `/dev/net/tun` 裝置(主機需支援 TUN/TAP
- 具備 `NET_ADMIN` 權限的環境
## 步驟
### 1. 設定 Auth Key
`.env` 檔案中填入 Headscale 預認證金鑰:
```
TS_AUTHKEY=your-preauth-key-here
```
### 2. 啟動容器
```bash
./run.sh
```
### 3. 連線至 Headscale
```bash
./docker_exec_tailscale_up.sh
```
### 4. 設定防火牆(如需子網路由/出口節點)
```bash
sudo ./iptables_reset_and_configure.sh
```
### 5. 驗證
```bash
./docker_exec_tailscale_status.sh
./docker_exec_tailscale_ip.sh
```
看到 Tailscale IP 和節點列表即代表連線成功。

35
README Normal file
View File

@@ -0,0 +1,35 @@
Tailscale 操作筆記(使用 Headscale
登出目前 Tailscale 使用者
tailscale logout
登入 Headscale 自架登入伺服器
tailscale up --login-server=https://headscale.lotimmy.com
使用預先產生的 Auth Key 進行登入
tailscale up --login-server=https://headscale.lotimmy.com --authkey <你的-preauth-key>
範例:使用實際的 Auth Key
tailscale up --login-server=https://headscale.lotimmy.com --authkey tskey-xxxxxxx
正式使用 Auth Key 登入(可取代上方範例)
tailscale up --login-server=https://headscale.lotimmy.com --authkey d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e
登入並接受子網路路由(子網路代理模式)
tailscale up --login-server=https://headscale.lotimmy.com --authkey d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e --accept-routes
完整範例:廣播子網段、設為出口節點、指定主機名稱
tailscale up \
--accept-routes \
--advertise-routes=192.168.88.0/24 \
--advertise-exit-node \
--login-server=https://headscale.lotimmy.com \
--authkey=d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e \
--hostname=ip-192-168-88-81
檢查目前連線狀態
tailscale status
查詢本機 Tailscale IP
tailscale ip

67
README.md Normal file
View File

@@ -0,0 +1,67 @@
# Tailscale Docker 部署Headscale
使用 Docker Compose 部署 Tailscale連線至自架的 Headscale 控制伺服器。
## 功能
- 透過 Docker 容器執行 Tailscale使用 host 網路模式
- 連線至 `https://headscale.lotimmy.com`
- 子網路由廣播192.168.88.0/24
- 出口節點Exit Node支援
- iptables NAT/轉送自動設定
- 透過 Watchtower 自動更新容器映像
## 檔案結構
| 檔案 | 說明 |
|------|------|
| `docker-compose.yml` | Docker 服務定義 |
| `.env` | 環境變數TS_AUTHKEY |
| `run.sh` | 啟動容器 |
| `stop.sh` | 停止容器 |
| `docker_exec_tailscale_up.sh` | 連線至 Headscale含路由與出口節點設定 |
| `docker_exec_tailscale_status.sh` | 查看連線狀態 |
| `docker_exec_tailscale_ip.sh` | 查詢 Tailscale IP |
| `tailscale` | Tailscale CLI 包裝腳本 |
| `iptables_reset_and_configure.sh` | 防火牆與 NAT 設定 |
## 快速開始
```bash
# 1. 設定 .env 中的 TS_AUTHKEY
# 2. 啟動
./run.sh
# 3. 連線至 Headscale
./docker_exec_tailscale_up.sh
# 4. 設定防火牆(如需路由功能)
sudo ./iptables_reset_and_configure.sh
# 5. 驗證
./docker_exec_tailscale_status.sh
```
## 網路架構
```
Tailscale 節點 ──► Headscale (headscale.lotimmy.com)
tailscale0 介面 (100.64.0.0/10)
NAT MASQUERADE
eth0 ──► LAN (192.168.88.0/24)
```
## 主機名稱慣例
使用 `ip-192-168-88-XX` 格式,對應主機的區域網路 IP。
## 相關文件
- [QUICKSTART.md](QUICKSTART.md) — 快速開始指南
- [OPERATIONS.md](OPERATIONS.md) — 維運操作手冊
- [SUMMARY.md](SUMMARY.md) — 專案摘要

25
SUMMARY.md Normal file
View File

@@ -0,0 +1,25 @@
# Summary
## 專案摘要
此專案是一個 Docker 化的 Tailscale 部署方案,用於將主機連線至自架的 Headscale 控制伺服器(`https://headscale.lotimmy.com`)。
## 核心元件
- **Docker Compose 服務**:以 `tailscale/tailscale:latest` 映像執行,採用 host 網路模式,具備 `NET_ADMIN``SYS_MODULE` 權限。
- **Headscale 整合**透過預認證金鑰Pre-auth Key自動註冊節點。
- **子網路由**:廣播 `192.168.88.0/24` 網段,讓遠端 Tailscale 節點可存取區域網路。
- **出口節點**:允許其他節點透過此主機路由所有流量。
- **iptables 設定**NAT MASQUERADE 處理 Tailscale CGNAT 流量,並啟用 `tailscale0``eth0` 轉送。
## 技術規格
| 項目 | 值 |
|------|---|
| 容器映像 | `tailscale/tailscale:latest` |
| 網路模式 | host |
| 控制伺服器 | `https://headscale.lotimmy.com` |
| 廣播子網 | `192.168.88.0/24` |
| Tailscale CGNAT | `100.64.0.0/10` |
| 狀態持久化 | `/opt/tailscale``/var/lib/tailscale` |
| 自動更新 | Watchtower透過 container label |

23
docker-compose.yml Normal file
View File

@@ -0,0 +1,23 @@
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
hostname: virmach-ubuntu
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
network_mode: host
# privileged: true
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
volumes:
- /dev/net/tun:/dev/net/tun
- /opt/tailscale:/var/lib/tailscale
labels:
- "com.centurylinklabs.watchtower.enable=true"
# command: >
# tailscaled
command: >
sh -c "env && tailscaled"

4
docker_exec_tailscale_ip.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
# docker exec -it tailscale tailscale ip
tailscale ip

View File

@@ -0,0 +1,2 @@
docker exec -it tailscale tailscale status

9
docker_exec_tailscale_up.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
tailscale up \
--authkey d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e \
--advertise-routes=192.168.88.0/24 \
--accept-routes \
--advertise-exit-node \
--login-server=https://headscale.lotimmy.com \
--hostname=ip-192-168-88-82

44
iptables_reset_and_configure.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
echo "🧹 清除所有規則並重設策略..."
iptables -F
iptables -t nat -F
iptables -X
# 設定預設策略
# iptables -P INPUT DROP
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
# iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
echo "✅ 設定 INPUT 安全規則..."
# 允許已建立與相關的連線(像是回應封包)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow established/related"
# 允許 loopback
iptables -A INPUT -i lo -j ACCEPT -m comment --comment "Allow loopback"
# 允許 ICMP (ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT -m comment --comment "Allow ping"
# 允許 SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT -m comment --comment "Allow SSH"
# 可選:允許 HTTP/HTTPS如果有 Web 應用)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow HTTP"
iptables -A INPUT -p tcp --dport 443 -j ACCEPT -m comment --comment "Allow HTTPS"
echo "🔧 設定 Tailscale 出口 NATMASQUERADE"
iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -o eth0 -j MASQUERADE -m comment --comment "Tailscale NAT"
echo "🔧 允許 Tailscale → LAN 轉送"
iptables -A FORWARD -i tailscale0 -o eth0 -j ACCEPT -m comment --comment "Tailscale → LAN"
iptables -A FORWARD -i eth0 -o tailscale0 -m state --state RELATED,ESTABLISHED -j ACCEPT -m comment --comment "LAN → Tailscale return"
echo "📦 儲存規則iptables-persistent"
iptables-save > /etc/iptables/rules.v4
echo "✅ 防火牆與 NAT 重設完成!"

2
run.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose up -d

4
stop.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
# docker stop caddy
# docker system prune -f
docker-compose down

3
tailscale Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
docker exec -i tailscale tailscale "$@"