Bootstrap FreeKB - Terraform - Run a remote command (remote-exec)
Terraform - Run a remote command (remote-exec)

Updated:   |  Terraform articles

Let's say you want to run a command on your Terraform system or on a remote system. There are two provisioners that can be used, local-exec and remote-exec. As an example, let's say you want to create the /tmp/foo.txt file on a remote system. In this scenario, you would use remote-exec. 

AVOID TROUBLE

The remote-exec provisioner must be within a resource block.

Let's say you have the following files on your Terraform server.

├── locals.tf
├── modules.tf
├── outputs.tf
├── provider.tf
├── terraform.tfstate
├── variables.tf
├── child (directory, child module)
│   ├── data.tf
│   ├── outputs.tf
│   ├── resources.tf

 

Let's say provider.tf has the following.

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
    }
  }
}

provider "docker" {}

 

Let's say modules.tf has the following.

module "child" {
  source = "./child"
}

 

And perhaps resources.tf in your child module has the following to create an Nginx image on Docker.. Notice that the remote-exec provisioner is within the resource block, and the remote-exec command will create the /tmp/foo.txt and /tmp/bar.txt files on the nginx system.

resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = false

  connection {
    type = "ssh"
    user = "john.doe"
    password = "itsasecret"
    host = "server1.example.com"
  }

  provisioner "remote-exec" {
    inline = [
      "touch /tmp/foo.txt",
      "touch /tmp/bar.txt",
    ]
  }
}

 

Or, a local script on your Terraform system can be copied to and then executed on the remote system.

resource "some_resource" "demo" {
  . . .
  provisioner "remote-exec" {
    script = "example.sh"
    connection {
      type = "ssh"
      user = "john.doe"
      password = "itsasecret"
      host = "server1.example.com"
    }
  }
}

 

Or the scripts option can be used to run multiple scripts on the remote system.

resource "some_resource" "demo" {
  . . .
  provisioner "remote-exec" {
    scripts = [
      "foo.sh",
      "bar.sh",
    ]
    connection {
      type = "ssh"
      user = "john.doe"
      password = "itsasecret"
      host = "server1.example.com"
    }
  }
}

 

However, there is a significant limitation to both script and scripts, in that command line options and flags cannot be included. For this reason, it is more common to use the file provisioner and then the inline provisioner to run the script on the remote system.

resource "some_resource" "demo" {
  . . .

  connection {
    type = "ssh"
    user = "john.doe"
    password = "itsasecret"
    host = "server1.example.com"
  }

  provisioner "file" {
    source = "example.sh"
    destination = "/tmp/example.sh"
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/example.sh",
      "/tmp/example.sh foo bar",
    ]
  }
}

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 27e602 in the box below so that we can be sure you are a human.