tailstick is a usb-delivered tailscale enrollment tool for authorized sysadmin workflows on windows and linux. it gives operators one command surface for controlled onboarding, bounded lease modes, and automatic cleanup that can continue after the usb is unplugged.
if you need to get a field machine onto your tailnet without building a backend service around the process, tailstick gives you a controlled local workflow. it keeps the operator flow simple, supports session, timed, and permanent access, and keeps cleanup tied to the same lease record instead of spreading state across ad hoc scripts.
- elevated privileges are required for enrollment and cleanup (
sudoon linux, administrator on windows). - linux: debian or ubuntu with
systemd. other distributions are not supported in the current release. - windows: standard windows with scheduled tasks available.
- go 1.25.6+ is required for building from source.
- go to releases and download the binary you want for your machine. use the cli if you want a direct command flow, or use the gui if you want the local browser flow. binaries are available for
linux/amd64,linux/arm64,windows/amd64, andwindows/arm64. - put that binary in a working folder, then place a
tailstick.config.jsonfile next to it. - write that config by hand from
configs/tailstick.config.example.json, or use the optional preset maker if you want a faster way to build it. - make sure you have the secrets your presets depend on. in most setups that means a tailscale auth key, a tailscale ephemeral auth key, and a tailscale api key for cleanup. if you want password-gated operator use, you also need an operator password.
- supply those values through environment variables such as
TAILSTICK_AUTH_KEY,TAILSTICK_EPHEMERAL_AUTH_KEY,TAILSTICK_API_KEY, andTAILSTICK_OPERATOR_PASSWORD. - run the binary once the config and secrets are in place.
for normal operator use, use the release binaries. building from source is only for development work.
| platform | cli | gui | full lease runtime |
|---|---|---|---|
linux (debian/ubuntu + systemd) |
supported | supported | supported |
| windows | supported | supported | supported |
release binaries are built for linux/amd64, linux/arm64, windows/amd64, and windows/arm64.
| command | purpose |
|---|---|
tailstick run |
enroll machine and create lease |
tailstick agent |
run reconciliation loop (--once for a single pass) |
tailstick cleanup |
force cleanup for one lease id |
tailstick version |
print version |
| flag | default | description |
|---|---|---|
--preset |
"" |
preset id from config |
--mode |
session |
lease mode: session, timed, or permanent |
--channel |
stable |
install channel: stable or latest |
--days |
3 |
timed lease duration in days (1, 3, or 7) |
--custom-days |
0 |
custom lease days (1–30, overrides --days) |
--suffix |
"" |
optional device name suffix |
--exit-node |
"" |
optional approved exit node |
--allow-existing |
false |
allow existing tailscale install |
--non-interactive |
false |
non-interactive mode |
--password |
"" |
operator password (or set TAILSTICK_OPERATOR_PASSWORD) |
--config |
tailstick.config.json |
config file path |
--state |
platform default | state file path |
--audit |
logs/tailstick-audit.ndjson |
audit log path (relative to config directory) |
--log |
platform default | log file path |
--dry-run |
false |
print commands without executing |
| flag | default | description |
|---|---|---|
--once |
false |
run one reconciliation pass and exit |
--interval |
1m |
reconciliation interval |
the agent also accepts --config, --state, --audit, --log, and --dry-run.
| flag | default | description |
|---|---|---|
--lease-id |
"" |
lease id to clean (required) |
the cleanup command also accepts --config, --state, --audit, --log, and --dry-run.
the gui binary (tailstick-linux-gui / tailstick-windows-gui) starts a local browser-based setup wizard. in addition to the shared flags (--config, --state, --audit, --log, --dry-run):
| flag | default | description |
|---|---|---|
--host |
127.0.0.1 |
bind host |
--port |
0 |
bind port (0 picks an ephemeral port) |
--open-browser |
true |
open browser automatically |
--non-interactive applies to tailstick run only.
| mode | behavior |
|---|---|
session |
cleaned after reboot/shutdown detection |
timed |
cleaned when expiry is reached (set duration with --days or --custom-days) |
permanent |
leaves normal tailscale install and no automatic cleanup |
for lease modes, tailstick installs local scheduling:
- linux:
tailstick-agent.service+tailstick-agent.timer - windows:
TailStickAgent-Startup+TailStickAgent-Periodic
the scheduled command runs from a machine-local binary copy:
- linux:
/var/lib/tailstick/tailstick-agent - windows:
%ProgramData%\TailStick\tailstick-agent.exe
secrets are resolved from environment variables. the config file supports authKeyEnv, ephemeralAuthKeyEnv, and apiKeyEnv fields that name the env var to read. common variables:
| variable | purpose |
|---|---|
TAILSTICK_AUTH_KEY |
tailscale auth key |
TAILSTICK_EPHEMERAL_AUTH_KEY |
tailscale ephemeral auth key |
TAILSTICK_API_KEY |
tailscale api key for cleanup |
TAILSTICK_OPERATOR_PASSWORD |
operator password for gated presets |
see .env.example for a template.
timed lease with advanced custom duration:
./tailstick-linux-cli run \
--preset ops-readonly \
--mode timed \
--custom-days 14 \
--channel stable \
--allow-existingsession lease with approved exit node:
./tailstick-linux-cli run \
--preset ops-readonly \
--mode session \
--exit-node 100.64.0.5 \
--channel latestmanual cleanup:
./tailstick-linux-cli cleanup --lease-id <lease-id>single agent pass:
./tailstick-linux-cli agent --oncego build ./cmd/tailstick-linux-cli
go build ./cmd/tailstick-linux-guicross-compile all targets:
make build-allrun tests:
go test ./...see the Makefile for additional targets (fmt, vet, sandbox-linux, icons).