Elevating IaC Workflows with Spacelift Stacks and Dependencies 🛠️

Register for the July 23 demo →


Terraform Cloud Agents vs. Spacelift Workers

Terraform Cloud Agents vs. Spacelift Workers

In the realm of Infrastructure as Code (IaC), both Terraform Cloud agents and Spacelift private workers are instrumental. Understanding their functionalities, differences, and similarities is key to efficient infrastructure management. They accomplish the same functionality, helping you achieve a hybrid model by having a SaaS product and a worker that resides in your infrastructure.

  1. What is a Terraform Cloud agent?
  2. Using Terraform Cloud Agents
  3. What is a Spacelift worker?
  4. Using Spacelift workers
  5. Terraform Cloud agents vs Spacelift workers comparison

What is a Terraform Cloud Agent?

Terraform Cloud Agents facilitate communication between Terraform Cloud and isolated, private, or on-premises infrastructure. Deployed within specific network segments, these agents enable provisioning operations and management, particularly useful for infrastructures like vSphere, and OpenStack, but not limited to these — you may have a use case in which you need an agent to communicate with your AWS infrastructure, and that can be easily achieved. Their pull-based architecture negates the need for inbound connectivity.

Terraform Cloud Agents on Terraform Cloud (TFC) vs Terraform Enterprise (TFE)

Terraform Cloud Agents on both TFC and TFE behave similarly, with a few exceptions. TFE has no limitations on agent count and offers support for custom Terraform bundles. Additionally, Terraform Enterprise has specific requirements for hostname registration and network access that Terraform Cloud does not.

Using Terraform Cloud Agents

To use a Terraform Cloud Agent, we have to first create an agent pool. To do that, go to your TFC account, select Settings → Agents, and then click on Create agent pool:

tfc agents

Select a name for your agent pool and click on Continue:

Terraform cloud agent pool

You will also need to create a token, so add a description to it and click on Create Token:

terraform cloud agent token

Copy the token, as you will only see it once, and refer to the instructions on how to create your agent:

setting up tfc agents

You will need to save your token to an environment variable called TFC_AGENT_TOKEN on your Docker host and also add a name to your agent in the TFC_AGENT_NAME. Then you can run the docker command shown above.

After performing these steps, this is what you’ll see in your cli:

2023-12-15T09:27:28.571Z [INFO]  agent: Starting: agent_name=first agent_version=1.14.1
2023-12-15T09:27:28.585Z [INFO]  core: Starting: version=1.14.1
2023-12-15T09:27:29.061Z [INFO]  core: Agent registered successfully with Terraform Cloud: agent_id=agent-eib6KfQchiqNiyCD agent_pool_id=apool-QNikAqNYwGVstAGP
2023-12-15T09:27:29.294Z [INFO]  agent: Newer core versions are available, but are ignored due to the auto-update configuration: version=1.15.0-rc.1
2023-12-15T09:27:29.295Z [INFO]  agent: Core version is up to date: version=1.14.1
2023-12-15T09:27:29.295Z [INFO]  core: Waiting for next job

In the Terraform Cloud console, you will see your agent in the idle state:

terraform cloud console agents

Let’s assign this agent to a workspace. To do that, you will need to select one of your Terraform Cloud workspaces, go to Settings → General Settings and select the appropriate agent pool:

agents settings

Now, let’s trigger a run on the workspace as we would normally do. The agent will receive the plan and do the run itself. It considers an init and a plan a single job:

2023-12-15T09:33:56.323Z [INFO]  core: Job received: job_type=plan job_id=run-plan
2023-12-15T09:33:56.323Z [INFO]  terraform: Handling run: run_id=run-plan run_operation=plan organization_name=saturnhead workspace_name=blog-examples
2023-12-15T09:33:56.607Z [INFO]  terraform: Extracting Terraform from release archive
2023-12-15T09:33:57.416Z [INFO]  terraform: Terraform CLI details: version=1.6.6
2023-12-15T09:33:57.416Z [INFO]  terraform: Downloading Terraform configuration
2023-12-15T09:33:57.512Z [INFO]  terraform: Running terraform init
2023-12-15T09:33:58.550Z [INFO]  terraform: Running terraform plan
2023-12-15T09:33:59.734Z [INFO]  terraform: Generating and uploading plan JSON
2023-12-15T09:33:59.968Z [INFO]  terraform: Generating and uploading provider schemas JSON
2023-12-15T09:34:01.175Z [INFO]  terraform: Generating and uploading redacted plan JSON
2023-12-15T09:34:01.390Z [INFO]  terraform: Persisting filesystem to remote storage
2023-12-15T09:34:01.698Z [INFO]  terraform: Finished handling run
2023-12-15T09:34:02.020Z [INFO]  core: Waiting for next job

And this is what you’ll see in the console:

agent pool

After you confirm the run, you will see that a new job is triggered:

2023-12-15T11:29:53.640Z [INFO]  terraform: Handling run: run_id=run-apply run_operation=apply organization_name=saturnhead workspace_name=blog-examples
2023-12-15T11:29:53.924Z [INFO]  terraform: Extracting Terraform from release archive
2023-12-15T11:29:54.717Z [INFO]  terraform: Terraform CLI details: version=1.6.6
2023-12-15T11:29:54.717Z [INFO]  terraform: Restoring filesystem from remote storage
2023-12-15T11:29:54.878Z [INFO]  terraform: Running terraform init
2023-12-15T11:29:55.876Z [INFO]  terraform: Running terraform apply
2023-12-15T11:29:58.136Z [INFO]  terraform: Uploading files required for instrumenting module/provider dependencies
2023-12-15T11:29:58.136Z [INFO]  terraform: file for runtime report was not found: filename=/home/tfc-agent/.tfc-agent/component/terraform/runs/run-apply/config/migration/.terraform/modules/modules.json
2023-12-15T11:29:58.136Z [INFO]  terraform: file for runtime report was not found: filename=/home/tfc-agent/.tfc-agent/component/terraform/runs/run-apply/config/migration/.terraform.lock.hcl
2023-12-15T11:29:58.926Z [INFO]  terraform: Finished handling run
2023-12-15T11:29:59.351Z [INFO]  core: Waiting for next job

You will see the apply in the console that ran on the agent:

terraform enterprise agents

What is a Spacelift worker?

Spacelift workers are designed to execute Spacelift workflows. Anyone with a Spacelift account has access to a public worker pool that can be leveraged for all of the workflows, but if your security compliance requires the use of private infrastructure, Spacelift offers the ability to configure private workers that will leverage the user’s own infrastructure. These workers process one run at a time, ensuring maximum concurrency equals the number of workers. They can be hosted on virtual servers like AWS EC2 or containerized.

spacelift workers

Using Spacelift workers

Asymmetric encryption is utilized to ensure that only workers within a specific worker pool can access any temporary run state. To facilitate this, you must generate a private key, which is then used to create a certificate signing request (CSR) for Spacelift. Spacelift will use this CSR to generate a certificate, enabling workers to authenticate with the Spacelift backend.

The process begins with running the following command to generate the key and CSR:

openssl req -new -newkey rsa:4096 -nodes -keyout spacelift.key -out spacelift.csr

To create a private worker pool, we need to log in to our Spacelift account, go to Worker pools, and click on Create Worker Pools.

worker pool spacelift

You need to specify a name for your worker pool, attach the csr file you have created before, and — if you want — add a description and some labels to the worker pool.

Clicking on Create will automatically download a file that contains your worker pool token. Keep it handy, as we will use it in an environment variable.

The most straightforward way to set up a worker is to download our amd or arm launchers (depending on your platform) and export the following variables:

export SPACELIFT_TOKEN=<worker_pool_token>
export SPACELIFT_POOL_PRIVATE_KEY=$(cat spacelift.key | base64 -w 0)

For the launcher to work, the SPACELIFT_POOL_PRIVATE_KEY should be base64 encoded. Now we can start our worker:

{"caller":"context.go:39","level":"info","msg":"Tracing enabled","ts":"2023-12-19T13:50:10.285467942Z"}
{"caller":"mothership.go:50","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"warning","msg":"[store]   memorystore wiped","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:50:11.294249603Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"mothership.go:50","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"warning","msg":"[store]   memorystore del: message1not found","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:50:11.324143434Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"setup.go:157","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"info","msg":"Docker ping OK","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:50:11.32741111Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"state_transitions.go:54","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"info","msg":"cleaning up...","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:50:11.32817177Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"state_transitions.go:61","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"info","msg":"disk usage threshold is set to 1.000000. Disk usage check is disabled","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:50:11.330978107Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}

If you go to your Spacelift console, you will now see that your worker pool has a worker inside it:

workers in spacelift console

Let’s assign the worker pool to one of our stacks. To do that, you will need to go to your stack, select Settings, then go to Behavior and use the drop-down list for the Work Pool option:

work pool option

Now, we are ready to run a job using our worker pool. As soon as a run is triggered, the worker picks it up and the information is visible inside the cli:

{"caller":"client.go:84","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"debug","msg":"starting logging session","run.ulid":"01HJ15Q0P26JND72H6CVXNSHTW","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:54:49.490674834Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"worker_mounter_saas.go:143","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"debug","msg":"verifying worker binary","run.ulid":"01HJ15Q0P26JND72H6CVXNSHTW","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:54:51.502823978Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"client.go:108","launcher.ulid":"01HJ15EMVDER1EM9AMTBDC220W","level":"debug","msg":"attempting to upload logs to S3","run.ulid":"01HJ15Q0P26JND72H6CVXNSHTW","spacelift.worker.ulid":"01HJ15EMVDER1EM9AMTBDC220W","ts":"2023-12-19T13:54:52.152933442Z","worker_pool_ulid":"01HHYKCS649QEBH58R268FY2BH"}
{"caller":"worker.go:850","level":"debug","msg":"loading workspace files","ts":"2023-12-19T13:54:53.289488184Z"}
"caller":"worker.go:351","level":"info","msg":"Evaluating plan policy","original_workflow":"test-and-apply","run_ulid":"01HJ15Q0P26JND72H6CVXNSHTW","step":"plan","ts":"2023-12-19T13:55:36.110731794Z","workflow_name":"test-and-apply"}
{"caller":"worker.go:164","has_delta":true,"level":"info","msg":"Changing state","new_state":"FINISHED","note":null,"original_workflow":"test-and-apply","run_ulid":"01HJ15Q0P26JND72H6CVXNSHTW","ts":"2023-12-19T13:55:36.20066767Z","username":null,"version":4,"workflow_name":"test-and-apply"}
{"caller":"client.go:52","level":"debug","msg":"closing session","run_ulid":"01HJ15Q0P26JND72H6CVXNSHTW","ts":"2023-12-19T13:55:36.201173104Z"}

And this is what you will see in the console:

tfe agents vs workers

Terraform Cloud agents vs Spacelift workers


Both Terraform Cloud Agents and Spacelift Private Workers are designed to manage isolated, private, or on-premises infrastructure. They enable Terraform operations within specific network segments, facilitating provisioning operations and management in protected environments. 

In addition, both systems encompass security – they use encryption and other secure methods to ensure that only authorized entities have access to manage the infrastructure. Both are built to work seamlessly with Terraform, allowing for efficient management of IaC. 


Since Terraform Cloud supports only Terraform, their agents are designed for their Terraform workflows. With Spacelift, however, private workers can be used to work with all the tools supported, such as Terraform, OpenTofu, Ansible, Kubernetes, CloudFormation, Terragrunt, and more.

Terraform Cloud agents support hooks only in two run types: plan and apply. You can run hooks before init and after plan or before init and after apply. Spacelift supports hooks in between all runner phases: Initialization, Planning, Applying, Destroying, Performing, and Finally.

With Spacelift, you can also see the queued runs on private workers, and you also enable the ability to prioritize runs:

agent vs worker pools

Table comparison

agents vs workers

Key points

While public workers are secure, both Terraform Cloud agents and Spacelift private workers are key to satisfying your organization’s rules and ensuring compliance. Both are designed to work with your infrastructure, use different encryption methods, and integrate seamlessly with Terraform (in Spacelift’s case, with other IaC tools as well).

Spacelift gives you the flexibility to set priorities inside your running queue and also enables you to control what happens before and after every runner phase for all the supported IaC tools.

If you are interested in a secure IaC management solution that offers all the flexibility your organization needs, create a free account with Spacelift or book a demo with one of our engineers.

Manage Terraform Better with Spacelift

Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.

Start free trial

How can Spacelift stacks & dependencies elevate your IaC workflows?

Don’t miss our July 23 webinar.

Register for the webinar