Variable
The variable resource defines input parameters that can be used throughout your lab configuration. Variables provide a way to parameterize your lab configuration, making it more flexible and reusable by allowing values to be customized without modifying the core configuration.
Use Cases
Section titled “Use Cases”As a lab author, you can use variables to create configurable lab experiences:
- Environment Customization: Define different resource allocations (CPU, memory) for different lab environments or user tiers
- User Personalization: Allow customization of usernames, workspace names, or personal preferences within labs
- Multi-Variant Labs: Create labs with different difficulty levels or feature sets controlled by variable values
- Resource Scaling: Configure container counts, instance sizes, or service configurations based on lab requirements
- Feature Flags: Enable or disable specific lab features, tools, or resources using boolean variables
- Dynamic Naming: Generate consistent naming patterns across resources using variable-based naming schemes
Variables make your lab configurations maintainable and adaptable to different scenarios and requirements.
HCL Syntax
Section titled “HCL Syntax”Basic Syntax
Section titled “Basic Syntax”variable "name" { default = "value"}Full Syntax
Section titled “Full Syntax”variable "name" { default = "default_value" description = "Description of what this variable controls"}Fields
| Field | Type | Required | Description |
|---|---|---|---|
default | any | — | Default value for the variable |
description | string | — | Description of the variable |
type | string | — | Variable type constraint Allowed any string number bool list map |
Variable Types
Section titled “Variable Types”Variables can hold different data types:
| Type | Example | Usage |
|---|---|---|
string | default = “admin” | Text values like usernames, passwords, names |
number | default = 2048 | Numeric values like CPU, memory, ports, counts |
bool | default = false | Enable/disable flags for features or resources |
list | default = [“web”, “api”, “db”] | Arrays of values like service names, ports |
object | default = { cpu = 1024, memory = 512 } | Complex configurations with multiple fields |
Variable Reference
Section titled “Variable Reference”Variables are referenced in other resources using the syntax:
variable.variable_nameSetting Variables at Launch
Section titled “Setting Variables at Launch”A lab started from an embed reads custom parameters from the embed link: URL query parameters whose name starts with icp_. Each one sets the variable of the same name, without the prefix, for that session. For example, icp_debug_enabled=true sets variable.debug_enabled to true.
variable "debug_enabled" { default = false description = "Start the debugging tools"}
resource "container" "debug_tools" { disabled = !variable.debug_enabled
image { name = "busybox:latest" }}Sessions started from the embed link with &icp_debug_enabled=true added to it run debug_tools. Sessions started from the plain link use the default, false, and skip it.
- Embeds only: Only a session started from an embed reads custom parameters. Sessions started from the editor’s Play button, a landing page or an invite ignore them. To try another value from the editor, see Testing a Value from the Editor.
- Declared variables: Declare a
variableblock for every variable you set this way. Validation rejects a reference to a variable that has novariableblock. - Value types: A whole number becomes a number,
trueorfalsebecomes a bool, and any other value stays a string, whatevertypethe variable declares. Custom parameters cannot set a list or object variable. - Reserved names: Custom parameters cannot set the
instruqt_system variables. - When values apply: Values are read each time a session starts or restarts. A running session keeps the values it started with.
- Same browser tab: A later start or restart in the same browser tab reuses the most recent custom parameters, even when the URL no longer has them. To start with the defaults again, paste the link without
icp_parameters into a new browser tab.
Testing a Value from the Editor
Section titled “Testing a Value from the Editor”While you build a lab, you can try it with another variable value, e.g. to turn on debugging tools, by changing the variable’s default in your editing session:
- In edit mode, set the new default, e.g.
default = truefordebug_enabled, and click Add changes. - Click Play. In edit mode, Play runs the changes you’ve added before they’re published. If the header shows Resume, click Stop first, then Play: a running session keeps the values it started with.
Users keep getting the published default until you publish.
System Variables
Section titled “System Variables”In addition to author-declared variables, Instruqt automatically provides a set of reserved system variables in every lab. These variables require no variable block — the platform injects their values at launch — and are referenced the same way as any other variable, e.g. variable.instruqt_session_id.
| Variable | Description |
|---|---|
instruqt_session_id | Unique ID for this lab session |
instruqt_team_id | ID of the team running this session |
instruqt_team_slug | Slug of the team running this session |
instruqt_lab_id | ID of this lab |
instruqt_lab_slug | Slug of this lab |
instruqt_user_id | ID of the user running this session |
instruqt_sandbox_domain | Base domain used to construct public URLs for this sandbox (e.g. labs.instruqt.com) |
For example, you can use the reserved session and domain variables to construct a public callback URL for OAuth configuration at setup time:
resource "exec" "configure_oauth" { target = resource.vm.workshop script = "scripts/exec/configure_oauth/script.sh"
environment = { CALLBACK_URL = "https://service-workshop-${variable.instruqt_session_id}.${variable.instruqt_sandbox_domain}" }}Examples
Section titled “Examples”String Variable
Section titled “String Variable”variable "username" { default = "admin" description = "Default username for system access"}
resource "container" "web" { image { name = "nginx:latest" }
environment = { USER = variable.username }}Numeric Variable
Section titled “Numeric Variable”variable "cpu_resources" { default = 2048 description = "CPU resources allocation in millicores"}
resource "container" "app" { image { name = "myapp:latest" }
resources { cpu = variable.cpu_resources }}Boolean Variable
Section titled “Boolean Variable”variable "debug_enabled" { default = false description = "Enable debug mode for applications"}
resource "container" "service" { image { name = "myservice:latest" }
disabled = !variable.debug_enabled
environment = { DEBUG = variable.debug_enabled ? "true" : "false" }}List Variable
Section titled “List Variable”variable "service_names" { default = ["web", "api", "database"] description = "List of services to deploy"}
resource "container" "services" { count = len(variable.service_names)
image { name = "${variable.service_names[count.index]}:latest" }
environment = { SERVICE_NAME = variable.service_names[count.index] }}Object Variable
Section titled “Object Variable”variable "database_config" { default = { username = "dbuser" password = "dbpass" database = "myapp" port = 5432 } description = "Database connection configuration"}
resource "container" "postgres" { image { name = "postgres:13" }
environment = { POSTGRES_USER = variable.database_config.username POSTGRES_PASSWORD = variable.database_config.password POSTGRES_DB = variable.database_config.database }
port { local = "5432" host = format("%d", variable.database_config.port) }}Multiple Variables Example
Section titled “Multiple Variables Example”variable "environment" { default = "development" description = "Environment name (development, staging, production)"}
variable "replica_count" { default = 1 description = "Number of application replicas to run"}
variable "enable_monitoring" { default = false description = "Enable monitoring and logging components"}
resource "container" "app" { count = variable.replica_count
image { name = "myapp:latest" }
environment = { INSTANCE_NAME = format("app-%s-%02d", variable.environment, count.index + 1) ENV = variable.environment }}
resource "container" "monitor" { image { name = "prometheus:latest" }
disabled = !variable.enable_monitoring}Best Practices
Section titled “Best Practices”- Descriptive Names: Use clear, descriptive variable names that indicate their purpose
- Provide Descriptions: Always include descriptions to document what each variable controls
- Reasonable Defaults: Set sensible default values that work for most use cases
- Type Consistency: Use consistent types for similar variables across your configuration
- Validation: Consider the range of values users might provide when setting defaults
- Documentation: Document variable usage patterns in your lab instructions or README
Common Patterns
Section titled “Common Patterns”Resource Scaling
Section titled “Resource Scaling”variable "worker_count" { default = 3 description = "Number of worker containers to create"}
resource "container" "worker" { count = variable.worker_count
image { name = "worker:latest" }
environment = { WORKER_NAME = format("worker-%02d", count.index + 1) }}Feature Toggles
Section titled “Feature Toggles”variable "features" { default = { monitoring = true debugging = false caching = true } description = "Feature flags for lab components"}
resource "container" "cache" { disabled = !variable.features.caching
image { name = "redis:alpine" }}Environment-Specific Configuration
Section titled “Environment-Specific Configuration”variable "config" { default = { dev = { cpu = 512 memory = 256 debug = true } prod = { cpu = 2048 memory = 1024 debug = false } } description = "Environment-specific configurations"}
variable "environment" { default = "dev" description = "Target environment"}
resource "container" "app" { image { name = "myapp:latest" }
resources { cpu = variable.config[variable.environment].cpu memory = variable.config[variable.environment].memory }
environment = { DEBUG = variable.config[variable.environment].debug ? "1" : "0" }}