Date researched: 2026-04-09 Sources: github.com/winfsp/sshfs-win, tailscale.com/docs, code.claude.com/docs, help.obsidian.md
Single connection mechanism (Tailscale + SSH) that serves all dev tools:
- Claude Desktop (SSH session to remote Linux box)
- Obsidian (SSHFS-mounted vault from same Linux box)
- VS Code (Remote-SSH extension to same box)
All use SSH over Tailscale. One tunnel, three apps. Works from Windows or Mac.
Windows or Mac Desktop Linux Server
┌─────────────────┐ Tailscale VPN ┌──────────────────┐
│ Claude Desktop │───── SSH ──────────│ Claude Code CLI │
│ VS Code │───── SSH ──────────│ workspace/ │
│ Obsidian │───── SSHFS ────────│ workspace/wiki/ │
└─────────────────┘ └──────────────────┘
All connections go through Tailscale mesh VPN
No port forwarding, no public IP needed
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Start and authenticate
sudo tailscale up
# Enable Tailscale SSH (optional -- lets you skip key management)
sudo tailscale set --ssh
# Verify
tailscale status
# Note the Tailscale IP (e.g., 100.x.y.z) or MagicDNS hostname- Download Tailscale from https://tailscale.com/download/windows
- Install and sign in with the same account
- Verify connection:
tailscale status # Should show the Linux box with its Tailscale IP
# Option A: Homebrew
brew install tailscale
# Option B: Mac App Store
# Search "Tailscale" and installSign in with the same account. Verify with tailscale status.
Visit https://login.tailscale.com/admin/acls and ensure SSH access is allowed:
{
"grants": [
{
"src": ["your-email@domain.com"],
"dst": ["tag:server"],
"ip": ["22"]
}
],
"ssh": [
{
"action": "accept",
"src": ["your-email@domain.com"],
"dst": ["autogroup:self"],
"users": ["autogroup:nonroot"]
}
]
}# From Windows PowerShell or Mac Terminal
ssh jared@<tailscale-ip-or-magicDNS-name>If using Tailscale SSH (tailscale set --ssh), no SSH keys needed -- Tailscale handles auth via WireGuard. Otherwise, set up keys:
Windows:
ssh-keygen -t ed25519 -C "windows-desktop"
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh jared@<tailscale-ip> "cat >> ~/.ssh/authorized_keys"Mac:
ssh-keygen -t ed25519 -C "mac-desktop"
ssh-copy-id -i ~/.ssh/id_ed25519.pub jared@<tailscale-ip>Once Tailscale is connected:
- Open Claude Desktop on Windows or Mac
- Click the environment dropdown (before starting a session)
- Select + Add SSH connection
- Fill in:
- Name:
Dev Server(or whatever you like) - SSH Host:
jared@<tailscale-ip>orjared@<magicDNS-hostname> - SSH Port: 22 (leave default)
- Identity File:
- Windows:
C:\Users\<you>\.ssh\id_ed25519 - Mac:
~/.ssh/id_ed25519 - Or leave empty if using Tailscale SSH
- Windows:
- Name:
- Click Save
Now select that connection from the environment dropdown and start a session. Claude runs on the Linux box with full access to files, tools, MCP servers, etc.
- Permission modes (Ask, Auto accept edits, Plan mode)
- Connectors (GitHub, Slack, Linear, etc.)
- Plugins and MCP servers
- @mention files with autocomplete
- Skills and slash commands
- Visual diff review, live app preview
- Computer use (requires local Windows/macOS desktop)
VS Code's built-in Remote-SSH extension uses the same Tailscale SSH connection.
- Install the Remote - SSH extension in VS Code (Microsoft first-party,
ms-vscode-remote.remote-ssh) Ctrl+Shift+P(Windows) orCmd+Shift+P(Mac) > Remote-SSH: Connect to Host...- Enter:
jared@<tailscale-ip> - VS Code opens a full remote session -- terminal, file tree, extensions all run on the Linux box
Add to ~/.ssh/config (Mac) or C:\Users\<you>\.ssh\config (Windows):
Host devbox
HostName <tailscale-ip-or-magicDNS>
User jared
IdentityFile ~/.ssh/id_ed25519
Then just connect to devbox in the Remote-SSH dropdown.
- Full terminal access
- File editing with all VS Code extensions (run on remote)
- Port forwarding (auto-forwards dev server ports)
- Integrated Git
- Claude Code extension (runs on remote, UI in local VS Code)
Install (one-time):
Option A -- winget (recommended):
winget install WinFsp.WinFsp
winget install SSHFS-Win.SSHFS-WinOption B -- manual:
- Install WinFsp from https://winfsp.dev/rel/
- Install SSHFS-Win from https://github.com/winfsp/sshfs-win/releases (x64)
Mount the wiki vault:
# Mount with SSH key auth, from root filesystem
net use W: \\sshfs.kr\jared@<tailscale-ip>\home\jared\workspace\wikiUNC path syntax breakdown:
sshfs.kr= root path + SSH key auth (uses%USERPROFILE%\.ssh\id_rsaorid_ed25519)sshfs.k= home-relative path + SSH key authsshfs.r= root path + password authsshfs= home-relative path + password auth
Using Windows Explorer:
- Open This PC > Map Network Drive
- Drive letter:
W:(or whatever) - Folder:
\\sshfs.kr\jared@<tailscale-ip>\home\jared\workspace\wiki - Check "Reconnect at sign-in"
- Click Finish
Keep connection alive -- apply ServerAliveInterval registry fix:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\WinFsp\Services\sshfs]
"CommandLine"="-oServerAliveInterval=30 -oServerAliveCountMax=3"Open in Obsidian: Open folder as vault > navigate to W:\
Install (one-time):
brew install macfuse
brew install gromgit/fuse/sshfs-macNote: macFUSE requires a kernel extension. After install, go to System Settings > Privacy & Security and approve the macFUSE extension. Reboot required.
Mount the wiki vault:
mkdir -p ~/wiki-mount
sshfs jared@<tailscale-ip>:/home/jared/workspace/wiki ~/wiki-mount \
-o ServerAliveInterval=30 \
-o reconnect \
-o volname=wikiUnmount:
umount ~/wiki-mount
# or: diskutil unmount ~/wiki-mountAuto-mount at login -- create a Launch Agent at ~/Library/LaunchAgents/com.sshfs.wiki.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.sshfs.wiki</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/sshfs</string>
<string>jared@TAILSCALE_IP:/home/jared/workspace/wiki</string>
<string>/Users/jared/wiki-mount</string>
<string>-o</string><string>ServerAliveInterval=30</string>
<string>-o</string><string>reconnect</string>
<string>-o</string><string>volname=wiki</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
</dict>
</plist>Replace TAILSCALE_IP with actual IP. Load with launchctl load ~/Library/LaunchAgents/com.sshfs.wiki.plist.
Open in Obsidian: Open folder as vault > navigate to ~/wiki-mount
- SSH keys must be passphrase-free for SSHFS key auth (or use ssh-agent)
- First mount may prompt for credentials -- save them (Windows Credential Manager / macOS Keychain)
- Large vaults may feel slightly slower than local due to network latency (Tailscale is fast but not zero)
- Obsidian's file watcher may be slower over SSHFS -- it polls rather than using inotify
- macFUSE kernel extension may need re-approval after macOS updates
Create a batch script and place in shell:startup:
@echo off
REM Mount Linux wiki vault
net use W: \\sshfs.kr\jared@<tailscale-ip>\home\jared\workspace\wiki /persistent:yes 2>nul
echo Wiki vault mounted on W:Or use Task Scheduler with condition "Start only if network connection is available."
Use the Launch Agent from Part 3 above, or a simple shell script in Login Items:
#!/bin/bash
sleep 5 # wait for Tailscale to connect
sshfs jared@<tailscale-ip>:/home/jared/workspace/wiki ~/wiki-mount \
-o ServerAliveInterval=30 -o reconnect -o volname=wiki- Verify SSH works first:
ssh jared@<tailscale-ip>from PowerShell - Check WinFsp service is running:
sc query WinFsp.Launcher - Try password-based mount first (
\\sshfs\...) to isolate key issues - Ensure key is at
%USERPROFILE%\.ssh\id_rsaorid_ed25519
- Verify macFUSE kernel extension is approved: System Settings > Privacy & Security
- Test SSH manually first:
ssh jared@<tailscale-ip> - Check mount point exists and is empty:
ls ~/wiki-mount - If "mount_macfuse: mount point is itself on a macFUSE volume": unmount first
- Verify Tailscale is connected:
tailscale status - Test SSH manually in terminal first
- Check that Claude Code CLI is installed on the Linux box:
claude --version
- Same SSH troubleshooting as Claude Desktop
- Check VS Code's Remote-SSH output log:
View > Output > Remote-SSH - Ensure
sshdis running on the Linux box:systemctl status ssh
- SSHFS mount may not reconnect before Obsidian starts
- Windows: use the startup script with a delay (
timeout /t 10) - Mac: add
sleep 5before sshfs in your login script - Or just re-mount manually
- Tailscale latency is usually <10ms on LAN, 20-50ms over internet
- If vault is large (1000+ files), consider mounting only the wiki subfolder
- Disable Obsidian plugins that do heavy file scanning (e.g., search indexing)
| App | Protocol | Windows | Mac |
|---|---|---|---|
| Claude Desktop | SSH session | Built-in env dropdown | Built-in env dropdown |
| VS Code | Remote-SSH | Remote-SSH extension | Remote-SSH extension |
| Obsidian | SSHFS mount | WinFsp + SSHFS-Win | macFUSE + sshfs-mac |
All three use the same Tailscale IP and SSH key. One mechanism across everything.
- Tailscale encrypts all traffic with WireGuard -- no data in the clear
- No ports exposed to the public internet
- If using Tailscale SSH: auth handled by Tailscale identity, no SSH keys to manage
- If using SSH keys: ed25519 recommended, stored in Windows Credential Manager / macOS Keychain
- Tailscale ACLs control who can reach which machines