A command-line tool written in Rust for managing your Tailscale network.
This application is currently under development and should be considered alpha release quality. I'm using it daily for Tailscale admin tasks but am also planning to make frequent updates.
cargo build --releaseThe binary will be at target/release/tsa.
Packages for popular distributions will be coming soon.
The tool requires a Tailscale API key. You can provide it via:
- Environment variable:
TAILSCALE_API_KEY - Command-line flag:
-aor--api-key
Generate an API key at: https://login.tailscale.com/admin/settings/keys
Optionally, set your tailnet name:
- Environment variable:
TAILSCALE_TAILNET - Command-line flag:
-nor--tailnet - Default:
-(uses the default tailnet for your API key)
| Flag | Description |
|---|---|
-a, --api-key |
Tailscale API key |
-n, --tailnet |
Tailnet name (default: -) |
-y, --yes |
Skip confirmation prompts |
-V, --version |
Display version information |
Note: The -y/--yes flag is a global option and must be placed before the subcommand:
# Correct usage
tsa -y devices rename myserver newserver
tsa -y devices delete -d oldserver
# Incorrect usage (will not work)
tsa devices rename -y myserver newserverDevice commands accept patterns that match by name, hostname, or ID. The matching priority is:
- Exact match on device ID
- Exact match on name
- Exact match on hostname
- Case-insensitive exact match
- Partial match (contains) - returns all matching devices
When multiple devices match a pattern, you'll be shown the list and asked to confirm before proceeding.
Note: If a pattern starts with a hyphen (e.g., -gpu-1), use the -d flag:
tsa devices info -d -gpu-serverWhen you run certain commands without specifying device patterns (or omit the -d flag), you'll be presented with an interactive device selector. The selector accepts:
- Single numbers:
1 3 5- selects devices 1, 3, and 5 - Ranges:
1-5- selects devices 1 through 5 - Combinations:
1 3-7 10- selects device 1, devices 3-7, and device 10 - All devices:
allor*- selects all devices - Cancel: empty input or
none- cancels the operation
List all devices in the tailnet.
tsa devices list
tsa devices list --no-paging
tsa devices list --columns hostname,status,locked
tsa devices list --locked
tsa devices list --json| Flag | Description |
|---|---|
--no-paging |
Disable automatic paging |
--columns <cols> |
Select which columns to display |
--locked |
Show only locked-out devices |
--json |
Output as JSON |
Output automatically pages to fit your terminal size:
- If output fits on one screen, it displays directly
- If longer, shows one page at a time:
- Press
SpaceorEnterfor next page - Press
qorEscto quit
- Press
id- Device IDhostname- Device hostnamename- Device nameowner(oruser) - Device owner emailos- Operating systemstatus- Online/offline statuslocked- Tailnet lock statustags- Device tagslast_seen- Last seen timestampnode_key- Node keytailnet_lock_key(orlock_key) - Tailnet lock keytailnet_lock_error(orlock_error) - Tailnet lock error messageblocks_incoming_connections(orblocks_incoming) - Whether device blocks incoming connections
# Show only specific columns
tsa devices list --columns hostname,name,status
# Show lock-related information
tsa devices list --columns hostname,locked,tailnet_lock_error
# Pipe JSON output to jq for filtering
tsa devices list --json | jq '.[] | select(.os == "linux")'Display detailed information about a specific device.
tsa devices info <device-pattern>
tsa devices info myserver --json| Flag | Description |
|---|---|
--json |
Output as JSON |
The info command displays:
- Device name and hostname
- Owner (user email)
- Operating system
- Online/offline status
- Tailnet lock status (if applicable)
- Tags
- Last seen timestamp
- Node keys and lock keys (if present)
- Any lock errors
Rename a device in your tailnet.
tsa devices rename <device-pattern> <new-name>
tsa -y devices rename myserver web-server-01Delete devices from your tailnet.
# Interactive selection
tsa devices delete
# Delete specific devices by pattern
tsa devices delete -d myserver
# Filter by pattern, then select interactively
tsa devices delete -d server
# Skip confirmation
tsa -y devices delete -d old-server| Flag | Description |
|---|---|
-d <pattern> |
Device pattern to match |
The delete command:
- Shows a warning that the action cannot be undone
- Displays the devices that will be deleted
- Requires confirmation unless
-yflag is used
Replace all tags on a device with the specified tags.
tsa devices update-tags -d <device-pattern> -t <tags>
tsa devices update-tags -t tag:server # interactive selection| Flag | Description |
|---|---|
-d <pattern> |
Device pattern to match |
-t <tags> |
Comma-separated list of tags |
Tags can be specified with or without the tag: prefix:
tsa devices update-tags -d myserver -t prod,web
# equivalent to:
tsa devices update-tags -d myserver -t tag:prod,tag:webAdd tags to a device without removing existing tags.
tsa devices add-tags -d <device-pattern> -t <tags>
tsa devices add-tags -t tag:monitored # interactive selection| Flag | Description |
|---|---|
-d <pattern> |
Device pattern to match (optional for interactive selection) |
-t <tags> |
Comma-separated list of tags to add |
Remove specific tags from a device.
tsa devices remove-tags -d <device-pattern> -t <tags>
tsa -y devices remove-tags -d server -t tag:deprecated| Flag | Description |
|---|---|
-d <pattern> |
Device pattern to match |
-t <tags> |
Comma-separated list of tags to remove |
Sign locked-out devices for Tailnet Lock.
This requires:
- The machine running
tsamust be a signing node (have a trusted Tailnet Lock key) - The
tailscaleCLI must be installed and accessible
# Interactive selection
tsa devices sign
# Sign specific devices
tsa devices sign -d <device-pattern>
# Skip confirmation
tsa -y devices sign -d server| Flag | Description |
|---|---|
-d <pattern> |
Device pattern to match (optional for interactive selection) |
The sign command will:
- Fetch devices from the API with their
nodeKeyandtailnetLockKey - Show the devices that will be signed
- Ask for confirmation
- Execute
tailscale lock sign <nodeKey> <tailnetLockKey>for each device
List all users in the tailnet.
tsa users list
tsa users list --json| Flag | Description |
|---|---|
--json |
Output as JSON |
The user list displays:
- Login name (email)
- Display name
- Role (owner, admin, member, etc.)
- Status (active, suspended, etc.)
- Device count
- Currently active status
Approve a pending user.
tsa users approve -u user@example.comSuspend a user, preventing tailnet access.
tsa users suspend -u user@example.comRestore a suspended user.
tsa users restore -u user@example.comDelete a user from the tailnet (permanent action).
tsa users delete -u user@example.com
tsa -y users delete -u user@example.comWhen specifying users with the -u flag, you can match by:
- Exact user ID
- Exact login name (email)
- Case-insensitive login name
- Partial match on login name or display name
If multiple users match, you'll see a table of matches and be asked to provide a more specific pattern.
List the tailnet's contact information.
tsa contacts list
tsa contacts list --json| Flag | Description |
|---|---|
--json |
Output as JSON |
Displays account, support, and security contacts.
- Tags must be defined in your tailnet policy file (ACL) before they can be applied to devices.
- Updating tags on a device does not change the device's key expiry unless you re-authenticate.
This project follows Semantic Versioning. To check the current version:
tsa --versionThe version number is defined in Cargo.toml and automatically included in the binary.
MIT