This script will migrate the following objects from TFC to Scalr in bulk:
- Workspaces with all attributes
- VCS settings and trigger patterns
- Terraform version
- Execution mode (remote/local)
- Working directory
- Auto-apply settings
- Remote state sharing
- Variable values (including sensitive variables when available)
- Workspace dependencies
- State file migration
- Preserves state history
- Variable migration (including sensitive variables from plan files)
- Variable set migration
- Variable set variables (including sensitive values recovery)
- Non-global variable set workspace links and environment access updates
- Only TFC variable sets in scope for this run are migrated: global sets, sets linked to
--tfc-project(when set), and sets linked to workspaces in scope for this run (workspace name patterns). TFC-global sets become Scalr shared (is-shared) variable sets with no explicit environment relationships; non-global sets get environment access merged by name across reruns.
- VCS provider configuration
- Provider configuration linking
- Remote state consumers
- Trigger patterns handling
- Workspace locking in TFC/E after migration to avoid conflicting runs
At the end of the migration, the Scalr Terraform provider code will be generated, allowing you to continue managing Scalr objects with code. A Scalr management environment and workspace will be created for managing Scalr environments and workspaces.
- Python 3.x (automatically detects python3.12, python3, or python)
- Terraform Cloud/Enterprise credentials
- Scalr credentials
- VCS provider configured in Scalr and
--vcs-nameset (only for workspaces that use VCS in TFC/E) - Provider configuration in Scalr (if linking workspaces to provider configurations)
This migration tool is designed to work seamlessly across different operating systems and environments:
- Linux/macOS: Native bash environments
- Windows: Git Bash, WSL (Windows Subsystem for Linux), Cygwin, MSYS2
- Python: Automatically detects and uses the best available Python 3.x installation
- Operating System: Automatically adapts paths and commands based on the detected platform
- Virtual Environment: Handles activation scripts for both Windows and Unix-like systems
- Home Directory: Cross-platform detection for credential file locations
- jq: Optional for reading Terraform credentials file (graceful fallback if not available)
- bash: Required shell environment (available on all supported platforms)
- Clone this repository:
git clone https://github.com/your-org/terraform-scalr-migrate-tfc.git
cd terraform-scalr-migrate-tfc- Make the scripts executable:
chmod +x migrate.shAuthentication can be provided in three ways. When the same value is set in more than one place, this order applies:
- Command-line arguments (highest priority)
- Environment variables
~/.terraform.d/credentials.tfrc.json(fallback when tokens are not set elsewhere)
Both --flag value and --flag=value formats are supported for all options (for example, --tfc-token "your-token" or --tfc-token=your-token).
./migrate.sh \
--tfc-token "your-token" \
--tfc-organization="my-org" \
--scalr-hostname "account.scalr.io" \
--scalr-token "your-token"Inline values passed this way are always used, even if tokens for the same hostnames exist in the credentials file.
export SCALR_HOSTNAME="account.scalr.io" # Replace `account` with the actual account name
export SCALR_TOKEN="your-token"
export TFC_TOKEN="your-token"Environment variables are used when a value is not passed on the command line. They take precedence over the credentials file.
When tokens are not provided via the command line or environment variables, the migrator reads them from the locally cached credentials file (usually written by the terraform login command). The Scalr hostname must be known (via --scalr-hostname or SCALR_HOSTNAME) to look up the Scalr token.
{
"credentials": {
"account.scalr.io": {
"token": "your-scalr-token"
},
"app.terraform.io": {
"token": "your-tfc-token"
}
}
}To use this auth method, run two commands first:
Cache TFC token:
terraform loginCache Scalr token (replace account with the actual account name):
terraform login account.scalr.io./migrate.sh --tfc-token "your-token" --tfc-organization="my-org" --scalr-hostname "your-account.scalr.io" --scalr-token "your-token"--scalr-hostname: Scalr hostname (e.g.,myorg.scalr.io)--scalr-token: Scalr API token--tfc-hostname: TFC/E hostname (e.g.,app.terraform.io)--tfc-token: TFC/E API token--tfc-organization: TFC/E organization name
-v|--vcs-name: VCS provider name in Scalr (required when any workspace in scope is VCS-driven; not checked at startup if omitted)--scalr-environment: Scalr environment to create (default:--tfc-projectif set, otherwise--tfc-organization)--pc-name: Provider configuration name in Scalr to link to workspaces--agent-pool-name: Agent pool name in Scalr to link to workspaces-w|--workspaces: Workspace name pattern (supports shell-style wildcards, default: "*")- Examples:
"prod-*"(starts with prod-),"*-staging"(ends with -staging),"test?"(test + any single char)
- Examples:
--skip-backend-secrets: Skip creation of shell variables for backend configuration--skip-tfc-lock: Skip locking TFC/E workspaces after migration--skip-post-migration: Skip post-migration Terraform/OpenTofu steps (fmt, init, apply)--skip-variable-sets: Skip migration of TFC variable sets to Scalr (workspace-level variables are still migrated)--migrate-variable-sets-only: Migrate only TFC variable sets. Workspaces, their state files and variables are not migrated; workspaces that already exist in the destination Scalr environment are reused to link non-global variable sets. Cannot be combined with--skip-variable-setsor--skip-variables="*". See Migrating variable sets separately.--management-env-name: Name of the management environment (default: "scalr-admin")--management-workspace-name: Name of the management workspace that holds the generated Terraform code (default: the--scalr-environmentname; spaces are replaced with-)--disable-deletion-protection: Disable deletion protection in workspace resources--tfc-project: TFC project name to filter workspaces by--skip-variables: Comma-separated list of variable key patterns to skip, or"*"to skip all variable migration (including variable sets)--use-opentofu: Use OpenTofu for workspaces with Terraform version >= 1.6.0 instead of downgrading to 1.5.7--opentofu-version: OpenTofu version to use when--use-opentofuis set (must be >= 1.6.0; default: latest active OpenTofu version in Scalr)--credentials-set-name: Name of the TFC variable set the migrator creates for backend/credential secrets during sensitive environment variable migration (default:Scalr-Creds). This set is skipped when migrating variable sets to Scalr.
The migration is idempotent, so variable sets and workspaces can be migrated in separate runs:
# 1st run: variable sets only
./migrate.sh --tfc-organization "my-org" --scalr-environment "my-env" --migrate-variable-sets-only
# 2nd run: workspaces (variable sets already exist and are updated in place and linked)
./migrate.sh --tfc-organization "my-org" --scalr-environment "my-env"In --migrate-variable-sets-only mode:
- TFC workspaces are still listed and filtered by
--workspaces/--tfc-projectto determine which variable sets are in scope, but no workspace, state file or workspace variable is migrated and no TFC workspace is locked. - Non-global variable sets are linked only to workspaces that already exist in the destination Scalr environment (from a previous run). Workspaces that do not exist yet are reported, and the links are created on the run that migrates them.
- The management environment/workspace and the generated Terraform code are still created, unless
--skip-post-migrationis set.
The tool generates the following files in the generated-terraform/$SCALR_ENVIRONMENT directory so you can manage your workspaces with the Scalr Terraform provider:
main.tf: Contains all Terraform resourcesbackend.tf: Remote backend configurationimport_commands.sh: Script to import resources and push state
After successful migration, the tool automatically runs the following steps (unless --skip-post-migration is specified):
- Navigate to the generated Terraform directory (
generated-terraform/$SCALR_ENVIRONMENT) - Run
fmtto format the generated code - Run
initto initialize the workspace - Run
applyto import all previously created resources into the management workspace state file
By default these steps use the terraform CLI. When --use-opentofu is enabled, they use tofu instead (tofu fmt, tofu init, tofu apply).
To skip these automatic steps and run them manually, use the --skip-post-migration flag.
- By default, supports up to Terraform 1.5.7. If a higher version is used, the script will downgrade it to 1.5.7.
- When
--use-opentofuis enabled, workspaces with Terraform version >= 1.6.0 use OpenTofu (latest active version in Scalr, or the version from--opentofu-version) instead of downgrading. This requires Scalr to support OpenTofu. - State migration requires at least one state file in the source TFC/E workspace.
- Sensitive terraform variables migration requires at least one plan file in the source TFC/E workspace.
- Sensitive environment variables requires triggering of the remote run in a TFC/E workspace
-
If you encounter authentication errors:
- Verify your tokens are correct
- Check that command-line tokens are not being overridden (CLI arguments take priority over the credentials file)
- Check the credentials file format
- Ensure you have the necessary permissions
-
If state migration fails:
- Check if the workspace has a valid state file
- Ensure you have sufficient permissions in both platforms
-
If workspace creation fails:
- Verify the VCS provider is correctly configured
- Check if the workspace name is available
- Ensure you have sufficient permissions
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.