
This post is part of a series on Terraform Modules Explained.
Reviewed for accuracy by Ryan Fee on June 6, 2025.
Effectively managing Infrastructure as Code (IaC) securely and at scale is a primary challenge for platform teams. Scalr provides a sophisticated platform for Terraform and OpenTofu operations. This post examines Scalr's SaaS architecture, its three-tiered hierarchical model, object inheritance, flexible backend options, agent-based execution, and how Scalr itself can be managed "as code," complete with practical examples.
Scalr is a Software-as-a-Service (SaaS) platform, acting as a remote state and operations backend for Terraform and OpenTofu, hosted and managed by Scalr. This model removes the user's burden of maintaining the IaC management tool's infrastructure. Scalr is hosted on IaaS platforms, with Scalr securing its deployed workloads. Underlying cloud providers maintain continuous monitoring and auditing, holding certifications like SOC2, ISO 27001, and PCI DSS. All data in Scalr is encrypted in transit and at rest.
Advantages of the SaaS model include:
Scalr offers features like Role-Based Access Control (RBAC), Open Policy Agent (OPA) integration, a private module registry, and full Terraform/Tofu CLI support. Billing is run-based, with nothing else factoring into the cost.
Scalr's architecture features a three-tiered hierarchical model: Account, Environment, and Workspace. This structure is key for organizing objects, enforcing policies, reporting, and balancing centralized governance with decentralized operations.

This hierarchy facilitates governance and team autonomy, comparable to AWS Organizations.
Using the Scalr Terraform provider is a best practice for managing this structure, aligning with GitOps principles.
Conceptual example:
terraform {
required_providers {
scalr = {
source = "registry.scalr.io/scalr/scalr"
version = "~> 1.5" # Check for the latest compatible version
}
}
}
provider "scalr" {
hostname = var.scalr_hostname
token = var.scalr_api_token
}
variable "scalr_hostname" {
type = string
description = "Scalr account hostname (e.g., myaccount.scalr.io)."
}
variable "scalr_api_token" {
type = string
sensitive = true
description = "Scalr API token."
}
variable "scalr_account_id" {
type = string
description = "Your Scalr Account ID (e.g., acc-xxxxxxxxxxxx)."
}
# Define an Environment
resource "scalr_environment" "production_env" {
name = "production"
account_id = var.scalr_account_id
}
# Define a Workspace within the Production Environment
resource "scalr_workspace" "app_server_prod" {
name = "app-server-prod"
environment_id = scalr_environment.production_env.id
vcs_provider_id = data.scalr_vcs_provider.github.id
vcs_repo {
identifier = "your-org/infra-repo"
branch = "main"
path = "terraform/app-server/prod"
}
terraform_version = "1.5.7"
}
data "scalr_vcs_provider" "github" {
name = "My-GitHub-Connection"
account_id = var.scalr_account_id
}This example creates a "production" environment and an "app-server-prod" workspace. Automating Scalr setup via Terraform (a "Scalr vending machine") reduces operational overhead.
Scalr's hierarchy enables object inheritance: configurations at higher scopes (Account/Environment) can be inherited by lower scopes (Environment/Workspace), ensuring consistency.

Scalr supports Terraform input variables (passed as .tfvars.json) and shell variables (exported to the runtime). Both are inheritable: Account -> Environment -> Workspace. Variables can be overridden at lower scopes unless marked "final." Sensitive variables are masked.
Example: Defining and Inheriting Variables with the Scalr Terraform Provider
The scalr_variable resource manages variables programmatically.
# In your Scalr Account configuration
variable "scalr_account_id" {
type = string
}
resource "scalr_variable" "global_region" {
key = "aws_region"
value = "us-east-1"
category = "shell"
account_id = var.scalr_account_id
final = true
description = "Global default AWS region, non-overridable."
}
resource "scalr_variable" "default_instance_type_tf_var" {
key = "TF_VAR_instance_type"
value = "t3.micro"
category = "shell"
account_id = var.scalr_account_id
description = "Default EC2 instance type, can be overridden."
}aws_region is final at account level. All workspaces will inherit it.
Scalr uses Open Policy Agent (OPA) for policy-as-code. OPA policy groups, created at the account scope, are assigned to environments and inherited by their workspaces. Policies evaluate at pre-plan (run context) or post-plan (Terraform plan output) stages.
Example: Defining an OPA Policy and Linking it
An OPA policy (Rego code) in VCS, e.g., to ensure S3 buckets are private:
#s3_private.rego
package terraform
import input.tfplan as tfplan
deny[reason] {
r := tfplan.resource_changes[_]
r.mode == "managed"
r.type == "aws_s3_bucket"
r.change.after.acl == "public-read" # Example check
reason := sprintf("%s: S3 bucket ACL must not be public-read.", [r.address])
}Using the Scalr Terraform provider:
data "scalr_vcs_provider" "main_vcs" {
name = "My-GitHub-Enterprise"
account_id = var.scalr_account_id
}
resource "scalr_policy_group" "s3_security_policies" {
name = "s3-security-best-practices"
account_id = var.scalr_account_id
vcs_provider_id = data.scalr_vcs_provider.main_vcs.id
vcs_repo {
identifier = "your-org/opa-policies"
path = "policies"
branch = "main"
}
environments = ["*"] # Link to all environments
}This policy group applies to all environments.

Provider configurations in Scalr manage cloud provider authentication. Created at the account scope, they can be assigned to environments (often as default) or workspaces. Workspaces inherit the environment's default if set.
Example: Defining and Setting Default Provider Configuration
resource "scalr_provider_configuration" "aws_prod_credentials" {
name = "aws-production-role"
account_id = var.scalr_account_id
aws {
account_type = "regular"
credentials_type = "role_delegation"
trusted_entity_type = "aws_service"
role_arn = "arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/ScalrProdExecutionRole"
}
}
resource "scalr_environment" "production_env" {
name = "production"
account_id = var.scalr_account_id
default_provider_configurations = [scalr_provider_configuration.aws_prod_credentials.id]
}Workspaces in production_env use aws_prod_credentials by default.

Scalr offers flexibility for Terraform state storage. Three primary models exist:
Scalr Remote Backend w/ Customer Managed State Storage ("Bring Your Own Bucket"): Scalr is the remote backend for operations, but state files, artifacts, plans, and logs are in the customer's AWS S3 or GCP bucket. Variables and provider configs remain in Scalr. Offers data location control. Requires creating a "storage profile" in Scalr.
Non-Scalr Backend w/ Customer Managed State Storage: Users configure standard backends (e.g., S3, Azure Blob) in Terraform code. Scalr can orchestrate runs, but state/locking is by the chosen backend. Customer handles state encryption.
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket-name"
key = "path/to/my/app.tfstate"
region = "us-west-2"
encrypt = true
}
}Scalr Remote Backend w/ Scalr State Storage (Default): Scalr manages state storage in a Scalr-managed, encrypted Google Cloud Storage bucket. Offers full feature functionality and simplified setup.
terraform {
backend "remote" {
hostname = "<your-account>.scalr.io"
organization = "<your-environment-id>"
workspaces {
name = "<your-workspace-name>"
}
}
}For security, private network access, or custom tooling, Scalr provides self-hosted agents for Terraform/OpenTofu runs and VCS interactions within customer infrastructure. This is vital for organizations unable to expose internal systems directly. Agents require only outbound HTTPS to Scalr.io.
Self-hosted agents execute runs on customer-controlled infrastructure. The agent polls Scalr.io for jobs, executes operations, and reports results. Scalr.io never needs network access to the agent. Each agent handles multiple concurrent runs (default 5), separate from Scalr.io's shared runners. Prerequisites include supported OS (Linux, Docker, Kubernetes), network access to *.scalr.io and *.docker.io, and appropriate sizing. ARM64 is supported.
Kubernetes Deployment (Helm): Scalr offers an official Helm chart.
helm repo add scalr-agent-helm https://scalr.github.io/agent-helm/
helm repo update
kubectl create secret generic scalr-agent-token-secret --from-literal=SCALR_TOKEN='<your-agent-token>' --namespace scalr-agents
# values-run-agent.yaml:
# agent:
# type: "run"
# scalr_url: "https://<your-account>.scalr.io"
# scalr_token_secret_name: "scalr-agent-token-secret"
helm install scalr-run-agent scalr-agent-helm/agent-local -f values-run-agent.yaml --namespace scalr-agents --create-namespaceThis uses the agent-local chart.
Docker Deployment Example:
docker run \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/scalr-agent:/var/lib/scalr-agent \
-e SCALR_URL="https://<your-account>.scalr.io" \
-e SCALR_TOKEN="<your-agent-token>" \
-e SCALR_DATA_HOME="/var/lib/scalr-agent" \
--rm -it --pull=always --name=scalr-run-agent scalr/agent:latest runFor internal VCS providers (e.g., GitHub Enterprise, GitLab Self-Managed) not publicly accessible, Scalr VCS agents enable secure integration. The agent relays communication: private VCS connects to the agent internally; the agent uses outbound HTTPS to Scalr.io for syncing repo data. Run and VCS agents should be on separate infrastructure. VCS agent pools are configured at Account scope in Scalr. Deployment is similar to Run agents, specifying type: "vcs" in configuration.
Scalr supports various deployment methods (VM, Docker, Kubernetes via Helm) for agents.

Scalr itself can be managed programmatically, aligning with "platform as code" principles for consistency and auditability. This reduces manual configuration and error risk.
The Scalr Terraform provider manages Scalr resources (Accounts, Environments, Workspaces, variables, policies, etc.) declaratively using HCL. It automates Scalr setup, enabling "Scalr vending machines." Authentication uses a Scalr API token or service account for runs within Scalr.
Basic Provider Configuration:
terraform {
required_providers {
scalr = {
source = "registry.scalr.io/scalr/scalr"
version = "~> 1.5" // Check registry for latest [6, 20, 21]
}
}
}
provider "scalr" {
hostname = var.scalr_hostname
token = var.scalr_api_token
}
variable "scalr_hostname" {
type = string
}
variable "scalr_api_token" {
type = string
sensitive = true
}The Scalr Ignite repository (https://github.com/sierra-cedar/scalr-ignite) offers comprehensive examples.
The Scalr CLI allows direct API interaction for scripting, ad-hoc tasks, and CI/CD integration. Configure with scalr -configure or environment variables (SCALR_HOSTNAME, SCALR_TOKEN). Syntax: scalr COMMAND. Create/update operations can use JSON blobs.
Example: Creating an Environment (flags):
export SCALR_HOSTNAME="myaccount.scalr.io"
export SCALR_TOKEN="your_cli_api_token"
scalr create-environment -name="cli-demo-env" -account-id="acc-your-account-id"A comprehensive REST API offers deep programmatic control for custom automation. Authenticate with a Bearer token. Exposes CRUD operations for most Scalr objects.
Scalr's architecture effectively addresses IaC management challenges at scale. Its SaaS model simplifies operations, while the three-tiered hierarchy (Account, Environment, Workspace) offers a robust framework for organization and governance. Object inheritance for variables, policies, and credentials ensures consistency. Flexible state management and self-hosted agents for runs and private VCS cater to diverse security needs. Critically, Scalr's "platform as code" approach via its Terraform provider, CLI, and API enables comprehensive automation and control. This combination empowers teams to manage cloud infrastructure with confidence, precision, and scalability.
