This article describes the environment in which each workload (run, task) is executed
If you take a look at the Environment screen of a stack you will notice it's pretty busy - in fact it's the second busiest view in Spacelift (run being the undisputed winner). Ultimately though, all the records here are either environment variables or mounted files. The main part of the view represents the synthetic outcome determining what your run will "see" when executed. If this does not make sense yet, please hang on and read the remainder of this article.

Environment variables

The concept of environment variables is instinctively understood by all programmers. It's represented as a key-value mapping available to all processes running in a given environment. Both with Pulumi and Terraform, environment variables are frequently used to configure providers. Additionally, when prefixed with TF_VAR_ they are used in Terraform to use environment variables as Terraform input variables.
Spacelift does not provide a dedicated mechanism of defining Terraform input variables because the combination of TF_VAR_ environment variables and mounted files should cover all use cases without the need to introduce an extra entity.
Adding an environment variable is rather straightforward - don't worry yet about the visibility (difference between plain and secret variables). This is described in a separate section:
...and so is editing:
Environment variable in the viewing mode
Environment variable in the editing mode

Computed values

You will possibly notice some environment variables being marked as <computed>, which means that their value is only computed at runtime. These are not directly set on the stack but come from various integrations - for example, AWS credentials (AWS_ACCESS_KEY_ID and friends) are set by the AWS integration and SPACELIFT_API_TOKEN is injected into each run to serve a number of purposes.
You cannot set a computed value but you can override it - that is, explicitly set an environment variable on a stack that has the same name as the variable that comes from integration. This is due to precedence rules that warrant its own dedicated section.
Overriding a computed value is almost like editing a regular stack variable, although worth noticing is Override replacing Edit and the lack of Delete action:
Computed variable in the viewing mode
When you click Override, you can replace the value computed at runtime with a static one:
Computed variable in the editing mode
Note how it becomes a regular write-only variable upon saving:
If you delete this variable, it will again be replaced by the computed one. If you want to get rid of the computed variable entirely, you will need to disable the integration that originally led to its inclusion in this list.

Spacelift environment

The Spacelift environment section lists a special subset of computed values that are injected into each run and that provide some Spacelift-specific metadata about the context of the job being executed. These are prefixed so that they can be used directly as input variables to Terraform configuration, and their names always clearly suggest the content:
Unless you know exactly what you're doing, we generally discourage overriding these dynamic variables, to avoid confusion.

Per-stage environment variables

The Spacelift flow can be broken down into a number of stages - most importantly:
In this model, only the Applying phase makes any actual changes to your resources and your state and needs the credentials that support it. Yet frequently, the practice is to pass the same credentials to all stages. The reason for that is either the lack of awareness or - more often - the limitations in the tooling. Depending on your flow, this may be a potential security issue because even if you manually review every job before it reaches the Applying stage, the Planning phase can do a lot of damage.
Spacelift supports a more security-conscious approach by allowing users to define variables that are passed to read (in practice, everything except for Applying) and write stages. By default, we pass an environment variable to all stages, but prefixes can be used to change the default behavior.
An environment variable whose name starts with the ro_ prefix is only passed to read stages but not to the write (Applying) stage. On the other hand, an environment variable whose name starts with the wo_ prefix is only passed to the write (Applying) stage but not to the read ones.
Combining the two prefixes makes it easy to create flows that limit the exposure of admin credentials to the code that has been thoroughly reviewed. The example below uses a GITHUB_TOKEN environment variable used by the GitHub Terraform provider variable split into two separate environment variables:
The first token will potentially be exposed to less-trusted code, so it makes sense to create it with read-only permissions. The second token on the other hand will only be exposed to the reviewed code and can be given write or admin permissions.
A similar approach can be used for AWS, GCP, Azure, or any other cloud provider credentials.

Mounted files

Every now and then an environment variable is not what you need - you need a file instead. Terraform Kubernetes provider is a great example - one of the common ways of configuring it involves setting a KUBECONFIG variable pointing to the actual config file which needs to be present in your workspace as well.
It's almost like creating an environment variable, though instead of typing (or pasting) the value you'll be uploading a file:
Before uploading a file
File uploaded
Notice how you can your file give a name that's different to the name of the uploaded entity. In fact, you can use / characters in the file path to nest it deeper in directory tree - for example a/b/c/d/e.json is a perfectly valid file path.
Similar to environment variables, mounted files can have different visibility settings - you can learn more about it here. One thing to note here is that plaintext files can be downloaded back straight from the UI or API while secret ones will only be visible to the run executed for the stack.

Project structure

When discussing mounted files, it is important to understand the structure of the Spacelift workspace. Every Spacelift workload gets a dedicated directory /mnt/workspace/, which also serves as a root for all the mounted files.
Your Git repository is cloned into /mnt/workspace/source/, which also serves as the working directory for your project, unless explicitly overridden by the project root configuration setting (either on the stack level or on in the runtime configuration).
Mounted files may be put into /mnt/workspace/source/ as well and it's a legitimate use case, for example, to dynamically inject backend settings or even add extra infra definitions. Just beware of path clashes as mounted files will override your project source code in case of conflict. Sometimes this is what you want, sometimes not.

Attached contexts

While contexts are important enough to warrant their own dedicated article, it's also crucial to understand how they interact with environment variables and mounted files set directly on the stack, as well as with computed values. Perhaps you've noticed the blue labels on one of the earlier screenshots. If you haven't, here they are again, with a proper highlight:
The highlighted label is the name of the attached context that supplies those values. The sorted list of attached contexts is located below the calculated environment view, and each entry can be unfurled to see its exact content.
Similar to computed values, those coming from contexts can also be overridden. Here's an example:
Variable from an attached context in the viewing mode
Variable from an attached context in the editing mode
Context variable overridden with a stack variable
Note how we can now Delete the variable - this would revert it to the value defined by the context. Contexts can both provide environment variables as well as mounted files, and both can be overridden directly on the stack.
If you want to get rid of the context-provided variable or file entirely, you will need to detach the context itself.

A note on visibility

Perhaps you may have noticed how environment variables and mounted files come in two flavors - plain and secret. Here they are in the form for the new environment variable:
...and here they are in the form for the new mounted file:
Functionally, the difference between the two is pretty simple - plain values are accessible in the web GUI and through the API, and secret ones aren't - they're only made available to Runs and Tasks. Here's an example of two environment variables in the GUI - one plain, and one secret (also referred to as write-only):
Note the asterisks for the secret (write-only) variable
Mounted files are similar - plain can be downloaded from the web GUI or through the API, and secret can't. Here's the difference in the GUI:
The grey icon above is meant to indicate that you cannot download the mounted file
While the content of secret (write-only) environment variables and mounted files is not accessible through the GUI or API, the checksums are always available so if you have the value handy and just want to check if that's the same value as the one set in Spacelift, you can compare its checksum with the one reported by us - check out the most recent GraphQL API schema for more details.
Though all of our data is encrypted both at rest and in transit, secret (write-only) values enjoy two extra layers of protection.
Last modified 2mo ago