Bird
Raised Fist0
Terraformcloud~10 mins

Remote-exec provisioner in Terraform - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - Remote-exec provisioner
Terraform starts apply
↓
Create resource (e.g., VM)
↓
Wait for resource to be ready
↓
Run remote-exec provisioner
↓
Connect via SSH or WinRM
↓
Execute commands on remote machine
↓
Provisioning complete
↓
Terraform apply finishes
Terraform creates the resource, then connects remotely to run commands on it using SSH or WinRM, completing provisioning.
Execution Sample
Terraform
resource "aws_instance" "example" {
  ami                         = "ami-12345678"
  instance_type               = "t2.micro"
  associate_public_ip_address = true
  key_name                    = "example-key"

  provisioner "remote-exec" {
    connection {
      type        = "ssh"
      user        = "ubuntu"
      host        = self.public_ip
      private_key = file("~/.ssh/mykey.pem")
    }
    inline = ["sudo apt-get update", "sudo apt-get install -y nginx"]
  }
}
This code creates an AWS instance and runs commands remotely to update packages and install nginx.
Process Table
StepActionResource StateProvisioner ConnectionCommands ExecutedResult
1Start terraform applyNo resourceNo connectionNo commandsBegin process
2Create aws_instanceInstance launchingNo connectionNo commandsInstance created but not ready
3Wait for instance readyInstance runningNo connectionNo commandsInstance ready for connection
4Connect via SSHInstance runningSSH connectedNo commandsConnection established
5Run command: sudo apt-get updateInstance runningSSH connectedsudo apt-get updateCommand success
6Run command: sudo apt-get install -y nginxInstance runningSSH connectedsudo apt-get install -y nginxCommand success
7Provisioning completeInstance runningSSH disconnectedAll commands doneProvisioning finished
8Terraform apply completeInstance runningNo connectionNo commandsApply finished successfully
💡 All commands executed successfully, provisioning finished, terraform apply completes.
Status Tracker
VariableStartAfter Step 2After Step 3After Step 4After Step 7Final
Resource StateNo resourceInstance launchingInstance runningInstance runningInstance runningInstance running
Provisioner ConnectionNo connectionNo connectionNo connectionSSH connectedSSH disconnectedNo connection
Commands ExecutedNoneNoneNoneNoneUpdate, Install nginxAll commands done
Key Moments - 3 Insights
Why does terraform wait before running remote-exec commands?
Terraform waits until the instance is fully running and accessible (see Step 3) before connecting via SSH (Step 4) to avoid connection failures.
What happens if the remote-exec commands fail?
If commands fail, terraform apply stops and reports an error at the provisioner step (between Steps 5-6), preventing incomplete provisioning.
Does remote-exec run before or after resource creation?
Remote-exec runs only after the resource is created and ready (after Step 3), as shown by connection established in Step 4.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step does terraform establish SSH connection?
AStep 4
BStep 2
CStep 6
DStep 8
💡 Hint
Check the 'Provisioner Connection' column for when it changes to 'SSH connected'.
At which step does terraform finish running all remote commands?
AStep 5
BStep 7
CStep 6
DStep 8
💡 Hint
Look for 'Commands Executed' column showing all commands done.
If the instance was not ready, what would happen to the connection step?
AConnection would succeed immediately
BTerraform would skip remote-exec
CTerraform would wait until instance is ready before connecting
DTerraform would fail apply instantly
💡 Hint
Refer to Step 3 and Step 4 showing waiting and then connection.
Concept Snapshot
Terraform Remote-exec provisioner:
- Runs commands on a remote resource after creation
- Connects via SSH (Linux) or WinRM (Windows)
- Waits for resource readiness before connecting
- Executes inline or script commands
- Fails apply if commands fail
- Used for initial setup/configuration
Full Transcript
Terraform Remote-exec provisioner works by first creating the resource, such as a virtual machine. Terraform waits until the resource is fully running and accessible. Then it connects remotely using SSH or WinRM. After connection, it runs the specified commands on the remote machine. These commands can update software or install packages. If any command fails, terraform stops and reports an error. Once all commands succeed, provisioning is complete and terraform finishes the apply process.

Practice

(1/5)
1. What is the main purpose of the remote-exec provisioner in Terraform?
easy
A. To run commands on a remote machine after it is created
B. To create a new virtual machine in the cloud
C. To store Terraform state files remotely
D. To manage user permissions on the local machine

Solution

  1. Step 1: Understand the role of provisioners

    Provisioners in Terraform run scripts or commands on resources after creation.
  2. Step 2: Identify what remote-exec does

    The remote-exec provisioner connects to the remote machine and runs commands there.
  3. Final Answer:

    To run commands on a remote machine after it is created -> Option A
  4. Quick Check:

    remote-exec runs remote commands = D [OK]
Hint: remote-exec runs commands remotely after resource creation [OK]
Common Mistakes:
  • Confusing remote-exec with resource creation
  • Thinking remote-exec manages local files
  • Mixing remote-exec with state management
2. Which of the following is the correct syntax to define a remote-exec provisioner inside a Terraform resource?
easy
A. remote_exec { commands = ["echo Hello"] }
B. provisioner remote-exec { script = "hello.sh" }
C. provisioner "remote-exec" { inline = ["echo Hello"] }
D. exec_remote { inline = ["echo Hello"] }

Solution

  1. Step 1: Recall Terraform provisioner syntax

    Provisioners are defined with the keyword provisioner followed by the provisioner type in quotes.
  2. Step 2: Check the correct block structure for remote-exec

    The remote-exec provisioner uses inline to run commands directly.
  3. Final Answer:

    provisioner "remote-exec" { inline = ["echo Hello"] } -> Option C
  4. Quick Check:

    Correct provisioner block syntax = B [OK]
Hint: Use provisioner "remote-exec" with inline commands [OK]
Common Mistakes:
  • Using underscores instead of hyphens in provisioner name
  • Omitting quotes around provisioner type
  • Using wrong block names like exec_remote
3. Given this Terraform snippet inside an AWS EC2 resource:
provisioner "remote-exec" {
  inline = ["sudo apt-get update", "sudo apt-get install -y nginx"]
  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key = file("~/.ssh/id_rsa")
    host        = self.public_ip
  }
}

What will happen when this runs successfully?
medium
A. The commands will run locally on the Terraform machine
B. The EC2 instance will update packages and install nginx via SSH
C. Terraform will fail because private_key cannot be a file
D. The EC2 instance will reboot automatically after installation

Solution

  1. Step 1: Understand remote-exec with connection block

    The provisioner connects via SSH using the given user, key, and host to run commands remotely.
  2. Step 2: Analyze the inline commands

    The commands update package lists and install nginx on the remote EC2 instance.
  3. Final Answer:

    The EC2 instance will update packages and install nginx via SSH -> Option B
  4. Quick Check:

    remote-exec runs commands remotely = C [OK]
Hint: remote-exec runs inline commands on remote host via SSH [OK]
Common Mistakes:
  • Thinking commands run locally
  • Assuming private_key cannot be a file
  • Expecting automatic reboot after install
4. You have this Terraform snippet:
provisioner "remote-exec" {
  inline = ["sudo apt-get update", "sudo apt-get install -y nginx"]
  connection {
    type     = "ssh"
    user     = "ubuntu"
    password = "mypassword"
    host     = self.public_ip
  }
}

After running Terraform apply, you get a connection timeout error. What is the most likely cause?
medium
A. The EC2 instance's security group does not allow SSH (port 22) inbound
B. The password authentication is not supported by SSH
C. The inline commands have syntax errors
D. The host attribute should be a private IP, not public IP

Solution

  1. Step 1: Understand connection timeout causes

    Timeout usually means network connection to SSH port 22 is blocked or unreachable.
  2. Step 2: Check common network issues

    If the EC2 security group lacks inbound SSH rules, connection fails despite correct credentials.
  3. Final Answer:

    The EC2 instance's security group does not allow SSH (port 22) inbound -> Option A
  4. Quick Check:

    Timeout = network block on SSH port 22 [OK]
Hint: Timeout usually means SSH port 22 blocked in firewall/security group [OK]
Common Mistakes:
  • Blaming inline command syntax for connection errors
  • Assuming password auth is always unsupported
  • Confusing public and private IP for SSH host
5. You want to use remote-exec to run a script on multiple newly created instances in a loop. Which approach is best to ensure commands run on each instance correctly?
hard
A. Use local-exec provisioner to SSH manually to each instance
B. Define one resource and run remote-exec with a list of all instance IPs in one provisioner
C. Run remote-exec provisioner only once after all instances are created using a null_resource
D. Use a for_each on the resource and include a remote-exec provisioner inside each resource block

Solution

  1. Step 1: Understand resource loops with provisioners

    Using for_each creates multiple resource instances, each with its own provisioner execution.
  2. Step 2: Why per-resource provisioner is best

    Provisioners inside each resource run commands on that specific instance, ensuring correct targeting.
  3. Final Answer:

    Use a for_each on the resource and include a remote-exec provisioner inside each resource block -> Option D
  4. Quick Check:

    Provisioner per resource instance = A [OK]
Hint: Use for_each with provisioner inside resource for multiple instances [OK]
Common Mistakes:
  • Trying to run remote-exec on all IPs in one provisioner
  • Using null_resource without proper triggers
  • Using local-exec instead of remote-exec for remote commands
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard