Introduction
This guide demonstrates how to use a destroy-time provisioner in Terraform. Destroy-time provisioners run during a terraform destroy operation, before the resource they are defined within is destroyed. This is useful for performing cleanup tasks on remote machines.
This example uses a null_resource with a remote-exec provisioner to connect to an existing Amazon EC2 instance and create a file during the destroy phase.
Prerequisites
Before you begin, you need the following:
- An active AWS account.
- An Amazon EC2 instance running and accessible from your local machine.
- A security group attached to the instance that allows inbound SSH traffic (TCP port
22) from your IP address. - An SSH key pair (
.ceror.pemfile) that provides access to the EC2 instance, stored on your local machine. - The public IP address of your EC2 instance.
- Terraform v0.12 or newer installed locally.
For more details, refer to the AWS documentation on prerequisites for connecting to your EC2 instance.
Procedure
-
Prepare the remote instance.
Connect to your EC2 instance using SSH. Replace
private-key.pemwith the path to your private key andXX.XX.XXX.XXXwith your instance's public IP address.$ ssh -i "private-key.pem" ec2-user@XX.XX.XXX.XXX
Once connected, create a test directory. This directory will help verify that the create-time provisioner runs correctly.
$ mkdir /home/ec2-user/hello
-
Create the Terraform configuration.
On your local machine, create a new directory for your Terraform configuration and create a file named
main.tf.$ mkdir terraform-destroy-test $ cd terraform-destroy-test $ touch main.tf
Add the following configuration to your
main.tffile. This configuration defines anull_resourcethat connects to your EC2 instance. It includes tworemote-execprovisioners:- The first runs
lsduring resource creation. - The second, a
destroy-time provisioner, runstouch bar.txtduring resource destruction.
Update the
private_keypath andhostIP address to match your environment.# main.tf resource "null_resource" "cleanup_example" { connection { type = "ssh" user = "ec2-user" private_key = file("./private-key.pem") host = "XX.XX.XXX.XXX" } provisioner "remote-exec" { inline = [ "ls /home/ec2-user/" ] } provisioner "remote-exec" { when = destroy on_failure = continue inline = [ "touch /home/ec2-user/bar.txt" ] } } - The first runs
-
Initialize and apply the configuration.
Initialize the Terraform working directory.
$ terraform init
Apply the configuration to create the
null_resource.$ terraform apply -auto-approve
The output shows the create-time provisioner executing the
lscommand, which lists thehellodirectory you created earlier.null_resource.cleanup_example: Creating... null_resource.cleanup_example: Provisioning with 'remote-exec'... null_resource.cleanup_example (remote-exec): Connecting to remote host via SSH... null_resource.cleanup_example (remote-exec): Host: XX.XX.XXX.XXX null_resource.cleanup_example (remote-exec): User: ec2-user ## ... null_resource.cleanup_example (remote-exec): Connected! null_resource.cleanup_example (remote-exec): hello null_resource.cleanup_example: Creation complete after 0s [id=...] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
-
Verify the initial state.
In your SSH session connected to the EC2 instance, list the contents of the home directory. Only the
hellodirectory should be present, as the destroy-time provisioner has not yet run.$ ls /home/ec2-user/
Expected Output:
hello
-
Destroy the resource.
On your local machine, run
terraform destroyto trigger the destroy-time provisioner.$ terraform destroy -auto-approve
The output confirms that a provisioner runs during the destruction phase.
null_resource.cleanup_example: Destroying... [id=...] null_resource.cleanup_example: Provisioning with 'remote-exec'... null_resource.cleanup_example (remote-exec): Connecting to remote host via SSH... null_resource.cleanup_example (remote-exec): Host: XX.XX.XXX.XXX null_resource.cleanup_example (remote-exec): User: ec2-user ## ... null_resource.cleanup_example (remote-exec): Connected! null_resource.cleanup_example: Destruction complete after 1s Destroy complete! Resources: 1 destroyed.
-
Verify the final state.
Return to your SSH session on the EC2 instance and list the directory contents again. The
bar.txtfile now exists, confirming the destroy-time provisioner executed successfully.$ ls /home/ec2-user/
Expected Output:
bar.txt hello
-
Clean up resources.
After verification, you can end your SSH session and terminate the EC2 instance in the AWS console to avoid incurring further charges.
Additional Information
For more details on provisioner syntax and behavior, refer to the official Terraform documentation on Provisioners.