Your costs = usage. Period.

Table of Contents:
Effectively managing Infrastructure as Code (IaC) securely and at scale is a primary challenge in cloud computing. 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.1 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.1 Underlying cloud providers maintain continuous monitoring and auditing, holding certifications like ISO 27001 and PCI DSS. All data in Scalr is encrypted in transit and at rest.1
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 CLI support.1 Billing is typically run-based, with some operations not counting towards usage quotas.2 Data retention policies cover run history and state files (e.g., 3 years for apply run history, last 100 state files per workspace).2
Scalr's architecture features a three-tiered hierarchical model: Account, Environment, and Workspace. This structure is key for organizing resources, enforcing policies, and balancing centralized governance with decentralized operations.3
This hierarchy facilitates governance and team autonomy, comparable to AWS Organizations.3
Using the Scalr Terraform provider is a best practice for managing this structure, aligning with GitOps principles.3
Conceptual example:
Terraform
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. The Scalr Ignite repository offers more examples.6 Automating Scalr setup via Terraform (a "Scalr vending machine") reduces operational overhead.3
Scalr's hierarchy enables object inheritance: configurations at higher scopes (Account/Environment) can be inherited by lower scopes (Environment/Workspace), ensuring consistency.3
Scalr supports Terraform input variables (passed as .tfvars.json
) and shell variables (exported to the runtime).8 Both are inheritable: Account -> Environment -> Workspace.8 Variables can be overridden at lower scopes unless marked "final." 8 Sensitive variables are masked.8
Example: Defining and Inheriting Variables with the Scalr Terraform Provider
The scalr_variable resource manages variables programmatically.9
Terraform
# 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."
}
# In an Environment's configuration
resource "scalr_environment" "development_env" {
name = "development"
account_id = var.scalr_account_id
}
resource "scalr_variable" "dev_instance_type_tf_var" {
key = "TF_VAR_instance_type"
value = "t3.small"
category = "shell"
environment_id = scalr_environment.development_env.id
description = "Development environment specific EC2 instance type."
}
# In a Workspace's configuration
resource "scalr_workspace" "my_app_dev" {
name = "my-app-dev"
environment_id = scalr_environment.development_env.id
#... other workspace settings
}
aws_region
is final at account level. TF_VAR_instance_type
is overridden at environment level.
Scalr uses Open Policy Agent (OPA) for policy-as-code.1 OPA policy groups, typically created at Account scope, are assigned to Environments and inherited by their Workspaces.3 Policies evaluate at pre-plan (run context) or post-plan (Terraform plan output) stages.10
Example: Defining an OPA Policy and Linking it
An OPA policy (Rego code) in VCS, e.g., to ensure S3 buckets are private:
Code snippet
# policies/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:
Terraform
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.12
Provider configurations in Scalr manage cloud provider authentication.13 Created at Account scope, they can be assigned to Environments (often as default) or Workspaces.3 Workspaces inherit the environment's default if set.3
Example: Defining and Setting Default Provider Configuration
Terraform
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.13
Scalr offers flexibility for Terraform state storage.15 Three primary models exist 15:
Terraform
terraform {
backend "remote" {
hostname = "<your-account>.scalr.io"
organization = "<your-environment-id>" // Scalr Environment ID [16]
workspaces {
name = "<your-workspace-name>"
}
}
}
Terraform
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket-name"
key = "path/to/my/app.tfstate"
region = "us-west-2"
encrypt = true
}
}
For security, private network access, or custom tooling, Scalr provides self-hosted agents for Terraform/OpenTofu runs and VCS interactions within customer infrastructure.18 This is vital for organizations unable to expose internal systems directly. Agents require only outbound HTTPS to Scalr.io.18
Self-hosted agents execute runs on customer-controlled infrastructure.18 The agent polls Scalr.io for jobs, executes operations, and reports results. Scalr.io never needs network access to the agent.18 Each agent handles multiple concurrent runs (default 5), separate from Scalr.io's shared runner limits.18 Prerequisites include supported OS (Linux, Docker, Kubernetes), network access to *.scalr.io
and *.docker.io
, and appropriate sizing.18 ARM64 is supported.18
Bash
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 run
Bash
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-namespace
agent-local
chart.19For internal VCS providers (e.g., GitHub Enterprise, GitLab Self-Managed) not publicly accessible, Scalr VCS agents enable secure integration.18 The agent relays communication: private VCS connects to the agent internally; the agent uses outbound HTTPS to Scalr.io for syncing repo data.18 Run and VCS agents should be on separate infrastructure.18 VCS agent pools are configured at Account scope in Scalr.18 Deployment is similar to Run agents, specifying type: "vcs"
in configuration.
Scalr supports various deployment methods (VM, Docker, Kubernetes via Helm) for agents.18
Scalr itself can be managed programmatically, aligning with "platform as code" principles for consistency and auditability.3 This reduces manual configuration and error risk.
The Scalr Terraform provider manages Scalr resources (Accounts, Environments, Workspaces, variables, policies, etc.) declaratively using HCL.3 It automates Scalr setup, enabling "Scalr vending machines." 3 Authentication uses a Scalr API token or service account for runs within Scalr.6
Terraform
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 CLI allows direct API interaction for scripting, ad-hoc tasks, and CI/CD integration.22 Configure with scalr -configure
or environment variables (SCALR_HOSTNAME
, SCALR_TOKEN
).22 Syntax: scalr COMMAND
. Create/update operations can use JSON blobs.23
Bash
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.25 Authenticate with a Bearer token.26 Exposes CRUD operations for most Scalr objects.25
Python
import requests
import os
token = os.environ.get("SCALR_API_TOKEN")
scalr_host = os.environ.get("SCALR_HOSTNAME") # e.g., "myaccount.scalr.io"
if not token or not scalr_host:
print("Error: SCALR_API_TOKEN and SCALR_HOSTNAME env vars must be set.")
exit(1)
base_url = f"https://{scalr_host}/"
env_id = "env-your-environment-id"
ws_id = "ws-your-workspace-id"
upload_archive_path = 'path/to/your/terraform_config.tar.gz'
is_dry_run = True
headers = {
'accept': 'application/vnd.api+json',
'content-type': 'application/vnd.api+json',
'Authorization': f'Bearer {token}'
}
# Step 1: Create Configuration Version (CV)
cv_url = f'{base_url}api/iacp/v3/configuration-versions'
cv_payload = {
'data': {
'attributes': {"auto-queue-runs": False},
'relationships': {'workspace': {'data': {'type': 'workspaces', 'id': ws_id}}},
'type': 'configuration-versions'
}
}
response_cv = requests.post(cv_url, headers=headers, json=cv_payload)
response_cv.raise_for_status() # Will raise an exception for HTTP error codes
result_cv = response_cv.json()
cv_id = result_cv['data']['id']
upload_url_for_cv = result_cv['data']['links']['upload']
print(f"CV '{cv_id}' created. Upload URL: {upload_url_for_cv}")
# Step 2: Upload archive
with open(upload_archive_path, 'rb') as f_archive:
upload_headers = {'Content-Type': 'application/octet-stream', 'Authorization': f'Bearer {token}'}
upload_response = requests.put(upload_url_for_cv, headers=upload_headers, data=f_archive)
upload_response.raise_for_status()
print("Archive uploaded.")
# Step 3: Create Run
run_url = f'{base_url}api/iacp/v3/runs'
run_payload = {
'data': {
'attributes': {"is-dry": is_dry_run, "message": "API triggered run"},
'relationships': {
'configuration-version': {'data': {'type': 'configuration-versions', 'id': cv_id}},
'workspace': {'data': {'type': 'workspaces', 'id': ws_id}}
},
'type': 'runs'
}
}
response_run = requests.post(run_url, headers=headers, json=run_payload)
response_run.raise_for_status()
print(f"Run created: {response_run.json()['data']['id']}")
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.1 Object inheritance for variables, policies, and credentials ensures consistency.3 Flexible state management 15 and self-hosted agents for runs and private VCS 18 cater to diverse security needs. Critically, Scalr's "platform as code" approach via its Terraform provider, CLI, and API enables comprehensive automation and control.3 This combination empowers teams to manage cloud infrastructure with confidence, precision, and scalability. The Scalr Ignite repository 7 provides practical starting points.