Skip to main content
Import resources created in the dashboard or via the CLI into Terraform management without recreating them.

Import syntax

terraform import <resource_type>.<name> "<import_id>"

Import IDs by resource

Each resource type uses a different identifier for import:
ResourceImport IDExample
devhelm_monitorMonitor nameterraform import devhelm_monitor.api "API Health"
devhelm_alert_channelChannel nameterraform import devhelm_alert_channel.slack "Slack Alerts"
devhelm_notification_policyPolicy nameterraform import devhelm_notification_policy.oncall "On-call routing"
devhelm_tagTag nameterraform import devhelm_tag.prod "production"
devhelm_environmentEnvironment slugterraform import devhelm_environment.staging "staging"
devhelm_secretSecret keyterraform import devhelm_secret.token "API_TOKEN"
devhelm_webhookWebhook URLterraform import devhelm_webhook.events "https://hooks.example.com/devhelm"
devhelm_resource_groupGroup name or slugterraform import devhelm_resource_group.payments "Payment Service"
devhelm_resource_group_membership<group_id>/<membership_id|monitor_id|subscription_id>terraform import devhelm_resource_group_membership.api "<group-uuid>/<monitor-uuid>"
devhelm_dependencyService slugterraform import devhelm_dependency.github "github"
devhelm_status_pagePage slugterraform import devhelm_status_page.public "acme-status"
devhelm_status_page_component<status_page_id>/<component_id>terraform import devhelm_status_page_component.api "<page-uuid>/<component-uuid>"
devhelm_status_page_component_group<status_page_id>/<group_id>terraform import devhelm_status_page_component_group.core "<page-uuid>/<group-uuid>"
devhelm_status_page_custom_domain<status_page_id>/<custom_domain_id>terraform import devhelm_status_page_custom_domain.www "<page-uuid>/<domain-uuid>"
Every resource also accepts its UUID as the import ID. Name-based imports fail with an ambiguity error when multiple resources share the name (names are not unique within an org) — import by UUID in that case. devhelm_status_page_custom_domain_verification is the one resource that cannot be imported: it is a synthetic verification barrier with no server-side counterpart.

Step-by-step

1. Write the resource block

Before importing, create the Terraform resource block that matches the existing resource:
resource "devhelm_monitor" "api_health" {
  name              = "API Health"
  type              = "HTTP"
  frequency_seconds = 60
  regions           = ["us-east"]

  config = jsonencode({
    url    = "https://api.example.com/health"
    method = "GET"
  })
}

2. Run import

terraform import devhelm_monitor.api_health "API Health"

3. Run plan

Verify the imported state matches your configuration:
terraform plan
If the plan shows changes, adjust your HCL to match the existing resource’s configuration.

Bulk import

For importing many resources, use a shell loop:
for name in "API Health" "Marketing Site" "Database Port"; do
  terraform import "devhelm_monitor.$(echo $name | tr ' ' '_' | tr '[:upper:]' '[:lower:]')" "$name"
done

Secrets import

Secret values are write-only, so an import stores the placeholder IMPORTED_PLACEHOLDER as the value in state. The next plan shows drift until you set the real value in HCL:
resource "devhelm_secret" "api_token" {
  key   = "API_TOKEN"
  value = var.api_token
}
terraform import devhelm_secret.api_token "API_TOKEN"

Next steps

Terraform in CI/CD

Automate plan and apply in CI pipelines.

Data sources

Reference resources without importing them.