github.com/hashicorp/packer@v1.14.3/website/content/docs/templates/legacy_json_templates/user-variables.mdx (about) 1 --- 2 description: | 3 The `variables` block contains parameterized values for your templates. Learn how to configure `variables` to improve a template's security, portability, and shareability. 4 page_title: variables reference for JSON templates 5 --- 6 7 # `variables` reference for JSON templates 8 9 This topic describes how to use user variables in Packer templates written in JSON. 10 11 `@include 'from-1.5/legacy-json-warning.mdx'` 12 13 ## Description 14 15 The `variables` block lets you further configure a template with variables 16 from the command-line, environment variables, Vault, or files. This lets you 17 parameterize your templates so that you can keep secret tokens, 18 environment-specific data, and other types of information out of your 19 templates. This maximizes the portability of the template. 20 21 Using user variables expects you to know how [configuration 22 templates](/packer/docs/templates/legacy_json_templates/engine) work. If you don't know how 23 configuration templates work yet, please read that page first. 24 25 ## Usage 26 27 In order to set a user variable, you must define it either within the 28 `variables` section within your template, or using the command-line `-var` or 29 `-var-file` flags. 30 31 Even if you want a user variable to default to an empty string, it is best to 32 explicitly define it. This explicitness helps reduce the time it takes for 33 newcomers to understand what can be modified using variables in your template. 34 35 The `variables` section is a key/value mapping of the user variable name to a 36 default value. A default value can be the empty string. An example is shown 37 below: 38 39 ```json 40 { 41 "variables": { 42 "aws_access_key": "", 43 "aws_secret_key": "" 44 }, 45 46 "builders": [ 47 { 48 "type": "amazon-ebs", 49 "access_key": "{{user `aws_access_key`}}", 50 "secret_key": "{{user `aws_secret_key`}}" 51 // ... 52 } 53 ] 54 } 55 ``` 56 57 In the above example, the template defines two user variables: `aws_access_key` 58 and `aws_secret_key`. They default to empty values. Later, the variables are 59 used within the builder we defined in order to configure the actual keys for 60 the Amazon builder. 61 62 If the default value is `null`, then the user variable will be _required_. This 63 means that the user must specify a value for this variable or template 64 validation will fail. 65 66 User variables are used by calling the `{{user}}` function in the form of 67 `{{user 'variable'}}`. This function can be used in _any value_ but `type` 68 within the template: in builders, provisioners, _anywhere outside the `variables` section_. 69 User variables are available globally within the rest of the template. 70 71 ## Environment variables 72 73 Environment variables can be used within your template using user variables. 74 The `env` function is available _only_ within the default value of a user 75 variable, allowing you to default a user variable to an environment variable. 76 An example is shown below: 77 78 ```json 79 { 80 "variables": { 81 "my_secret": "{{env `MY_SECRET`}}" 82 } 83 } 84 ``` 85 86 This will default "my_secret" to be the value of the "MY_SECRET" environment 87 variable (or an empty string if it does not exist). 88 89 -> **Why can't I use environment variables elsewhere?** User variables are 90 the single source of configurable input to a template. We felt that having 91 environment variables used _anywhere_ in a template would confuse the user 92 about the possible inputs to a template. By allowing environment variables only 93 within default values for user variables, user variables remain as the single 94 source of input to a template that a user can easily discover using 95 `packer inspect`. 96 97 -> **Why can't I use `~` for home variable?** `~` is an special variable 98 that is evaluated by shell during a variable expansion. As Packer doesn't run 99 inside a shell, it won't expand `~`. 100 101 ## Consul keys 102 103 Consul keys can be used within your template using the `consul_key` function. 104 This function is available _only_ within the default value of a user variable, 105 for reasons similar to environment variables above. 106 107 ```json 108 { 109 "variables": { 110 "soft_versions": "{{ consul_key `my_image/softs_versions/next` }}" 111 } 112 } 113 ``` 114 115 This will default `soft_versions` to the value of the key 116 `my_image/softs_versions/next` in consul. 117 118 The configuration for consul (address, tokens, ...) must be specified as 119 environment variables, as specified in the 120 [Documentation](/consul/docs/commands#environment-variables). 121 122 ## Vault variables 123 124 Packer can read secrets read from HashiCorp Vault and add them to your template as user variables. You can only use the `vault` function 125 in the default value of a user variable. This allows you to default a user variable to a Vault secret. Refer to the [Vault documentation](https://developer.hashicorp.com/vault/docs/secrets) for additional information about integrating with Vault secrets engines. 126 127 An example of using a v2 kv engine: 128 129 If you store a value in vault using `vault kv put secret/hello foo=world`, you 130 can access it using the following template engine: 131 132 ```json 133 { 134 "variables": { 135 "my_secret": "{{ vault `/secret/data/hello` `foo`}}" 136 } 137 } 138 ``` 139 140 which will assign "my_secret": "world" 141 142 An example of using a v1 kv engine: 143 144 If you store a value in vault using: 145 146 vault secrets enable -version=1 -path=secrets kv 147 vault kv put secrets/hello foo=world 148 149 You can access it using the following template engine: 150 151 { 152 "variables": { 153 "VAULT_SECRETY_SECRET": "{{ vault `secrets/hello` `foo`}}" 154 } 155 } 156 157 This example accesses the Vault path `secret/data/foo` and returns the value 158 stored at the key `bar`, storing it as "my_secret". 159 160 In order for this to work, you must set the environment variables `VAULT_TOKEN` 161 and `VAULT_ADDR` to valid values. 162 163 The api tool we use allows for more custom configuration of the Vault client via 164 environment variables. 165 166 The full list of available environment variables is: 167 168 ```text 169 "VAULT_ADDR" 170 "VAULT_AGENT_ADDR" 171 "VAULT_CACERT" 172 "VAULT_CAPATH" 173 "VAULT_CLIENT_CERT" 174 "VAULT_CLIENT_KEY" 175 "VAULT_CLIENT_TIMEOUT" 176 "VAULT_SKIP_VERIFY" 177 "VAULT_NAMESPACE" 178 "VAULT_TLS_SERVER_NAME" 179 "VAULT_WRAP_TTL" 180 "VAULT_MAX_RETRIES" 181 "VAULT_TOKEN" 182 "VAULT_MFA" 183 "VAULT_RATE_LIMIT" 184 ``` 185 186 and detailed documentation for usage of each of those variables can be found 187 [here](/vault/docs/commands#environment-variables). 188 189 ## AWS Secrets Manager variables 190 191 Secrets can be read from [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) 192 and used within your template as user variables. The `aws_secretsmanager` function is 193 available _only_ within the default value of a user variable, allowing you to default 194 a user variable to an AWS Secrets Manager secret. 195 196 ### Plaintext secrets 197 198 ```json 199 { 200 "variables": { 201 "password": "{{ aws_secretsmanager `globalpassword` }}" 202 } 203 } 204 ``` 205 206 In the example above it is assumed that the secret `globalpassword` is not 207 stored as a key pair but as a single non-JSON string value. Which the 208 `aws_secretsmanager` function will return as a raw string. 209 210 ### Single key secrets 211 212 ```json 213 { 214 "variables": { 215 "password": "{{ aws_secretsmanager `sample/app/password` }}" 216 } 217 } 218 ``` 219 220 In the example above it is assumed that only one key is stored in 221 `sample/app/password` if there are multiple keys stored in it then you need 222 to indicate the specific key you want to fetch as shown below. 223 224 ### Multiple key secrets 225 226 ```json 227 { 228 "variables": { 229 "db_password": "{{ aws_secretsmanager `sample/app/passwords` `db` }}", 230 "api_key": "{{ aws_secretsmanager `sample/app/passwords` `api_key` }}" 231 } 232 } 233 ``` 234 235 In order to use this function you have to configure valid AWS credentials using 236 one of the following methods: 237 238 - [Environment Variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html) 239 - [CLI Configuration Files](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) 240 - [Container Credentials](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) 241 - [Instance Profile Credentials](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) 242 243 ## Use array values 244 245 Some templates call for array values. You can use template variables for these, 246 too. For example, the `amazon-ebs` builder has a configuration parameter called 247 `ami_regions`, which takes an array of regions that it will copy the AMI to. 248 You can parameterize this by using a variable that is a list of regions, joined 249 by a `,`. For example: 250 251 ```json 252 { 253 "variables": { 254 "destination_regions": "us-west-1,us-west-2" 255 }, 256 "builders": [ 257 { 258 "ami_name": "packer-qs-{{timestamp}}", 259 "instance_type": "t2.micro", 260 "region": "us-east-1", 261 "source_ami_filter": { 262 "filters": { 263 "name": "*ubuntu-xenial-16.04-amd64-server-*", 264 "root-device-type": "ebs", 265 "virtualization-type": "hvm" 266 }, 267 "most_recent": true, 268 "owners": ["099720109477"] 269 }, 270 "ami_regions": "{{user `destination_regions`}}", 271 "ssh_username": "ubuntu", 272 "type": "amazon-ebs" 273 } 274 ] 275 } 276 ``` 277 278 ## Set variables 279 280 Now that we covered how to define and use user variables within a template, the 281 next important point is how to actually set these variables. Packer exposes two 282 methods for setting user variables: from the command line or from a file. 283 284 ### CLI 285 286 To set user variables from the command line, the `-var` flag is used as a 287 parameter to `packer build` (and some other commands). Continuing our example 288 above, we could build our template using the command below. The command is 289 split across multiple lines for readability, but can of course be a single 290 line. 291 292 ```shell-session 293 $ packer build \ 294 -var 'aws_access_key=foo' \ 295 -var 'aws_secret_key=bar' \ 296 template.json 297 ``` 298 299 As you can see, the `-var` flag can be specified multiple times in order to set 300 multiple variables. Also, variables set later on the command-line override any 301 earlier set variable of the same name. 302 303 **warning** If you are calling Packer from cmd.exe, you should double-quote 304 your variables rather than single-quoting them. For example: 305 306 `packer build -var "aws_secret_key=foo" template.json` 307 308 ### From file 309 310 Variables can also be set from an external JSON file. The `-var-file` flag 311 reads a file containing a key/value mapping of variables to values and sets 312 those variables. An example JSON file may look like this: 313 314 ```json 315 { 316 "aws_access_key": "foo", 317 "aws_secret_key": "bar" 318 } 319 ``` 320 321 It is a single JSON object where the keys are variables and the values are the 322 variable values. Assuming this file is in `variables.json`, we can build our 323 template using the following command: 324 325 ```text 326 On Linux : 327 $ packer build -var-file=variables.json template.json 328 On Windows : 329 packer build -var-file variables.json template.json 330 ``` 331 332 The `-var-file` flag can be specified multiple times and variables from 333 multiple files will be read and applied. As you'd expect, variables read from 334 files specified later override a variable set earlier. 335 336 Combining the `-var` and `-var-file` flags together also works how you'd 337 expect. Variables set later in the command override variables set earlier. So, 338 for example, in the following command with the above `variables.json` file: 339 340 ```shell-session 341 $ packer build \ 342 -var 'aws_access_key=bar' \ 343 -var-file=variables.json \ 344 -var 'aws_secret_key=baz' \ 345 template.json 346 ``` 347 348 Results in the following variables: 349 350 | Variable | Value | 351 | -------------- | ----- | 352 | aws_access_key | foo | 353 | aws_secret_key | baz | 354 355 ## Sensitive variables 356 357 If you use the environment to set a variable that is sensitive, you probably 358 don't want that variable printed to the Packer logs. You can make sure that 359 sensitive variables won't get printed to the logs by adding them to the 360 "sensitive-variables" list within the Packer template: 361 362 ```json 363 { 364 "variables": { 365 "my_secret": "{{env `MY_SECRET`}}", 366 "not_a_secret": "plaintext", 367 "foo": "bar" 368 }, 369 370 "sensitive-variables": ["my_secret", "foo"], 371 ... 372 } 373 ``` 374 375 The above snippet of code will function exactly the same as if you did not set 376 "sensitive-variables", except that the Packer UI and logs will replace all 377 instances of "bar" and of whatever the value of "my_secret" is with 378 `<sensitive>`. This allows you to be confident that you are not printing 379 secrets in plaintext to our logs by accident. 380 381 ## Recipes 382 383 ### Make a provisioner step conditional on the value of a variable 384 385 There is no specific syntax in Packer templates for making a provisioner step 386 conditional, depending on the value of a variable. However, you may be able to 387 do this by referencing the variable within a command that you execute. For 388 example, here is how to make a `shell-local` provisioner only run if the 389 `do_nexpose_scan` variable is non-empty. 390 391 ```json 392 { 393 "type": "shell-local", 394 "command": "if [ ! -z \"{{user `do_nexpose_scan`}}\" ]; then python -u trigger_nexpose_scan.py; fi" 395 } 396 ``` 397 398 ### Using HOME Variable 399 400 In order to use `$HOME` variable, you can create a `home` variable in Packer: 401 402 ```json 403 { 404 "variables": { 405 "home": "{{env `HOME`}}" 406 } 407 } 408 ``` 409 410 And this will be available to be used in the rest of the template, i.e.: 411 412 ```json 413 { 414 "builders": [ 415 { 416 "type": "google", 417 "account_file": "{{ user `home` }}/.secrets/gcp-{{ user `env` }}.json" 418 } 419 ] 420 } 421 ```