Packer Builds Stuck at "Waiting for SSH/WinRM": A Diagnostic Guide
Packer hangs on "Waiting for SSH/WinRM" until the timeout kills the instance and the evidence. A cause table, ordered checks, targeted fixes, and escalation criteria.
23 Dec 2025, 19:28 UTC

Your Packer build launches the instance successfully, then the log freezes on Waiting for SSH to become available... (or the WinRM equivalent) until communicator_timeout — 10 minutes by default — expires and Packer tears the instance down. You lose the machine and most of the evidence with it.
The useful takeaway: this symptom almost always means one of five things — wrong credentials, a blocked port, the guest service not running yet, wrong host resolution, or a slow first boot. You can narrow it to one of them in a few ordered checks instead of guessing at timeouts.
Recognize the condition
The signature is a build that gets past instance creation and then stalls. With PACKER_LOG=1 set, you will see repeated connection attempts to port 22 (SSH) or 5985/5986 (WinRM) that either time out or are refused. Two sub-patterns matter:
- Connection refused usually means the network path works but nothing is listening yet — the guest is still booting or the service failed to start.
- Connection timeout usually means packets are being dropped — security groups, NACLs, or the OS firewall — or you are targeting the wrong address entirely.
Cause and quick-diagnostic table
| Likely cause | How to tell |
|---|---|
Wrong ssh_username / communicator type for the image | Log shows authentication failures, or the image publisher documents a different default user (e.g., ubuntu vs ec2-user vs admin) |
| Security group or firewall blocks 22/5985 | Connection attempts time out; port unreachable from the Packer host |
| Guest not running sshd/WinRM yet | Connection refused early, then succeeds if you retry manually later |
| Wrong interface (public vs private IP) | Packer targets an IP your build host cannot route to; common in private subnets |
| cloud-init or first-boot scripts delay startup | Provider console/serial log shows cloud-init still running past the timeout |
Ordered checks
Work through these in order; each is cheaper than the next.
- Confirm the image's expected credentials and communicator. Check the source image publisher's documentation for the default user and whether the image even runs SSH/WinRM. If the image needs no provisioning at all, set
communicator = "none"and skip this entire class of problem. - Test port reachability from the Packer host. While a build is hung (or against a manually launched instance), run
nc -zv <instance-ip> 22from the machine running Packer. You need network access to the instance's subnet. A timeout here points at networking, not Packer. - Audit security groups, NACLs, and the guest firewall. Confirm inbound 22 (or 5985/5986) is allowed from the Packer host's IP. Scope the rule to that IP — do not open
0.0.0.0/0as a workaround. - Read the instance console or serial log. Most cloud providers expose boot output. Look for kernel panics, cloud-init errors, or sshd failing to start. This distinguishes "service never came up" from "network is broken." On Linux,
/var/log/cloud-init-output.logis the usual suspect once you can get in. - Launch the same image by hand and connect manually. Use the same credentials Packer would use. If manual SSH/WinRM also fails, the problem is the image or account configuration, not your template.
Preserve the evidence before it is destroyed
Packer's default cleanup deletes the failed instance. Run the build with -on-error=ask or -on-error=abort so the machine stays up and you can connect manually and inspect logs. Alternatively, packer build -debug pauses at each step.
Two cautions: an aborted build leaves a billable, possibly insecure instance running — clean it up as soon as you finish debugging. And do not disable host key checking permanently to force a connection; that hides real problems and weakens the build.
Fixes tied to findings
- Wrong user: set
ssh_usernameto the publisher's documented default for that image. - Blocked port: add a scoped ingress rule for the builder's IP; verify with the
nccheck again. - Slow first boot: add
pause_before_connecting(e.g.,30s) or increaseboot_wait. Raisecommunicator_timeoutonly after you have confirmed the guest eventually becomes healthy — a bigger timeout masks real faults and makes every failed build more expensive. - No public IP: set
ssh_interface = "private_ip"(or the builder's session-manager interface option where supported) so Packer targets a reachable address. - No provisioning needed:
communicator = "none"removes the wait entirely.
Option names vary across Packer and plugin versions — confirm them against the plugin version pinned in your required_plugins block, since some builders have moved inline fields into dedicated blocks.
Verify the fix
Reproduce first with a minimal template using the same source image and communicator, running with PACKER_LOG=1 to capture connection attempts. After applying a fix, run the full build end-to-end and confirm two things: provisioning steps actually execute (not just that the wait disappeared), and the artifact registers in your cloud account. If you fixed it by setting communicator = "none", verify the resulting image boots and behaves as expected without the provisioning you skipped.
When to escalate
- Manual connection to a hand-launched instance of the same image also fails — this is an image or account-level issue, not a Packer one. Take it to whoever owns the image.
- Packet captures or flow logs show traffic dropped outside your security groups — escalate to the network team with the capture evidence.
- The build works locally but fails only in CI — suspect IAM permissions, CI-specific credentials, or ephemeral network differences in the CI environment, and compare the two environments' effective configuration.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.