{"id":2266,"date":"2018-10-11T14:57:11","date_gmt":"2018-10-11T11:57:11","guid":{"rendered":"https:\/\/upcloud.com\/global\/us\/resources\/tutorials\/terraform-variables\/"},"modified":"2018-10-11T14:57:11","modified_gmt":"2018-10-11T11:57:11","slug":"terraform-variables","status":"publish","type":"tutorial","link":"https:\/\/upcloud.com\/global\/resources\/tutorials\/terraform-variables\/","title":{"rendered":"How to use Terraform variables"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Variables in <a href=\"https:\/\/upcloud.com\/global\/blog\/upcloud-verified-terraform-provider\/\">Terraform<\/a> are a great way to define centrally controlled reusable values.&nbsp;The information in Terraform variables is saved independently from the deployment plans, which makes the values easy to read and edit from a single file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this guide, we\u2019ll go over the types of available variables in Terraform, how to define them, and how to put them to use. You can use the general information about the variables as a quick cheat sheet, but the examples are a direct continuation of our Terraform Beginners article. If you haven\u2019t installed Terraform yet, <a href=\"https:\/\/upcloud.com\/global\/community\/tutorials\/get-started-terraform\/\" target=\"_blank\" rel=\"noopener\">follow the guide here to get started<\/a>.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\">Terraform variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform supports a few different variable formats. Depending on the usage, the variables are generally divided into inputs and outputs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The input variables define the values that configure your infrastructure. These values can be used again and again without having to remember every occurrence in the event that it needs to be updated.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Output variables, in contrast, are used to get information about the infrastructure after deployment. These can be useful for passing on information such as IP addresses for connecting to the server.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/signup.upcloud.com\/\">Test out Terraform for free<\/a><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Input variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Input variables are usually defined by a name, type, and default value. However, the type and default values are not strictly necessary. Terraform can deduct the variable&#8217;s type from the default or input value.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Variables can be predetermined in a file or included in the command-line options. The simplest variable is just a name, while the type and value are selected based on the input.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"variable_name\" {}<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">terraform apply -var variable_name=\"value\"<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The input variables, like the one above, use several different types: strings, lists, maps, and boolean. Here are some examples of how each type is defined and used.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">String<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Strings mark a single value per structure and are commonly used to simplify and make complicated values more user-friendly. Below is an example of a string variable definition.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"template\" {\n  type = string\n&nbsp; default = \"01000000-0000-4000-8000-000030080200\"\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A string variable can then be used in resource plans. Surrounded by double quotes, string variables are simple substitutions, such as the example below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">storage = var.template<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">List<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Another type of Terraform variables lists. They work much like a numbered catalogue of values. Each value can be called by its corresponding index in the list. Here is an example of a list variable definition.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"users\" {\n  type    = list\n  default = [\"root\", \"user1\", \"user2\"]\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lists can be used in the resource plans similarly to strings, but you\u2019ll also need to denote the index of the value you are looking for.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">username = var.users[0]<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Map<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Maps are a collection of string keys and string values. They can be useful for selecting values based on predefined parameters, such as the server configuration and monthly price.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"plans\" {<br>  type = map<br>  default = {<br>    \"7EUR\"  = \"1xCPU-1GB\"<br>    \"13EUR\" = \"1xCPU-2GB\"<br>    \"26EUR\" = \"2xCPU-4GB\"<br>  }<br>}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can access the right value by using the matching key. For example, the variable below would set the plan to&nbsp;<tt>\"1xCPU-1GB\".<\/tt><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">plan = var.plans[\"7EUR\"]<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The values matching their keys can also be used to look up information on other maps. For example, a shortlist of plans and their corresponding storage sizes is underneath.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"storage_sizes\" {\n  type = map\n  default = {\n    \"1xCPU-1GB\"  = \"25\"\n    \"1xCPU-2GB\"  = \"50\"\n    \"2xCPU-4GB\"  = \"80\"\n  }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These can then be used to find the right storage size based on the monthly price as defined in the previous example.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">size = lookup(var.storage_sizes, var.plans[\"7EUR\"])<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Boolean<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The last of the available variable types is boolean. They give the option to employ simple true or false values. For example, you might wish to have a variable that decides when to generate the root user password on a new deployment.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"set_password\" {\n  default = false\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The above example boolean can be used similarly to a string variable by simply marking down the correct variable.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">create_password = var.set_password<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">By default, the value is set to false in this example. However, you can overwrite the variable at deployment by assigning a different value in a command-line variable.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">terraform apply -var set_password=\"true\"<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Output variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Output variables provide a convenient way to get useful information about your infrastructure. As you might have noticed, much of the server details are calculated at deployment and only become available afterwards. You can extract any server-specific values, including the calculated details, using output variables.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Configuring output variables is really quite simple. All you need to do is define a name for the output and what value it should represent. For example, you could have Terraform show your server\u2019s IP address after deployment with the output variable below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">output \"public_ip\" {\n  value = upcloud_server.server_name.network_interface[0].ip_address\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that the place of the public network interface on the list of network interfaces depends on which order the NICs are defined in the resources.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform would then output the public IP address at the end of the apply command process. Alternatively, output variables can also be called on-demand using the <tt>terraform output<\/tt> command.\u00a0Next, continue on to set up a variable file for server configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Defining variables in a file<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You should have a Terraform project with a basic plan already set up. If not, follow our <a href=\"https:\/\/upcloud.com\/global\/community\/tutorials\/ \/get-started-terraform\/\" target=\"_blank\" rel=\"noopener\">getting started guide for Terraform<\/a> to begin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Go to your Terraform project directory.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd ~\/terraform\/base<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform variables can be defined within the infrastructure plan but should be stored in their own variables file. All files in your Terraform directory using the <tt>.tf<\/tt> format will automatically be loaded during operations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a variables file, for example,&nbsp;<tt>variables.tf<\/tt>&nbsp;and open the file for editing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the below variable declarations to the variables file. Replace the SSH key private file path and the public key with our own.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable \"private_key_path\" {<br>  type = string<br>  default = \"<span style=\"color: #ff0000;\">\/home\/user\/.ssh\/terraform_rsa<\/span>\"<br>}<br><br>variable \"public_key\" {<br>  type = string<br>  default = \"<span style=\"color: #ff0000;\">ssh-rsa terraform_public_key<\/span>\"<br>}<br><br>variable \"zones\" {<br>  type = map<br>  default = {<br>    \"amsterdam\" = \"nl-ams1\"<br>    \"london\"    = \"uk-lon1\"<br>    \"frankfurt\" = \"de-fra1\"<br>    \"helsinki1\" = \"fi-hel1\"<br>    \"helsinki2\" = \"fi-hel2\"<br>    \"chicago\"   = \"us-chi1\"<br>    \"sanjose\"   = \"us-sjo1\"<br>    \"singapore\" = \"sg-sin1\"<br>  }<br>}<br><br>variable \"plans\" {<br>  type = map<br>  default = {<br>    \"7EUR\"  = \"1xCPU-1GB\"<br>    \"13EUR\" = \"1xCPU-2GB\"<br>    \"26EUR\" = \"2xCPU-4GB\"<br>  }<br>}<br><br>variable \"storage_sizes\" {<br>  type = map<br>  default = {<br>    \"1xCPU-1GB\" = \"25\"<br>    \"1xCPU-2GB\" = \"50\"<br>    \"2xCPU-4GB\" = \"80\"<br>  }<br>}<br>variable \"templates\" {<br>  type = map<br>  default = {<br>    \"ubuntu24\" = \"01000000-0000-4000-8000-000030240200\"<br>    \"centos9\"  = \"01000000-0000-4000-8000-000050010600\"<br>    \"debian12\" = \"01000000-0000-4000-8000-000020070100\"<br>  }<br>}<br><br>variable \"set_password\" {<br>  type = bool<br>  default = false<br>}<br><br>variable \"users\" {<br>  type = list<br>  default = [\"root\", \"user1\", \"user2\"]<br>}<br><br>variable \"plan\" {<br>  type = string<br>  default = \"13EUR\"<br>}<br><br>variable \"template\" {<br>  type = string<br>  default = \"ubuntu24\"<br>}<br><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The above example is really just information storage. It uses the Terraform map variable for the most part which allows you to change the values to be more human-readable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Variables set in the file can be overridden at deployment. This allows you to reuse the variables file while still customising the configuration at deployment. For example, although set_password is false in the variables file, you could enable it on the command line.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">terraform apply -var set_password=\"true\"<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In the same way, you could override the other variables as well.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Loading variables automatically<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The variables file described in the previous section can easily be used across many configurations. However, if you need to make more than a couple of changes, it\u2019s worth putting the customisation in a file, too.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A variable definitions file uses the same basic syntax as Terraform language files but consists only of variable name assignments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform automatically loads a number of variable definitions files if named the following way:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Files named exactly <tt>terraform.tfvars<\/tt> or <tt>terraform.tfvars.json<\/tt>.<br>Any files with names ending in <tt>.auto.tfvars<\/tt> or <tt>.auto.tfvars.json<\/tt>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now, create a new file to define the custom variables called <tt>terraform.tfvars<\/tt> then add the following content.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">set_password = \"true\"<br>users = [\"root\", \"admin\"]<br>plan = \"26EUR\"<br>templates = {\"ubuntu20\":\"01000000-0000-4000-8000-000030080200\", \"centos8\":\"01000000-0000-4000-8000-000050010300\"}<br>template = \"ubuntu20\"<br><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to use JSON formatting instead, files with <tt>.tfvars.json<\/tt> ending are parsed as JSON objects. The root object properties correspond to variable names.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{<br>  \"set_password\": \"true\",<br>  \"users\": [\"root\", \"admin\"],<br>  \"plan\": \"26EUR\"<br>  \"templates\": {\"ubuntu20\":\"01000000-0000-4000-8000-000030200200\", \"centos8\":\"01000000-0000-4000-8000-000050010400\"},<br>  \"template\": \"ubuntu20\"<br>}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Next, continue with the section below on how to put the variables in use.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using variables in resources<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The values that are defined in the <tt>variables.tf<\/tt> files can be used in the Terraform plans to avoid hard-coding parameters. The following example uses the highlighted variables to select the parameters for deploying a new cloud server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notice the two last variables set in <tt>variables.tf<\/tt> which are used as selectors to choose the server plan and OS template.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">resource \"upcloud_server\" \"server1\" {\n  # System hostname\n  hostname = \"terraform.example.com\"\n\n  # Availability zone\n  zone = <span style=\"color: #3366ff;\">var.zones[\"amsterdam\"]<\/span>\n    \n  # Number of CPUs and memory in GB\n  plan = <span style=\"color: #3366ff;\">var.plans[var.plan]<\/span>\n\n  template {\n    # OS root disk size\n    size = <span style=\"color: #3366ff;\">lookup(var.storage_sizes, var.plans[var.plan])<\/span>\n\n    # Template UUID for Ubuntu 18.04\n    storage = <span style=\"color: #3366ff;\">var.templates[var.template]<\/span>\n  }\n\n  network_interface { \n    type = \"public\" \n  }\n  network_interface { \n    type = \"utility\" \n  }\n  # Include at least one public SSH key\n  login {\n    user = <span style=\"color: #3366ff;\">var.users[0]<\/span>\n    create_password = <span style=\"color: #3366ff;\">var.set_password<\/span>\n    keys = [\n      <span style=\"color: #3366ff;\">var.public_key<\/span>\n    ]\n  }\n\n  connection {\n    host = self.network_interface[0].ip_address\n    type = \"ssh\"\n    user = <span style=\"color: #3366ff;\">var.users[0]<\/span>\n    private_key = <span style=\"color: #3366ff;\">file(var.private_key_path)<\/span>\n  }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform variables are useful for defining server details without having to remember infrastructure-specific values. They are similarly handy for reusing shared parameters like public SSH keys that do not change between configurations.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is also important that the resource plans remain clear of personal details for security reasons. Using the variables, sensitive information such as private keys and usernames won\u2019t get shared unintentionally.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Defining output variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Output variables provide a convenient way to get useful information about your infrastructure. As you might have noticed, much of the server details are calculated at deployment and only become available afterwards. You can extract any server-specific values, including the calculated details using output variables.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Configuring output variables is really quite simple. All you need to do is define a name for the output and what value it should correspond to. These can be included in your Terraform plan or in their own file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Start by creating an output variables file called <tt>output.tf<\/tt> and open it for edit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following three variable definitions in the file to output the server\u2019s IP addresses and hostname after deployment. Replace the <tt>server_name<\/tt> with the name of your Terraform host.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">output \"public_ip\" {\n  value = upcloud_server.<span style=\"color: #ff0000;\">server_name<\/span>.network_interface[0].ip_address\n}\n\noutput \"utility_ip\" {\n  value = upcloud_server.<span style=\"color: #ff0000;\">server_name<\/span>.network_interface[1].ip_address\n}\n\noutput \"hostname\" {\n  value = upcloud_server.<span style=\"color: #ff0000;\">server_name<\/span>.hostname\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Save the file and test the output by deploying the server using the usual commands below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">terraform plan<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">terraform apply<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">upcloud_server.server1: Creation complete after 39s (ID: 00b784aa-15c1-44dc-8252-f4bad865f853)\n\nApply complete! Resources: 1 added, 0 changed, 0 destroyed.\n\nOutputs:\n\nhostname = terraform.example.com\nprivate_ip = 10.5.4.82\npublic_ip = 94.237.45.221<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The variables you defined will be shown at the end of the deployment, as in the example above. However, you can also retrieve these at any time using the Terraform command. For example, to get the public IP address, you can use the example command below.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">terraform output public_ip<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">94.237.45.221<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In the same way, you could ask Terraform about any other output variables.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using environmental variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can also set sensitive variables in your environment variables with the TF_VAR_ prefix, avoiding the need to save them in a file. For example, you can set your password in your local environmental variables.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">export TF_VAR_PASSWORD=\"password\"<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You\u2019ll also need to declare the password variable in your <tt>variables.tf<\/tt> fie.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">variable PASSWORD { default = \"\" }<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The password variable is then usable in the Terraform resources.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  provisioner \"remote-exec\" {\n    inline = [\n      \"useradd ${var.users[0]}\",\n      \"echo '${var.users[0]}:${var.PASSWORD}' | chpasswd\"\n    ]\n  }<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When deployed, the remote execution provisioner will create a new user according to the <tt>users<\/tt> variable with the <tt>PASSWORD<\/tt> as set in the environmental variable.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Terraform variables provide many convenient uses for infrastructure management. Dividing your deployment plan and configuration parameters into their own files helps to keep everything in order. However, that is just the general purpose of Terraform variables. Defining your infrastructure using variables is the first step towards the advanced features in Terraform.<\/p>\n","protected":false},"author":3,"featured_media":27318,"comment_status":"open","ping_status":"closed","template":"","community-category":[223,235],"class_list":["post-2266","tutorial","type-tutorial","status-publish","has-post-thumbnail","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2266","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial"}],"about":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/types\/tutorial"}],"author":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/comments?post=2266"}],"version-history":[{"count":0,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/tutorial\/2266\/revisions"}],"wp:attachment":[{"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/media?parent=2266"}],"wp:term":[{"taxonomy":"community-category","embeddable":true,"href":"https:\/\/upcloud.com\/global\/wp-json\/wp\/v2\/community-category?post=2266"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}