- Home /
- Resources /
- Learning center /
- Managing Terraform...
Managing Terraform Secrets when using Equinix Metal
Learn how to carefully manage your Terraform secrets when using the Equinix Metal provider.

On this page
This guide will walkthrough how to manage secrets in Terraform scripts while using the Equinix Metal provider. Terraform authenticates with Equinix to deploy resources and perform the planned actions. But to run those scripts Terraform will need some sensitive information or secrets to gain access to the services. For example, an API key would be considered a secret because that is sensitive information.
Prerequisites
- An Equinix Metal Account.
- An Equinix Metal Project ID.
- An Equinix Metal API key.
- Terraform installed on your workstation.
- The Equinix Terraform Provider installed.
- Know how to deply an Equinix Metal instance Using Terraform
- (Optional) An IDE, like VS Code.
- (Optional) Install and Configure Metal CLI Metal CLI.
Secrets in plain text are a bad idea
Before using environmental variables, you could hardcode your sensitive information into your script file in plain text, but this is problematic because anyone who gains access to this file will be able to see your sensitive information, like your API keys! Below is an example of a script with a hardcoded API key.
Getting rid of that auth_token = "someEquinixMetalApiKey"
line would be a great idea!
terraform {
required_providers {
equinix = {
source = "equinix/equinix"
version = "1.13.0"
}
}
}
provider "equinix" {
auth_token = "someEquinixMetalApiKey"
}
resource "equinix_metal_device" "web1" {
hostname = "example"
plan = "c3.small.x86"
metro = "da"
operating_system = "ubuntu_20_04"
billing_cycle = "hourly"
project_id = "someProjectId"
}
This is not ideal for a variety of reasons. We wouldn't want someone to take that API key of ours and start spinning up that drive up cost or deleting servers that we're using to host applications.
We need a way to handle this sensitive information carefully!
Use Enviormental Variables
One way to handle this sensitive information carefully would be to leverage Environment Variables. It's very common for Terraform providers (and other SDKs and Clients) to allow users to set API keys and other sensitive information by leveraging environment variables. Let's see what the Equinix Terraform Providers docs say:
variable | description |
---|---|
client_id |
API Consumer Key available under "My Apps" in developer portal. This argument can also be specified with the EQUINIX_API_CLIENTID shell environment variable. |
client_secret |
API Consumer secret available under "My Apps" in developer portal. This argument can also be specified with the EQUINIX_API_CLIENTSECRET shell environment variable. |
token |
API tokens are generated from API Consumer clients using the OAuth2 API. This argument can also be specified with the EQUINIX_API_TOKEN shell environment variable. |
auth_token |
This is your Equinix Metal API Auth token. This can also be specified with the METAL_AUTH_TOKEN environment variable. |
Perfect! We can set the auth_token
information in an METAL_AUTH_TOKEN
environment variable and remove auth_token = "someEquinixMetalApiKey"
from the provider block. It should now looks like this:
provider "equinix" {
}
To create the environmental variable by run the export
command in a terminal and replace someEquinixMetalToken
with your API key.
export METAL_AUTH_TOKEN=someEquinixMetalToken
We no longer have to owrry about our API key being stored in plain text!
Use a variables.tf
file
Now, let's say you also want to remove your project ID from plain text as well. Another way to reduce sensitive information showing up would be to define input variables in a file. First create a new file named variables.tf
then create a new input variable block named project_id
and give it some values. Below is an early example I created:
variable "project_id" {
description = "Your project UUID inside the Metal Console or from the Metal CLI"
type = string
sensitive = true
# default = ''
}
Let's see what the sensitive
flag does, according to the documentation.
Because you flagged the new variables as sensitive, Terraform redacts their values from its output when you run a plan
, apply
, or destroy
command. ... If you were to run terraform apply
now, Terraform would prompt you for values for these new variables since you haven't assigned defaults to them.
After creating your new variable.tf
file and adding the variables you would like to use. Go back into your Terraform script file and locate project_id = "someProjectId"
inside your metal device resource block and replace it with project_id = var.project_id
as so.
(Tip: whenever you create a new variable block in variables.tf
to reference it in another place it will be var.nameofvariable
)
resource "equinix_metal_device" "web1" {
hostname = "example"
plan = "c3.small.x86"
metro = "da"
operating_system = "ubuntu_20_04"
billing_cycle = "hourly"
project_id = var.project_id
}
As expected, when you run terraform apply
it will prompt you to give the variable an input in the terminal before running the script. One way to work around this would be to create another environment variable.
From a terminal set the environment variable TF_VAR_project_id
and replace someProjectId
with your actual project ID. This will give the new sensitive variable you created a value to reference and no longer prompt you to input the value.
export TF_VAR_project_id=someProjectId
Use an inputs.tfvars
file
But, what if you have a lot of input variable and you don't want to export each one individually or wait for the terminal to prompt you to add them when you run terraform apply
. Another option is to create a file known as a .tfvars
file.
In this example we will name it inputs.tfvars
and inside this file it will hold the values for the variables created earlier in the variables.tf
file. We'll also be using all variables for a metal device resource block in main.tf
replacing all previous hardcoded information. It would look like this:
terraform {
required_providers {
equinix = {
source = "equinix/equinix"
version = "1.13.0"
}
}
}
provider "equinix" {
}
resource "equinix_metal_device" "web1" {
hostname = var.hostname
plan = var.plan
metro = var.metro
operating_system = var.os
billing_cycle = var.billing
project_id = var.project_id
}
In variables.tf
it would looke like this:
variable "hostname" {
description = "The name you want to give the host/metal device "
type = string
#default = ''
}
variable "plan" {
description = "The type of plan you want to deploy "
type = string
#default = ''
}
variable "metro" {
description = "The metro you want to deploy in"
type = string
#default = ''
}
variable "os" {
description = "The operating system you want to be put on the machine"
type = string
#default = ''
}
variable "billing" {
description = "The billing cycle you want for the machine"
type = string
#default = ''
}
variable "project_id" {
description = "Your project UUID inside the Metal Console or from the Metal CLI"
type = string
sensitive = true
#default = ''
}
Then in our inputs.tfvars
file we could give those variables a value. It would look like this:
hostname = "test"
plan = "c3.small.x86"
metro = "da"
os = "ubuntu_20_04"
billing = "hourly"
Notice we don't list project_id
because we already exported it as an environment variable earlier. Terraform will automatically look for variables in this order:
- Environment variables
- The
terraform.tfvars
file, if present. - The
terraform.tfvars.json
file, if present. - Any
*.auto.tfvars
or*.auto.tfvars.json
files, processed in lexical order of their filenames. - Any
-var
and-var-file
options on the command line, in the order they are provided. (This includes variables set by - a Terraform Cloud workspace.)
After creating these new files and variables you should have a folder structure that looks like this:
❯ terraform-project-folder
.
└── main.tf
└── variables.tf
└── inputs.tfvars
You can now apply the changes to your plan by running terraform plan -var-file="inputs.tfvars"
and it will show you the resources in your plan with the sensitive variables being shown as redacted and the other ones as normal and if everything looks correct you can run terraform apply -var-file="inputs.tfvars"
then you will be prompted to input yes if you would like for the plan to be executed and to begin deployment.
terraform plan -var-file="inputs.tfvars"
terraform apply -var-file="inputs.tfvars"
Now to destroy the plan you will run terraform destroy -var-file="inputs.tfvars"
and say yes to running the command when prompted.
terraform destroy -var-file="inputs.tfvars"
You can now hide secrets in environmental variables and store less sensitive information as input variables by using variables.tf
and .tfvars
files.
Configure a Remote Backend
Although the secrets are hidden in your files and show up as redacted when you run terraform apply
they can still potentially be stored in plain text in Terraform's state file. That is because whenever you run terraform apply
it creates a state file that keeps track of resources created by your configuration and maps them to real-world resources. By default, the file will be stored locally inside the directory of the Terraform project.
To secure this file and your secrets you can configure a remote backend. That is done by creating a new block inside your main.tf
with the credentials needed so that the state file will be stored somewhere else and or encrypted. Now if you are working alone or just testing something this may not be necessary, but if you are in a team or working on a big project it is highly recommended. Here is Terraform's Official Developer Docs on how to do that, it will not only show examples on how to setup a remote backend but also list all the available options for backends on Terraform.
Conclusion
Thanks for following along with this guide! This guide showcased how to carefully use secrets when utilizing Terraform to deploy Equinix Metal servers and things to think about when it comes to managing secrets. Specifically, we covered:
- Creating enviormental Variables as a way to encrypt sensitive information in your files.
- How to utilize input variables and .tfvars files to store variable values instead of hardcoding them.
- Mentioned the option of using a remote backend to store state files in different locations with better security.
You may also like
Dig deeper into similar topics in our archives
Crosscloud VPN with WireGuard
Learn to establish secure VPN connections across cloud environments using WireGuard, including detailed setups for site-to-site tunnels and VPN gateways with NAT on Equinix Metal, enhancing...

Kubernetes Cluster API
Learn how to provision a Kubernetes cluster with Cluster API

Kubernetes with kubeadm
Learn how to deploy Kubernetes with kubeadm using userdata

OpenStack DevStack
Use DevStack to install and test OpenStack on an Equinix Metal server.