Introduction

Terraform provisioners are executing scripts or commands during resource creation or destruction, and these executions are failing. Provisioners run after resource creation or before destruction, and failures prevent Terraform from completing the operation successfully.

Symptoms

For remote-exec provisioner:

``` Error: error executing provisioner "remote-exec": timeout - last error: dial tcp 10.0.0.1:22: i/o timeout

Error: remote-exec provisioner error: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]

Error: Provisioner "remote-exec" failed: exit status 1: sudo: no tty present and no askpass program specified ```

For local-exec provisioner:

``` Error: error executing provisioner "local-exec": exit status 1: /bin/sh: 1: my-script.sh: not found

Error: local-exec provisioner error: command "ansible-playbook -i inventory deploy.yml" exited with non-zero status 2

Error: Provisioner "local-exec" failed: command execution failed: permission denied ```

For file provisioner:

``` Error: error uploading file: ssh: handshake failed: connection refused

Error: file provisioner error: scp: /var/www/html/config.conf: Permission denied ```

Common Causes

Provisioner failures occur due to:

  1. 1.Connection timeout - Cannot reach remote host for SSH/WinRM
  2. 2.Authentication failure - Wrong credentials or SSH key issues
  3. 3.Permission denied - User lacks permissions to execute commands
  4. 4.Script errors - Script itself has syntax errors or missing dependencies
  5. 5.Command not found - Required binaries not installed on target
  6. 6.Working directory issues - Script path not found
  7. 7.Environment variables missing - Required env vars not set
  8. 8.Provisioner timing - Resource not ready when provisioner runs

Step-by-Step Fix

  1. 1.Check logs for specific error messages
  2. 2.Verify configuration settings
  3. 3.Test network connectivity
  4. 4.Review recent changes
  5. 5.Apply corrective action
  6. 6.Verify the fix

Step 1: Debug Provisioner Execution

Enable detailed logging:

```bash export TF_LOG=DEBUG export TF_LOG_PATH=./terraform-debug.log terraform apply

# Find provisioner-specific errors grep -i "provisioner|ssh|exec" terraform-debug.log grep -i "error|timeout|failed" terraform-debug.log ```

Step 2: Fix Remote-exec Connection Issues

Verify SSH connectivity:

```bash # Test SSH manually ssh -v user@10.0.0.1 -i ~/.ssh/key.pem

# Check if host is reachable ping 10.0.0.1

# Verify SSH port open nc -zv 10.0.0.1 22 ```

Fix connection configuration:

```hcl resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro"

provisioner "remote-exec" { inline = [ "sudo yum update -y", "sudo yum install -y nginx", ]

connection { type = "ssh" user = "ec2-user" host = self.public_ip private_key = file("~/.ssh/my-key.pem") timeout = "5m" # Increase timeout } } } ```

Handle SSH key issues:

```bash # Verify key file exists and is readable ls -la ~/.ssh/my-key.pem chmod 600 ~/.ssh/my-key.pem

# Test key manually ssh -i ~/.ssh/my-key.pem ec2-user@10.0.0.1 ```

Step 3: Fix Authentication Failures

For SSH authentication:

```hcl provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" # Verify correct user host = self.public_ip private_key = file(var.ssh_key_path)

# For password authentication (less secure) # password = var.ssh_password } }

# For AWS instances, use the correct user: # Amazon Linux: ec2-user # Ubuntu: ubuntu # Debian: admin # RHEL: ec2-user or root # CentOS: centos ```

For WinRM (Windows):

```hcl provisioner "remote-exec" { connection { type = "winrm" user = "Administrator" password = var.admin_password host = self.public_ip port = 5985 timeout = "10m"

# HTTPS for secure connection use_ssl = true insecure = true # For self-signed certificates }

inline = [ "powershell.exe -Command \"Install-WindowsFeature -Name Web-Server\"", ] } ```

Step 4: Fix Permission Issues

Handle sudo permission issues:

```hcl provisioner "remote-exec" { inline = [ # Use sudo with -S flag to read password from stdin "echo '${var.sudo_password}' | sudo -S yum install -y nginx",

# Or run as root directly (if connection uses root) "yum install -y nginx", ]

connection { user = "root" # ... } } ```

For file upload permission issues:

```hcl provisioner "file" { source = "local-config.conf" destination = "/tmp/config.conf" # Upload to tmp first

connection { type = "ssh" user = "ec2-user" private_key = file(var.ssh_key) host = self.public_ip } }

provisioner "remote-exec" { inline = [ "sudo mv /tmp/config.conf /etc/nginx/nginx.conf", "sudo chown root:root /etc/nginx/nginx.conf", "sudo systemctl restart nginx", ]

connection { type = "ssh" user = "ec2-user" private_key = file(var.ssh_key) host = self.public_ip } } ```

Step 5: Fix Local-exec Errors

Verify command exists locally:

```bash # Check if command is available which ansible-playbook which my-script.sh

# Verify script is executable chmod +x scripts/my-script.sh

# Test script manually ./scripts/my-script.sh ```

Fix local-exec configuration:

```hcl provisioner "local-exec" { # Use absolute paths command = "/usr/local/bin/ansible-playbook -i ${self.public_ip}, deploy.yml"

# Or relative path from module directory command = "${path.module}/scripts/deploy.sh ${self.public_ip}"

# Set working directory working_dir = "${path.module}/scripts"

# Add environment variables environment = { ANSIBLE_HOST_KEY_CHECKING = "False" TARGET_HOST = self.public_ip } }

# Handle command failure gracefully provisioner "local-exec" { command = "my-script.sh || echo 'Script failed but continuing'"

# Use on_failure to control behavior on_failure = continue # or fail } ```

Step 6: Handle Timing and Dependency Issues

Wait for resource readiness:

```hcl resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro"

# Wait for instance to be fully running provisioner "remote-exec" { inline = [ "while ! systemctl is-active sshd; do sleep 2; done", "sudo yum update -y", ]

connection { type = "ssh" user = "ec2-user" host = self.public_ip private_key = file(var.ssh_key) timeout = "10m" # Allow extra time } } }

# Use depends_on for proper ordering provisioner "local-exec" { command = "ansible-playbook deploy.yml" working_dir = "${path.module}"

depends_on = [ aws_instance.web, aws_security_group.web ] } ```

Step 7: Use Null Resource for Complex Provisioning

For better control over provisioning:

```hcl resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro" }

# Separate provisioning control resource "null_resource" "configure_web" { # Triggers when instance changes triggers = { instance_id = aws_instance.web.id config_hash = filesha256("${path.module}/config.sh") }

provisioner "remote-exec" { inline = [ "${file("${path.module}/config.sh")}", ]

connection { type = "ssh" user = "ec2-user" host = aws_instance.web.public_ip private_key = file(var.ssh_key) } }

depends_on = [aws_instance.web] } ```

Step 8: Handle Provisioner on Destruction

Use destroy provisioners carefully:

```hcl resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro"

provisioner "remote-exec" { when = destroy # Run on destruction

inline = [ "sudo systemctl stop nginx", "sudo rm -rf /var/log/nginx/*", ]

connection { type = "ssh" user = "ec2-user" host = self.public_ip # Must use self for destroy private_key = file(var.ssh_key) }

on_failure = continue # Don't block destruction on failure } } ```

Step 9: Migrate to Better Alternatives

Consider replacing provisioners with better approaches:

```hcl # Instead of provisioner, use user_data for EC2 resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro"

user_data = <<-EOF #!/bin/bash yum update -y yum install -y nginx systemctl start nginx EOF }

# Use cloud-init for more complex setup user_data = file("${path.module}/cloud-init.yaml")

# Use Ansible/Terraform separately after Terraform apply # terraform apply # ansible-playbook -i inventory deploy.yml ```

Step 10: Handle Specific Common Errors

SSH handshake timeout:

```bash # Check security group allows SSH aws ec2 describe-security-groups --group-ids sg-12345678

# Verify instance is running aws ec2 describe-instances --instance-ids i-12345678 --query 'Reservations[].Instances[].State.Name'

# Check network connectivity nc -zv PUBLIC_IP 22 ```

"No tty present and no askpass program":

hcl
# Use sudo with password piped
inline = [
  "echo '${var.password}' | sudo -S command",
]

"Connection refused":

bash
# SSH service not running - wait longer
# Use timeout and retry logic in inline script
inline = [
  "for i in {1..30}; do ssh -o StrictHostKeyChecking=no localhost && break || sleep 2; done",
]

Verification

After resolving provisioner issues:

```bash # Test SSH connectivity ssh -i ~/.ssh/key.pem user@INSTANCE_IP

# Run apply to verify provisioner works terraform apply

# Check provisioner executed successfully terraform show | grep -A20 provisioner ```

Prevention

Avoid provisioners when possible:

```hcl # Prefer user_data over remote-exec user_data = file("setup.sh")

# Prefer native Terraform resources over local-exec # Instead of: local-exec running kubectl # Use: terraform-provider-kubernetes

# Use configuration management tools separately # terraform apply -> ansible-playbook deploy.yml ```

Document provisioning dependencies:

markdown
## Provisioning Requirements
- SSH key in ~/.ssh/my-key.pem
- Ansible installed locally
- Target host accessible on port 22

Related Articles

  • [Fix Fix Terraform API Token Issue in Terraform](fix-terraform-api-token)
  • [Fix Terraform Apply Timeout - Resource Creation Hanging Indefinitely](fix-terraform-apply-timeout)
  • [How to Fix Terraform AWS Provider Errors](fix-terraform-aws-provider)
  • [Fix Fix Terraform Azure Backend Issue in Terraform](fix-terraform-azure-backend)
  • [Fix Terraform Backend Configuration Error - State Backend Setup Failure](fix-terraform-backend-config-error)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Terraform Provisioner Failed - Remote Execution Script Failure", "description": "Complete troubleshooting guide for Terraform provisioner execution failures including remote-exec, local-exec, and file provisioners.", "url": "https://www.fixwikihub.com/fix-terraform-provisioner-failed", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-11-27T13:49:18.457Z", "dateModified": "2025-11-27T13:49:18.457Z" } </script>