---
title: "Installation"
description: "Install TSLink on macOS, Linux and Windows, and verify release artifacts."
url: "https://tslink.md/docs/installation"
locale: "en"
product_version: "0.1.1"
source: "https://github.com/anydoor7/tslink/blob/v0.1.1/docs/getting-started.md"
---

> Documentation index: https://tslink.md/llms.txt · Installed binary is authoritative: `tslink manifest`.

## Prerequisites

You need a **Tailscale account** with [MagicDNS and HTTPS](https://tailscale.com/docs/how-to/set-up-https-certificates). Private receiving devices need [Tailscale](https://tailscale.com/download) and policy permission. The app host uses TSLink's embedded Tailscale nodes and needs no separate Tailscale daemon. A stored API token or OAuth client is optional for the first private share. macOS hosts need macOS 13 Ventura or later: current releases are built with Go 1.27, which no longer supports macOS 12 Monterey or earlier ([platform guide](https://github.com/anydoor7/tslink/blob/v0.1.1/docs/platforms.md)).

## macOS (Homebrew)

```bash
brew install --cask anydoor7/tap/tslink
```

The macOS binary is signed with a Developer ID certificate and notarized by Apple. The first run needs network access to look up its notarization ticket.

## Linux

Homebrew on Linux uses the same command:

```bash
brew install --cask anydoor7/tap/tslink
```

Alternatively, select a `.deb`, `.rpm` or `tslink_0.1.1_linux_<arch>.tar.gz` from the [v0.1.1 release](https://github.com/anydoor7/tslink/releases/tag/v0.1.1), for `amd64` or `arm64`. Install the package with your system package manager, or extract the archive and place `tslink` in a directory on `PATH`.

## Windows

Download `tslink_0.1.1_windows_amd64.zip` or `tslink_0.1.1_windows_arm64.zip` from the [v0.1.1 release](https://github.com/anydoor7/tslink/releases/tag/v0.1.1). Extract it, add the directory containing `tslink.exe` to your user `PATH`, and run:

```powershell
tslink install
```

TSLink then starts when you sign in. The zip is **not Authenticode-signed**. Verify it through the signed checksums and attestations described below.

## From source

Source builds need **Git and Go 1.27.1+**. Commands below use bash/zsh; the [platform guide](https://github.com/anydoor7/tslink/blob/v0.1.1/docs/platforms.md) covers each shell.

```bash
git clone https://github.com/anydoor7/tslink.git
cd tslink
go install .
export PATH="$PATH:$(go env GOPATH)/bin"
```

On PowerShell, add `$(go env GOPATH)\bin` to your user `PATH` in system settings.

## Verify a release

Follow the [release verification commands](https://github.com/anydoor7/tslink/blob/v0.1.1/docs/verify-release.md) with `version="v0.1.1"` and the exact downloaded asset name. They require `gh` 2.49+ with `gh attestation verify`, `cosign` with `verify-blob --bundle`, and `sha256sum` or `shasum`.

Download the chosen artifact, `checksums.txt` and `checksums.txt.sigstore.json`. Check the artifact's SHA-256 against its entry in `checksums.txt`, verify that checksum file's Sigstore bundle, then verify the artifact's GitHub attestation. Verification pins these four values:

* OIDC issuer: `https://token.actions.githubusercontent.com`
* Workflow identity: `https://github.com/anydoor7/tslink/.github/workflows/release.yml@refs/tags/v0.1.1`
* Source ref: `refs/tags/v0.1.1`
* Signer workflow: `github.com/anydoor7/tslink/.github/workflows/release.yml`

Archive SBOM sidecars have their own checksums, bundles and attestations; verify them separately using the same guide.

## Verify installation

```bash
tslink --version
tslink --help
```

The first command prints the installed version; the second lists commands.

## Upgrade

For Homebrew, upgrade the cask:

```bash
brew upgrade --cask tslink
```

If TSLink runs as a background service:

```bash
tslink install
```

This updates the service's executable path to the upgraded binary. For an archive, Windows zip or Linux package, replace or upgrade the binary first, then run `tslink install` again if you use the background service. Check `tslink --version` and `tslink status --json` afterwards.

## Authentication

TSLink has two credential tiers. Tier 1 is the default and needs no stored API credential; enrollment and approval still follow tailnet policy.

### Tier 1 — interactive enrollment (default)

Start a share without the stored-credential `tslink login` command; first-node browser login remains part of enrollment.

```bash
tslink share ./build
```

The first time a node needs to join your tailnet, TSLink prints one Tailscale authorization URL and exits. Open it, approve the node, then run `tslink url <name> --wait` for the live URL. In `--json` mode the same information comes back as one structured record, so a script or an agent reads a field rather than parsing prose:

```json
{"type":"tslink.result","ok":true,"schema_version":1,"command":"share","code":0,"data":{"status":"needs_login","auth_url":"https://login.tailscale.com/a/..."}}
```

Nodes enrolled this way are user-owned and untagged. Enrollment, approval, access, and node-key expiry follow your tailnet policy; re-authorization may be required when that policy expires the key. See [Quick Start](https://tslink.md/docs/quickstart.md) for the handoff and readiness sequence.

### Tier 2 — stored credential (optional)

Stored credentials support tagged node authentication. Tag ownership and policy permissions still apply; ordinary ACL automation needs explicit `--manage-acl`. Remote stale-device cleanup requires exact ownership proof and device permissions. A tagged identity's node-key expiry behavior is separate from API-token expiry. See [Tag Configuration](https://tslink.md/docs/configuration.md#tag-configuration) rather than treating credential storage alone as successful provisioning.

```bash
tslink login
```

This presents a menu — choose `[1]` for an API access token or `[2]` for an OAuth client secret, with step-by-step guidance for each.

A regular `tskey-api-*` API access token grants full Tailscale API permission; [trust credentials](https://tailscale.com/docs/reference/trust-credentials), including OAuth clients, provide scoped access. Verified October 6, 2026 against the [Tailscale API documentation](https://tailscale.com/docs/reference/tailscale-api). Prefer Tier 1 unless you need what Tier 2 provides.

### Which key type to use?

| Key Type            | Prefix           | Expiry               | How It Works                                                                                                 | Best For                                                 |
| ------------------- | ---------------- | -------------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------- |
| API access token    | `tskey-api-*`    | Expires periodically | TSLink derives short-lived, single-use auth keys; node ephemerality follows the service's `--ephemeral` flag | Required REST automation after validating permissions    |
| OAuth client secret | `tskey-client-*` | Does not expire      | Used directly by tsnet; REST tag/device automation is narrower today                                         | Long-running setups after validating required operations |

Generate API access tokens at [Admin → Keys](https://login.tailscale.com/admin/settings/keys). Generate OAuth client secrets at [Admin → OAuth](https://login.tailscale.com/admin/settings/oauth) — click "+ credential" → "OAuth client" → configure the scopes required by your intended API operations → copy the **client secret** (not the shorter client ID above it).

### Credential storage

TSLink stores credentials in the **system keychain** when it is available, relying on the OS protection model:

| Platform | Backend                                  |
| -------- | ---------------------------------------- |
| macOS    | Keychain                                 |
| Linux    | Secret Service (GNOME Keyring / KWallet) |
| Windows  | Credential Manager                       |

Credentials prefer the system keychain (macOS Keychain, Linux Secret Service, Windows Credential Manager). Plaintext `0600` file fallback is allowed only on macOS/Linux after TSLink proves an old keychain value is absent or has been deleted. An unreachable or uncertain keychain fails closed; restore access and retry. Windows does not allow credential file fallback. Headless operation alone does not guarantee fallback.

| File           | Content             |
| -------------- | ------------------- |
| `apikey`       | API access token    |
| `clientsecret` | OAuth client secret |
| `authkey`      | Legacy auth key     |

### Non-interactive setup

If you can't open a browser (e.g., headless servers), inject credentials from a secret manager into stdin or the environment:

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

Environment variables are also accepted when they are supplied by your secret manager:

```bash
TSLINK_API_KEY="$TSLINK_API_KEY" tslink login
TSLINK_CLIENT_SECRET="$TSLINK_CLIENT_SECRET" tslink login
```

Compatibility argv flags and legacy credential files may still be read by TSLink, but official automation should not place secrets in argv, shell history, or manually written credential files.

## Autostart on Login

Default add/share handle background setup. To explicitly register or update login autostart, use:

```bash
tslink install
```

### macOS

Creates a **LaunchAgent** at `~/Library/LaunchAgents/com.tslink.daemon.plist` with `KeepAlive` enabled. TSLink starts on login, not at the boot login window, and restarts after a crash or a manual stop while the agent remains installed.

### Linux

Creates a **systemd user service** at `~/.config/systemd/user/tslink.service` with auto-restart on failure. Automatically enabled and started. Without lingering, it starts with user login; `loginctl enable-linger "$USER"` permits boot-time operation without login and continued operation after logout. If lingering was enabled only for TSLink, disable it after uninstall.

### Windows

Registers a Task Scheduler task and starts the built-in supervisor immediately, with daemon crash recovery and later sign-in autostart. `tslink install --startup` is the explicit Startup fallback without crash recovery. This is user-login scope, not unattended boot.

Check `tslink status --json` and its `data.supervision.autostart_scope` for the observed login/boot scope; an unknown scope does not establish unattended boot availability. Enrollment/approval and service readiness are separate from autostart.

To remove the auto-start:

```bash
tslink uninstall
```

Windows uninstall disables and stops its owned task/supervisor before deleting the task; Startup-only fallback leaves a current process for a separate `tslink stop`. macOS/Linux attempt managed shutdown, but errors or unverified-removal warnings require attention. To stop serving or perform maintenance, follow [verified shutdown](https://tslink.md/docs/daemon.md#verified-shutdown) and inspect status before continuing.

## Custom Control Server (Headscale)

Tailscale API-derived node auth keys are refused for a non-Tailscale control server with `credential_control_url_mismatch`. Custom-control enrollment and HTTPS support need separate validation; end-to-end Headscale validation remains pending.

If you're using [Headscale](https://headscale.net/) or another custom control server instead of Tailscale's hosted service:

```bash
# Set globally for all services
tslink config set control-url https://headscale.example.com
```

This setting persists in `~/.config/tslink/config.json` and applies to all services. If the gateway is already running, follow the [restart sequence](https://tslink.md/docs/daemon.md#restarting-after-configuration-changes) to apply a changed global setting.

You can also override the control server for individual services:

```bash
# Per-service override
tslink add my-service --proxy localhost:3000 --control-url https://headscale.example.com
```

## Docker Integration

Docker label discovery is [roadmap/experimental](https://tslink.md/docs/experimental-roadmap.md#docker-auto-discovery). Register container-backed services explicitly with `tslink add`.

## Configuration Directory

By default, local configuration and runtime files live in `~/.config/tslink/`; primary stored credentials live in the system keychain. `TSLINK_CONFIG_DIR` can select another local directory and must match the gateway/supervisor environment.

```
~/.config/tslink/
  ├── registry.json       # Service registry
  ├── config.json          # Global config (control-url)
  ├── tslink.pid           # Daemon PID
  ├── apikey               # API key (file fallback)
  ├── clientsecret         # OAuth secret (file fallback)
  ├── authkey              # Legacy auth key
  ├── nodes/               # Per-service tsnet state
  └── logs/                # Daemon and access logs
```

## Next Steps

With the TSLink binary available, follow [Quick Start](https://tslink.md/docs/quickstart.md) to register your first service, complete any enrollment handoff, and wait for readiness. A stored credential is optional.
