Skip to content

Solution Variables

Variables allow solutions to have environment-specific configuration without modifying the underlying actions or sequences.

Variables are placeholders in your solution that can have different values per environment:

VariableDevelopmentStagingProduction
database_hostdev-db.localstaging-db.company.comprod-db.company.com
log_leveldebuginfowarn
replica_count125

There is no Variables tab or template editor on the solution page. A variable is a row authored in the Variable Sets UI (or through the variables API); the set is then linked to a solution with POST /api/v1/solutions/{solution_id}/variable-sets. scope_solution_id is a read-only column that no request accepts. These are its properties:

PropertyColumnRequired
NamenameYes
DescriptiondescriptionNo
Typevariable_typeYes
Valuevalue / value_encryptedNo
Promptedis_promptedYes
Prompt labelprompt_labelNo
Prompt descriptionprompt_descriptionNo
Prompt control typeprompt_control_type (defaults text)No
Prompt requiredprompt_requiredYes
Select optionsprompt_select_optionsNo

variable_type is one of string, sensitive, certificate or execution_pool.

prompt_control_type sets how a prompt is presented where Lens asks for its answer: the deployment wizard’s Config step and the schedule form. The database constrains it to the five values below (chk_prompt_control), and it defaults to text.

Single-line text input:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Database Hostname β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ db.example.com β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ Enter the primary database server address β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use for: Hostnames, URLs, paths, simple values

Multi-line text area:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Configuration JSON β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ { β”‚ β”‚
β”‚ β”‚ "feature_flags": { β”‚ β”‚
β”‚ β”‚ "new_checkout": true β”‚ β”‚
β”‚ β”‚ } β”‚ β”‚
β”‚ β”‚ } β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ JSON configuration for the application β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use for: JSON, YAML, configuration files, scripts

Dropdown selection:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Log Level β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ info β–Ό β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β€’ debug β”‚
β”‚ β€’ info β”‚
β”‚ β€’ warn β”‚
β”‚ β€’ error β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use for: Predefined options, log levels, regions

Boolean toggle:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Enable Debug Mode β”‚
β”‚ β”Œβ”€β”€β”€β” β”‚
β”‚ β”‚ βœ“ β”‚ Enable β”‚
β”‚ β””β”€β”€β”€β”˜ β”‚
β”‚ Turn on detailed logging for troubleshooting β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use for: Feature flags, on/off settings

Masked input for secrets:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ API Key β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’β€’ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ API key for external service integration β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Use for: Passwords, API keys, tokens, secrets

Every path that deploys a solution answers its prompted variables. One that leaves a required prompt unanswered is refused before anything runs or is recorded.

PathWhere the answers come from
Create deploymentThe request’s prompted_values
RedeployThe request’s prompted_values, else the answers the source deployment recorded
PromotionThe answers the source deployment recorded
ScheduleThe schedule’s deployment_config.variables, checked on save and again each run
Failure handlerNone, so a solution with required prompts cannot be a failure handler

Every deployment records the answers it ran with, which is what a redeploy or promotion of it carries: never a value its plan resolved for the same name. A schedule’s answers to sensitive prompts are sealed with its other sensitive overrides. A scheduled run that a changed prompt leaves unanswered is skipped, and the schedule stays due. A schedule applied from a config repository is checked when it runs.

Author variables in the Variable Sets UI (or via the variables API), then link the set to the solution with POST /api/v1/solutions/{solution_id}/variable-sets β€” see How a Variable Is Stored above.

Per-environment values are set on the variable itself, by giving it a scope_environment_id (there is no β€œConfigure Variables” button on the environment page). Create one variable per environment value, or use a variable set scoped to both the solution and the environment.

Resolved variables reach an action in two ways during deployment:

  1. #{...} templates in command arguments, the working directory, declared environment variable values, and a script’s file name and content.
  2. MANTIS_* environment variables injected into the executed process, for each non-sensitive variable. Each resolved variable is exposed as an uppercased, MANTIS_-prefixed environment variable (for example, database_host becomes MANTIS_DATABASE_HOST).
FormRenders
#{database_host}The variable’s value
#{log_level | ToUpper}The value through a filter; filters chain with |
#{if Live}...#{else}...#{/if}One branch; Live is false when empty, false, 0 or null
#{if Count == 5}...#{/if}Comparisons: == != < <= > >=, not and or
#{each host in Hosts}...#{/each}The body once per item of Hosts, a JSON array or a comma-separated list; #{host}, #{hostIndex}, #{hostFirst} and #{hostLast} inside
#{calc Replicas * 2}Arithmetic: + - * / %, negation, parentheses
#{ | NowDateUtc}A filter with no subject
#{Mantis.Environment.Name}A system variable (below)

A bare reference to a variable the deployment does not define is left in the output as written β€” note that #{Typo} left standing at a word boundary is read by a shell as a # comment, so a misspelled reference can silently truncate a command. An undefined variable in a condition, a loop or a filtered reference fails the step, as does a template that does not parse; the error names the field.

A sensitive variable is referenced bare, as #{DbPassword}: its value is filled in when the command is delivered to the target, so it is never stored in plaintext with the queued command, and only the actions that reference it receive it. It cannot take a filter or appear in a condition, and a template that tries fails the step. Text that merely looks like a reference β€” inside another variable’s value, for instance β€” is never filled in.

Write ##{ for a literal #{. The names if, else, each, in and calc are template keywords and cannot be used as variable names.

Filter names are case-insensitive.

FilterResult
ToLower, ToUpper, TrimCase conversion; surrounding whitespace removed
Truncate(10), Truncate(10, "...")The first 10 characters, with the suffix if it was cut
Substring(2), Substring(2, 5)From position 2, optionally 5 characters long
Replace("old", "new")Every occurrence replaced
PadLeft(8), PadRight(8, "0")Padded to the width, with a space or the given character
HtmlEscape, XmlEscape, JsonEscape, UrlEscape, MarkdownEscapeEscaped for that format
ToBase64, FromBase64Base64 encoded or decoded
Contains("x"), StartsWith("x"), EndsWith("x"), Match("regex")true or false
UriPart("host")scheme, host, port, path, query or fragment of a URI
VersionMajor, VersionMinor, VersionPatch, VersionPrereleaseThat part of a semantic version
FormatDate("%Y-%m-%d", "%d/%m/%Y")A date re-formatted from the first format to the second
NowDate, NowDateUtc, NowDateUtc("%Y-%m-%d")The current local or UTC date and time
VariableValue
Mantis.Deployment.IdThe deployment’s id
Mantis.Deployment.CreatedAtWhen the deployment was planned, RFC 3339
Mantis.Environment.Id, Mantis.Environment.NameThe target environment, when the deployment names one
Mantis.Tenant.Id, Mantis.Tenant.NameThe deploying tenant, for a tenant deployment
Mantis.Solution.Id, Mantis.Solution.NameThe solution, for a solution deployment
Mantis.Sequence.Id, Mantis.Sequence.NameThe sequence this step belongs to
Mantis.Action.Id, Mantis.Action.NameThe action this step runs
Mantis.Step.NumberThe action’s configured order within its sequence
Mantis.Target.Id, Mantis.Target.NameThe target, for a step a target runs
Mantis.Worker.IdThe Thorax instance, for a step that runs off-target

A system variable that does not apply to a step is not defined for it.

Command payloads are structured (a binary plus ordered arguments), so reference variables inside individual arguments:

  • Binary: docker
  • Argument 1: run
  • Argument 2: --env
  • Argument 3: DB_HOST=#{database_host}
  • Argument 4: --env
  • Argument 5: LOG_LEVEL=#{log_level | ToUpper}
  • Argument 6: myapp

When using the DefaultShell executor (the default), arguments are passed directly to the binary without any shell interpretation, so shell metacharacters are treated as literal values. When using the Sh, Bash, Pwsh, or Zsh executors, each argument is shell-quoted before the command line is composed β€” POSIX single-quoting for Sh, Bash and Zsh, PowerShell single-quoting for Pwsh. A metacharacter in a resolved variable is therefore made inert rather than rejected, so a value containing ;, |, $ or a quote deploys as written and still cannot chain, pipe or expand. Only the binary name is filtered for metacharacters; an argument is refused for a null byte alone.

A script’s content is a template like any other field, and its resolved variables are also available as MANTIS_* environment variables:

#!/bin/bash
echo "Connecting to $MANTIS_DATABASE_HOST"
docker compose up -d --scale web="$MANTIS_REPLICA_COUNT"

Mantis resolves each variable by additive specificity: every variable with the key whose scopes all match the deployment context is a candidate, each scored by the sum of its scopes’ points, and the highest total wins. Solution scope is worth 40 points β€” well below tenant (200), environment (100) and target (500) β€” so a solution-level default is a low-priority fallback, not β€œlevel 1”.

ScopePoints
Current action1000
Current target500
Tenant200
Environment100
Solution40
Variable set20
Global0

(The full 10-level table is in Tenant Variables.)

A variable whose scope does not match the context is discarded outright. If no candidate matches a required variable, the deployment errors; otherwise the highest-scoring match wins β€” when only a global or solution-scoped variable exists, that fallback value is what deploys.

Good: database_primary_host, api_gateway_url
Bad: db, host1, var1

Help operators understand what values to provide:

Variable: connection_string
Help: PostgreSQL connection string in format:
postgres://user:pass@host:5432/dbname

Provide defaults for development/testing:

Variable: log_level
Default: info
(Production can override to "warn")

Encryption and log masking key off the variable’s type (variable_type = sensitive), not the control type. Set the variable’s type to sensitive for:

  • Passwords
  • API keys
  • Tokens
  • Certificates
  • Connection strings with credentials

Set variables as required when they must have values:

Variable: database_host
Required: true
(Deployment fails if not set)
VariableControl typeExample
database_hosttextdb.example.com
database_porttext5432
database_nametextmyapp_production
database_usertextapp_user
database_passwordsensitiveβ€’β€’β€’β€’β€’β€’β€’
VariableControl typeExample
feature_new_uicheckboxtrue
feature_beta_apicheckboxfalse
feature_analyticscheckboxtrue
VariableControl typeExample
web_replicastext3
worker_replicastext2
max_connectionstext100

Symptom: Seeing #{variable_name} in output

Solutions:

  • Check variable is defined on solution
  • Check environment has a value set
  • Verify spelling matches exactly

Symptom: Deployment fails with β€œMissing required prompted variables: ”

Solution: Answer the prompt where that path takes its answers (see Answering Prompts). A promotion takes the source deployment’s answers, so redeploy the source with the answer first.

Symptom: Secret appears in deployment logs

Solution: Set the variable’s type to sensitive (variable_type = sensitive). Masking and encryption read variable_type, never the free-text control type β€” setting the control type to β€œsensitive” does not mask or encrypt the value.