Skip to content

Releases: matchory/tslink

v0.3.6

Choose a tag to compare

@github-actions github-actions released this 29 Oct 12:09
Immutable release. Only release title and notes can be modified.
v0.3.6
7319e51

What's Changed

Full Changelog: v0.3.5...v0.3.6

v0.3.5

Choose a tag to compare

@github-actions github-actions released this 19 Oct 17:40
Immutable release. Only release title and notes can be modified.
v0.3.5
3a19a05

What's Changed

Full Changelog: v0.3.4...v0.3.5

Added

  • A container can be the backend of several Tailscale Services, with the
    labels tslink.service.<name>.serve.<port>; each Service is advertised once
    its own configuration and certificate are in place, and all are drained
    together on stop. /ready lists each Service's state under services.
    Upgrade every node before deploying these labels: older versions ignore
    them. tslink.service with tslink.serve.<port> works as before.
  • tslink version prints the versions of tslink and its bundled Tailscale.

Changed

  • A Service whose serve configuration fails is retried in place, with a
    warning in the endpoint's status until it succeeds; before, tailscaled
    restarted, without draining what it advertised.

  • At start, tslink removes Services in the node's state that the container's
    labels no longer name, and a drain clears every Service the node advertises.
    A node that had such Services removed, or could not have them removed, is
    drained when it stops, even if its container names no Service.

  • A readiness endpoint (tslink.health) accepts at most 16 connections at a
    time, and closes a connection that has not sent its request headers within 2 s
    (was 5 s), so a flood of connections cannot hold it.

  • /ready reports two more states before ready, so a healthcheck on it
    now waits until control routes traffic to the host: awaiting-control
    until control has fetched the node's Service list after tslink advertised
    a Service, and ports-uncovered when the host does not serve every port
    of the Service's definition, which control treats as partially configured
    and sends nothing to. The status file warns of both (control/<service>,
    ports/<service>). The ports come from the node's capabilities or, for an
    OAuth client with the services:read scope, from Tailscale's API. A
    latched endpoint stays ready and shows them under services.

  • tslink diag --preflight checks more: E1 also flags a container that
    enables forwarding by sysctl or runs without seccomp or AppArmor
    confinement, and E2 a container that mounts the shared certificate
    directory (the plugin's shared.source). A deployment that passed before
    may now report "violated".

  • With a shared certificate directory, stack tasks keep their certificates
    in certs/by-stack/<stack>/, with a copy of the shared ACME account key;
    other containers keep certs/. A stack takes over a valid certificate for
    its Service from certs/ instead of getting a new one, but a Service
    moved to another stack, or a renamed stack, gets a new certificate, which
    counts against Let's Encrypt's limit of 5 for each name in a week.

  • The documentation states that tslink is not tested with Tailnet Lock, and
    is expected to work under it only with a pre-signed auth key. It also
    describes failed DNS-01 validations of HTTPS certificates,
    Services that control does not fetch, and drains that control fetches
    after tslink's 10 s limit.

  • The plugin creates its data directory, /var/lib/docker-plugins/tailscale,
    as it starts: it no longer needs to exist before the install, and a host
    without it no longer leaves the plugin disabled. For this, Docker mounts
    the host's /var/lib into the plugin, which unmounts it before it serves;
    docker plugin upgrade --grant-all-permissions grants the new mount. The
    default of shared.source is now /var/lib, which sets no shared
    directory: as with the old default, the data directory, certificates stay
    in the data directory's certs/.

Removed

  • The tslink.loginserver network option. The control server is now the
    plugin setting TSLINK_LOGIN_SERVER, for every network on the host: an
    https URL, or an http URL with an IP address, since tailscaled resolves
    names with the container's DNS servers and plain http does not
    authenticate the server. Any other value keeps the plugin from starting.
    Recreate networks that set the option without it, with the same auth key:
    with another key, their containers register as new nodes.

Fixed

  • With TSLINK_LOG_LEVEL at warn or error, the plugin still logged its
    start line at info, before the setting applied.
  • A login that control answered after more than 60 s, as during a rollout
    of many tasks, restarted tailscaled, which then registered a second node:
    control named it <hostname>-1, and the first, offline node kept the
    name (#127). tslink now warns at 60 s and waits up to 4 more minutes for
    the registration in progress. A registration answered even later still
    leaves the orphaned first node; tslink now reports a node named
    <hostname>-N as a node-name warning in the status and the log.
  • After a plugin restart, which drains each Service backend on shutdown and
    advertises it again on start, control sometimes never fetched the node's
    new Service list: the host stayed inactive, and a Service with no other
    host unreachable, until the next change. tslink now advertises a Service
    anew when control has not fetched it within 15 s, up to 3 times.
  • The plugin binary, run with arguments it does not know, exits with usage
    instead of starting a plugin instance, which on the host could install
    isolation chains the host's settings turn off.
  • Without arguments, the plugin binary starts a plugin instance only inside a
    Docker plugin, which it recognizes by the plugin socket directory Docker
    mounts. On a host or in a container, it exits with usage (#96).
  • Builds from a source tree without Git metadata, such as the cluster test
    bed's, reported tslink (devel). The builds now stamp the version
    (scripts/version.sh) into the binary, and the plugin logs it at start.
  • With a shared certificate directory (shared.source), a stack that named
    another stack's Service took its certificate lease, which control never
    let it use, and the other stack's replicas waited for the lease: its
    certificate was neither issued nor renewed while the first stack ran.
    Each stack now keeps its certificates and leases in a directory of its
    own.

Security

  • A network that names a control server of its own is refused: creating one
    with the tslink.loginserver option fails, whatever its credential. On one
    that an earlier version created, a container fails to start with an error
    naming TSLINK_LOGIN_SERVER, and one already running when the plugin
    restarts gets the status failed, naming it. A network could
    otherwise have nodes present their credential, one minted from the cluster
    credential included, to a server it chose
    (GHSA-28r2-gm83-4qwq;
    affects v0.2.0 to v0.3.4).

Release checks

On 3a19a05 (docs/releasing.md): CI green (34 checks on the release PR and on #144); weekly fuzz run within 7 days (2026-10-19); SECURITY.md has no manual checks. The red team ran on 2026-10-19 on commits whose product code (pkg, cmd, docker, go.mod, go.sum) is identical to this release: on a fresh single-host testbed (b401da1, Docker 29.9.1, kernel 6.8) and on a five-node Swarm bed against a real tailnet (aa8cf8a), with all probes passing and their control runs getting through; the cluster suite (R1 to R18), an upgrade from v0.3.2 and disruptions (Docker restart and kill, reboot, power off) passed on the same bed.

Guarantees and their tests

  • G1: pkg/docker/driver_test.go:824 pkg/docker/isolation_test.go:50 pkg/docker/isolation_test.go:78 pkg/docker/isolation_test.go:124 pkg/docker/isolation_test.go:157 pkg/docker/isolation_test.go:201 pkg/netutil/bypass_test.go:12 pkg/netutil/container_test.go:56 pkg/netutil/hoststate_test.go:59 pkg/netutil/isolate_test.go:91 pkg/netutil/i...
Read more

v0.3.4

Choose a tag to compare

@github-actions github-actions released this 17 Oct 17:04
Immutable release. Only release title and notes can be modified.
v0.3.4
4498e7f

What's Changed

Full Changelog: v0.3.3...v0.3.4

Fixed

  • A start without the saved list of Docker's bridges, as the first after an
    upgrade from v0.3.2 or earlier, keeps the bridges the host's tailnet
    isolation already covers. Before, it covered only Docker's default
    interface names until Docker listed its bridges, so containers on a bridge
    with its own name could reach the host's tailnet for that time.
  • The list of Docker's bridges is synced to disk when saved, so it survives
    a host crash, and saved again at the next listing if saving it failed.
  • While Docker cannot list its bridges at start, the plugin no longer
    reapplies its isolation and warns every second: it warns once, and
    applies the list once Docker answers. With TSLINK_ISOLATE_HOST_TAILNET
    off, it does not list them at all.

Release checks

On 7cb5042 (docs/releasing.md): CI green (34 checks); weekly fuzz run within 7 days (2026-10-12); red team on a fresh testbed (Docker 29.9.1, kernel 6.8) passed; test/security/report.sh reports nothing missing. No guarantee is marked Manual:.

Guarantees and their tests

  • G1: pkg/docker/driver_test.go:792 pkg/docker/isolation_test.go:50 pkg/docker/isolation_test.go:78 pkg/docker/isolation_test.go:124 pkg/docker/isolation_test.go:157 pkg/docker/isolation_test.go:201 pkg/netutil/bypass_test.go:12 pkg/netutil/container_test.go:56 pkg/netutil/hoststate_test.go:59 pkg/netutil/isolate_test.go:91 pkg/netutil/isolate_test.go:179 pkg/netutil/isolate_test.go:198 pkg/netutil/isolate_traffic_test.go:256 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 pkg/netutil/tailnet_test.go:83 test/integration/run.sh:382 test/integration/run.sh:384 test/integration/run.sh:386 test/integration/run.sh:388 test/integration/run.sh:391
  • G2: pkg/netutil/isolate_test.go:225 pkg/netutil/isolate_traffic_test.go:179 pkg/netutil/isolate_traffic_test.go:211 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 test/integration/run.sh:461 test/integration/run.sh:462 test/integration/run.sh:465
  • G4: pkg/core/config_test.go:143 pkg/core/network_test.go:309 pkg/core/network_test.go:354 pkg/core/statedir_fuzz_test.go:86 pkg/core/statedir_fuzz_test.go:107
  • G5: pkg/docker/credentials_test.go:41 pkg/tailscale/authkey_test.go:144 pkg/tailscale/authkey_test.go:163 pkg/tailscale/logout_test.go:262 pkg/tailscale/resolver_test.go:264 pkg/tailscale/up_test.go:66 pkg/tailscale/up_test.go:107 pkg/tailscale/up_test.go:131 test/integration/run.sh:588 test/integration/run.sh:589 test/integration/run.sh:590 test/integration/run.sh:591

v0.3.3

Choose a tag to compare

@github-actions github-actions released this 17 Oct 16:40
Immutable release. Only release title and notes can be modified.
v0.3.3
2bf2257

What's Changed

Full Changelog: v0.3.2...v0.3.3

Fixed

  • With TSLINK_ISOLATE_HOST_TAILNET on, the plugin no longer comes up disabled after a host reboot. It listed Docker's bridge networks before opening its socket, and Docker, which answers no API call involving plugins until the socket is open, gave up waiting and disabled it. The plugin now starts with the bridges Docker listed last, saved in the data directory as bridges, and lists them once Docker answers.

Release checks

On fa5ca3d (docs/releasing.md): CI green (34 checks); weekly fuzz run within 7 days (2026-10-12); red team on the testbed (Docker 29.9.0, kernel 6.8) passed; test/security/report.sh reports nothing missing. No guarantee is marked Manual:.

Guarantees and their tests

  • G1: pkg/docker/driver_test.go:792 pkg/docker/isolation_test.go:50 pkg/docker/isolation_test.go:78 pkg/docker/isolation_test.go:124 pkg/docker/isolation_test.go:156 pkg/netutil/bypass_test.go:12 pkg/netutil/container_test.go:56 pkg/netutil/isolate_test.go:91 pkg/netutil/isolate_test.go:178 pkg/netutil/isolate_traffic_test.go:256 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 pkg/netutil/tailnet_test.go:83 test/integration/run.sh:382 test/integration/run.sh:384 test/integration/run.sh:386 test/integration/run.sh:388 test/integration/run.sh:391
  • G2: pkg/netutil/isolate_test.go:205 pkg/netutil/isolate_traffic_test.go:179 pkg/netutil/isolate_traffic_test.go:211 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 test/integration/run.sh:461 test/integration/run.sh:462 test/integration/run.sh:465
  • G4: pkg/core/config_test.go:143 pkg/core/network_test.go:309 pkg/core/network_test.go:354 pkg/core/statedir_fuzz_test.go:86 pkg/core/statedir_fuzz_test.go:107
  • G5: pkg/docker/credentials_test.go:41 pkg/tailscale/authkey_test.go:144 pkg/tailscale/authkey_test.go:163 pkg/tailscale/logout_test.go:262 pkg/tailscale/resolver_test.go:264 pkg/tailscale/up_test.go:66 pkg/tailscale/up_test.go:107 pkg/tailscale/up_test.go:131 test/integration/run.sh:588 test/integration/run.sh:589 test/integration/run.sh:590 test/integration/run.sh:591

v0.3.2

Choose a tag to compare

@github-actions github-actions released this 14 Oct 19:54
Immutable release. Only release title and notes can be modified.
v0.3.2
579680e

What's Changed

Full Changelog: v0.3.1...v0.3.2

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 14 Oct 08:53
Immutable release. Only release title and notes can be modified.
v0.3.1
fac06c8

What's Changed

Full Changelog: v0.3.0...v0.3.1

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 20:24
Immutable release. Only release title and notes can be modified.
v0.3.0
081cad6

What's Changed

Full Changelog: v0.2.4...v0.3.0

Security guarantees

The guarantees published in SECURITY.md and the tests that guard them on this commit. CI, the end-to-end test with its probes and the weekly fuzz run (2026-10-12) passed. The red-team run of docs/releasing.md step 3 is still to follow; the last one ran on e0061b2.

G1: pkg/docker/driver_test.go:796 pkg/docker/isolation_test.go:48 pkg/docker/isolation_test.go:76 pkg/netutil/bypass_test.go:12 pkg/netutil/container_test.go:55 pkg/netutil/isolate_test.go:91 pkg/netutil/isolate_test.go:178 pkg/netutil/isolate_traffic_test.go:256 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 pkg/netutil/tailnet_test.go:83 test/integration/run.sh:382 test/integration/run.sh:384 test/integration/run.sh:386 test/integration/run.sh:388 test/integration/run.sh:391
G2: pkg/netutil/isolate_test.go:205 pkg/netutil/isolate_traffic_test.go:179 pkg/netutil/isolate_traffic_test.go:211 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 test/integration/run.sh:459 test/integration/run.sh:460 test/integration/run.sh:463
G4: pkg/core/config_test.go:140 pkg/core/network_test.go:309 pkg/core/network_test.go:354 pkg/core/statedir_fuzz_test.go:86 pkg/core/statedir_fuzz_test.go:107
G5: pkg/docker/credentials_test.go:40 pkg/tailscale/authkey_test.go:144 pkg/tailscale/authkey_test.go:163 pkg/tailscale/logout_test.go:262 pkg/tailscale/resolver_test.go:264 pkg/tailscale/up_test.go:67 pkg/tailscale/up_test.go:111 pkg/tailscale/up_test.go:138 test/integration/run.sh:586 test/integration/run.sh:587 test/integration/run.sh:588 test/integration/run.sh:589

v0.2.4

Choose a tag to compare

@github-actions github-actions released this 13 Oct 19:02
Immutable release. Only release title and notes can be modified.
v0.2.4
8b3b648

What's Changed

Full Changelog: v0.2.3...v0.2.4

Security guarantees

The guarantees published in SECURITY.md and the tests that guard them on this commit. CI, the end-to-end test with its probes and the weekly fuzz run (2026-10-12) passed. The red-team run of docs/releasing.md step 3 is still to follow; the last one ran on e0061b2.

G1: pkg/docker/driver_test.go:788 pkg/docker/isolation_test.go:48 pkg/docker/isolation_test.go:76 pkg/netutil/bypass_test.go:12 pkg/netutil/container_test.go:55 pkg/netutil/isolate_test.go:91 pkg/netutil/isolate_test.go:178 pkg/netutil/isolate_traffic_test.go:256 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 pkg/netutil/tailnet_test.go:83 test/integration/run.sh:382 test/integration/run.sh:384 test/integration/run.sh:386 test/integration/run.sh:388 test/integration/run.sh:391
G2: pkg/netutil/isolate_test.go:205 pkg/netutil/isolate_traffic_test.go:179 pkg/netutil/isolate_traffic_test.go:211 pkg/netutil/procs_test.go:212 pkg/netutil/repair_traffic_test.go:132 test/integration/run.sh:459 test/integration/run.sh:460 test/integration/run.sh:463
G4: pkg/core/config_test.go:138 pkg/core/network_test.go:309 pkg/core/network_test.go:354 pkg/core/statedir_fuzz_test.go:86 pkg/core/statedir_fuzz_test.go:107
G5: pkg/docker/credentials_test.go:40 pkg/tailscale/authkey_test.go:144 pkg/tailscale/authkey_test.go:163 pkg/tailscale/logout_test.go:262 pkg/tailscale/resolver_test.go:264 pkg/tailscale/up_test.go:67 pkg/tailscale/up_test.go:111 pkg/tailscale/up_test.go:138 test/integration/run.sh:586 test/integration/run.sh:587 test/integration/run.sh:588 test/integration/run.sh:589

v0.2.3

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:02
Immutable release. Only release title and notes can be modified.
v0.2.3
367192f

What's Changed

Full Changelog: v0.2.2...v0.2.3

Security guarantees

The guarantees published in SECURITY.md and the tests that guard them on this commit. CI, the end-to-end test with its probes and the weekly fuzz run (2026-10-12) passed. The red-team run of docs/releasing.md step 3 is still to follow; the last one ran on e0061b2.

G1: pkg/docker/driver_test.go:741 pkg/docker/isolation_test.go:48 pkg/docker/isolation_test.go:76 pkg/netutil/bypass_test.go:12 pkg/netutil/isolate_test.go:91 pkg/netutil/isolate_test.go:178 pkg/netutil/isolate_traffic_test.go:257 pkg/netutil/tailnet_test.go:83 test/integration/run.sh:382 test/integration/run.sh:384 test/integration/run.sh:386 test/integration/run.sh:388 test/integration/run.sh:391
G2: pkg/netutil/isolate_test.go:205 pkg/netutil/isolate_traffic_test.go:180 pkg/netutil/isolate_traffic_test.go:212 test/integration/run.sh:459 test/integration/run.sh:460 test/integration/run.sh:463
G4: pkg/core/config_test.go:138 pkg/core/network_test.go:272 pkg/core/network_test.go:317 pkg/core/statedir_fuzz_test.go:86 pkg/core/statedir_fuzz_test.go:107
G5: pkg/docker/credentials_test.go:40 pkg/tailscale/authkey_test.go:144 pkg/tailscale/authkey_test.go:163 pkg/tailscale/logout_test.go:262 pkg/tailscale/resolver_test.go:264 pkg/tailscale/up_test.go:67 pkg/tailscale/up_test.go:111 pkg/tailscale/up_test.go:138 test/integration/run.sh:586 test/integration/run.sh:587 test/integration/run.sh:588 test/integration/run.sh:589

v0.2.2

Choose a tag to compare

@github-actions github-actions released this 12 Oct 11:39
Immutable release. Only release title and notes can be modified.
v0.2.2
f655fe9

What's Changed

Full Changelog: v0.2.1...v0.2.2