How to Set Terraform Variables from the Command Line for Module Inputs

Terraform's -var and -var-file flags can only set variables in the root module; to configure a child module from the CLI, you must expose a root variable and forward it through the module block.

When working with the hashicorp/terraform repository, infrastructure engineers frequently need to override configuration values at runtime. While Terraform provides robust command-line interfaces for variable injection, understanding how to set Terraform variables from the command line for module inputs requires knowledge of the root module's exclusive role in the variable hierarchy.

Understanding Root Module vs. Child Module Variables

Terraform organizes configurations into a hierarchy beginning with the root module. When you execute commands like terraform apply or terraform plan, the CLI parses arguments and constructs a dependency graph starting from this root context.

According to the source code in internal/command/arguments/vars.go, the -var and -var-file flags are explicitly designed to populate the root module's variable map. The parser validates these inputs and stores them for evaluation during the planning phase.

Why You Cannot Set Child Module Variables Directly

Child modules—those invoked via module blocks—do not accept CLI arguments directly. As implemented in internal/terraform/transform_module_variable.go, Terraform resolves module variables only after the parent module has been processed and its variables evaluated.

The evaluation order follows this sequence:

  1. CLI flags populate root module variables (handled in internal/terraform/variables.go)
  2. Terraform builds the resource graph starting from the root
  3. Child module variables are resolved using values passed through module block arguments

This architecture ensures deterministic evaluation and prevents circular dependencies, but it means that attempting to pass -var="module.child.var=value" will result in an error indicating the variable is not defined in the root module.

How to Pass Values to Child Modules from the Command Line

To set Terraform variables from the command line for use within a child module, you must create a bridge through the root module configuration.

Step 1 – Define a Root Module Variable

First, declare a variable in your root configuration that will receive the CLI input:


# variables.tf in root module

variable "database_password" {
  description = "Password for the database module"
  type        = string
  sensitive   = true
}

Step 2 – Forward the Variable to the Child Module

Next, pass the root variable into the child module's configuration:


# main.tf in root module

module "database" {
  source   = "./modules/database"
  password = var.database_password
}

Step 3 – Set the Value via Command Line

Now you can use the -var flag to inject the value at runtime:

terraform apply -var="database_password=superSecret123"

For multiple variables, use a .tfvars file:

terraform apply -var-file="production.tfvars"

Technical Implementation Details in the Terraform Source Code

The restriction against direct child module variable assignment is enforced at multiple layers in the hashicorp/terraform codebase.

In internal/command/arguments/vars.go, the argument parser processes -var flags and explicitly scopes them to the root module context. The help text generated in internal/command/plan.go (line 227) clarifies that these flags set "input variables in the root."

The variable transformation logic in internal/terraform/transform_module_variable.go demonstrates that module variables are derived from the parent module's evaluation context, not from CLI arguments. This occurs during the graph transformation phase, after root variables have been populated via internal/terraform/variables.go.

Summary

  • Terraform CLI flags (-var and -var-file) only target root module variables, as enforced by the argument parser in internal/command/arguments/vars.go.
  • Child module variables must be passed through the root module using variable definitions and module block arguments.
  • To set a child module value from the CLI, expose a root variable with the same or mapped name, forward it to the child module, and use -var or -var-file at runtime.
  • Multiple variables are best managed through .tfvars files rather than numerous -var flags.

Frequently Asked Questions

Can I use -var to set a variable inside a module directly?

No. The -var and -var-file flags can only set variables in the root module. According to the implementation in internal/command/arguments/vars.go, the CLI parser explicitly scopes these arguments to the root module context. To configure a child module, you must define a root variable and pass it through the module block.

What is the difference between root module and child module variables?

The root module is the top-level configuration directory where you run Terraform commands. Its variables can be set via CLI flags, environment variables, or .tfvars files. Child modules are reusable components invoked via module blocks; their variables are resolved during the graph construction phase only after the parent module's variables are evaluated, as shown in internal/terraform/transform_module_variable.go.

How does Terraform handle variable precedence when using -var flags?

Terraform evaluates variables in a specific precedence order: environment variables (TF_VAR_*) are overridden by .tfvars files, which are overridden by -var-file arguments, with -var flags taking the highest precedence. This hierarchy is managed during the variable loading phase in internal/terraform/variables.go, ensuring that CLI-specified values always win over file-based or environment defaults.

Is there a way to pass sensitive variables to modules via CLI?

Yes, but you must mark the root variable as sensitive = true in your configuration. When you pass the value using -var="secret=value", Terraform will redact the value from logs and UI output while still transmitting it to the child module through the variable forwarding mechanism. The sensitive flag is checked during the variable validation phase to ensure proper handling throughout the execution pipeline.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →