Terraform SSH握手失败排查:连接目标与诊断方法问询
一、Terraform到底在连哪里?
没错,它就是在尝试连接你新部署的Google Compute Engine实例——也就是配置里的google_compute_instance.deploy-nixos。从你的模块配置能明确看到:
target_host = "${google_compute_instance.deploy-nixos.network_interface.0.access_config.0.nat_ip}"
这个参数直接指向了该实例的公网IP,所以Terraform的SSH连接目标就是这台刚创建的NixOS虚拟机。
二、一步步诊断SSH认证失败的问题
你的错误提示是ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain,说明SSH连接到了实例,但身份验证完全失败,下面是具体的排查步骤:
1. 先揪出防火墙规则的潜在问题
看你的防火墙配置,这里有个明显的错误:你用了source_tags = ["nixos"],但这个参数的作用是允许来自带有nixos标签的资源的流量,而不是允许外部访问带有nixos标签的实例。你应该把它改成target_tags = ["nixos"],这样防火墙规则才会应用到你的目标实例上,开放22端口给外部:
resource "google_compute_firewall" "deploy-nixos" { name = "deploy-nixos" network = data.google_compute_network.default.name allow { protocol = "icmp" } allow { protocol = "tcp" ports = ["22", "80", "443"] } target_tags = ["nixos"] # 替换原来的source_tags }
这可能是导致连接超时或认证失败的首要原因,先修正这个再继续排查。
2. 手动测试SSH连接,排除Terraform本身的问题
先拿到实例的公网IP(在GCP控制台的实例详情里找“外部IP”),然后在本地终端手动尝试登录:
ssh root@<你的实例公网IP> -i ~/.ssh/id_rsa
如果手动都连不上,那问题肯定出在实例的SSH配置或者密钥上,和Terraform无关:
- 检查你的私钥是否对应实例里的公钥:如果是自定义NixOS镜像,要确保镜像构建时已经把你的公钥写入了
/root/.ssh/authorized_keys;如果用GCE的元数据注入密钥,要确认实例的元数据里已经添加了你的公钥。 - 确认NixOS的SSH服务配置:必须启用
services.openssh.enable = true,并且允许root用户通过公钥登录,比如在NixOS配置里加:services.openssh = { enable = true; permitRootLogin = "prohibit-password"; # 只允许公钥登录root };
3. 检查Terraform使用的SSH密钥是否正确
Terraform的SSH provisioner默认会用当前用户的~/.ssh/id_rsa,如果你的密钥不在这个路径,或者模块里需要指定特定密钥,要确保模块的连接配置里明确指定了私钥:
比如在deploy_nixos模块的null_resource里,应该有类似的连接配置:
resource "null_resource" "deploy_nixos" { # ... 其他配置 connection { type = "ssh" user = var.target_user host = var.target_host private_key = file("/path/to/your/private_key") # 显式指定私钥路径 } }
如果模块里没指定,就确保~/.ssh/id_rsa的公钥确实在实例的authorized_keys里。
4. 查看实例的系统日志,找SSH服务的问题
登录GCP控制台,找到实例的串行端口输出或者日志查看器,搜索sshd相关的日志,看看SSH服务有没有启动失败,或者拒绝连接的具体原因——比如密钥格式不对、权限设置错误(~/.ssh目录权限必须是700,authorized_keys必须是600)。
5. 开启Terraform的详细调试日志
如果上面的步骤都没找到问题,就开启Terraform的DEBUG日志重新运行,能看到完整的SSH握手过程:
TF_LOG=DEBUG terraform apply
日志里会显示Terraform用了哪个私钥、连接的IP、握手的每一步细节,帮你精准定位问题。
内容的提问来源于stack exchange,提问作者Chris Stryczynski

