1. 为什么VSCode远程开发绕不开密钥免密先说个很现实的场景你手里一台Windows笔记本公司或家里的服务器跑着Ubuntu代码在服务器上数据在服务器上GPU也在服务器上。你不想在Windows里装一堆环境也不想每次改代码都用scp传上去再跑更不想打开笨重的IDE忍受到处卡顿。这时候VSCode的Remote-SSH就是最顺手的方案而密钥免密则是这套方案里最值得先搞定的一环。很多初次接触的人会想我直接用密码登录不就行了吗确实行但只要你连续用上三五天就会崩溃。每次打开VSCode窗口、每次重载远程窗口、每次git操作触发扩展刷新都可能要求你重新输入密码。要是服务器密码设得复杂一点光输密码的时间就够你喝两杯水了。更麻烦的是某些网络环境下SSH会话很容易断开重连一次输一次体验非常割裂。密钥免密解决的不只是少打几个字的问题它实际改变的是远程开发的流畅度。另一个容易忽略的点是安全性。密码认证意味着你的账号密码在网络上传输虽然SSH协议本身会加密传输内容但密码认证始终面临暴力破解的风险尤其是服务器暴露在公网时。密钥认证用的是非对称加密私钥永远留在本地公钥放在服务器上攻击者拿到公钥也无法反推私钥。只要你本地私钥的权限设置正确安全性比密码高一个量级。这篇文章写的不是那种特别高深的东西而是把整个流程里最容易卡住的地方全部拆开Windows怎么生成密钥、Ubuntu端公钥放哪儿、文件权限哪里容易出错、VSCode连接时遇到各种报错怎么办。我会把每一步背后的原理和判断方法也讲清楚而不只是让你跟着敲命令。适合刚接触远程开发的初学者也适合已经连通过但想彻底搞懂原理、顺便解决历史遗留问题的老手。2. 前置准备Windows和Ubuntu两边各自需要什么2.1 Windows端不必额外装OpenSSHWindows 10较新版本和Windows 11系统里OpenSSH客户端已经是内置组件了。怎么判断自己有没有打开PowerShell或者CMD输入ssh -V如果弹出类似OpenSSH_for_Windows_8.1p1的版本信息说明已经具备。如果提示找不到命令去设置 → 应用 → 可选功能里添加OpenSSH 客户端就行不需要下载第三方工具。这一步很多教程不提但很重要VSCode的Remote-SSH本质上是调用Windows系统里的ssh.exe来建立连接不是VSCode自己实现了一套SSH协议。所以Windows端SSH客户端的状态直接决定后面所有操作能不能走通。我记得早期有人装了Git for Windows以为Git自带的SSH能替代系统OpenSSH结果VSCode默认仍然去找C:\Windows\System32\OpenSSH\ssh.exe两边版本和配置不一致时就容易出现莫名其妙的连接失败。建议直接用系统自带的省心。版本确认无误后再顺手确认一下VSCode本身是最新版插件市场能正常访问。Remote-SSH插件在软件市场的名字就叫Remote - SSH由Microsoft发布装这一个就够它会连带安装Remote Development相关组件。2.2 Ubuntu端openssh-server是前提Ubuntu服务器上必须已经安装并运行SSH服务。检查方法sudo systemctl status ssh如果提示Unit ssh.service could not be found说明压根没装服务端需要sudo apt update sudo apt install openssh-server -y sudo systemctl enable --now ssh装好之后确认22端口在监听sudo ss -tlnp | grep 22看到LISTEN状态就说明服务正常。这里有一个新手常踩的坑很多Ubuntu最小化安装或者云镜像默认只装了openssh-client也就是只能连别人自己不能被连。所以第一步一定是先检查服务端是否存在别急着生成密钥。Ubuntu端还有一件事值得顺手做——确认防火墙没挡22端口。如果启用了ufw执行sudo ufw allow 22/tcp sudo ufw status在公网服务器上建议把/etc/ssh/sshd_config里的PasswordAuthentication暂时保持为yes等密钥验证通过之后再改回no并重启ssh服务。直接改no风险很高尤其是你第一次配密钥、手一抖公钥放错位置的话等于把自己锁在门外。循序渐进稳妥第一。3. 密钥生成与公钥部署Windows本地的私钥和Ubuntu端的authorized_keys3.1 在Windows生成密钥对打开PowerShell执行ssh-keygen -t ed25519 -C your_email_or_comment这里解释一下为什么用ed25519而不是传统的rsa。ed25519是Curve25519椭圆曲线算法密钥更短、生成更快、安全性也足够高。OpenSSH从7.0版本开始就原生支持Windows自带的OpenSSH完全兼容。如果你需要连接的是特别老旧的Linux发行版比如CentOS 6里的OpenSSH 5.3那才需要考虑rsa或ecdsa。正常现代Ubuntu版本ed25519是最优选择没有之一。系统会让你选择密钥保存位置默认是C:\Users\你的用户名\.ssh\id_ed25519直接回车用默认值就好。接着会让你设置passphrase也就是私钥的使用密码。这一步有讲究如果留空私钥文件就是裸奔状态任何拿到你电脑的人都能直接用来登录服务器如果设置passphrase每次连接时都要额外输入一次稍微麻烦但安全性高不少。我个人的建议是如果是个人电脑、全盘加密已开启、平时电脑不会借给别人passphrase可以留空换取最丝滑的体验。如果是公司电脑或者有合规要求设置一个passphrase是更稳妥的做法。而且Windows的OpenSSH支持把私钥添加到ssh-agent服务里设置passphrase之后只需在首次添加时输入一次后续连接不用重复输入两边的好处可以兼得。生成完成后~/.ssh/目录下会出现两个文件id_ed25519私钥和id_ed25519.pub公钥。私钥文件必须保持私有公钥是要上传到服务器的那个。3.2 把公钥上传到Ubuntu的三种方式方式一ssh-copy-id推荐Windows 10较新版本和Windows 11已经原生支持ssh-copy-id命令直接执行ssh-copy-id -i ~/.ssh/id_ed25519.pub usernameserver_ip需要输入一次服务器密码脚本会自动把公钥追加到服务器上~/.ssh/authorized_keys文件的末尾同时自动处理好权限。这是最不容易出错的路径因为权限问题脚本全包了。方式二手动追加如果你的Windows版本没有ssh-copy-id一些旧版本确实没有就需要手动操作。先查看公钥内容cat ~/.ssh/id_ed25519.pub复制输出的整行内容。然后SSH登录服务器ssh usernameserver_ip登录后执行mkdir -p ~/.ssh chmod 700 ~/.ssh echo 你复制的公钥内容 ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys这里的chmod是很多人容易忽略的致命细节。SSH服务端对~/.ssh目录和authorized_keys文件的权限有严格要求.ssh目录不能是其他用户可写authorized_keys文件不能是其他用户可读写。如果权限太宽松sshd为了安全会直接忽略这个文件表现为密钥看起来是对的但就是登录不了。方式三用scp传文件如果你倾向于先把公钥文件弄到服务器上再追加scp ~/.ssh/id_ed25519.pub usernameserver_ip:/tmp/mykey.pub然后登录服务器执行mkdir -p ~/.ssh chmod 700 ~/.ssh cat /tmp/mykey.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys rm /tmp/mykey.pub三种方式本质一样区别只是操作路径。你自己习惯哪种就用哪种只要最终~/.ssh/authorized_keys里的内容正确、权限正确效果没有差别。3.3 免密登录验证回到Windows PowerShell执行ssh usernameserver_ip如果不需要输入密码就进入了Ubuntu的shell说明密钥认证已生效。如果仍然要求密码别急着怀疑人生按顺序排查公钥内容是否完整复制有没有少字符或多了换行authorized_keys是否在正确的用户目录下比如你用ubuntu用户登录公钥就必须在/home/ubuntu/.ssh/authorized_keys而不是/root/.ssh/权限是否正确~/.ssh是700~/.ssh/authorized_keys是600Ubuntu端/etc/ssh/sshd_config里是否启用了PubkeyAuthentication yes执行ssh -v usernameserver_ip可以查看详细连接日志重点看有没有Authentication succeeded或者具体的拒绝原因。这个命令是排查密钥连接问题的第一利器比瞎猜高效得多。4. VSCode Remote-SSH配置从安装插件到成功连接4.1 插件安装与基本设置VSCode扩展市场搜索Remote - SSH认准发布者为Microsoft的那个点击安装。安装完左侧栏会多个远程资源管理器图标VSCode底部状态栏也会出现一个远程窗口相关的入口。首次连接时VSCode会在远程服务器上自动下载并安装一个vscode-server服务端组件用于在远端执行插件、终端命令等。这个过程需要服务器能访问外网下载资源。如果你的服务器在内网环境、无法访问外网这一步就会卡住后面我会专门讲离线安装的替代方案。打开命令面板CtrlShiftP输入Remote-SSH: Connect to Host选择Configure SSH Hosts会要求你选择或创建SSH配置文件。默认配置文件路径是C:\Users\你的用户名\.ssh\config。这个配置文件记录了你要连接的服务器信息后续所有远程连接都从这里读取主机列表。4.2 配置文件写法与参数说明打开config文件填入类似这样的内容Host my-ubuntu HostName 192.168.1.100 Port 22 User ubuntu IdentityFile ~/.ssh/id_ed25519逐行解释Host my-ubuntu你在VSCode里看到的主机别名随便起好记就行HostName服务器的IP地址或域名PortSSH端口默认22如果服务器改过端口就写实际端口User登录用户名IdentityFile指定私钥路径。如果不写SSH会尝试默认路径但写明白更不容易出错尤其是你有多把密钥时保存文件后再次打开命令面板点Remote-SSH: Connect to Host就能看到my-ubuntu出现在列表里。选中它VSCode会新开一个窗口并开始连接。首次连接会提示确认服务器指纹选择Continue即可。这个指纹确认是为了防止中间人攻击正常情况下服务器指纹不会变你可以在服务器端用ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub查看实际指纹来核对。4.3 连接成功后的目录操作连接成功后VSCode左下角状态栏会显示SSH: my-ubuntu。这时候用文件 → 打开文件夹在弹出框里输入远程路径比如/home/ubuntu/projects就能直接浏览和编辑服务器上的文件。左侧资源管理器里所有的文件操作都是直接在远端执行的本地不产生副本。终端面板Ctrl打开后也默认是远端shell相当于直接在Ubuntu上敲命令。你可以同时打开多个终端窗口跑htop查看系统负载、用git操作代码、启动开发服务器全部在远端执行和坐在服务器前操作没有任何区别。扩展方面VSCode会自动在远端重新安装你本地已装的扩展比如Python、ESLint、Prettier这些。有个别扩展不支持远程模式VSCode会自动禁用并在扩展面板里提示不影响使用。5. 实战排查从报错信息定位问题的完整思路5.1 Permission denied (publickey) 的排查链路这是密钥连接最经典也最常见的报错。当VSCode连接时弹出Permission denied (publickey)先别慌回到PowerShell手动执行ssh -v my-ubuntu看详细日志。日志里会出现几个关键片段Offering public key: ...说明本地正在尝试提供密钥Authentications that can continue: publickey,password说明服务器拒绝了当前密钥但允许其他认证方式Connection closed by ...说明服务器端拒绝了连接这时按顺序排查第一步确认Ubuntu端authorized_keys文件权限。在服务器上执行ls -la ~/.ssh/正常应该看到drwx------700的目录和-rw-------600的文件。如果权限不对立刻用chmod修正。第二步确认sshd配置。执行sudo sshd -T | grep pubkey如果返回pubkeyauthentication yes说明服务端允许密钥认证。如果显示no去/etc/ssh/sshd_config里把这一项改过来或者检查是否存在/etc/ssh/sshd_config.d/目录下面的覆盖配置。第三步确认公钥确实在正确的文件里。在服务器上执行cat ~/.ssh/authorized_keys看内容和Windows端的id_ed25519.pub是否完全一致。复制粘贴过程中很容易出现行尾被截断或者多出空格的情况用diff (ssh usernameserver cat .ssh/authorized_keys) ~/.ssh/id_ed25519.pub可以直接对比差别一目了然。5.2 连接成功但VSCode卡在Setting up SSH Host怎么办这种情况最痛苦命令行SSH能连上但VSCode一直卡在初始化界面。原因是VSCode要在远端安装vscode-server而这个过程需要从微软的服务器下载压缩包。网络慢、被墙、服务器无法访问外网都会导致无限卡住。排查方法是看远端是否有vscode-server目录ls ~/.vscode-server/bin/如果目录为空或者没有这个目录说明没装成功。手动安装的办法是在本地VSCode窗口找到Help → About里的Commit ID或者打开VSCode的安装目录里的product.json查看commit字段。然后在服务器上执行mkdir -p ~/.vscode-server/bin cd ~/.vscode-server/bin wget https://update.code.visualstudio.com/commit:你的COMMIT_ID/server-linux-x64/stable下载完成后解压把文件夹改名为对应的commit id再重新连接。这个方法同样适用于内网服务器——只需在一台能访问外网的机器上下载好再通过U盘或者内网传输工具拷过去。如果服务器上已经装过vscode-server但版本过旧也可能导致连接异常。先清掉旧的再重试rm -rf ~/.vscode-serverVSCode的远程机制设计上是自动管理这个组件的但现实中确实偶尔需要手动干预。搞明白了原理遇到这类问题就不慌了。5.3 连接经常断线或响应慢远程开发中还有一个高频问题长时间没有操作后SSH连接断了在VSCode里输入命令转半天才报错。造成这个现象的原因通常是网络设备NAT、防火墙把空闲的TCP连接回收了。SSH本身有ServerAliveInterval机制来发送心跳包保持连接活性。在~/.ssh/config里给目标主机加上Host my-ubuntu HostName 192.168.1.100 User ubuntu IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 ServerAliveCountMax 3ServerAliveInterval 60表示每60秒客户端主动发一个心跳包给服务器ServerAliveCountMax 3表示连续3次心跳无响应才断开连接。这样空闲连接也能维持住。如果是Wi-Fi网络本身不稳定那就不是软件层面能完全解决的了需要考虑换有线连接或者优化网络环境。5.4 Windows公钥文件权限问题Windows上还有一个独特的问题C:\Users\你的用户名\.ssh\目录和id_ed25519私钥文件的权限如果不对OpenSSH会拒绝使用这把密钥。很多人明明配置都对但连接时报Unprotected private key file或者直接忽略这个密钥文件就是这个原因。Windows下检查权限的方法是右键私钥文件 → 属性 → 安全 → 高级确认只有当前用户有完全控制权限不要有SYSTEM或Administrators组的多余权限。如果不小心从其他地方拷贝过密钥文件很容易出现权限继承错乱。修正方式是icacls $env:USERPROFILE\.ssh\id_ed25519 /inheritance:r /grant $env:USERNAME:F执行后重新连接即可。这条命令其实做了两件事移除所有继承权限再给当前用户授予完全控制权限。Windows上的SSH对这块卡的比较紧这算是Windows平台独有的小麻烦但一旦理解了它的逻辑就不再是坑了。6. 进阶技巧与日常使用心得6.1 用config管理多台服务器随着服务器数量增加别再去命令面板里手动输入用户名、IP那样既容易记错也低效。在config文件里把所有主机都列出来每台一个唯一的Host别名连接时从列表里选就行。Host work-server HostName 10.0.0.5 User deploy Port 22 IdentityFile ~/.ssh/id_ed25519_work Host home-nas HostName 192.168.31.2 User admin Port 2222 IdentityFile ~/.ssh/id_ed25519_home Host cloud-gpu HostName 123.45.67.89 User ubuntu IdentityFile ~/.ssh/id_ed25519_gpu ServerAliveInterval 60每台服务器用独立密钥对也是安全上更推荐的做法一台机器的私钥泄露不影响其他机器。生成多把密钥时记得用-f参数指定不同文件名ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C work6.2 远程端口转发让本地服务也能访问远端资源Remote-SSH插件自带端口转发功能但这个功能依赖VSCode的UI操作。如果你需要在纯终端场景下用建议直接在SSH命令里加参数ssh -L 3306:127.0.0.1:3306 cloud-gpu这条命令把远端服务器的3306端口比如MySQL映射到本地3306端口。之后本地程序连接127.0.0.1:3306就是在访问远端的数据库。对调试远程API、访问远程数据库这类需求非常实用。如果需要在config里固定配置可以在对应主机下加LocalForward 3306 127.0.0.1:3306。6.3 禁用密码登录的时机与操作当密钥认证确认无误后可以考虑把密码登录关掉进一步降低暴力破解风险。操作前切记确认你能用密钥正常登录并且当前SSH会话没有断开。编辑配置文件sudo vim /etc/ssh/sshd_config找到PasswordAuthentication改成no。确认PubkeyAuthentication是yes。保存后重启服务sudo systemctl restart ssh然后不要关闭当前会话另开一个终端尝试用密钥登录。登录成功再关掉旧会话。这是唯一的保险做法。如果新终端连不上还能在旧会话里把配置改回来。我在实际使用中见过不少因操作顺序颠倒导致服务器失联的例子最终只能通过云控制台VNC或者物理机去恢复既尴尬又浪费时间。谨慎永远比能力强重要。6.4 备份私钥与恢复私钥文件一旦丢失意味着你配置过的所有服务器都进不去了。务必备份好~/.ssh/id_ed25519和对应的.pub文件但备份时要注意安全不要把私钥明文放在云笔记、Git仓库或者随便一个U盘里。可以加密后存储比如用7-Zip加密压缩或者放入密码管理器。换新电脑时把备份的密钥文件恢复到C:\Users\你的用户名\.ssh\目录下修正权限再保证config文件内容一致即可无缝恢复所有远程连接不需要重新配置任何服务器。这也是密钥认证比密码认证明显的优势之一——跨设备迁移成本极低。7. 实用经验速查常见问题与解决要点汇总直接用一张表把高频问题和不常见但棘手的场景都列出来方便遇到问题时快速定位现象可能原因解决思路密钥登录仍要密码authorized_keys权限过宽chmod 700 ~/.sshchmod 600 ~/.ssh/authorized_keys报错Permission denied (publickey)公钥内容不匹配或sshd未启用PubkeyAuthentication对比公钥内容、检查sshd -T输出连接超时防火墙/安全组未放行端口检查ufw、云安全组、路由器端口转发VSCode一直卡在Setting upvscode-server未安装或版本不匹配手动下载对应commit的server并解压到~/.vscode-server/bin/连接自动断开空闲连接被网络设备回收config里加ServerAliveInterval 60私钥文件被拒绝使用Windows文件权限含多余用户用icacls重置权限其他用户无法登录.ssh目录属于其他用户确认目录owner是当前登录用户系统提示Host key verification failed服务器系统重装过公钥指纹变化在本地~/.ssh/known_hosts里删除旧记录后重连有一个细节值得特别提醒当你重装系统、重置云主机之后SSH连接的指纹会发生变化Windows端会拒绝连接并提示Host key verification failed。解决方法是在本地执行ssh-keygen -R 服务器IP把known_hosts里的旧指纹删掉重新连接时确认新指纹即可。这是服务器重装后最常遇到、又最容易被忽略的一个小坑。另外VSCode连接远程服务器时打开的每个窗口本质上是同一个vscode-server实例在服务多个本地窗口。如果服务器端~/.vscode-server目录被误删或权限错乱可能出现能连上但插件全部异常的情况。这时在服务器端执行rm -rf ~/.vscode-server然后断开重连让VSCode重新安装一次通常能解决问题。使用了一段时间后我的个人体会是密钥免密连接这件事本质上就是在本地生成一对钥匙把公钥交给服务器保管以后每次进门用私钥“对暗号”。Windows和Ubuntu的SSH生态现在非常成熟官方文档齐全社区也有海量讨论。真正需要投入时间去理解的不是命令本身而是整个认证链路和权限体系的工作方式。一旦理解了你会发现VSCode远程开发不再是需要小心翼翼维护的“高级功能”而是一个可以放心依赖的日常工具。