Last Updated on August 7, 2025 by Arnav Sharma
Terraform, developed by HashiCorp, is a leading open-source infrastructure as code (IaC) tool that allows users to define and provision data center infrastructure using a declarative configuration language. Among the many resources and providers available in Terraform, the terraform null provider and null resource are particularly unique and useful in certain scenarios.
What is the Null Resource?
The null_resource in Terraform is a placeholder resource that doesn’t manage any actual infrastructure. Instead, it is used to execute provisioners and trigger certain actions based on changes in its triggers argument. The null_resourceis part of the null_provider, which is a special provider in Terraform that facilitates the implementation of actions that don’t directly interact with any external APIs or services.
Key Features of the Null Resource
- Provisioners:
- Local-exec: Executes local shell commands on the machine running Terraform.
- Remote-exec: Executes commands on remote machines.
- Triggers:
- The
triggersargument allows thenull_resourceto run its provisioners based on changes to specified values. Any change in the trigger values will force thenull_resourceto be recreated, thereby re-running the provisioners.
- The
- Dependency Management:
- The
null_resourcecan be used to enforce dependencies between resources that donโt have a direct dependency relationship, ensuring the correct order of operations.
- The
- Arbitrary Actions:
- It enables running arbitrary scripts or commands as part of the Terraform deployment process.
Example Use Cases
1. Running Local Scripts
You might want to execute a local script after deploying some infrastructure.
resource "null_resource" "example" {
provisioner "local-exec" {
command = "echo 'Hello, World!' > hello.txt"
}
triggers = {
always_run = "${timestamp()}"
}
}
In this example, the local-exec provisioner runs a shell command to create a file named hello.txt with the content “Hello, World!”.
2. Custom Configuration Management
Use null_resource to trigger custom configuration scripts after resource creation.
resource "null_resource" "configure_server" {
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 = aws_instance.example.public_ip
}
}
triggers = {
instance_id = aws_instance.example.id
}
}
This example installs Nginx on an AWS EC2 instance after its creation.
3. Dependency Management
Enforce dependencies between resources that Terraform doesn’t directly support.
resource "null_resource" "wait_for_db" {
depends_on = [aws_db_instance.example]
provisioner "local-exec" {
command = "sleep 60"
}
triggers = {
db_instance = aws_db_instance.example.id
}
}
In this example, the null_resource ensures a 60-second delay after the creation of an AWS RDS instance, allowing it time to become fully available before other actions are taken.
4. Conditional Actions
Perform actions based on the state of other resources or conditions.
resource "null_resource" "conditional_action" {
provisioner "local-exec" {
command = "echo 'Resource has changed' > status.txt"
}
triggers = {
condition = var.condition
}
}
In this example, the null_resource executes a command to write to a file if a specific condition (var.condition) changes.
What is the Null Provider?
The null_provider in Terraform is a special provider that enables the use of resources that don’t interact with any external services. It is primarily used to define null_resource resources, which can execute local or remote scripts, manage dependencies, and trigger actions based on changes to their configuration. The null_provider itself doesn’t require any configuration and acts as a facilitator for creating null_resource instances.
Key Features of the Null Provider
- No External Interaction:
- The
null_providerdoes not interact with any APIs or external services, making it a lightweight and versatile tool for handling internal actions and orchestration within Terraform configurations.
- The
- Supports Null Resources:
- The primary use of the
null_provideris to definenull_resourceresources, which can execute arbitrary scripts and commands.
- The primary use of the
- Provisioners Support:
- The
null_providersupports various provisioners, such aslocal-execandremote-exec, allowing you to run commands on the local machine or on remote machines.
- The
- Triggers Mechanism:
- Allows the definition of
triggersthat determine when thenull_resourceshould be re-created and its provisioners re-executed, based on changes in specified values.
- Allows the definition of
Example Use Cases
1. Initializing Local Environment
You might want to run a script to initialize your local development environment as part of your Terraform workflow.
provider "null" {
# No configuration needed
}
resource "null_resource" "init_local_env" {
provisioner "local-exec" {
command = "bash init_script.sh"
}
triggers = {
always_run = "${timestamp()}"
}
}
In this example, the null_resource executes a local script init_script.sh to set up the local environment.
2. Post-Deployment Configuration
Perform additional configuration steps after deploying infrastructure, such as updating configuration files or performing cleanup tasks.
provider "null" {
# No configuration needed
}
resource "null_resource" "post_deployment" {
provisioner "local-exec" {
command = "bash post_deploy.sh"
}
triggers = {
resource_id = aws_instance.example.id
}
}
This example runs a post-deployment script post_deploy.sh after the creation of an AWS instance.
3. Remote Script Execution
Execute commands on a remote machine after deploying infrastructure.
provider "null" {
# No configuration needed
}
resource "null_resource" "remote_command" {
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 = aws_instance.example.public_ip
}
}
triggers = {
instance_id = aws_instance.example.id
}
}
In this example, the null_resource runs commands on a remote AWS instance to install Nginx.
4. Enforcing Dependencies
Use the null_provider to enforce dependencies between resources that don’t have a direct dependency relationship.
provider "null" {
# No configuration needed
}
resource "null_resource" "wait_for_service" {
depends_on = [aws_service.example]
provisioner "local-exec" {
command = "sleep 30"
}
triggers = {
service_id = aws_service.example.id
}
}
This example ensures a 30-second wait after the creation of an AWS service before proceeding with further actions.
Example: Using Null Provider and Null Resource with Azure
# Configure the Azure provider
provider "azurerm" {
features {}
}
# Create an Azure Resource Group
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "East US"
}
# Create an Azure Virtual Network
resource "azurerm_virtual_network" "example" {
name = "example-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
# Null provider configuration (not needed explicitly)
provider "null" {
# No configuration is required for the null provider
}
# Null resource to execute a local script
resource "null_resource" "example" {
provisioner "local-exec" {
command = "echo 'Azure deployment complete for resource group and VNet' > deployment_status.txt"
}
triggers = {
resource_group = azurerm_resource_group.example.name
virtual_network = azurerm_virtual_network.example.name
always_run = "${timestamp()}"
}
}
# Output the location of the resource group
output "resource_group_location" {
value = azurerm_resource_group.example.location
}
# Output the name of the virtual network
output "virtual_network_name" {
value = azurerm_virtual_network.example.name
}
# Output the result of the null resource
output "null_resource_output" {
value = null_resource.example.id
}
In this example, the null_resource named “example” runs a local-exec provisioner that echoes a message when the Azure Linux virtual machine is created. The triggers block ensures that the provisioner runs whenever the virtual machine is created or modified.