Scalr
Scalr
May 20, 2025

Deep Dive into Scalr's Platform Architecture

By
Sebastian Stadil

Mastering Scalable Infrastructure: A Deep Dive into Scalr's Platform Architecture

Table of Contents:

  • Scalr Overview
  • Platform Architecture
  • SaaS Model
  • Hierarchical Structure
  • Object Inheritance
  • Backend State Storage
  • Agent-Based Execution
  • Infrastructure as Code Management
  • Conclusion
  • 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.

    The Scalr Platform: A SaaS Approach to IaC Management

    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:

    • Reduced Operational Overhead: Teams focus on IaC, not tool management.
    • Scalability: Handles growing IaC needs without user intervention for scaling.
    • Accessibility: Cloud-based for distributed team collaboration.
    • Managed Security: Scalr secures the platform, leveraging provider security.1

    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

    The Architectural Cornerstone: Scalr's Three-Tiered Hierarchy

    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

    • Account Scope: The highest administrative level, typically managed by central DevOps/platform teams.3 It handles global configurations like IAM, OPA policies, module registry, provider credentials, VCS providers, and shared variables.2 The account scope offers a unified dashboard for all workspaces and runs across environments, crucial for oversight.3 Objects defined here can cascade down, ensuring organizational consistency.
    • Environment Scope: Nested under Accounts, environments enable self-service by decentralizing operations.3 They act as logical groupings (e.g., "production," "development") or akin to cloud sub-accounts, isolating workspaces, teams, and configurations.3 Access requires explicit permissions, separating concerns and reducing change impact.3
    • Workspace Scope: The most granular level, children of an Environment, where Terraform/OpenTofu runs execute and state files are stored.3 Each workspace links to a single state file and related objects like variables and run history.3 Engineers interact here via CLI, VCS, or Scalr's no-code module deployments.3

    This hierarchy facilitates governance and team autonomy, comparable to AWS Organizations.3

    Managing the Hierarchy with the Scalr Terraform Provider

    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

    The Power of Inheritance: Variables, Policies, and Credentials

    Scalr's hierarchy enables object inheritance: configurations at higher scopes (Account/Environment) can be inherited by lower scopes (Environment/Workspace), ensuring consistency.3

    Variable Inheritance

    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.

    Policy Inheritance (OPA)

    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

    Credential Inheritance (Provider Configurations)

    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

    Flexible State Management: Scalr-Managed vs. Customer-Managed Backend

    Scalr offers flexibility for Terraform state storage.15 Three primary models exist 15:

    1. Scalr Remote Backend w/ Scalr State Storage (Default): Scalr manages state storage in a Scalr-managed, encrypted Google Cloud Storage bucket.15 Offers full feature functionality and simplified setup.15

    Terraform

    terraform {
     backend "remote" {
       hostname     = "<your-account>.scalr.io"
       organization = "<your-environment-id>" // Scalr Environment ID [16]
       workspaces {
         name = "<your-workspace-name>"
       }
     }
    }

    1. 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.15 Variables and provider configs remain in Scalr.15 Offers data location control. Requires creating a "storage profile" in Scalr.15 Terraform backend block is the same as above.
    2. 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.15 Offers maximum control but may limit some Scalr features. Customer handles state encryption.15

    Terraform

    terraform {
     backend "s3" {
       bucket         = "my-terraform-state-bucket-name"
       key            = "path/to/my/app.tfstate"
       region         = "us-west-2"
       encrypt        = true
     }
    }

    Secure and Flexible Execution: Self-Hosted Agents

    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

    Agents for Runs

    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

    • Docker Deployment Example:

    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

    • 18
    • Kubernetes Deployment (Helm): Scalr offers an official Helm chart.18

    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

    • This uses the agent-local chart.19

    Agents for Private VCS Providers

    For 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

    Managing Scalr as Code: Automation and Control

    Scalr itself can be managed programmatically, aligning with "platform as code" principles for consistency and auditability.3 This reduces manual configuration and error risk.

    Scalr Terraform Provider

    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

    • Basic Provider Configuration:

    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
    }

    Scalr CLI

    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

    • Example: Creating an Environment (flags):

    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"

    • 23

    Scalr API

    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

    • Example: Python Script to Create CV and Trigger Run 26:

    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']}")

    Conclusion: Building a Scalable and Governed IaC Practice with Scalr

    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.

    Note: Check out our new Learning Center here for technical guides and how-tos.

    Your costs = usage. Period.

    A screenshot of the modules page in the Scalr Platform