TSLinkTSLink 文档

故障排除

常见 TSLink 问题的解决方案

查看 Markdown

认证

"未登录"错误

症状: TSLink 命令因认证错误而失败。

解决方案: 先检查 tslink status --json。默认 add/share 可以不存储凭据就入网:needs_login 是成功的授权交接,请打开其 auth_url、完成入网/审批,再轮询 tslink url <name> --wait,无需执行 tslink login。需要存储凭据的操作可使用 API 访问令牌(tskey-api-*)或 OAuth 客户端密钥(tskey-client-*):

bash
tslink login

如果你之前已经登录过,你的 API 访问令牌可能已过期。OAuth 客户端密钥不会周期性过期,但 API-token 模式当前对 Tailscale 标签/设备自动化支持最完整。使用 tslink status 查看你的认证状态。

API 密钥已过期

症状: tslink serve 在之前正常工作后出现认证错误。

解决方案: API 访问令牌会定期过期。诊断确认存储令牌已过期时,通过 tslink login 替换 管理后台 → Keys 的凭据。网关已运行时,按凭据/配置重启管理处理。这与 Tier 1 节点的浏览器入网不同。

OAuth 客户端密钥可以避免周期性 token 过期,但当前 Tailscale REST 标签/设备操作仍以 API-token 路径最完整。

钥匙串访问被拒绝

症状: TSLink 无法读写系统钥匙串中的凭证。

解决方案: 先恢复预期凭据提供方的访问:解锁它,并在提示时授予 TSLink 二进制文件访问权限。钥匙串不可达或状态不确定时拒绝写入。macOS/Linux 只有在 TSLink 证明旧钥匙串值不存在或已删除后,才允许 0600 文件回退;Windows 没有凭据文件回退。无头运行本身不能证明满足这些条件。

存储访问恢复后,stdin 可作为安全的非交互输入方式。它使用同一个存储后端,不能绕过钥匙串故障:

bash
printf %s "$TSLINK_API_KEY" | tslink login --api-key-stdin
printf %s "$TSLINK_CLIENT_SECRET" | tslink login --client-secret-stdin

受限权限文件回退和旧版 credential files 仍可能因兼容性存在,但排障说明不应指导直接写 secret 文件,因为 shell history 和 chmod 前窗口都可能泄漏凭证。

认证密钥派生失败

症状: TSLink 日志显示从 API 令牌派生认证密钥的错误。

解决方案: 认证密钥通过 Tailscale API 从 API 访问令牌动态派生。这需要:

  1. 有效的、未过期的 API 访问令牌。
  2. 到 Tailscale API(api.tailscale.com)的网络连接。
  3. API 令牌必须具有足够的权限(设备写入权限)。

如果使用 OAuth 客户端密钥,tsnet 可以直接使用该密钥,但 Tailscale REST 标签/设备操作当前仍依赖 API-token 路径。

网关

网关启动失败

症状: tslink serve 立即退出或显示错误。

可能原因:

  1. 另一个实例已在运行。 检查 tslink status --json。默认 add/share 已会启动后台网关,请完成可能的入网授权并轮询 URL。维护需要重启时,按平台重启流程操作,不要启动第二个网关。

  2. 端口冲突。 如果嵌入式 tsnet 节点无法绑定监听器,检查其他 Tailscale 相关进程。

  3. 网络问题。 tsnet 节点需要互联网访问以连接到 Tailscale 协调服务器。验证你的网络连接。

  4. 无效的控制 URL。 如果使用 Headscale,检查你的控制 URL 是否正确:

    bash
    tslink config get control-url
  5. 节点状态错误。 检查实际错误并按节点状态恢复说明操作。网关或监督程序可能仍持有状态时,不要删除它。

服务无法访问

症状: 网关正在运行但你无法从另一台设备访问服务。

检查清单:

  1. 本地服务是否在运行? 对于代理服务,验证目标 host:port 在本地可达:

    bash
    curl http://localhost:3000
  2. 访问设备是否有网络路径? 使用获准的 tailnet 成员,或已接受该应用设备分享的外部 Tailscale 账号。使用人员授权时还要检查实际登录身份与期限;Funnel 则是公开访问。

  3. 服务是否已注册? 使用 tslink list 确认服务存在。

  4. 当前授权是否允许访问? 对私有 HTTP/文件应用,检查人员授权的应用范围、期限和撤销状态,或适用的旧 --allow 邮箱/设备标签规则。已登记人员的授权优先于旧 allow 规则。

  5. 就绪与 DNS。 用 tslink url <name> --wait 获取实际就绪端点,再检查接收设备的 DNS 及 tailnet 访问策略。直接向 IP 发 HTTPS 请求可能因主机名/证书验证失败,不能代替相同 URL 的测试。

  6. 临时节点生命周期。 短暂断连不证明设备已删除,控制面在不活跃后清理节点。考虑重启或重新入网前,先检查本地状态及远端节点状态,见临时节点未自动移除。

TCP 服务无法工作

症状: 无法连接到 TCP 服务(数据库、Redis 等)。

检查清单:

  1. 本地服务是否在监听? 验证 TCP 目标可达:

    bash
    nc -zv localhost 5432
  2. 是否使用实际端点? 读取 tslink url mydb --wait。CLI 注册会记录目标端口;手工条目缺少 port 时回退到 443。对于 5432 示例,请替换为返回的主机名:

    bash
    psql -h <tslink-url-返回的主机名> -p 5432
  3. 客户端 Tailscale 是否在运行? 访问设备必须运行并连接 Tailscale 应用。

  4. 无 HTTP ACL、中间件或请求头。 TCP 转发原始字节;CLI 和 registry 验证都拒绝 TCP 非空 --allow / allowed_users。请使用 tailnet 策略及目标服务自身认证和所需 TLS,见 TCP 服务。

文件服务返回 404

症状: 文件服务正在运行但所有路径都返回 404。

解决方案: 验证 --dir 路径指向一个有效且可读的目录:

bash
ls -la /path/to/your/directory

确保目录中包含你期望提供的文件。文件服务通过 HTTPS 直接提供目录内容。

证书

TLS 证书问题

症状: 浏览器在访问服务时显示证书警告。

可能原因:

  1. 首次延迟。 TLS 证书在首次使用时配置,可能需要几秒钟。稍后刷新页面。

  2. HTTPS 功能未启用。 确保在 Tailscale 管理控制台的 DNS 设置中为你的 tailnet 启用了 HTTPS。

  3. 时钟偏差。 如果你的系统时钟严重偏差,证书验证可能会失败。同步你的系统时间。

自定义域名证书错误(Roadmap / experimental)

自定义域名和 ACME 支持属于 roadmap/experimental。--domain / --acme-email 标志已移除。旧 domain / acme_email registry 键即使为空也会以 unknown_config_key 拒绝,请删除。已交付流程请使用默认 <service>.<tailnet>.ts.net 主机名。

文件和权限

权限错误

症状: TSLink 无法读取目录或写入配置路径。

解决方案:

  • 确保 --dir 路径存在且你的用户可读。
  • 修改前先检查所选配置目录的所有权和权限。默认路径可检查:
    bash
    ls -ld ~/.config/tslink ~/.config/tslink/nodes
    确认实际服务用户和目录。修改运行时状态前完成确认停机,不要把通用递归所有权变更当作未经验证的修复。

节点状态目录问题

症状: 服务启动时出现关于节点状态的错误。

解决方案: 每个服务将 tsnet 状态存储在 ~/.config/tslink/nodes/<service-name>/ 中。出现错误本身不证明状态已损坏。恢复前,保留 registry.json 中实际完整的服务条目,并检查:

bash
tslink list --json
tslink status --json

保留原 type、target/path、port、allowed_users(--allow)、tags、control_url、ephemeral、Funnel/公共确认/到期时间及其他所有设置。不要把条目替换成通用的 3000 端口代理;丢失 --allow 可能扩大访问范围。

处理节点状态前先完成确认停机;遇到错误、所有权仍不确定的警告,或仍运行/受管理的网关时停止操作。诊断保存的错误,恢复同一有效服务条目及原访问策略。明确选择完整重置时,保留配置后按配置中的受保护重置流程操作;这不是常规首选修复。随后按对应平台恢复运行、完成可能的新入网授权,并验证端点及访问限制。

注册表文件损坏

症状: TSLink 拒绝启动或显示 JSON 解析错误。

解决方案: 服务注册表(~/.config/tslink/registry.json)必须是有效的 JSON。验证它:

bash
python3 -m json.tool ~/.config/tslink/registry.json

修复前保留原文件。先完成确认停机,再修复或恢复已知有效的注册表,保留相同的完整服务条目和访问限制。通用的删除/重新添加操作会丢失这些设置。恢复受管理运行前先验证修复后的文件,见注册表配置。

守护进程

守护进程无法停止

症状: tslink stop 似乎不起作用。

解决方案:

  1. 检查进程是否确实在运行:

    bash
    tslink status
  2. Unix 五秒超时只返回错误,不会强制退出,进程可能仍在运行;Windows 使用立即进程终止。已安装的 macOS KeepAlive 可重新拉起停止的进程。按确认停机操作,状态不确定时停止。不要删除 PID 记录来绕过所有权检查;stop 仅在确认进程不存在后清理过时记录。

自动启动不工作

症状: 运行 tslink install 后,登录时 TSLink 未自动启动。

各平台解决方案:

  • macOS: 检查 LaunchAgent 是否已加载:

    bash
    launchctl list | grep tslink

    用 tslink status --json / tslink doctor --json 查看监督诊断。安装的 plist 是 ~/Library/LaunchAgents/com.tslink.daemon.plist;需要修复时按已确认停机的重启流程操作。

  • Linux: 检查 systemd 用户服务:

    bash
    systemctl --user status tslink

    如果失败,检查日志并重启:

    bash
    journalctl --user -u tslink -n 50
    systemctl --user restart tslink
  • Windows: 查看已验证的 Task Scheduler/supervisor 状态:

    powershell
    tslink status --json
    # Inspect data.supervision; Task Scheduler is the default, --startup is fallback.

守护进程启动时崩溃

症状: 守护进程启动但立即退出。日志可能显示关于绑定或认证的错误。

解决方案:

  1. 检查端口或资源冲突:
    bash
    tslink status
  2. 检查 tslink status --json / tslink doctor --json。Tier 1 的 needs_login 是入网交接,不要求存储 API 凭据;按实际模式和错误参考认证诊断。
  3. 用 tslink logs 查看 stderr 应用/错误日志,见结构化日志。需要重启时按平台管理操作。

热重载

热重载不工作

症状: 在网关运行时添加或移除服务没有效果。

可能原因:

  • 文件系统事件不支持。 某些网络挂载或虚拟化文件系统不触发 fsnotify 事件。先检查实际错误;需要重启时按平台重启流程操作。
  • 注册表文件损坏。 使用 JSON 校验工具验证 ~/.config/tslink/registry.json 中的 JSON。

中间件更改未生效

症状: 你在 registry.json 中更新了中间件设置但没有生效。

解决方案: 可配置 middleware 尚不可用。已移除的 middleware registry 键即使为空也会以 unknown_config_key 拒绝。删除该键时保留完整服务条目及已有访问设置,见 Roadmap 配置字段。

服务类型/目标/端口更改需要重启

症状: 你在 registry.json 中更改了服务的类型、目标或端口,但更改未反映。

解决方案: 对服务 type、target 或 port 的更改需要受影响的 tsnet 节点重启。网关会自动处理此操作,但重启可能需要几秒钟,因为节点需要重新连接。

中间件(Roadmap / experimental)

Rate limiting、Basic Auth、IP allow list 和 CORS middleware 属于 roadmap/experimental,当前没有实现或 registry schema。已交付保护层是 proxy/file HTTP 服务的 --allow 加 Tailscale ACL/tag policy。

Funnel

Funnel 不工作

症状: 使用 --funnel --public 的代理服务无法从公共互联网访问。

检查清单:

  1. Tailscale 中已启用 Funnel。 必须在 Tailscale 管理控制台中为你的 tailnet 启用 Funnel。
  2. 显式公共暴露确认。 TSLink CLI 需要 --public(带不带 --json 都一样),它会在该服务的 registry.json 条目中记录 public_ack: true。
  3. 仅代理服务。 Funnel 仅适用于代理服务,不适用于文件或 TCP 服务。
  4. DNS 传播。 <service>.<tailnet>.ts.net 的公共 DNS 记录可能需要一些时间传播。
  5. 允许公开服务。 策略的 nodeAttrs Funnel 授权需允许该服务节点公开服务。它不认证访客:公网访客没有 tailnet 调用者身份检查,TSLink --allow 不保护公网端点。需要的访客授权由后端应用负责,见 Tailscale Funnel。

Funnel 与中间件

症状: 中间件(速率限制、Basic Auth)不适用于 Funnel 流量。

解决方案: Configurable middleware 属于 roadmap/experimental,不是已交付的 Funnel 保护层。另请注意身份头(X-Tailscale-User-*)对于公共 Funnel 请求不可用,因为请求者不在你的 tailnet 上。

Headscale / 自定义控制服务器

无法连接到 Headscale

症状: 使用自定义控制 URL 时 TSLink 无法连接。

检查清单:

  1. 验证控制 URL 是否正确且可达:

    bash
    tslink config get control-url
    curl https://headscale.example.com/health
  2. 检查你的 Headscale 服务器是否正在运行且可从 TSLink 主机访问。

  3. 如果在 registry.json 中使用按服务的控制 URL,确保每个服务的 control_url 正确。

  4. 更改控制服务器身份或处理节点状态前,保留完整服务设置,按节点状态恢复说明操作。先确认停机,不要删除 runtime 仍持有的目录。

混合控制服务器

症状: 某些服务连接到了错误的控制服务器。

解决方案: TSLink 同时支持全局和按服务的控制 URL:

  • 全局: tslink config set control-url <url> — 适用于所有没有按服务覆盖的服务。
  • 按服务: 在 registry.json 中的服务条目中设置 control_url — 仅覆盖该服务的全局设置。

检查你的全局配置和每个服务的注册表条目,确保使用了正确的 URL。

Docker(Roadmap / experimental)

Docker 标签发现属于 roadmap/experimental。当前 TSLink 没有 Docker discovery 包或 event watcher。容器背后的服务请用 tslink add 显式注册。

指标(Roadmap / experimental endpoint)

Prometheus /metrics 属于 roadmap/experimental。TSLink 当前没有 HTTP metrics instrumentation 或 scrape endpoint。如果 curl https://<service-name>.<your-tailnet>.ts.net/metrics 失败,这是受保护 endpoint 接入前的预期状态。

管理 API(Roadmap / experimental)

Admin dashboard 和 REST API 属于 roadmap/experimental。当前 TSLink 没有 admin handler 或 dashboard;可选的 tailnet-only MCP 控制面是远程管理入口。已交付自动化请使用带 --json 的 CLI。

集群(Roadmap / experimental)

Cluster sync 属于 roadmap/experimental。当前 TSLink 没有 cluster 实现。

日志

访问日志未出现

症状: 尽管流量通过 TSLink 服务,但没有访问日志条目。

解决: 用 tslink access log --app <name> --since 24h 并检查 status/doctor 的 drops 与 missing history。访问历史说明身份、隐私与缺口;tslink logs 仍用于 daemon 诊断。

bash
ls -la ~/.config/tslink/logs/

WhoIs 解析出的 login / node 可能为空,缺少身份不证明访问日志已停止。完整字段及来源/缓存边界见结构化日志。

日志格式

症状: 需要理解或解析 TSLink 日志输出。

解决: 用 tslink access log --app <name> --since 24h 并检查 status/doctor 的 drops 与 missing history。访问历史说明身份、隐私与缺口;tslink logs 仍用于 daemon 诊断。

守护进程日志与访问日志

症状: 不确定应该检查哪个日志文件。

解决方案: 结构化网关生命周期、警告/错误及代理/文件 HTTP 访问条目共用 stderr / tslink.err.log。Daemon stdout 写入 tslink.out.log,不是结构化访问流,没有单独的 access.log。排查请求时按记录类型/服务区分;Docker events 与 cluster heartbeats 仍属 roadmap/experimental,见日志文件位置。

Tailscale API 集成

过时设备未被清理

症状: 旧的 TSLink 服务设备在移除后仍然保留在 Tailscale 管理控制台中。

解决方案: tslink remove 始终移除本地服务条目。远端 tailnet 清理是保守的:只有能证明精确所有权时,TSLink 才会删除远端设备。如果过时设备仍然存在:

  1. 先检查 tslink status --json 及清理警告。启动时可能尝试所有权安全的清理;确需重启时按平台重启管理操作。
  2. 确保使用的凭证具有足够的 Tailscale API 权限(设备删除权限)。
  3. 如果 TSLink 报告 protected 候选或 skipped cleanup,请手动确认并从 Tailscale 管理控制台移除过时设备。

临时节点未自动移除

症状: 使用 --ephemeral 创建的服务在断开连接后仍保留在 tailnet 中。

解决方案: Tailscale 控制面在一段不活跃时间后移除临时节点,不是每次断开都移除。节点已注册/运行时,即使没有应用流量也可能仍活跃。用 tslink list --json 确认本地 ephemeral 设置,并在 Tailscale 管理控制台确认实际远端节点状态;本地标志本身不证明远端删除。不要仅因短暂断连就重启或重新注册。

远端设备清理不删除本地服务注册,注册保留至 tslink remove。详见临时节点行为及 Tailscale 生命周期契约。状态恢复或明确维护时,保留完整服务条目并遵循节点状态恢复。

获取帮助

GitHub issue tracker 已公开,可反馈不敏感的问题或更正。不要在公开 issue 中提交凭据、邀请链接、个人数据或私有 tailnet 信息。

协作者准备报告时,可附上:

  • 你的操作系统和 TSLink 版本(tslink --version)
  • 确切的错误消息或异常行为
  • 重现问题的步骤
  • ~/.config/tslink/logs/ 中的相关日志输出

分享诊断前,请移除凭据、授权 URL 及敏感本地或调用者信息。

目录