Skip to content
tslink

Files and paths

tslink keeps every file it writes in its data directory, /var/lib/docker-plugins/tailscale on the host, which the plugin sees as /data. Several files are per endpoint: one container’s connection to one tslink network.

Data directory

/var/lib/docker-plugins/tailscale/
├── by-hostname/<hostname>/          state directory of a container outside a stack
├── by-stack/<stack>/<hostname>/     state directory of a container in a stack
├── sock/<endpoint>.sock             tailscaled socket of each endpoint
├── status/<endpoint>.json           status file of each endpoint
├── status/<endpoint>.ready          readiness latch of each endpoint
├── certs/                           HTTPS certificates, if shared.source is not set
├── oauth-client.secret              cluster credential (optional)
└── plugin.log                       plugin log

<endpoint> is the first 12 characters of the Docker endpoint ID. The sockets live in sock/ rather than in the state directories because a Unix socket path can’t be longer than 108 bytes. <hostname> and <stack> start with a letter or digit, and contain only letters, digits, ., _ and -.

The plugin creates the data directory, with mode 0755, as it starts. Don’t delete it while the plugin is installed.

State directory

Each node has one state directory, and only one endpoint at a time can use it.

FileContent
tailscaled.state
The identity of the node, with its private keys
tailscaled.log
The log of tailscaled
tailscaled.sock
A link to the socket in sock/
ephemeral
A marker that the node is ephemeral
Warning

Whoever can read tailscaled.state can act as the node. Keep the data directory readable by root only.

Logs

tslink rotates each log at a fixed size, and keeps one rotated file, so the logs can’t fill the disk.

LogRotated atMaximum on disk
<state directory>/tailscaled.log10 MB20 MB for each endpoint
plugin.log50 MB100 MB

Status files

tslink writes status/<endpoint>.json while the endpoint exists.

FieldTypeContent
endpointstringThe endpoint ID
hostnamestringThe hostname of the node
stackstringThe stack’s name. Absent outside a stack.
statestringrunning, retrying or failed
errorstringThe last error. Absent without one.
attemptsnumberThe number of start attempts
updatedstringThe time of the last change, in RFC 3339 format
warningsarrayConditions worth a look. Absent without any.
StateMeaning
running
tailscaled is running.
retrying
The start failed, and tslink tries again.
failed
The start failed, and tslink won’t try again, for example because the stack isn’t allowed a tag.

Each item in warnings has the fields key, message and since.

KeyCondition
dns-upstreams
tailscaled found no DNS server of the container or the host, and uses a fallback.
renewal-blocked/<domain>
Let’s Encrypt refuses to renew the certificate of <domain>.
cert-expiry/<domain>
The certificate of <domain> expires in less than 14 days.
health
tslink can’t start the readiness endpoint on the port of tslink.health.
node-name
The control server named the node <hostname>-N, because another node holds the name. See slow registrations.
service/<service>
Configuring the Service failed. tslink retries, and clears the warning once it succeeds.
ports/<service>
The container doesn’t serve every port of the Service. The message names the ports.
control/<service>
The control server hasn’t fetched the node’s Service list after tslink advertised the Service again 3 times.

Shared directory

With the plugin setting shared.source, tslink keeps HTTPS certificates and their ACME account key in certs/ in that directory; otherwise in certs/ in the data directory.