Terraform Backend Reconfiguration Required: How to Fix
Fix the Terraform 'Backend configuration changed' error. Migrate state between backends (local to S3, S3 to S3), resolve lock conflicts
Troubleshooting
Fix the Terraform remote-exec connection refused error. Covers security groups, SSH keys, instance readiness, bastion hosts, and user_data alternatives.
Terraform can't SSH into the instance. Check that the security group allows port 22 from your IP, the instance is fully booted, and the SSH key/user are correct. Consider using user_data instead of remote-exec provisioners.
Error: timeout - last error: dial tcp 10.0.1.50:22: connect: connection refusedError: timeout - last error: dial tcp 52.1.2.3:22: i/o timeoutError: timeout waiting for SSH to become availablePort 22 isn't open from your machine's IP address:
# Missing or wrong CIDR — your IP isn't allowed
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"] # Doesn't include your public IP
}The EC2 instance is running but SSH daemon hasn't started. This is common with large user_data scripts or slow-booting AMIs.
Each AMI has a different default SSH user:
| AMI | Default User |
|---|---|
| Amazon Linux / AL2023 | ec2-user |
| Ubuntu | ubuntu |
| Debian | admin |
| RHEL | ec2-user |
| CentOS | centos |
| SUSE | ec2-user |
The instance has no public IP and you're trying to SSH from outside the VPC.
The key pair specified doesn't match the private key in the connection block.
resource "aws_security_group" "allow_ssh" {
name = "allow-ssh"
vpc_id = aws_vpc.main.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.my_ip] # e.g., "203.0.113.50/32"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
key_name = aws_key_pair.deploy.key_name
vpc_security_group_ids = [aws_security_group.allow_ssh.id]
subnet_id = aws_subnet.public.id
# Ensure public IP for direct SSH
associate_public_ip_address = true
connection {
type = "ssh"
user = "ubuntu" # Match your AMI
private_key = file("~/.ssh/deploy-key.pem") # Match key_name
host = self.public_ip
timeout = "5m" # Increase timeout
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx",
]
}
}connection {
type = "ssh"
user = "ec2-user"
private_key = file(var.private_key_path)
host = self.public_ip
timeout = "10m" # Default is 5m; increase for slow boots
}resource "aws_instance" "private_server" {
ami = data.aws_ami.al2023.id
instance_type = "t3.micro"
subnet_id = aws_subnet.private.id
key_name = aws_key_pair.deploy.key_name
connection {
type = "ssh"
user = "ec2-user"
private_key = file(var.private_key_path)
host = self.private_ip
bastion_host = aws_instance.bastion.public_ip
bastion_user = "ec2-user"
bastion_private_key = file(var.private_key_path)
}
provisioner "remote-exec" {
inline = ["echo 'Connected via bastion!'"]
}
}HashiCorp recommends avoiding provisioners. Use user_data or cloud-init instead:
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y nginx
systemctl enable nginx
systemctl start nginx
EOF
user_data_replace_on_change = true
}Benefits over remote-exec:
# Test SSH manually
ssh -i key.pem -v ubuntu@52.1.2.3
# Check instance status
aws ec2 describe-instance-status --instance-ids i-1234567890abcdef0
# View system log for boot issues
aws ec2 get-console-output --instance-id i-1234567890abcdef0user_data over remote-exec — no SSH dependencyassociate_public_ip_address = true when SSH is needed from outside VPCConnection refused means Terraform can't reach SSH on the target instance. Fix the security group, verify the SSH user and key match the AMI, increase timeouts for slow boots, and use a bastion for private instances. Better yet, replace remote-exec with user_data — it's simpler, more reliable, and doesn't require SSH access.
Fix the Terraform 'Backend configuration changed' error. Migrate state between backends (local to S3, S3 to S3), resolve lock conflicts
Fix Terraform provider version conflicts between modules, lock files, and constraint mismatches. Resolve dependency lock errors, upgrade providers safely
Fix the Terraform 'Reference to undeclared resource' error. Causes include typos, missing resources, wrong module references, and for_each/count confusion.
Fix the Terraform 'An argument named X is not expected here' error. Common causes include wrong provider version, deprecated arguments, typos