外观
Tailscale 组网
完成后,NAS 作为一台设备加入你的 Tailscale 网络(tailnet),你的手机、笔记本只要登录同一个 Tailscale 账号,不管在哪里,都能直接访问 NAS。路由器上不需要做端口映射,也可以让 NAS 顺带把整个家里的局域网分享给 tailnet。
适合谁
- 家里在运营商级 NAT(CG-NAT)后面,没有公网 IP,自建 WireGuard 连不进来。
- 不想管端口映射和动态域名,愿意把设备的接入和管理交给 Tailscale 的管理控制台。
和 OMV 的 WireGuard 插件相比:
| Tailscale(本文) | WireGuard 插件 | |
|---|---|---|
| 路由器端口映射 | 通常不需要,Tailscale 靠 NAT 穿透,穿不透时走它的中继服务器 | 需要转发一个 UDP 端口 |
| 公网 IP | 不需要 | 需要 |
| 设备和密钥管理 | 在 Tailscale 的管理控制台里 | 在 OMV 里手工管理每个客户端 |
| 控制面 | 协调服务器由 Tailscale 公司托管,用第三方账号登录 | 完全自己掌控 |
| 费用 | 有免费和付费方案,以官网为准 | 免费 |
总原则见 远程访问:别把 NAS 直接暴露到公网:用 VPN,不要映射管理界面和 SMB。
加入 tailnet 之后,NAS 对 tailnet 里的设备是开放的
- 影响范围:Tailscale 官方文档说明,新 tailnet 的默认策略是允许所有设备互访。NAS 上所有监听在所有地址上的服务,包括 SMB、NFS、Web 界面、SSH,对 tailnet 里的设备都是可达的。作为子网路由器时,整个局域网都对 tailnet 开放。auth key 和状态目录等于这台 NAS 在 tailnet 里的身份,泄露了别人就能冒充它。
- 前置条件:给 Tailscale 账号开两步验证;写好访问控制规则,收紧谁能访问 NAS 的哪些端口;按下文保管 auth key 和状态目录。
- 怎么回退:在 OMV 里停止并删除容器;在 Tailscale 管理控制台的 Machines 页面删除这台设备,撤销用过的 auth key,取消批准的子网路由;删除状态目录。
方案说明
官方建议额外软件优先用容器,所以这里用 Compose 插件跑官方镜像 tailscale/tailscale。Compose 插件的示例清单里有 tailscale,核对时(2026-10-23)清单共 197 个示例,它的说明是「Connect your devices and users together in your own secure virtual private network」,示例文件头标注的日期是 2025-06-01。本文以 Tailscale 官方的 Docker 文档为准,没有直接用这个示例,原因是它和官方文档有几处不同:
- 示例没有设置
TS_USERSPACE,按官方文档这个变量默认开启,容器会用用户态网络,性能较低,宿主机上也不会出现tailscale0接口。本文用内核网络。 - 示例用
privileged: true加sys_module,权限比官方最小示例(只需net_admin和net_raw)大。 - 示例把宿主机
/var/lib下的一个目录挂进容器的/var/lib,没设TS_STATE_DIR;官方推荐把状态目录设成/var/lib/tailscale并作为卷挂载。 - 示例的环境变量文件是空的,没有登录用的 auth key。
开始之前
- 已装好 Compose 插件并设置好共享文件夹,见 安装 Docker 与 Compose 插件;会在界面里添加和启动应用,见 部署第一个应用。
- 一个 Tailscale 账号,在 Tailscale 的管理控制台里操作。登录用的是第三方账号,例如 Google、Microsoft、GitHub。
- 宿主机有
/dev/net/tun:在 OMV 的 shell 里运行ls -l /dev/net/tun,不存在就运行modprobe tun。
1. 生成 auth key,并按保管要求设置
Tailscale 管理控制台 → 设置 → Keys → Generate auth key。Auth key 可以让新设备不经浏览器登录就加入,官方文档说明,设备会以生成这把 key 的用户的身份登录。选项这样选:
| 选项 | 建议 | 原因 |
|---|---|---|
| Reusable | 不勾选 | 一次性的 key 用完就自动失效。官方警告:可重复使用的 key 被偷了会很危险,最好放进专门的密钥保管工具 |
| Ephemeral | 不勾选 | 临时节点离线后会被自动移除,NAS 是长期设备 |
| Pre-approved | 按需 | tailnet 开了设备批准时,勾选可免去手动批准 |
| Tags | 暂不选 | 用标签要先在访问控制里定义 tagOwners,见下文 |
| Expiry | 选最短,例如 1 天 | 官方允许 1 到 90 天,默认和上限都是 90 天;key 只用一次,没必要留长 |
key 只在生成的那个对话框里显示,关掉后就看不到了,现在复制好。
2. 在 OMV 里添加 Tailscale 应用
服务 → Compose → 文件(Services → Compose → Files)→ 添加,名称填 tailscale,在 compose 文件里填:
yaml
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
network_mode: host
environment:
- TS_HOSTNAME=omv-nas # 在 tailnet 里显示的设备名
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false # 用内核网络,宿主机上会出现 tailscale0
- TS_AUTH_ONCE=true # 已经登录过就不再重新登录
# 作为子网路由器时再加下面一行,网段换成你自己的局域网
# - TS_ROUTES=192.168.2.0/24
env_file:
- tailscale.env # 只放 TS_AUTHKEY,见下
volumes:
- ./state:/var/lib/tailscale # 状态目录,在这个栈的文件夹里
devices:
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
- net_raw
restart: unless-stopped环境变量文件的内容只有一行,把 key 填进去:
text
TS_AUTHKEY=<粘贴刚才生成的 auth key>说明:
network_mode: host让容器共享宿主机的网络,tailscale0接口和 Tailscale 的地址出现在 NAS 上,所以 NAS 本身用 Tailscale 地址就能访问。TS_USERSPACE=false要求/dev/net/tun和net_admin,对应devices和cap_add,这是官方文档对内核网络的要求。- 相对路径
./state解析到 compose 文件所在的目录,也就是<Compose 文件共享文件夹>/tailscale/state。Compose 文件共享文件夹默认权限是 700,只有管理员能进,比放进会被 SMB 共享的数据目录安全;写绝对路径或占位符的规则见 写好 compose 文件。 - 想固定版本,把
latest换成官方发布的版本标签。
保存后,在 文件 页选中它,点 Up(对应 docker compose up -d,中文界面里这个按钮可能显示成「上移」,以界面为准)。先点 Check 可以检查语法。
3. 确认登录成功,然后清理 key
- 在 OMV 的 shell(root)里查看:
sh
# 在 OMV 的 shell 里执行(root),只读
docker logs tailscale --tail 30
docker exec tailscale tailscale status # 列出 tailnet 里的设备
ip -br addr show tailscale0 # 应有 100 开头的地址- 在管理控制台的 Machines 页面,应出现名为
omv-nas的设备。 - 马上清理:把环境变量文件里的
TS_AUTHKEY那一行删掉,保存,再在 文件 页点 Up,让容器按新的环境重建。因为设了TS_AUTH_ONCE=true并且状态目录保存了登录信息,容器重启不再需要 key。如果容器没有重建(用docker inspect tailscale看环境变量里还有没有TS_AUTHKEY),先点 Down(对应docker compose down,可能显示成「下移」)删掉容器,再点 Up,状态目录是挂载进去的,不会丢。 - 到 Tailscale 管理控制台的 Keys 页面撤销这把 key。官方说明撤销 key 不会让已经用它登录的设备失效,所以放心撤销。
key 出现过的地方,都要当机密:环境变量文件(Compose 插件的备份会把 compose 文件和环境变量文件一起复制到备份目录)、docker inspect 的输出、你的 shell 历史、聊天记录。这就是要用一次性、短有效期、用完即清的原因。
4. 状态目录和设备密钥
- 状态目录就是这台 NAS 的身份。 官方文档说明,
TS_STATE_DIR的卷让容器在重启后保持身份,否则每次重启都会在管理控制台里新建一个设备。所以不要删它,也不要把它放在会被别人读到的地方。它会随 Compose 插件的备份一起被带走,备份目录和异地备份要加密,见 更新与备份容器。 - 节点密钥默认 180 天过期,过期后这台 NAS 会掉出 tailnet。服务器类设备,可以在管理控制台的 Machines 页面,用该设备右侧菜单里的 Disable Key Expiry 关闭过期。官方说明带标签的设备默认就是禁用过期的。关闭意味着少了一道定期重新验证的保险,只对你信任的服务器这样做。
- 重新验证时不要在远程用
--force-reauth,官方提醒这可能让 tailnet 连接断开。
5. 可选:作为子网路由器
想让外面的设备访问整个局域网(打印机、其他电脑、路由器管理页),让 NAS 通告局域网的网段。
- 宿主机打开转发。 先看是否已经开了:
sysctl net.ipv4.ip_forward。没开,在 OMV 的 shell(root)里照官方文档写成一个单独的文件,不要改 OMV 管理的文件:
sh
# 在 OMV 的 shell 里执行(root)
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.d/99-tailscale.conf
sysctl -p /etc/sysctl.d/99-tailscale.confOMV 管理的是名字带 99-openmediavault- 的文件,这个文件它不会动。容器用 network_mode: host,不能在容器里设这些内核参数,必须在宿主机上设。 2. 通告网段。 把 compose 文件里 TS_ROUTES 那一行取消注释,改成你的局域网网段,再点 Up。 3. 批准路由。 官方文档说明通告的路由需要在管理控制台批准才生效:Machines 页面里这台设备有 Subnets 标记,批准它。也可以用访问控制里的 autoApprovers 自动批准。 4. Linux 客户端要运行 tailscale set --accept-routes 才会使用这些路由;Windows、macOS、iOS、Android 自动接受。
默认情况下,子网路由会做地址转换,局域网里的设备看到的来源是 NAS,不是远端的设备,所以不需要在路由器上加静态路由。两个网络的网段相同(都是 192.168.1.0/24)会冲突,家里的网段换成不常见的。
6. MagicDNS 和访问控制
- MagicDNS:官方说明 2022-10-20 及以后创建的 tailnet 默认开启。每台设备有一个完整名称,形如
omv-nas.<tailnet 名>.ts.net,在装了 Tailscale 的设备上直接用短名omv-nas也行。容器里的 NAS 默认不接受 Tailscale 下发的 DNS 设置(TS_ACCEPT_DNS默认不接受),所以 NAS 自己解析不了 tailnet 里的名字,这对访问 NAS 没有影响。 - 访问控制:官方的访问控制是默认拒绝的:一旦写了规则,没有被允许的访问就不通。没写规则时则是默认全部允许,所以要主动收紧。在管理控制台的 Access controls 页面编辑,规则的基本格式如下,取自官方示例页,只放行你自己的设备访问带
tag:nas标签的设备的 SSH 和 SMB 端口:
json
{ "action": "accept", "src": ["autogroup:member"], "dst": ["tag:nas:22,445"] }给 NAS 打标签,要先在策略里用 tagOwners 指定谁能用这个标签,再让设备带标签登录:生成 auth key 时选上这个标签,官方文档说明带标签的 key 会给用它登录的设备打上标签。完整写法和更多例子见官方的 ACL 示例。保存前先用管理控制台的校验。
检查结果
docker exec tailscale tailscale status里能看到你的其他设备,连接方式显示 direct 或 relay,relay 表示走中继,会慢一些。- 在另一台已登录 Tailscale 的设备上,用 NAS 的 Tailscale 地址或 MagicDNS 名字,访问 SMB 共享和 Web 界面。把那台设备切到移动数据,不在家里的网络,再测一次。
- 子网路由:在家以外的设备上,访问局域网里另一台设备的局域网地址,应当通。
- 重启 NAS 和容器,设备在管理控制台里仍然是同一台,没有多出一个新设备,也不需要重新登录。
备份与维护
- 升级:
latest标签会跟着走。用 Compose 插件的计划任务更新镜像,见 更新与备份容器,更新前确认状态目录已备份。 - 改动 compose 文件之后重新点 Up,容器会重建,状态目录保留。
- 移除这台设备:先在管理控制台的 Machines 页面删除,再停止并删除容器,最后删除状态目录。只删容器,不删管理控制台里的设备,它会一直显示离线。
常见问题
容器启动后马上退出,日志里提示找不到 /dev/net/tun。 宿主机没有这个设备,运行 modprobe tun,需要长期生效就在 /etc/modules-load.d/ 里加一个文件,写上 tun。
每次重启都多出一个新设备。 状态目录没有挂载对,或者路径指到了容器里别的位置。确认 TS_STATE_DIR 和 volumes 一致。
日志提示 key 无效、已用过或已过期。 一次性 key 只能用一次,有效期也很短。重新生成一把,填进环境变量文件,再启动。
设备在线,但连不上 SMB 或 Web 界面。 先检查访问控制规则有没有挡住;再检查 OMV 的防火墙。Tailscale 会往系统防火墙里添加规则,而 OMV 的防火墙脚本在你配置了规则时,会在应用时清空并重建输入和输出链。两者同时用时,改完 OMV 的防火墙规则要确认 tailnet 还通,必要时重启 Tailscale 容器,这个相互影响没有在实机上验证过,待核实。
子网路由不通。 没有在管理控制台批准;Linux 客户端没有 --accept-routes;宿主机转发没开;两个网络的网段相同。
参考资料
- Tailscale 官方文档:Docker、Docker 配置参数、Auth keys、子网路由器、密钥过期、MagicDNS、访问控制、防火墙端口
- Compose 插件示例清单:compose-files