tslink diag
tslink diag shows the state of every endpoint on a host. tslink diag --preflight checks the environment
properties that the guarantees in SECURITY.md rely on, so you know they hold on a host before
you depend on them.
Commands
tslink diag- Shows every endpoint with its state directory, tailnet address, hostname, backend state and status file
tslink diag --preflight- Checks the environment properties on the host where it runs
tslink diag --preflight --shared-dir <dir>- Also checks the owner and mode of the shared certificate directory (E7), mounted at
<dir> tslink version- Shows the versions of tslink and its bundled Tailscale
tslink help- Shows the usage
Any other argument exits with status 2 and prints the usage. Without arguments, the binary starts the plugin, so leave that to Docker.
To see which version a host runs, run the binary from the plugin’s root filesystem, as root:
/var/lib/docker/plugins/$(docker plugin inspect -f '{{.Id}}' tslink)/rootfs/tslink version
Exit codes of the preflight check
0- No property is violated. A result of “unknown” doesn’t change the exit code.
1- A property is violated, or a check couldn’t run.
The preflight check looks only at the host it runs on, so run it on every host, every Swarm node included.
Run tslink diag
ghcr.io/matchory/tslink holds Docker plugins, not images docker run can pull, so build an image from a clone of
the repository:
docker build -t tslink-diag -f docker/Dockerfile .
Then run diag:
docker run --rm -v /var/lib/docker-plugins/tailscale:/data \
--entrypoint /tslink tslink-diag diag
Or run the preflight check:
docker run --rm --network host --cap-add NET_ADMIN \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker-plugins/tailscale:/data \
--entrypoint /tslink tslink-diag diag --preflight
To check the owner and mode of the shared certificate directory (E7) too, add -v <shared directory>:/shared:ro and
--shared-dir /shared. E2 doesn’t need --shared-dir: it checks the host path in each tslink plugin’s
shared.source setting.
For several hosts, build the image once and copy it to each with docker save and docker load.
Without an image
On a host with the plugin installed, the plugin’s root filesystem has the same binary. Run it from a root shell on
the host, for example after sudo -i:
rootfs="$(docker info -f '{{.DockerRootDir}}')/plugins/$(docker plugin inspect -f '{{.Id}}' tslink)/rootfs"
TS_DATA_DIR=/var/lib/docker-plugins/tailscale PATH="$rootfs/usr/local/bin:/usr/sbin:/sbin:$PATH" \
"$rootfs/tslink" diag --preflight
TS_DATA_DIR points diag at the plugin’s data directory, which is /data only inside the plugin. The isolation
check (E5) runs the host’s iptables and ip6tables, and the Tailnet Lock check (E9) runs the tailscale CLI; the
PATH gives them the host’s sbin directories and the plugin’s own tailscale. Without that, on a host with no
tailscale of its own, E9 is unknown. Leave out --preflight to run diag.
scripts/tslink-diag.sh
The script shows the same information from the host, without any image. Run it from a clone of the repository.
./scripts/tslink-diag.sh- Shows the diagnostics once
./scripts/tslink-diag.sh --json- Shows the diagnostics as JSON
./scripts/tslink-diag.sh --watch- Shows the diagnostics again every 5 seconds