【Tailscale + SSH + Git】使用 Tailscale + SSH + Git 搭建跨网络远程开发工作流

📅 2026/7/8 3:06:33 👁️ 阅读次数 📝 编程学习
【Tailscale + SSH + Git】使用 Tailscale + SSH + Git 搭建跨网络远程开发工作流

使用 Tailscale + SSH + Git 搭建跨网络远程开发工作流

  • 技术背景
  • 机器角色
  • 配置教程
    • 1. 在两端安装 Tailscale
    • 2. 在台式机 VM 开启 SSH
    • 3. 在台式机 VM 初始化 Git 远程仓库
    • 4. 添加 .gitignore 并提交源码
    • 5. 修复 bare 仓库默认分支
    • 6. 在笔记本侧 clone 仓库
    • 7. 在 Windows 端配置 SSH alias
  • 日常工作流
  • 踩过的坑
    • 1. `ping` 通不代表 SSH 登录成功
    • 2. Tailscale IP 不是普通局域网 IP
    • 3. VMware 共享目录不适合作为 Linux 内核源码主仓库
    • 4. Windows OpenSSH 会严格检查 `.ssh/config` 权限
    • 5. `git branch -M main` 要在第一次 commit 后执行
    • 6. clone 成功但无法检出分支
    • 7. 不要让 Git 同步构建现场

技术背景

我的开发环境比较特殊:我平时在工位使用一台轻薄本,宿舍有一台性能更好的台式机。近期在做嵌入式 SDK 驱动开发,常常需要Agent阅读源码帮我定位bug,但源码、交叉编译环境和构建产物都比较大,如果频繁手工拷贝整个工程,效率会很低。

最开始容易想到的是把两台机器放进同一个局域网,用192.168.x.x访问。但实际情况是:笔记本和台式机不在同一个网段,普通内网 IP 无法直接访问。

最后采用的方案是:

Tailscale 负责打通网络 SSH 负责远程执行命令 Git 负责同步源码变化 台式机 VM 负责真正编译 笔记本/Agent 负责阅读、分析和小范围修改代码

在这个方案里,台式机 Ubuntu VM 相当于一个“私人 Git 服务器”。不需要 GitHub,也不需要公网 IP、DDNS 或路由器端口映射。

机器角色

这套环境里我统一使用下面的命名:

笔记本 Windows 运行 Agent 笔记本 VM 笔记本上的 Ubuntu 虚拟机 台式机 Windows 承载远程桌面和 VMware 台式机 VM 台式机上的 Ubuntu 虚拟机,主要开发和编译环境

本文命令使用下面这些占位符。实际操作时,把它们替换成你自己的信息:

DESKTOP_VM_TAILSCALE_IP 台式机 Ubuntu VM 的 Tailscale IP YOUR_LINUX_USER 台式机 Ubuntu VM 的 Linux 用户名 DESKTOP_VM_SDK_DIR 台式机 Ubuntu VM 上的 SDK 工作目录

例如,台式机 VM 中 SDK 主工作区可以写成:

/home/YOUR_LINUX_USER/work/embedded-sdk

台式机 VM 中 bare Git 仓库可以写成:

/home/YOUR_LINUX_USER/git/embedded-sdk.git

配置教程

1. 在两端安装 Tailscale

如果是windows,访问https://tailscale.com/download下载客户端

如果是 Ubuntu/Debian 虚拟机,可以使用官方安装脚本:

curl-fsSLhttps://tailscale.com/install.sh|shsudotailscale up

执行sudo tailscale up后,终端会给出一个网页登录授权地址。两台机器登录同一个 Tailscale 账号即可。

检查 Tailscale 服务是否运行:

systemctl status tailscaled

设置开机自启并立即启动:

sudosystemctlenable--nowtailscaled

查看当前机器的 Tailscale IP:

tailscaleip-4tailscale status

Tailscale 的100.x.x.x地址通常会绑定设备。只要不重装系统、不删除 Tailscale 节点、不清空/var/lib/tailscale/,这个 IP 一般不会变化。

2. 在台式机 VM 开启 SSH

desktop-vm上执行:

sudoaptupdatesudoaptinstall-ygitopenssh-serversudosystemctlenable--nowssh

在笔记本侧测试连接:

sshYOUR_LINUX_USER@DESKTOP_VM_TAILSCALE_IP

这里会提醒你输入密码,这里的密码是台式机 Ubuntu VM 中YOUR_LINUX_USER用户的密码,不是笔记本密码,也不是 Windows 开机密码。

第一次连接时会提示确认主机指纹:

Are you sure you want to continue connecting (yes/no/[fingerprint])?

输入完整的:

yes

看到Welcome to Ubuntu 20.04.6 LTS之类的欢迎信息,就说明 SSH 登录成功。

3. 在台式机 VM 初始化 Git 远程仓库

在台式机 VM 上创建一个 bare 仓库。bare 仓库不直接编辑文件,只作为远程同步仓库使用,类似自己的 GitHub。

mkdir-p~/gitgitinit--bare~/git/embedded-sdk.git

然后进入台式机 VM 上真正的 SDK 工作目录:

cd~/work/embedded-sdk

如果这里还不是 Git 仓库,推荐一开始就指定默认分支:

gitinit-bmain

如果已经执行过普通git init,也没关系,后面第一次 commit 成功后再执行:

gitbranch-Mmain

注意:如果还没有任何 commit,直接运行git branch -M main可能报:

error: refname refs/heads/master not found fatal: Branch rename failed

这是因为 Git 仓库还没有真正创建出master分支,不是严重错误。先 commit,再改分支名即可。

4. 添加 .gitignore 并提交源码

嵌入式 SDK 里通常有大量编译产物,例如:

out/ temp/ *.o *.ko *.cmd *.d *.img *.bin *.log

这些不应该进 Git。尤其嵌入式 SDK 这种目录,编译产物和源码混在一起。因此需要创建.gitignore文件,设置规则避免将这些文件上传到仓库中,否则Git 仓库会非常臃肿。

提交前先预览将要加入 Git 的文件:

gitadd-n.

确认没有大量构建输出、镜像、临时文件后,再真正提交:

gitadd.gitcommit-m"Initial SDK source import"gitbranch-Mmaingitremoteaddorigin ~/git/embedded-sdk.gitgitpush-uorigin main

如果 Git 提示没有配置用户名和邮箱,可以先设置:

gitconfig--globaluser.name"Your Name"gitconfig--globaluser.email"you@example.com"

5. 修复 bare 仓库默认分支

如果 clone 时出现:

warning: remote HEAD refers to nonexistent ref, unable to checkout 警告:远程 HEAD 指向一个不存在的引用,无法检出

说明 bare 仓库的HEAD还指向默认的master,但实际分支已经是main

在台式机 VM 上修复:

cd~/git/embedded-sdk.gitgitsymbolic-ref HEAD refs/heads/maingitsymbolic-ref HEAD

最后一条命令应该输出:

refs/heads/main

6. 在笔记本侧 clone 仓库

如果是在笔记本 VM 的 Linux ext4 目录中 clone,推荐:

mkdir-p~/workcd~/workgitclone YOUR_LINUX_USER@DESKTOP_VM_TAILSCALE_IP:/home/YOUR_LINUX_USER/git/embedded-sdk.gitcdembedded-sdk

如果只是为了让 Windows 侧 Agent 快速读取源码,也可以 clone 到 VMware 共享目录,但要明确它只是“轻量阅读/小改副本”,不能作为主编译目录。

例如:

cd/mnt/hgfs/SharedFolders/embedded-sdkgitclone YOUR_LINUX_USER@DESKTOP_VM_TAILSCALE_IP:/home/YOUR_LINUX_USER/git/embedded-sdk.git.gitconfig core.filemodefalsegitconfig core.autocrlffalse

检查配置:

gitconfig--getcore.filemodegitconfig--getcore.autocrlf

期望输出:

false false

7. 在 Windows 端配置 SSH alias

为了让 Agent 能直接在 Windows/Codex 环境里远程执行命令,可以在 Windows 的 SSH config 中配置 alias:

Host desktop-vm HostName DESKTOP_VM_TAILSCALE_IP User YOUR_LINUX_USER IdentityFile ~/.ssh/id_ed25519_remote_dev IdentitiesOnly yes

生成一把专用 key:

ssh-keygen -t ed25519 -f "%USERPROFILE%\.ssh\id_ed25519_remote_dev" -C "laptop-to-desktop-vm"

把公钥加入台式机 VM:

type "%USERPROFILE%\.ssh\id_ed25519_remote_dev.pub" | ssh desktop-vm "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

测试免密登录:

ssh desktop-vm "hostname && whoami && pwd"

成功后,Agent 就可以用这种方式远程查看状态:

ssh desktop-vm"cd ~/work/embedded-sdk && git status --short --branch"

远程搜索:

ssh desktop-vm"cd ~/work/embedded-sdk && rg 'driver_name' path/to/source"

远程编译:

ssh desktop-vm"cd ~/work/embedded-sdk && <build-command>"

日常工作流

台式机 VM 是主开发和编译环境:

cd~/work/embedded-sdkgitstatusgitadd-Agitcommit-m"描述这次修改"gitpush

笔记本同步:

gitpull --ff-only

git pull --ff-only的意思是:

如果本地没有额外提交,就把远程所有新提交同步下来; 如果本地和远程分叉了,就停止,让人手动处理。

如果笔记本也做了修改:

gitstatusgitadd-Agitcommit-m"描述这次修改"gitpush

然后台式机 VM 再同步并编译:

gitpull --ff-only

踩过的坑

1.ping通不代表 SSH 登录成功

曾经遇到过:

pingDESKTOP_VM_TAILSCALE_IP

能通,但:

sshdev@DESKTOP_VM_TAILSCALE_IP

一直Permission denied

原因是dev只是示例用户名,真实环境里要替换为台式机 VM 的 Linux 用户名。正确命令应该是:

sshYOUR_LINUX_USER@DESKTOP_VM_TAILSCALE_IP

SSH 密码也是台式机 Ubuntu VM 中YOUR_LINUX_USER用户的密码。

2. Tailscale IP 不是普通局域网 IP

192.168.x.x只能在同一个局域网里用。两台机器跨网络、跨地点时,应该使用 Tailscale 分配的100.x.x.x地址。

例如台式机 VM 可以记作:

DESKTOP_VM_TAILSCALE_IP

Git remote 可以写成:

YOUR_LINUX_USER@DESKTOP_VM_TAILSCALE_IP:/home/YOUR_LINUX_USER/git/embedded-sdk.git

后续如果开启 MagicDNS 或配置 SSH alias,可以把 IP 隐藏成:

desktop-vm:/home/YOUR_LINUX_USER/git/embedded-sdk.git

3. VMware 共享目录不适合作为 Linux 内核源码主仓库

我曾经把完整 SDK clone 到:

/mnt/hgfs/SharedFolders/embedded-sdk

然后git status出现大量莫名修改,例如:

xt_DSCP.h xt_MARK.h xt_TCPMSS.h ipt_TTL.h ip6t_HL.h aux.c aux

这不是因为手动删错了文件,而是因为 Linux 内核源码里有大小写仅不同的文件名,以及 Windows 保留名,例如aux。VMware 共享目录底层受 Windows 文件系统影响,不能完全忠实表示 Linux/ext4 的文件名语义。

结论:

/mnt/hgfs 可以给 Agent 读代码、写文档、做小 patch 不要把它当主仓库 不要在这里编译 不要轻易提交这里显示出来的异常 git status

真正的主工作区应该放在台式机 VM 的 Linux 文件系统中:

/home/YOUR_LINUX_USER/work/embedded-sdk

4. Windows OpenSSH 会严格检查.ssh/config权限

Windows 上曾经出现:

Bad owner or permissions on C:\Users\YOUR_WINDOWS_USER\.ssh\config

这个问题不是 Tailscale,也不是 SSH 服务端,而是本机.ssh/config权限太开放。尤其如果Everyone有完全控制,OpenSSH 会拒绝读取。

可以用完整路径调用icacls.exe修复:

C:\Windows\System32\icacls.exe "%USERPROFILE%\.ssh\config" /inheritance:r C:\Windows\System32\icacls.exe "%USERPROFILE%\.ssh\config" /grant:r "%USERNAME%:F" C:\Windows\System32\icacls.exe "%USERPROFILE%\.ssh\config" /remove "Everyone" "Users" "Authenticated Users"

如果临时想绕过 config,可以用:

ssh -F none YOUR_LINUX_USER@DESKTOP_VM_TAILSCALE_IP

5.git branch -M main要在第一次 commit 后执行

如果刚git init,还没有 commit,直接改分支名可能失败:

error: refname refs/heads/master not found fatal: Branch rename failed

推荐从一开始就用:

gitinit-bmain

如果已经git init,就先 commit:

gitadd.gitcommit-m"Initial SDK source import"gitbranch-Mmain

6. clone 成功但无法检出分支

出现:

warning: remote HEAD refers to nonexistent ref, unable to checkout

不是对象没拉下来,而是 bare 仓库默认HEAD指错了。修复:

cd~/git/embedded-sdk.gitgitsymbolic-ref HEAD refs/heads/main

7. 不要让 Git 同步构建现场

Git 适合同步源码和配置,不适合同步整个编译现场。嵌入式 SDK 的构建产物、镜像、临时对象文件应该通过.gitignore排除。

最终边界是:

Git 同步源码变化 SSH 远程执行命令 台式机 VM 负责编译 笔记本/笔记本 VM 负责查看和小改

这个边界清楚之后,整个远程开发链路就顺了很多。