Skip to main content
Servers, policies and other objects you made in the app or the API can move to Terraform without being recreated. Terraform imports each object, writes its configuration for you, and from then on manages it like any other resource. This page uses Terraform import blocks with terraform plan -generate-config-out. Set up the provider first: see Terraform Provider.

What you need

  • Terraform 1.5 or later (OpenTofu 1.6 or later)
  • Runlayer provider 1.14.1 or later. Earlier versions plan changes right after an import: a replace for a catalog server whose catalog_entry_name is left out, server settings reset to their defaults, and runlayer_agent owner_id set to null.
  • A user API key, set up as in Terraform Provider

Adopt resources

1

Find the IDs

Each import needs the object’s import ID. For most resources it is the object’s ID; the import ID table lists the others.List servers and policies with the API:
One call returns at most 500 servers or 100 policies. If a call returns that many, fetch the next page with skip, for example ?skip=500&limit=500, until a page comes back short.
2

Write import blocks

Add one import block per object, in a file such as import.tf. Do not write the resource blocks: Terraform generates them in the next step.
To adopt every server at once, write the blocks from the API listing:
Two servers whose names differ only in punctuation or case get the same address; rename one before you plan. With more than 500 servers, run it once per page and append (>>) the output.
Config generation does not work with for_each in import blocks. Write one block per object, as above.
3

Generate the configuration

Terraform reads each object and writes a resource block for it to generated.tf, which must not exist yet. The plan should end with:
4

Review the generated configuration

Treat generated.tf as a starting point:
  • Set every secret from a variable. Terraform cannot write secret values, so it writes null # sensitive instead. A secret left as null is cleared on apply. On runlayer_server this covers transport_config.headers, transport_config.env and placeholder defaults.
  • Remove settings you do not want to manage. On runlayer_server and most other resources, a setting left out of the configuration keeps the value stored in Runlayer, so removing a line does not change the object.
  • Replace hard-coded IDs with references to other resources or data sources, such as runlayer_group.
  • Move the blocks into the files and modules you want.
5

Plan until there are no changes

Edit the configuration until the plan shows only imports:
A planned change means the configuration differs from what is stored in Runlayer. Fix the configuration, not the object, unless you mean to change it. Stop if the plan shows a replace (-/+): applying it deletes the live object and creates a new one.
6

Apply

The apply imports the objects without changing them. The plan after it shows No changes. You can now delete import.tf; import blocks for objects already in state do nothing.

Things to know

  • disable_auto_auth is not stored, so it cannot be read back, and generated configuration leaves it out. Leaving it out keeps the server’s auth_type. Add disable_auto_auth = true only if later applies must keep auth_type as written; the first apply after adding it shows a one-line update.
  • Policy scope wildcards. When a policy’s scope.tools or scope.resources is all (*), generated configuration leaves it out, and that block imports and plans clean. To create a new policy from such a block, set tools and resources explicitly.
  • Resources without import. runlayer_team_member and runlayer_team_group_binding adopt an existing membership or binding when you apply them. Singletons such as runlayer_organization write their settings on apply, so declare them with the values you want. See Importing existing resources.
  • Users, groups and roles are not resources; read them with the runlayer_user, runlayer_group and runlayer_role data sources, or write their IDs to a tfvars file with uvx runlayer terraform export. See How the CLI can help.
  • Server secrets that Runlayer never returns, such as manual_oauth_client_secret and broker_vendor_client_secret, are absent after import and from generated configuration. Leaving them out plans no change.