Chapter 4 · Part II — Access Control

Client Setup and SSH Access

This chapter covers setup from the operator's perspective — the engineer who wants to SSH into a Spark from their laptop. At this point the Sparks are enrolled and tagged (Chapter 2), and the ACL is configured (Chapter 3). The only remaining steps are installing Tailscale on the client machine, joining the tailnet, and verifying that the SSH connection works.

The steps below use macOS with Homebrew. The Tailscale process is identical on Linux and Windows; only the installation command differs.

Step 1 — Install Tailscale on macOS

brew install tailscale

This installs the tailscale CLI and the tailscaled background daemon via Homebrew. The Tailscale macOS app (from the App Store) is an alternative with a menu-bar UI — both work identically for CLI usage.

Start the daemon

sudo brew services start tailscale

Verify it is running:

brew services list | grep tailscale

Expected output: tailscale started ...

Step 2 — Login and Verify

Authenticate to the tailnet

tailscale login

This opens a browser window to the Tailscale login page. Sign in with the same account whose email was added to group:operators in the ACL policy. On success the terminal prints:

Success.

Bring up the connection

tailscale up

The client connects to the tailnet. No extra flags are needed on a workstation — --ssh is only required on machines that accept inbound SSH.

Check network status

tailscale status

You should see your machine and both Spark nodes listed:

100.124.xx.xx  serverlesss-macbook-pro  mohnishbasha@   macOS  -
100.109.xx.xx  spark-bundle1-1          tagged-devices  linux  -
100.104.xx.xx  spark-bundle1-2          tagged-devices  linux  -
100.70.xx.xx   spark-bundle2-1          tagged-devices  linux  -
100.67.xx.xx   spark-bundle2-2          tagged-devices  linux  -
ColumnMeaning
IP (100.x.x.x)Stable Tailscale IP — does not change even if the machine's LAN IP changes
HostnameMachine name as registered in the tailnet
LoginThe Tailscale account that owns this device (tagged-devices for machines with ACL tags)
OSOperating system of the peer
Status- = idle, active = currently communicating

Inspect peer tags

Confirm both Sparks carry the tag:spark tag:

tailscale status --json | jq '.Peer[] | {name: .HostName, tags: .Tags}'

Expected output:

{
  "name": "spark-bundle1-1",
  "tags": ["tag:spark"]
}
{
  "name": "spark-bundle1-2",
  "tags": ["tag:spark"]
}
{
  "name": "spark-bundle2-1",
  "tags": ["tag:spark"]
}
{
  "name": "spark-bundle2-2",
  "tags": ["tag:spark"]
}

If a machine shows "tags": null, return to the admin console and apply the tag (Chapter 2, Step 3).

Step 3 — SSH into a Spark Node

You can connect using either the Tailscale IP or the MagicDNS hostname. Both work from any device on the tailnet.

By Tailscale IP

tailscale ssh stoke@100.70.xx.xx   # spark-bundle2-1
tailscale ssh stoke@100.67.xx.xx   # spark-bundle2-2

By MagicDNS hostname

tailscale ssh stoke@spark-bundle2-1.tail8a84f6.ts.net
tailscale ssh stoke@spark-bundle2-2.tail8a84f6.ts.net

You can also use plain ssh if MagicDNS is resolving correctly on your system:

ssh stoke@100.70.xx.xx
Prefer tailscale ssh over ssh for the first connection
tailscale ssh bypasses ~/.ssh/known_hosts checking and always authenticates through tailnet identity. Vanilla ssh works too, but you may see an SSH host-key warning the first time you connect via the Tailscale IP because it is a different path than any previous LAN connection.

A successful connection displays the DGX Spark welcome banner and drops you into a shell as stoke:

Welcome to Ubuntu 22.04.x LTS (GNU/Linux 6.x.x aarch64)

 * Documentation:  https://help.ubuntu.com
 ...

stoke@spark-bundle2-1:~$

Routing across all four Sparks

Once on the tailnet, you can SSH between any Spark node directly — also without keys:

# From your laptop — reach any of the four nodes
tailscale ssh stoke@100.109.xx.xx   # spark-bundle1-1
tailscale ssh stoke@100.104.xx.xx   # spark-bundle1-2
tailscale ssh stoke@100.70.xx.xx    # spark-bundle2-1
tailscale ssh stoke@100.67.xx.xx    # spark-bundle2-2

The tailnet provides end-to-end encrypted connectivity between all enrolled peers.

Summary: what you now have

CapabilityHow it works
SSH to spark-bundle1-1tailscale ssh stoke@100.109.xx.xx
SSH to spark-bundle1-2tailscale ssh stoke@100.104.xx.xx
SSH to spark-bundle2-1tailscale ssh stoke@100.70.xx.xx
SSH to spark-bundle2-2tailscale ssh stoke@100.67.xx.xx or hostname
Add a new operatorInvite to tailnet + add login to group:operators
Remove an operatorRemove from tailnet — access revoked everywhere instantly
Add a new SparkEnroll it + apply tag:spark — ACL covers it automatically