Setting Up Passwordless SSH Across All Machines in Your Tailscale Network
If you have multiple machines connected through Tailscale, you’ve probably found yourself typing SSH passwords repeatedly when jumping between systems. In this guide, I’ll show you how to set up passwordless SSH authentication across all your Tailscale machines, creating...
If you have multiple machines connected through Tailscale, you’ve probably found yourself typing SSH passwords repeatedly when jumping between systems. In this guide, I’ll show you how to set up passwordless SSH authentication across all your Tailscale machines, creating a seamless mesh network where any machine can connect to any other without passwords.
By the end of this guide, you’ll have:
-
Passwordless SSH authentication between all machines
-
Easy-to-remember SSH aliases (e.g., ssh laptop, ssh server)
-
A fully connected mesh network where every machine can reach every other machine
-
Works across different operating systems (Windows, Linux, macOS)
-
Tailscale installed and running on all machines
-
SSH server enabled on all machines
-
Basic command line knowledge
-
Administrator/sudo access on all machines
For each machine, we’ll:
-
Generate SSH keys without passphrases
-
Distribute public keys to all other machines
-
Create SSH config files for easy connections
-
Test the connections
# Check if SSH server is installedGet-WindowsCapability -Online | Where-Object Name -like 'OpenSSH.Server*'
# Install if needed (run as Administrator)Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Start and enable the serviceStart-Service sshdSet-Service -Name sshd -StartupType 'Automatic'
# Verify it's runningGet-Service sshd# Ubuntu/Debiansudo apt updatesudo apt install openssh-serversudo systemctl enable sshsudo systemctl start ssh
# macOS (usually pre-installed)sudo systemsetup -setremotelogin onList all your Tailscale machines and their IPs:
tailscale statusYou’ll see output like:
100.x.x.1 laptop1 user@ linux -100.x.x.2 laptop2 user@ windows -100.x.x.3 server1 user@ linux -100.x.x.4 macmini user@ darwin -Take note of the IPs and hostnames – you’ll need them later.
Important: Generate keys WITHOUT a passphrase for passwordless authentication.
# Generate keyssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
# View your public keycat ~/.ssh/id_ed25519.pub# Generate keyssh-keygen -t ed25519 -f "$env:USERPROFILE\.ssh\id_ed25519" -N ""
# View your public keyGet-Content "$env:USERPROFILE\.ssh\id_ed25519.pub"Save each machine’s public key – you’ll need to distribute them.
For each machine, you need to add the public keys of ALL OTHER machines to its authorized_keys file.
# Add a public key to authorized_keysecho "ssh-ed25519 AAAA...rest-of-key... user@hostname" >> ~/.ssh/authorized_keys
# Set correct permissionschmod 700 ~/.sshchmod 600 ~/.ssh/authorized_keysFor non-administrator users:
# Create .ssh directory if neededmkdir "$env:USERPROFILE\.ssh" -Force
# Add public key$key = "ssh-ed25519 AAAA...rest-of-key... user@hostname"Add-Content -Path "$env:USERPROFILE\.ssh\authorized_keys" -Value $key
# Set permissionsicacls.exe "$env:USERPROFILE\.ssh\authorized_keys" /inheritance:ricacls.exe "$env:USERPROFILE\.ssh\authorized_keys" /grant:r "$($env:USERNAME):(R)"icacls.exe "$env:USERPROFILE\.ssh\authorized_keys" /grant:r "SYSTEM:(F)"For administrator users (Windows treats them differently):
# Also add to administrators file$key = "ssh-ed25519 AAAA...rest-of-key... user@hostname"Add-Content -Path "C:\ProgramData\ssh\administrators_authorized_keys" -Value $key
# Set permissionsicacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /inheritance:ricacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /grant "SYSTEM:(F)"icacls.exe "C:\ProgramData\ssh\administrators_authorized_keys" /grant "Administrators:(F)"Instead of typing ssh user@100.x.x.x, create aliases like ssh laptop.
# Create/edit ~/.ssh/configcat > ~/.ssh/config **Important:** The `IdentitiesOnly yes` option prevents the “Too many authentication failures” error when you have multiple SSH keys.
## Step 6: Test Connections
From any machine, try connecting to others:
```bash# Test individual connectionsssh laptop1 "hostname"ssh server1 "whoami"ssh macmini "uptime"
# Test from one machine to another and then to a thirdssh laptop1 'ssh server1 "echo Connected through laptop1 to server1"'If everything works, you should connect without any password prompts!
-
Verify the public key is in authorized_keys:# On the target machine cat ~/.ssh/authorized_keys
-
Check permissions:
Linux/macOS: ~/.ssh should be 700, authorized_keys should be 600
-
Windows: Use icacls as shown above
-
For Windows administrators: Make sure the key is in C:\ProgramData\ssh\administrators_authorized_keys
Add IdentitiesOnly yes to your SSH config file (shown above).
# Verify Tailscale connectivitytailscale ping 100.x.x.x
# Check if SSH is listening# On target machinenetstat -an | grep :22 # Linux/macOSnetstat -an | Select-String ":22" # Windows PowerShellYour SSH key has a passphrase. Either:
-
Use ssh-agent to cache the passphrase, OR
-
Generate a new key without a passphrase (as shown in Step 3)
-
Private keys never leave their machine – only public keys are shared
-
Tailscale provides the network security – SSH traffic is already encrypted by Tailscale
-
Passwordless keys are safe when:
The private key file is protected (correct permissions)
-
The machine itself is secured (disk encryption, strong login password)
-
You trust the Tailscale network (all machines are yours or your team’s)
-
For extra security:
Use PasswordAuthentication no in /etc/ssh/sshd_config to disable password login entirely
-
Use Tailscale ACLs to restrict which machines can connect to which
-
Consider keeping passphrases on keys for highly sensitive servers
Once completed, you’ll have this connection matrix:
| From ↓ / To → | laptop1 | laptop2 | server1 | macmini |
|---|---|---|---|---|
| laptop1 | – | ✅ | ✅ | ✅ |
| laptop2 | ✅ | – | ✅ | ✅ |
| server1 | ✅ | ✅ | – | ✅ |
| macmini | ✅ | ✅ | ✅ | – |
Here’s a helper script to test all connections from the current machine:
#!/bin/bashHOSTS=("laptop1" "laptop2" "server1" "macmini")CURRENT_HOST=\$(hostname)
echo "Testing SSH connections from \$CURRENT_HOST..."echo "=========================================="
for host in "\${HOSTS[@]}"; do if [ "\$host" != "\$CURRENT_HOST" ]; then echo -n "Testing \$host... " if ssh -o ConnectTimeout=5 "\$host" "echo OK" &>/dev/null; then echo "✅" else echo "❌" fi fidone\$hosts = @("laptop1", "laptop2", "server1", "macmini")\$currentHost = hostname
Write-Host "Testing SSH connections from \$currentHost..."Write-Host "=========================================="
foreach (\$host in \$hosts) { if (\$host -ne \$currentHost) { Write-Host -NoNewline "Testing \$host... " try { \$result = ssh -o ConnectTimeout=5 \$host "echo OK" 2>&1 if (\$LASTEXITCODE -eq 0) { Write-Host "✅" -ForegroundColor Green } else { Write-Host "❌" -ForegroundColor Red } } catch { Write-Host "❌" -ForegroundColor Red } }}You now have a fully connected mesh of machines where any system can SSH to any other without passwords! This setup is incredibly powerful for:
-
Running distributed tasks across machines
-
Quickly hopping between systems for maintenance
-
Setting up cluster computing
-
Remote development workflows
-
Automated deployment scripts
The combination of Tailscale’s secure network and SSH key authentication gives you both security and convenience. Enjoy your passwordless SSH mesh network!
-
Tailscale Documentation
-
OpenSSH Manual
-
SSH Config File Reference