Variable Types & Secrets
This page covers every variable type Amnify renders, with paired .tf ↔ template.json examples, and the encryption flow for sensitive variables.
For the field-by-field manifest reference, see template.json Reference. This page is the practical companion: how each type actually behaves.
string
The default. Renders a single-line text input. With options, renders a dropdown. With sensitive: true, renders a masked password field.
Plain string
{
"name": "resource_group_name",
"type": "string",
"description": "Name of the resource group",
"required": true,
"sensitive": false
}
variable "resource_group_name" {
description = "Name of the resource group"
type = string
}
String with dropdown (options)
{
"name": "location",
"type": "string",
"description": "Azure region",
"default": "West Europe",
"required": true,
"sensitive": false,
"options": ["West Europe", "North Europe", "East US"]
}
variable "location" {
description = "Azure region"
type = string
default = "West Europe"
}
The user's choice is passed to Terraform verbatim — no transformation. Choose options values that are also valid Terraform inputs (e.g. AWS region codes, Azure region names).
number
Numeric input, parsed and serialized as a JSON number.
{
"name": "backup_retention_days",
"type": "number",
"description": "Backup retention (7-35 days)",
"default": 7,
"required": false,
"sensitive": false
}
variable "backup_retention_days" {
description = "Backup retention (7-35 days)"
type = number
default = 7
}
For range checks, use a validation block in your .tf file:
variable "backup_retention_days" {
type = number
default = 7
validation {
condition = var.backup_retention_days >= 7 && var.backup_retention_days <= 35
error_message = "Backup retention must be between 7 and 35 days."
}
}
bool
Renders as a toggle / checkbox.
{
"name": "enable_versioning",
"type": "bool",
"description": "Enable bucket versioning",
"default": false,
"required": true,
"sensitive": false
}
variable "enable_versioning" {
description = "Enable bucket versioning"
type = bool
default = false
}
Booleans pair well with condition to reveal advanced fields only when the toggle is on. See the Conditional Visibility section.
object
A group of nested fields. Use it when you have a logical sub-structure (e.g. a "backup config" with retention + window + geo flags) that is always present as a single unit.
{
"name": "nacl",
"type": "object",
"description": "Network ACL config (omit to use VPC default)",
"required": false,
"sensitive": false,
"schema": [
{
"name": "ingress_default_action",
"type": "string",
"required": true,
"sensitive": false,
"options": ["allow", "deny"]
},
{
"name": "egress_default_action",
"type": "string",
"required": true,
"sensitive": false,
"options": ["allow", "deny"]
}
]
}
variable "nacl" {
type = object({
ingress_default_action = string
egress_default_action = string
})
default = null
}
If the object is optional in template.json ("required": false), use default = null (or optional(object({...}))) in Terraform.
list(object)
A repeating group of nested fields. Renders with add and remove controls in the UI. Use it for things like "list of subnets", "list of firewall rules", "list of IAM bindings".
{
"name": "subnets",
"type": "list(object)",
"description": "List of subnets to create",
"required": true,
"sensitive": false,
"min_items": 1,
"schema": [
{
"name": "name",
"type": "string",
"required": true,
"sensitive": false
},
{
"name": "cidr",
"type": "string",
"required": true,
"sensitive": false
},
{
"name": "availability_zone",
"type": "string",
"required": true,
"sensitive": false
}
]
}
variable "subnets" {
description = "List of subnets to create"
type = list(object({
name = string
cidr = string
availability_zone = string
}))
}
min_items enforces "at least N entries" in the UI. There is no max_items field today — use Terraform validation if you need an upper bound.
Nesting list(object) inside list(object)
You can nest as deeply as you need. The shipped AWS VPC template does this for NACL ingress/egress rules: each subnet has an optional NACL object, which contains a list of ingress rules and a list of egress rules.
{
"name": "subnets",
"type": "list(object)",
"schema": [
{ "name": "name", "type": "string", "required": true, "sensitive": false },
{
"name": "nacl",
"type": "object",
"required": false,
"sensitive": false,
"schema": [
{
"name": "ingress_rules",
"type": "list(object)",
"required": true,
"sensitive": false,
"schema": [
{ "name": "rule_number", "type": "number", "required": true, "sensitive": false },
{ "name": "protocol", "type": "string", "required": true, "sensitive": false }
]
}
]
}
]
}
The matching Terraform uses optional(...) for non-required nested objects:
variable "subnets" {
type = list(object({
name = string
nacl = optional(object({
ingress_rules = list(object({
rule_number = number
protocol = string
}))
}))
}))
}
Sensitive Variables
Setting "sensitive": true in template.json triggers Amnify's secret-handling pipeline. Here is exactly what happens:
Key properties:
- Plaintext is never persisted. Only the encrypted
iv:authTag:ciphertexttriple lives in the database, in thesensitive_variablesJSON column on the deployment row. - Encryption key is org-scoped. Each organization has its own salt; values cannot be decrypted across orgs.
- Decryption happens once, in memory, just before
terraform.tfvars.jsonis written. The plaintext exists only inside the deploy worker process, for the duration of one deployment run. - The UI never re-displays the plaintext. Once submitted, users see a masked indicator. To change the value, they enter a new one — they cannot retrieve the old one.
Declaring a sensitive variable
{
"name": "admin_password",
"type": "string",
"description": "Admin password",
"required": true,
"sensitive": true
}
variable "admin_password" {
description = "Admin password"
type = string
sensitive = true # optional; only affects Terraform CLI log output
}
The sensitive = true on the Terraform side is independent of Amnify's encryption — it just prevents Terraform from printing the value in plan/apply logs. Set both: sensitive in JSON for Amnify storage, and sensitive = true in .tf for Terraform log hygiene.
Sensitive outputs
If a deployment produces a secret value (e.g. a generated connection string), mark the output as sensitive:
output "connection_string" {
value = "postgres://..."
sensitive = true
}
The Amnify UI will mask sensitive outputs by default; users can reveal them with an explicit click.
Auto-Injected Variables
Amnify merges several values into terraform.tfvars.json automatically. You declare a variable block for them in your .tf file, but you do not add them to template.json:
| Variable | Provider | Source |
|---|---|---|
subscription_id | Azure | Project's Azure environment config |
region | AWS | Project's AWS environment config |
location | Azure | Project default; can be overridden by including in template.json |
tags | All | Project tag policy + deployment metadata, merged |
If you want users to override one of these per deployment, add a matching entry to template.json — the user-supplied value takes precedence in the merge.
Next Steps
- Example — Azure Resource Group — apply this to a simple template.
- Example — AWS VPC — apply this to a template that exercises
list(object)deeply.