命令参考
TSLink 所有命令的完整参考
概述
TSLink 提供了一组简洁的命令来管理 Tailscale 网络上的服务。所有命令遵循 tslink <命令> [参数] [标志] 的模式。
认证
tslink login#
通过引导菜单录入并存储凭据。普通 login 不是浏览器 OAuth callback;单独的页面打开 helper 是另一项操作。
tslink login非交互式模式(适用于 CI/CD 和自动化):
# 通过 stdin(不把 secret 放进 argv 或 history)
printf %s "$TSLINK_API_KEY" | tslink login --api-key-stdin
printf %s "$TSLINK_CLIENT_SECRET" | tslink login --client-secret-stdin
# 通过 secret manager 预注入的环境变量
tslink login选择恰好一个明确凭据来源(一个 stdin flag 或一个兼容 argv flag);多个明确来源是 usage error。未指定明确来源时,先考虑环境变量,再进入交互提示。--json 禁用交互录入;自动化优先使用 stdin 或 secret manager 注入的环境,避免 argv/history 泄漏。
标志:
| 标志 | 描述 |
|---|---|
--api-key-stdin | 从 stdin 读取 API 访问令牌 |
--client-secret-stdin | 从 stdin 读取 OAuth 客户端密钥 |
--manage-acl | 显式 opt in 远端 ACL tag-owner mutation;默认 login 不会改写共享 ACL policy |
--api-key <令牌> | 兼容性 API 访问令牌路径;自动化中避免使用,因为 argv 可能泄漏 |
--client-secret <密钥> | 兼容性 OAuth 客户端密钥路径;自动化中避免使用,因为 argv 可能泄漏 |
--expires-in <时长> | 以「从现在起的时长」记录 API 访问令牌有效期(90d、30d 或 Go duration);仅适用于 api-key |
--expires-at <时间戳> | 以 RFC3339 时间戳记录 API 访问令牌有效期;仅适用于 api-key,且与 --expires-in 互斥 |
--retire-other | 当前凭证验证并提交成功后,删除另一个凭证槽位;默认 api-key 与 client-secret 两个槽位并存 |
--open-keys-page | 独立辅助命令:打开 Tailscale API keys 页面,退出码 0 且不存储任何凭证 |
--open-oauth-page | 独立辅助命令:打开 Tailscale OAuth 页面,退出码 0 且不存储任何凭证 |
TSLink 接受两种密钥类型:
- API 访问令牌(
tskey-api-*)— 输入时自动验证,tslink serve时自动派生认证密钥。 - OAuth 客户端密钥(
tskey-client-*)— 不会周期性过期,但当前 Tailscale REST 标签/设备自动化能力比 API-token 模式更窄。
凭据优先使用系统钥匙串(macOS Keychain、Linux Secret Service、Windows Credential Manager)。明文 0600 文件回退仅在 macOS/Linux 证明旧钥匙串值不存在或已删除后允许;钥匙串不可达或状态不确定时拒绝写入,应恢复访问后重试。Windows 不允许凭据文件回退。无头运行本身不保证可以回退。
API 令牌生成地址:管理后台 → Keys。OAuth 密钥生成地址:管理后台 → OAuth(点击 "+ credential" → "OAuth client" → 按所需 API 操作配置 scopes → 复制 client secret)。
API 访问令牌会过期,TSLink 会记录过期时间。传 --expires-in 或 --expires-at 时按你声明的值存储;两个都不传时,TSLink 按 90 天上限假定,并记录 expires_at_source=assumed_max,这样后续 tslink doctor 能区分「假定的期限」和「声明的期限」,而不会把猜测当成事实。
--open-keys-page 和 --open-oauth-page 是引导辅助命令,不是登录方式。只有当 stdin 是交互式终端且 CI 未设置时才真的打开浏览器,否则打印 URL 和引导步骤。两种情况下都以退出码 0 结束且不存储任何东西,因此可以安全地在「还在找凭证从哪来」的脚本里运行。
tslink logout#
清除 Tailscale 认证状态并移除已存储的凭证(API 密钥和/或 OAuth 客户端密钥)。在登出之前必须先停止网关。
tslink logout这会从系统钥匙串中移除所有凭证(以及旧文件),并移除 ~/.config/tslink/ 中的节点状态。你的服务注册表(registry.json)会被保留。
Flags:
| Flag | 说明 |
|---|---|
--kind <api-key|client-secret> | 只移除该凭证槽位及其 metadata;节点状态和另一个槽位保留 |
用 --kind 可以在保留另一个凭证继续可用的前提下退役其中一个,例如把自动化从 OAuth client secret 迁移到 API 访问令牌之后。
服务管理
tslink add <名称>#
默认 add 会确保后台网关运行,可能返回授权交接。完成授权后用 url --wait;不要在默认 add 后再启动另一个 serve。同名条目会被替换。
注册一个新服务以暴露到你的 tailnet。必须提供 --proxy、--dir 或 --tcp 之一。
服务类型标志:
| 标志 | 描述 | 示例 |
|---|---|---|
--proxy <目标> | 反向代理到本地 Web 服务 | --proxy localhost:3000 |
--dir <路径> | 通过 HTTPS 暴露文件目录 | --dir ~/Documents/shared |
--tcp <host:port> | 原始 TCP 代理(数据库、自定义协议) | --tcp localhost:5432 |
行为标志:
| 标志 | 描述 | 要求 |
|---|---|---|
--ephemeral | 请求临时节点;控制面按不活跃状态清理,而非断开即移除 | 任何类型 |
--tags <标签> | 逗号分隔的 ACL 标签(如 tag:web,tag:internal)。省略时使用默认标签(tag:tsmain)。 | 任何类型 |
--allow <身份> | proxy/file HTTP 服务的允许身份。拒绝与 --tcp 和 --funnel 组合;原始 TCP 由 Tailscale ACL/tag 和目标服务自身认证保护。 | --proxy 或 --dir |
--funnel | 请求通过 Tailscale Funnel 公开暴露 | 仅 --proxy |
--public | 确认 --funnel 会将代理服务暴露到公共互联网 | --funnel |
--funnel-ttl <时长> | 访问期限至少 1h,默认 24h,公网上限默认 7d;支持相对/绝对形式,新的公开拒绝 never。 | --funnel |
--no-auto-provision | 关闭 Funnel policy 自动 provisioning | --funnel |
--control-url <URL> | 服务级控制服务器 URL(如 Headscale) | 任何类型 |
--no-daemon-install | 只保存配置,不安装也不启动后台服务 | 任何类型 |
--dry-run | 校验并打印服务,不写 registry、不启动网关,默认 false | 任意类型 |
--wait <时长> | 等待一个精确的 runtime URL 或 enrollment URL(默认 30s;--wait=0 表示注册后不等待) | 任何类型 |
其他标志:
| Flag | 说明 |
|---|---|
--ack-unlimited-request-body | 明确确认移除 HTTP 请求体上限;需 --max-request-body unlimited。 |
--force-unsafe-public | 危险:覆盖 recipe 的 never-public 拒绝,可能公开主机控制或私有数据;需 --funnel --public,add 还需 --recipe。 |
--health-body | 匹配前 64 KiB 正文中的子串,仅 proxy;勿把秘密放入参数。 |
--health-interval | 后端检查间隔,10s 至 1d,默认 1m。 |
--health-path | HTTP 后端检查路径,默认 /,仅 proxy。 |
--health-status-max | HTTP 期望状态上限,默认 299,仅 proxy。 |
--health-status-min | HTTP 期望状态下限,默认 200,仅 proxy。 |
--health-timeout | 后端检查超时,100ms 至 30s,默认 5s。 |
--idle-timeout | HTTP keep-alive 空闲超时,默认 60s。 |
--max-request-body | HTTP 上传上限,默认 32MiB;unlimited 需 --ack-unlimited-request-body。 |
--preserve-host | 转发节点可信的 canonical 外部 Host,仅 proxy;普通注册默认关闭,recipe 有自己的默认值。 |
--recipe | 应用 recipe ID;默认预览,--yes 应用。 |
--request-header-timeout | HTTP header 读取超时,默认 10s。 |
--request-read-timeout | 请求体无读取进展的最长时间,默认 30s,不是总上传时长。 |
--yes | 应用审阅过的 recipe plan;add 需要 --recipe。 |
--requestable | 明确在私有 portal 请求表单披露此应用名称;仅私有 HTTP/文件,默认关闭。 |
示例:
# 暴露一个 Web 应用
tslink add webapp --proxy localhost:3000
# 暴露一个 API 服务器,带 ACL 标签
tslink add api --proxy 127.0.0.1:8080 --tags tag:api,tag:prod
# 暴露一个目录用于文件共享
tslink add docs --dir ~/Documents/shared
# 通过 TCP 暴露 PostgreSQL 数据库
tslink add mydb --tcp localhost:5432
# 请求临时节点;本地注册保留至主动移除
tslink add devserver --proxy :8080 --ephemeral
# 通过 Tailscale Funnel 公开访问
tslink add public-site --proxy localhost:3000 --funnel --public
# 限制特定用户访问
tslink add internal --proxy localhost:9090 --allow user@example.com,tag:admin
# 为该服务指定控制服务器
tslink add headscale-app --proxy localhost:3000 --control-url https://headscale.example.comtslink remove <名称>#
按名称移除已注册的服务。本地 registry 移除会立即完成。本地 tsnet state 只有在远端身份被证明已清除后才删除;daemon 运行时由其 reconciliation 负责删除 state。远端 tailnet 清理只有在 TSLink 拥有匹配设备的精确所有权证明时才会尝试;否则匹配候选会报告为 protected,并跳过清理。
tslink remove webappremove 是幂等的。移除一个从未注册过的名字是一次成功调用,只是什么都没移除,所以要回答「服务是否已经没了」看 removed 而不是 ok:
{"type":"tslink.result","ok":true,"schema_version":1,"command":"remove","code":0,"data":{"name":"docs-example-nonexistent","removed":false,"device_cleaned":false,"device_cleanup_skipped":false}}如果网关正在运行,服务将通过热重载移除,无需重启。
Flags:
| Flag | 说明 |
|---|---|
--strict | 服务不存在时返回 not_found(退出码 5),而不是上面那种幂等成功 |
幂等是清理脚本该有的默认行为:重跑第二遍不应该失败。--strict 面向相反的场景 —— 调用方希望「这个名字确实注册过」成为一个被强制检查的前置条件。
tslink list#
以表格格式显示所有已注册的服务,无论网关是否运行。
tslink list输出列:
| 列 | 描述 |
|---|---|
NAME | 服务在 tailnet 上的主机名 |
TYPE | 服务类型(proxy、file 或 tcp) |
BACKEND | 本地目标(proxy/tcp 为 host:port,file 为路径) |
ENDPOINT | 预期的 tailnet 端点类型 |
EXPOSURE | 暴露方式(tailnet、allow-list 或 Funnel) |
标志:
| 标志 | 描述 |
|---|---|
--name <name> | 只返回名字完全匹配的那个服务 |
--type <type> | 按服务类型过滤:proxy、file 或 tcp |
--fields <list> | --json 视图的逗号分隔精简字段 |
--verbose | 返回完整的 owner-only 诊断视图 |
--tailnet | 只读:列出整个 tailnet 中每一台带 TSLink 标签的设备,而非本机已注册的服务 |
tslink list --tailnet#
默认列表读的是本机的 ~/.config/tslink/registry.json。--tailnet 改为查询 Tailscale API,报告 tailnet 中每一台带 TSLink 标签的设备:本机注册的服务、其它机器注册的服务,以及孤儿节点。它回答的是单机注册表回答不了的跨机器问题。
tslink list --tailnet
tslink list --tailnet --json每一行都标明它来自机器边界的哪一侧:
origin | 含义 |
|---|---|
local_registry | 本机 registry.json 中有一个主机名完全相同的服务 |
local_name_variant | 该主机名是本机某个已注册服务的 <service>-N tsnet 冲突变体,这是本机留下孤儿节点的常见形态 |
unregistered | 本机注册表对该主机名一无所知:它是另一台机器的服务,或是一个孤儿节点 |
人类可读输出以 N of M TSLink-owned tailnet devices are not registered on this machine. 结尾,JSON 负载在 count 之外还带 registered_count 与 unregistered_count。每个结果都带一个常量字段 cleanup_authority,因为这个视图暴露了一条真实的限制:tslink cleanup 只删除精确 NodeID 记录在本机 node-ownership.json 中的设备,所以本机注册表没有命名的设备,必须回到创建它的那台机器上清理。--tailnet 永远不输出 NodeID,也永远不删除任何东西。
--tailnet 需要已存储的 Tailscale API 凭证(tskey-api-* 访问令牌或 OAuth 客户端密钥)。没有凭证时它以 auth_error(退出码 3)失败,并在 error.next 中给出 bootstrap 指引;它不会返回空列表。它与 --name、--type、--fields、--verbose 互斥(usage_error,退出码 2),因为那些 flag 过滤的是本机已注册服务,而 --tailnet 报告的是 tailnet 设备。
tslink share <path|port|host:port>#
注册一个一次性的 proxy 或 file 服务,需要时启动 daemon,并等待一个精确的 runtime URL——这是从零到一个 URL 最快的路径。已存在的目录会作为 file 服务暴露其内容;普通文件只暴露选中的文件并返回该文件的 URL,不暴露同级文件或父目录列表;裸端口或 host:port 目标会变成 HTTP 代理。分享默认是临时(ephemeral)的,重复分享同一目标会复用已有服务,而不是创建带后缀的孤立节点。
tslink share ./build
tslink share ./report.html # URL 直接指向 report.html
tslink share 3000
tslink share localhost:8080 --name preview
tslink share ./build --ephemeral=false在零凭据首次运行时,stdout 只有一行——Tailscale 授权 URL,stderr 会打印出精确的续接命令(tslink url <name> --wait)。加 --json 时,这是一个成功的 status:"needs_login" 结果,携带 auth_url——不是认证错误。
标志:
| 标志 | 描述 |
|---|---|
--name <名称> | 请求的服务名(DNS label)。匹配的目标会复用它;不相关的名字冲突会得到一个数字后缀,而不是覆盖已有服务。 |
--ephemeral | 使用临时 tailnet 节点(默认 true;传 --ephemeral=false 获得持久状态) |
--wait <时长> | 等待一个精确的 runtime URL(默认 30 秒;与 tslink url 不同,share 不需要传这个标志就会等待) |
--no-daemon-install | 要求后台服务已在运行;不去安装它 |
| Flag | 说明 |
|---|---|
--ack-unlimited-request-body | 明确确认移除 HTTP 请求体上限;需 --max-request-body unlimited。 |
--idle-timeout | HTTP keep-alive 空闲超时,默认 60s。 |
--max-request-body | HTTP 上传上限,默认 32MiB;unlimited 需 --ack-unlimited-request-body。 |
--preserve-host | 转发节点可信的 canonical 外部 Host,仅 proxy;普通注册默认关闭,recipe 有自己的默认值。 |
--request-header-timeout | HTTP header 读取超时,默认 10s。 |
--request-read-timeout | 请求体无读取进展的最长时间,默认 30s,不是总上传时长。 |
tslink url <name>#
打印一个已注册服务的精确 runtime URL,可选择等待它就绪。
tslink url myapp
tslink url myapp --wait
tslink url myapp --wait --raw标志:
| 标志 | 描述 |
|---|---|
--wait [时长] | 只有传入时才等待精确 runtime URL;裸 --wait 表示 30 秒 |
--raw | 只打印 URL 和一个换行符,不带 JSON envelope;与 --json 冲突 |
如果 runtime 尚未报告精确的 tailnet 主机名,且你没有传 --wait,tslink url 会以非零状态退出,error.code 为 url_not_ready,而不是打印占位符。
网关
tslink serve#
启动 TSLink 网关。为每个已注册的服务启动一个嵌入式 tsnet 节点并开始服务。
标志:
| 标志 | 描述 |
|---|---|
--daemon | 作为守护进程在后台运行 |
--control-url <URL> | 自定义控制服务器 URL(如 Headscale)— 覆盖全局配置 |
--manage-acl | 显式开启普通启动 tag-owner ensure;另行确认公开的 Funnel auto-provisioning 仍默认开启 |
--mcp | 在专用的 tailnet-only 节点上提供远程 MCP 控制面;默认关闭,且要求 config.json 中配置非空 owner mcp.allow 或明确 mcp.bindings。参见远程 MCP 控制面 |
--no-auto-provision | 对本次 serve 进程内的所有服务关闭 Funnel policy 自动 provisioning |
--no-browser | 打印 Tailscale 登录 URL,不打开浏览器 |
# 在前台运行
tslink serve
# 作为后台守护进程运行
tslink serve --daemon
# 使用 Headscale 控制服务器(单次覆盖)
tslink serve --control-url https://headscale.example.com启动时,TSLink 自动:
- 解析凭证并为每个服务启动一个 tsnet 节点。
- 使用
--manage-acl和具有所需 scopes 的凭据配置普通 tag-owner policy。显式公开的 Funnel 默认配置共享 grant,除非--no-auto-provision或服务设置关闭。准确所有权设备清理是独立 API 操作。 - 监视
registry.json的变化并热重载服务。
tslink stop#
停止正在运行的 TSLink 网关(前台或守护进程)。读取 tslink.pid 并验证进程属于 TSLink,最多等待 5 秒终止。macOS/Linux 使用 SIGTERM 正常关闭;Windows 使用进程终止,不是正常关闭。
stop 不会移除自动启动注册。受管理的 macOS LaunchAgent 启用了 KeepAlive,停止后会按 30 秒节流重启;需要持续停止时先执行 tslink uninstall。Linux systemd 用户服务的重启策略是 on-failure,成功的正常关闭会让它保持停止。Windows 的启动注册在卸载前仍会于下次登录生效。卸载后,停止任何剩余的手动网关,再用 tslink status --json 验证后才删除状态。
tslink stoptslink status#
JSON 的 data.supervision 报告已验证的 manager、installed、autostart、restart_on_exit,以及可选 detail / evidence / autostart_scope。它与 daemon_running 分开;进程存活不证明自动启动或监督有效。
显示 TSLink 网关的当前状态:守护进程状态、认证状态和已注册服务数量。
tslink status输出示例:
→ tslink: running (pid 12345)
→ tailnet: authenticated
→ services: 3 registeredFlags:
| Flag | 说明 |
|---|---|
--urls | 显示仅限所有者可见的服务端点概览 |
--name <name> | 按准确服务名过滤 --urls;要求 --urls |
--urls 打印每个服务的可达位置。这是 owner-only 输出:它列出的端点就是你自己注册表里定义的那些,因此请按对待注册表本身的方式对待这份结果。
标签管理
tslink tags#
管理 TSLink 服务的 ACL 标签。API-key 模式可以通过 Tailscale API 创建或拉取标签;client-secret-only 模式不要在验证前依赖标签/设备自动化。
子命令:
| 子命令 | 描述 |
|---|---|
list | 列出所有已注册服务及其标签 |
pull | 从 Tailscale API 打印当前 ACL 标签 |
add <服务> <标签> | 为特定服务添加标签 |
set <服务> <标签> | 用一个标签替换特定服务的标签 |
set-default <标签> | 设置未指定 --tags 时使用的默认标签 |
delete-remote <标签> --force --manage-acl | 通过本地安全检查和显式远端 ACL opt-in 后,经 API 从 Tailscale ACL 策略中全局移除 ACL 标签所有者规则 |
tslink tags list#
列出所有已注册服务及其标签。
tslink tags listtslink tags pull#
从 Tailscale API 打印当前 ACL 标签。 client-secret-only 模式会跳过该远端拉取,因为它需要 API 访问令牌。
tslink tags pulltslink tags add <服务> <标签>#
为特定已注册服务添加标签。
tslink tags add webapp tag:stagingtslink tags set <服务> <标签>#
用一个标签替换特定服务的标签。
tslink tags set webapp tag:webtslink tags set-default <标签>#
设置未指定 --tags 时应用于服务的默认标签。持久化在 GlobalConfig.DefaultTag 中。
# 将默认值从 tag:tsmain 更改为自定义标签
tslink tags set-default tag:myteamtslink tags delete-remote <标签> --force --manage-acl#
通过本地安全检查后,经 API 从 Tailscale ACL 策略中全局移除 ACL 标签所有者规则。此操作会全局修改你的 tailnet ACL 策略,且远端 ACL mutation 默认关闭,因此必须同时显式传入 --force 和 --manage-acl。
tslink tags delete-remote tag:deprecated --force --manage-acl维护
tslink cleanup#
对照本地 registry 与 tailnet:停用已过期 Funnel、删除本机具有准确所有权证明且不再需要的设备,并报告本机对共享 Funnel grant 的使用情况。永不删除共享 grant。
# 预览 -- 这是默认行为
tslink cleanup
# 实际执行
tslink cleanup --dry-run=falseFlags:
| Flag | 默认 | 说明 |
|---|---|---|
--dry-run | true | 预览对账结果,不做注册表、设备或 ACL 删除;传 --dry-run=false 才实际执行 |
--manage-acl | false | 只报告本机是否使用共享 Funnel tag-owner / nodeAttrs grant;永不删除共享 grant,也不查询 tailnet ACLs |
--adopt <hostname> | 无 | 为一个字面量 TSLink-tagged 遗留设备 hostname 预览或记录精确 ownership |
--force | false | 确认显式指名的 --adopt 迁移 |
--dry-run 默认为 true,所以裸命令不删除任何东西。这个默认值是安全属性而不是便利性:删除要求持久化的精确 NodeID ownership proof,hostname 匹配仅用于发现。hostname 匹配上但 NodeID 未被证明的设备会出现在 devices_protected 里,永不删除。
--adopt 面向那些在 ownership proof 机制之前创建的设备。它只接受一个字面量 hostname,写入 proof 要求恰好一个 TSLink-tagged 远端匹配,外加 --force --dry-run=false;匹配多于一个时报 cardinality 冲突而不是替你猜。预览过程是只读的。
JSON envelope 会说明这次 cleanup 为什么什么都没做 —— 这比「它没做事」这个事实本身更重要:device_cleanup_skipped 配合 device_skip_reason 区分了 registry.json 结构上不可信、ownership ledger 不可用、orphan 缺少 retired_at provenance、没有可用的 API client、hostname-only 匹配受保护、以及远端清理失败这几种情况。输出中永远不出现 NodeID,只出现 hostname。
tslink registry#
直接检视本地服务注册表,不经过 runtime。
tslink registry check [path]#
严格校验一份 registry.json 并报告其中所有问题,且不修改文件。不带参数时校验当前生效的注册表;传路径则校验别处的文件,例如你正准备安装的候选文件,或来自另一台机器的副本。
tslink registry check
tslink registry check ./candidate-registry.json --json返回结果包含 path、schema_version、valid_services、total_services,以及一个 issues[] 数组,其中每一项用 index 和 name 指名出问题的服务,并带稳定的 code 和给人读的 message。所有被拒绝的条目在一次调用中全部报出,因此 valid_services 小于 total_services 时,你能准确知道 runtime 会丢弃哪些服务、以及为什么,而不是只看到 loader 恰好最先撞上的那一个问题。
邀请
tslink invite#
邀请某个人加入你的 tailnet,或把某个 TSLink 拥有的服务设备共享给 tailnet 之外的人。
这里的每个子命令都会通过 Tailscale API 产生对外副作用:真实的人会收到真实的邀请。它们是 TSLink 中仅有的、效果能被你之外的人感知到的命令,因此每一条都显式指名收件人、要求由 tslink login 存储的 user-owned tskey-api- 令牌,并在 JSON envelope 中返回一个记录本次发送内容的 remote_side_effect_plan 对象。
设备共享还有第二重要求:TSLink 只共享它自己注册的设备,按精确 nodeId 匹配。无法证明归属的设备永远不会成为候选,因此打错服务名的结果是失败,而不是共享出一台不相干的机器。
子命令:
| 子命令 | 说明 |
|---|---|
user <email> | 邀请一个用户加入 tailnet |
device <service> <email> | 把一个 TSLink 拥有的服务设备共享给外部用户 |
list | 列出未接受的用户邀请和 TSLink 拥有的设备邀请 |
revoke <id> --kind <user|device> | 撤销一个用户或设备邀请 |
resend <id> --kind <user|device> | 重发一个以邮件方式创建的用户或设备邀请 |
tslink invite user <email>#
邀请一个人加入你的 tailnet。
tslink invite user teammate@example.com
tslink invite user teammate@example.com --role auditor
tslink invite user teammate@example.com --print-link| Flag | 默认 | 说明 |
|---|---|---|
--role <角色> | member | 接受邀请后分配的角色:member、admin、it-admin、network-admin、billing-admin、auditor |
--print-link | false | 不发邮件;返回 API 提供的邀请 URL 供你自行送达 |
--print-link 改变的是由谁送达邀请,不是谁可以接受邀请。JSON envelope 明确陈述送达事实而不是暗示它:Tailscale 发出邮件时 emailed: true,你自行送达时 emailed: false 并附带 invite_url。该 URL 由 Tailscale API 原样返回 -- TSLink 从不自行构造 -- 并且它是 bearer 凭证:谁持有谁就能接受。
tslink invite device <service> <email>#
把某个已注册服务背后的设备共享给外部用户,让对方无需加入你的 tailnet 就能访问那一台机器。
tslink invite device my-api partner@example.com
tslink invite device my-api partner@example.com --multi-use| Flag | 默认 | 说明 |
|---|---|---|
--print-link | false | 不发邮件;返回 API 提供的邀请 URL 供你自行送达 |
--multi-use | false | 允许该设备邀请被接受多次 |
--allow-exit-node | false | 允许接收方把共享设备用作 exit node |
--multi-use 和 --allow-exit-node 各自都会放大这份邀请授予的范围,各自都默认关闭。multi-use 邀请 URL 在第一次被接受之后仍然有效;exit-node 共享则允许接收方把自己的流量路由经过这台机器。
tslink invite list#
列出未接受的用户邀请,以及这个 TSLink 拥有的服务对应的设备邀请。
tslink invite list
tslink invite list --json| Flag | 默认 | 说明 |
|---|---|---|
--show-urls | false | 在人类可读输出和 JSON 输出中包含 bearer 邀请 URL |
URL 默认不打印,因为它们是 bearer 凭证:打印一次就等于把一份可被接受的邀请放进你的终端回滚区,以及任何会捕获它的地方。
JSON envelope 把「空结果」和「不完整结果」区分开。complete: true 表示每个被请求的设备目标都无错误地检查过;false 表示有部分设备结果缺失。device_targets[] 携带逐服务的结果,因此一个已检查、invite_count: 0 的目标读作「没有未接受的邀请」,而不是「没查到」。
tslink invite revoke <id> --kind <user|device>#
撤销一个未接受的邀请。
tslink invite revoke 12345 --kind user| Flag | 默认 | 说明 |
|---|---|---|
--kind <user|device> | 必填 | 邀请命名空间 |
--kind 刻意没有默认值。用户邀请 ID 和设备邀请 ID 是两个独立的数字命名空间,同一个数字可以在两边各指向一个邀请;要求显式给出命名空间,是为了让目标是被指定的而不是被猜出来的。撤销设备邀请还要求精确的 TSLink 节点 ownership proof。只有在 Tailscale API 接受撤销之后才会出现 revoked: true。
tslink invite resend <id> --kind <user|device>#
重发一个最初以邮件方式创建的邀请。
tslink invite resend 12345 --kind user| Flag | 默认 | 说明 |
|---|---|---|
--kind <user|device> | 必填 | 邀请命名空间 |
用 --print-link 创建的邀请没有邮件地址,无法重发。重发输出也不会再次打印邀请 URL:把一份 bearer 凭证重印到第二个界面上没有任何收益,因此结果只报告 emailed 就停下。
诊断、访问解释与模板
tslink doctor#
运行本地诊断,并通过与其它命令相同的 JSON envelope 和退出码 contract 返回 warning/critical 阈值。
Flags:
| Flag | 说明 |
|---|---|
--probe-external | 探测非 loopback 的服务目标 |
--probe-remote | 用一次 device-list 读取向 Tailscale API 验证每个已存储凭证,并把 last_verified 记入 credential-meta.json |
两者默认关闭,因为两者都会伸到本进程之外:--probe-external 会向非 loopback 目标建立连接,--probe-remote 每个已存储凭证消耗一次 Tailscale API 调用。默认运行保持在本地且不产生费用。
Doctor 还会从本机 tailscaled 读取并报告本节点是否开启了 Tailscale SSH。人类可读输出打印 Tailscale SSH (this node): <state>;JSON 负载带有 tailscale_ssh.state 与 tailscale_ssh.acl_rule_required: true。这项检查存在的原因是:tailscale ssh <host> tslink <command> 是从 tailnet 内另一台机器操作这份安装的零代码路径,而这条路径需要两个都位于 Tailscale 层的条件:本节点开启了 Tailscale SSH,且 tailnet ACL 中有一条允许调用者的 ssh 规则。TSLink 只检测第一个条件并指出两者;它不会开启 Tailscale SSH,也不会修改 policy 文件。
| 状态 | Finding code | 含义 |
|---|---|---|
enabled | tailscale_ssh_enabled | 一旦 tailnet ACL 有 ssh 规则允许调用者,tailscale ssh <this-host> tslink list --json 即可用 |
disabled | tailscale_ssh_disabled | 在这台机器上运行 tailscale set --ssh 并添加 ACL ssh 规则,才能使用远程路径 |
unknown | tailscale_ssh_unknown | 一秒内无法读取本机 Tailscale client 状态;检查 tailscale status |
三种结果都是 informational,永远不会改变 doctor 的 status 或退出码。
tslink access explain#
解释一个已注册服务如何被访问,包括 tailnet endpoint、--allow 行为和 Funnel 暴露。
tslink template list#
列出内置个人模板。
tslink template show#
显示一个内置模板定义。
tslink template apply#
应用内置模板。使用 --dry-run 可在不写入 registry 的情况下预览 plan。
| 标志 | 描述 |
|---|---|
--dry-run | 预览模板 plan,不写入 registry |
--yes | 把模板里缺失的服务写入 registry |
--no-daemon-install | 只应用配置,不安装也不启动后台服务 |
配置
tslink config#
管理持久化在 ~/.config/tslink/config.json 中的全局 TSLink 设置。
子命令:
| 子命令 | 描述 | 示例 |
|---|---|---|
set <键> <值> | 设置配置值 | tslink config set control-url https://hs.example.com |
get <键> | 获取配置值 | tslink config get control-url |
list | 列出所有配置值 | tslink config list |
可用配置键:
| 键 | 描述 | 默认值 |
|---|---|---|
control-url | 自定义控制服务器 URL(Headscale) | Tailscale 默认 |
# 设置 Headscale 控制服务器
tslink config set control-url https://headscale.example.com
# 查看当前值
tslink config get control-url
# 清除(恢复 Tailscale 默认)
tslink config set control-url ""
# 显示所有设置
tslink config listtslink logs#
查看 TSLink 守护进程日志输出。默认读取 stderr 日志(tslink.err.log)的最后 50 行。
标志:
| 标志 | 描述 | 默认值 |
|---|---|---|
--last <N> | 显示的行数 | 50 |
--level <级别> | 按最低日志级别过滤(debug、info、warn、error) | (无) |
--source <源> | 日志源:out(标准输出)或 err(标准错误) | err |
# 显示最后 50 行日志
tslink logs
# 显示最后 100 行
tslink logs --last 100
# 仅显示错误
tslink logs --level error
# 显示标准输出日志
tslink logs --source out
# JSON 输出
tslink logs --last 20 --json系统
tslink install#
注册 TSLink 为开机自启动。
tslink install- macOS:创建 LaunchAgent(
~/Library/LaunchAgents/com.tslink.daemon.plist) - Linux:创建 systemd 用户服务(
~/.config/systemd/user/tslink.service) - Windows:注册交互用户 Task Scheduler 任务,启动内建 supervisor 并恢复 daemon 崩溃。
--startup为明确选择的 fallback,无崩溃恢复。
| Flag | 含义 |
|---|---|
--force | 仅 macOS;Linux/Windows 不支持。即使 launchd 域不可用也继续升级(可能启动第二个守护进程) |
--no-auto-provision | 在已安装后台服务中关闭自动 Funnel policy provisioning,并在受管理重启后保留 |
在 macOS 上,gui/$(id -u) 只在该用户存在桌面(Aqua)会话时才存在。可用性取决于会话本身,而不是你是否通过 SSH 连接。首次安装会回退到 user/$(id -u);升级时若某个曾经使用过的域无法检查,则拒绝执行,因为 TSLink 无法证明那个域是空的。该拒绝以 exit 1 返回,error.code 为 launchctl_domain_unavailable,其 data 给出不可用的域、完整的 --force 命令以及残留风险。
| Flag | 说明 |
|---|---|
--startup | 仅 Windows:明确使用 Startup fallback,无崩溃恢复。 |
tslink uninstall#
移除自启动注册。
tslink uninstall| Flag | 含义 |
|---|---|
--force | 仅 macOS;Linux/Windows 不支持。即使 launchd 域不可用也移除 plist(可能留下一个仍在运行的守护进程) |
同样的域规则适用。当没有任何域确认任务已卸载、且至少有一个域无法检查时,uninstall 保留 plist 并以 exit 1 退出,使恢复句柄得以保存。--force 会照样移除它,并说明如何检查以及如何移除可能仍在加载的任务。
编程式访问
已发布 manifest 中的命令,除 stdio 的 tslink mcp 服务器外,都接受 --json,并向 stdout 写出一个带版本的信封,因此 owner 侧自动化就是同一套 CLI 加一个 flag。Cobra 的 help 和 completion 命令不在 manifest 中,只输出纯文本。MCP client 通过 tslink mcp 或远程 MCP 控制面执行同样的操作。
常见自动化命令:
| 自动化 action | 当前入口 |
|---|---|
list | tslink list --json |
add | tslink add <name> --proxy <host:port> --json(或 --dir、--tcp) |
remove | tslink remove <name> --json |
status | tslink status --json |
doctor | tslink doctor --json |
access_explain | tslink access explain <name> --json |
template_list | tslink template list --json |
template_plan | tslink template apply <template> --dry-run --json |
template_apply | tslink template apply <template> --yes --json |
manifest | tslink manifest --json |
# 列出本机已注册的服务
tslink list --json
# 添加服务
tslink add myapp --proxy localhost:3000 --json
# 删除服务
tslink remove myapp --json
# 查看状态
tslink status --json
# 运行只读诊断
tslink doctor --json
# 解释一个服务的本地访问模型
tslink access explain myapp --json
# 先预览、再应用内置模板
tslink template list --json
tslink template apply local-web --dry-run --json
tslink template apply local-web --yes --json--json 只改变输出格式。tslink add --json 与人类路径使用同一套安全护栏:Funnel 服务必须传 --public,TCP 服务会拒绝 --allow,因为 TSLink 不会对原始 TCP 字节流应用 HTTP 身份检查。
每个 --json 响应都使用 JSON 输出格式 一节描述的带版本信封:命令载荷放在 data 下,结构化错误放在 error 下,command 记录产生该输出的命令。一次成功(在没有任何服务的机器上执行 tslink list --json)如下:
{"type": "tslink.result", "ok": true, "schema_version": 1, "command": "list", "code": 0, "data": {"schema_version": 1, "services": [], "count": 0}}一次用法错误(tslink list --tailnet --verbose --json)如下:
{"type": "tslink.result", "ok": false, "schema_version": 1, "command": "list", "code": 2, "error": {"code": "usage_error", "message": "--tailnet conflicts with --verbose; --verbose filters this machine's registered services, while --tailnet reports tailnet devices", "next": ["tslink --help"]}}MCP client 可以通过 tslink mcp(stdio)以及 tslink serve --mcp 启动的 tailnet-only 远程控制面执行同样的操作;参见 TSLink 作为 MCP 服务器。
tslink mcp#
在本地通过 stdio 启动一个 Model Context Protocol 服务器,让 MCP 客户端把 TSLink 当作工具来驱动,而不必解析 CLI 输出。它在 stdin/stdout 上使用按行分隔的 JSON-RPC 2.0,owner 会话暴露 44 个工具,精简角色更少:从 share、list、unshare、status,到 add、url、tags_*、access_explain、doctor、logs、invite_* 和 template_*。
tslink mcpMCP 进程本身不会打开任何网络监听端口,也不需要 mcp.allow 条目;share 可能会启动独立的 TSLink daemon 和它请求的 tsnet 服务。协议帧走 stdout、诊断信息走 stderr,因此这里会拒绝 --json:stdout 已被协议帧独占。
tslink serve --mcp 在一个专用的 tailnet-only tsnet 节点上通过 HTTPS 提供依角色变化的工具集合(owner 为 44 个),供 tailnet 内其它机器上的 MCP client 使用。它默认关闭,且要求 config.json 中配置非空 owner mcp.allow 或明确 mcp.bindings。
客户端配置、完整的工具 schema、远程控制面和端到端示例,请看 TSLink 作为 MCP 服务器。
| 选项 | 说明 |
|---|---|
--apps | 精简 MCP 会话可见的逗号分隔应用。 |
--inventory | 明确允许 viewer 读取全部应用清单;不授予应用访问或访问历史。 |
--max-duration | 单应用人员授权的最长时长;精简本地 operator/manager 默认 24h。 |
--scope | MCP 角色:owner、viewer、app-operator 或 people-manager;默认 owner。 |
tslink manifest#
打印已安装二进制文件对自身的机器可读描述:每个命令、每个标志、退出码、错误码、凭据来源,以及导出的安全能力清单。这是 agent——以及本文档站点自己的 parity 检查——用来确认某个具体安装的构建实际支持什么,而不是相信文字描述的方式。
tslink manifest 对 tslink --help 隐藏(它是面向机器的命令,不是人类的操作步骤),但它和其它子命令一样可以直接运行:
tslink manifest # 完整 manifest,缩进 JSON
tslink manifest --compact # 仅命令、标志和稳定错误码
tslink manifest --json # 完整 manifest,包在标准 --json envelope 里标志:
| 标志 | 描述 |
|---|---|
--compact | 只打印命令、标志和稳定错误码 |
本文档站点的 CLI parity 检查(pnpm parity:check)把已提交的 fixture 与这份 manifest 的形状逐项比对;该 fixture 由 TSLink 自己的 go run ./tools/gen-manifest 生成,不是手工维护的。
Roadmap / Experimental 命令和字段
关于 roadmap 命令和字段(middleware、Docker 集成、Admin REST API、自定义域名/ACME)的详情,请参阅实验性与路线图。
全局标志
| 标志 | 描述 |
|---|---|
--json | 带版本 CLI JSON;tslink mcp 因 stdout 保留给协议 frames 而拒绝 |
--version | 显示已安装版本 |
--help | 显示任何命令的帮助信息 |
tslink --help
tslink add --help
tslink status --json退出码
所有命令返回语义化退出码,便于程序化错误处理:
| 退出码 | 含义 | 示例 |
|---|---|---|
| 0 | 成功 | 命令完成 |
| 1 | 一般错误 | 意外失败 |
| 2 | 用法错误 | 无效的参数或标志 |
| 3 | 认证错误 | 缺少或无效的凭证 |
| 4 | 冲突 | tslink serve 时已在运行 |
| 5 | 未找到 | tslink url 指向不存在的服务。tslink remove 是幂等的:移除一个未注册的名字是一次成功调用,只是什么都没移除(removed: false,exit 0) |
| 64 | 警告 | tslink doctor 完成但有警告 |
| 65 | 严重 | tslink doctor 发现严重问题 |
JSON 输出格式
传递 --json 时,CLI 命令输出 JSON 信封;tslink mcp 是明确的例外:
{
"type": "tslink.result",
"ok": true,
"schema_version": 1,
"command": "status",
"code": 0,
"data": {
"supervision": {
"manager": "none",
"installed": false,
"autostart": false,
"restart_on_exit": false,
"detail": "No launchd ownership/autostart could be verified. Run: tslink install"
},
"daemon_running": false,
"daemon_state": "absent",
"daemon_pid": 0,
"ownership_proof_available": true,
"authenticated": false,
"credential_stored": false,
"credentials": {
"api_key": {
"present": false,
"expiry_state": "none",
"early_warning": {
"state": "none",
"source": ""
}
},
"client_secret": {
"present": false,
"expiry_state": "none",
"early_warning": {
"state": "none",
"source": ""
}
}
},
"credential_expiry_state": "none",
"node_authorized": false,
"authorized_service_count": 0,
"auth_status": "not_authenticated",
"service_count": 0,
"services": [],
"guest_links": [],
"access_log": {
"current": false,
"enabled": true,
"last_write": null,
"drops": 0,
"size_bytes": 0,
"error": "access_log_not_started",
"updated_at": "0001-01-01T00:00:00Z"
},
"portal": {
"enabled": false,
"state": "disabled"
},
"alerts": {
"notifier": "none",
"events": []
}
}
}错误时,error 字段是带稳定字符串 code 的结构化对象。下面是网关未运行时 tslink url nonexistent --json 的实际前提错误;即使名称不存在,也会先返回 exit 1 / daemon_not_running。网关运行后,对不存在服务的查询才会到达 exit 5 / not_found:
{
"type": "tslink.result",
"ok": false,
"schema_version": 1,
"command": "url",
"code": 1,
"error": {
"code": "daemon_not_running",
"message": "TSLink is not running; install and start its background service with 'tslink install'",
"next": [
"tslink install"
]
}
}应用与访问者
tslink apps#
通过 recipes 列出、发现和分享自托管应用,不安装或配置应用。
tslink apps list#
列出带版本的 recipe catalog 与应用侧配置建议。
tslink apps detect#
只读、有限的 loopback HTTP GET 指纹检测。部分结果返回 complete: false;匹配不能证明认证或健康。
tslink apps share#
默认预览,--yes 才应用,--dry-run 优先。保留已有名称;先核对应用登录、proxy trust、健康路径与主机端口。
| Flag | 说明 |
|---|---|
--ack-unlimited-request-body | 明确确认移除 HTTP 请求体上限;需 --max-request-body unlimited。 |
--allow | 私有 HTTP 身份,逗号分隔;与 Funnel 冲突。 |
--control-url | 自定义控制服务器 URL;不能与 Funnel 同用。 |
--dry-run | 只预览,不写入,即使同时使用 --yes。 |
--ephemeral | 请求临时节点,不会自动删除本地注册信息。 |
--force-unsafe-public | 危险:覆盖 recipe 的 never-public 拒绝,可能公开主机控制或私有数据;需 --funnel --public,add 还需 --recipe。 |
--funnel | 公共互联网暴露,需 --public;不支持人员授权或 --allow。 |
--funnel-ttl | 访问期限至少 1h,默认 24h,公网上限默认 7d;支持相对/绝对形式,新的公开拒绝 never。 |
--health-body | 匹配前 64 KiB 正文中的子串,仅 proxy;勿把秘密放入参数。 |
--health-interval | 后端检查间隔,10s 至 1d,默认 1m。 |
--health-path | HTTP 后端检查路径,默认 /,仅 proxy。 |
--health-status-max | HTTP 期望状态上限,默认 299,仅 proxy。 |
--health-status-min | HTTP 期望状态下限,默认 200,仅 proxy。 |
--health-timeout | 后端检查超时,100ms 至 30s,默认 5s。 |
--idle-timeout | HTTP keep-alive 空闲超时,默认 60s。 |
--max-request-body | HTTP 上传上限,默认 32MiB;unlimited 需 --ack-unlimited-request-body。 |
--name | 覆盖 recipe 默认服务名。 |
--no-auto-provision | 禁用 Funnel policy 自动配置。 |
--no-daemon-install | 只保存注册表,不安装或启动 daemon。 |
--preserve-host | 转发节点可信的 canonical 外部 Host,仅 proxy;普通注册默认关闭,recipe 有自己的默认值。 |
--proxy | 覆盖实际 loopback HTTP(S) 主机端口。 |
--public | 明确确认 Funnel 将应用公开到互联网。 |
--request-header-timeout | HTTP header 读取超时,默认 10s。 |
--request-read-timeout | 请求体无读取进展的最长时间,默认 30s,不是总上传时长。 |
--tags | 逗号分隔的 tag: 标签;Tier 1 入网仍为用户拥有的无标签节点。 |
--yes | 应用审阅过的 recipe plan;add 需要 --recipe。 |
tslink apps share jellyfin
tslink apps share jellyfin --yestslink people#
管理人员的私有 HTTP/文件访问。TCP 与公共 Funnel 无法按人限制。见人员分享。
tslink people add#
为新访问者授权,--apps 必填。首次授权收紧应用范围。--invite 创建逐应用邀请,--print-links 展示 bearer link。本地授权不需 token;创建邀请需用户自己的 API token。
| Flag | 说明 |
|---|---|
--apps | 私有 HTTP/文件应用,逗号分隔,或当前支持应用的 all;不含未来应用。 |
--for | 访问期限;预设 1h、8h、24h、3d、7d,支持相对或 until <date/time>;新人员默认 24h,update 省略时保留期限。Guest/公开拒绝 never。 |
--invite | 创建或续做逐应用 single-use device invitations,需用户自己的 API token。 |
--print-links | 明确展示 bearer invitation URL;需要 --invite。 |
tslink people add alice@example.com --apps photos --for 7d| 选项 | 说明 |
|---|---|
--ack-never | 明确确认 tailnet 成员永久授权;device-invited guest 不允许。 |
--qr | 把准确 portal URL(portal 停用时首个有效应用)渲染成终端 QR。 |
--qr-invite | 改为指定应用的 bearer 邀请;需 --invite --print-links 加 --qr 或 --qr-png,QR 是凭证。 |
--qr-png | 把私有 QR PNG 写入已存在目录;JSON 只包含 payload 文本。 |
--until | 绝对截止时间:RFC3339、YYYY-MM-DD 或 YYYY-MM-DDTHH:MM,无 offset 时用本地时区;与 --for 互斥。 |
tslink people list#
读取人员、授权、期限与撤销记录,不创建邀请。
tslink people update#
修改应用范围、期限或明确续做邀请。只改应用时保留已有期限,新增应用默认 24h;--for 应用于所有选定应用。查看 complete 与逐应用 state/code。未知 POST 需主人核对后 reconcile;替换邀请保留授权和期限。
| Flag | 说明 |
|---|---|
--apps | 私有 HTTP/文件应用,逗号分隔,或当前支持应用的 all;不含未来应用。 |
--for | 访问期限;预设 1h、8h、24h、3d、7d,支持相对或 until <date/time>;新人员默认 24h,update 省略时保留期限。Guest/公开拒绝 never。 |
--invite | 创建或续做逐应用 single-use device invitations,需用户自己的 API token。 |
--print-links | 明确展示 bearer invitation URL;需要 --invite。 |
--reconcile-invite | 主人核对后指定 app=id 或 app=none 解决未知 POST;update 需 --invite。 |
--replace-invite | 主人确认 app=旧记录ID,远端证实缺失后替换;需 --invite,不能同时 --apps 或 --for。 |
| 选项 | 说明 |
|---|---|
--ack-never | 明确确认 tailnet 成员永久授权;device-invited guest 不允许。 |
--qr | 把准确 portal URL(portal 停用时首个有效应用)渲染成终端 QR。 |
--qr-invite | 改为指定应用的 bearer 邀请;需 --invite --print-links 加 --qr 或 --qr-png,QR 是凭证。 |
--qr-png | 把私有 QR PNG 写入已存在目录;JSON 只包含 payload 文本。 |
--until | 绝对截止时间:RFC3339、YYYY-MM-DD 或 YYYY-MM-DDTHH:MM,无 offset 时用本地时区;与 --for 互斥。 |
tslink people remove#
先保存本地拒绝,再清理待接受邀请。没有 token 也能拒绝;远端清理可能未完成,已接受的网络分享可能保留。新 HTTP/文件请求被拒绝,已有流可继续。
| Flag | 说明 |
|---|---|
--reconcile-invite | 主人核对后指定 app=id 或 app=none 解决未知 POST;update 需 --invite。 |
访问流程与历史
tslink access log#
读取保留的历史与汇总,不调用远程 API、不创建文件/锁。见访问历史。
| 选项 | 类型 / 默认值 | 说明 |
|---|---|---|
--app | string | 按应用/服务过滤。 |
--decision | string | 过滤 allowed 或 denied。 |
--limit | int / 100 | 返回事件数量 1..10000;summary 覆盖所有匹配,默认 100。 |
--since | string | 正 Go duration(如 24h)或 RFC3339 下界。 |
--until | string | RFC3339 上界,包含端点。 |
--who | string | 按 login、节点名或 tag 过滤。 |
tslink access path <app> <prefix|full|off|inherit|true|false>#
设置单应用路径隐私。全局 off 优先,full 可能保存敏感应用路径,inherit 清除本地覆盖。
tslink extend <service>#
把一个人员授权(--person)或 Funnel(省略)设为当前时间加时长,始终返回 JSON。到期需 --regrant,撤销仍拒绝。见期限。
| 选项 | 类型 / 默认值 | 说明 |
|---|---|---|
--ack-never | bool / false | 明确确认 tailnet 成员永久授权;device-invited guest 不允许。 |
--for | string | 访问期限;预设 1h、8h、24h、3d、7d,支持相对或 until <date/time>;新人员默认 24h,update 省略时保留期限。Guest/公开拒绝 never。 |
--person | string | 选择人员在此服务上的授权;省略时选择 Funnel。 |
--regrant | bool / false | 明确重新激活已到期授权或 Funnel;人员撤销仍生效。 |
--until | string | 绝对截止时间:RFC3339、YYYY-MM-DD 或 YYYY-MM-DDTHH:MM,无 offset 时用本地时区;与 --for 互斥。 |
tslink guest#
管理单个 HTTP proxy 应用的浏览器 guest 授权,公网 Funnel 必须有访客 gate。
tslink guest create <app>#
--for 必填,启用 gate 时显式 --public。--print-link 前需私有应用在线,只展示一次 bearer 链接;拒绝 file/TCP 与已有开放 Funnel。见访客链接。
| 选项 | 类型 / 默认值 | 说明 |
|---|---|---|
--for | string | 必填,按共同期限策略选择;预设 1h、8h、24h、3d、7d,访客/公开拒绝 never。 |
--label | string | 主人给链接的备注,不代表身份。 |
--pin | bool / false | 从隐藏终端输入或 stdin 读取 PIN,不得放入 argv。 |
--print-link | bool / false | 明确返回一次 bearer 链接与可发送消息。 |
--public | bool / false | 确认通过 Funnel 暴露公网,并强制访客认证。 |
tslink guest list#
列出不含秘密的授权、期限和本地使用估计,不返回 bearer token。
tslink guest revoke <id>#
永久撤销该 ID,取消受跟踪的 guest 流;已经接受的有界请求可能完成。
tslink guest show <id>#
检查单个授权,不恢复链接或 PIN。
tslink mcp-audit#
Owner 读取有界 intent/completion receipt;缺 completion 表示结果未知,不保证审计完整。
tslink portal#
管理每台主机的私有 portal,不汇总多主机、不改变应用注册。
tslink portal disable#
只关闭 portal 监听,保留入网状态及 owner/admin 身份。
tslink portal enable#
--owner 必填,保存私有 portal 配置,由 daemon 应用。用 status --urls 获取准确运行 URL。远程 MCP 还需当前 portal owner;首次设置/恢复需本地进行。
| 选项 | 类型 / 默认值 | 说明 |
|---|---|---|
--admins | stringSlice / [] | 额外管理员 login;这些身份可打开所有私有应用。 |
--funnel | bool / false | 明确拒绝:portal 必须保持 tailnet-only。 |
--hostname | string / home | Portal 节点 hostname,默认 home。 |
--owner | string | 主人实际的 Tailscale login,必填。 |
tslink requests#
查看真人 tailnet 成员从 portal 发出的访问请求。见portal 与请求。
tslink requests approve <id>#
--for 必填,按主人选择的期限授权单应用;相同重试不续期。远程 owner/people-manager 还需当前 portal owner、应用/期限范围;精简角色要求人员已存在。
| 选项 | 类型 / 默认值 | 说明 |
|---|---|---|
--ack-never | bool / false | 明确确认 tailnet 成员永久授权;device-invited guest 不允许。 |
--for | string | 必填,按共同期限策略选择;预设 1h、8h、24h、3d、7d,访客/公开拒绝 never。 |
tslink requests deny <id>#
拒绝一个请求,相同重试返回原决定;远程调用有相同 portal-owner 检查。
| 选项 | 类型 / 默认值 | 说明 |
|---|---|---|
--reason | string | 可选拒绝原因,最多 500 个字符,会展示给访问者。 |
tslink requests list#
读取持久 inbox,保留维护可能写入;备注是不可信数据。
普通命令继承 --json;extend 始终返回 JSON。MCP stdout 专用于协议 frames。