GCE VM has no external IP / SSH key not recognized
gcloud compute ssh <INSTANCE> times out or reports Connection refused
Focused incident mode — strips away everything but this runbook.
Symptoms
- gcloud compute ssh <INSTANCE> times out or reports Connection refused
- Instance has no External IP address in the console
- SSH key authentication fails with Permission denied (publickey)
- Fresh VM was created with a different service account or SSH keys
Internal-only VMs are common in security-hardened projects — reach them with IAP Tunneling (gcloud compute ssh --tunnel-through-iap) instead of adding public IPs.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Network interfaces and external IP
gcloud compute instances describe <INSTANCE> --zone=<ZONE> --format='value(networkInterfaces)'Project/instance metadata SSH keys
gcloud compute instances describe <INSTANCE> --zone=<ZONE> --format='value(metadata.ssh-keys)'
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- networkInterfaces accessConfigs is empty
- Instance is behind only an internal VPC with no NAT or bastion
Confirm before fixing
gcloud compute instances describe <INSTANCE> --zone=<ZONE> --format='value(networkInterfaces[0].accessConfigs[0].natIP)'Check for an external NAT IP
Expected: Empty result
Fix
gcloud compute instances add-access-config <INSTANCE> --zone=<ZONE> --access-config-name=external-nat --nat-ip=<EPHEMERAL_IP>Attach an ephemeral external IP to reach the VM directly
Expected: Adding access config to instance [<INSTANCE>]...
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
gcloud compute instances describe <INSTANCE> --zone=<ZONE> --format='value(networkInterfaces[0].accessConfigs[0].natIP)'Confirm an external IP exists
gcloud compute firewall-rules list --filter='allowed[].ports=22' --format='table(name,network,sourceRanges)'Make sure tcp:22 is allowed from your source range
gcloud compute ssh <INSTANCE> --zone=<ZONE> --troubleshootUse Google's SSH diagnostics to find the blocker
gcloud compute ssh <INSTANCE> --zone=<ZONE> --command='echo reachable'Confirm end-to-end connectivity
Prevention
- Enable OS Login so key management is IAM-driven instead of metadata-based.
- Prefer IAP Tunneling or a managed proxy over direct external IPs for SSH.
- Scaffold firewall rules for SSH as part of the network module.
- Test gcloud compute ssh before first deploy to catch missing IP/key issues early.
Related runbooks
Same stack, same failure family — worth a skim.
gcloud compute instances list shows PROVISIONING for minutes
Outbound requests from VMs time out while inbound to the VPC works
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.