Skip to main content
The 2.0.0 Runpod Terraform provider is a breaking release. It is generated entirely from the Runpod REST v2 API. Every resource therefore needs both a configuration edit and a state action before it plans cleanly. This guide maps each 1.x attribute to its 2.0.0 equivalent and gives the exact edit and state command each resource needs.
New to the Runpod Terraform provider? You don’t need this guide. Start with Manage Runpod infrastructure with Terraform to install 2.0.0 and deploy your first Pod.

What changed

The 1.x provider was assembled from more than one backend, so its attribute names came in several styles. Some attributes were even accepted by Terraform but ignored by the service. The 2.0.0 provider has one source of truth. Every attribute maps to a documented v2 field. Names follow the v2 schema: image, not image_name, and disk, not container_disk_in_gb. Anything the API never supported is gone rather than silently accepted. Throughout this guide, “1.x” means 1.0.8, the last release that worked end to end and the baseline that 2.0.0 preserves. Some things 1.x did have no v2 field yet. 2.0.0 keeps these and marks them deprecated rather than dropping them. The machine surface and the account read run on GraphQL. The three 1.x billing data sources read the v2 billing routes in their 1.x record shape. A few attributes on Pods, templates, and Serverless endpoints read from GraphQL or REST v2, or are kept only so a 1.x configuration still plans. Terraform warns about each one on every plan. The mapping tables below flag them row by row, and Deprecated shims lists them all. 2.0.0 makes no REST v1 calls, so the REST v1 retirement on November 15, 2026 doesn’t affect it.

Requirements

  • Terraform 1.6 or later.
  • An existing configuration and state built with the 1.x provider.
  • A Runpod API key, set through the api_key argument or the RUNPOD_API_KEY environment variable.
  • The resource ids from your current state, recorded before you upgrade. Step 2 below covers this.

Provider block and authentication

Pin the new major version and raise the Terraform floor. The 1.x block:
The 2.0.0 block:
Authentication is unchanged in substance. The provider reads api_key, falls back to the RUNPOD_API_KEY environment variable, and errors at configure time if neither is set. The base_url argument now points at a different host. In 1.0.8, base_url and the RUNPOD_BASE_URL environment variable both set the REST v1 host (https://rest.runpod.io/v1). In 2.0.0, base_url sets the REST v2 host that everything except the GraphQL shims calls. It falls back to RUNPOD_API_BASE_URL, then the production API. 2.0.0 doesn’t read RUNPOD_BASE_URL.
If your 1.x configuration sets base_url, remove it. If you leave it, the provider sends every v2 call to the REST v1 host. Set base_url or RUNPOD_API_BASE_URL only to point the provider at a non-production v2 host.
One more provider argument applies only to the deprecated shims. Everything on REST v2 ignores it:
  • graphql_url: The GraphQL endpoint for the runpod_machine resource, the runpod_machine and runpod_machines data sources, the runpod_user data source, and the deprecated attributes on runpod_pod, runpod_template (resource and data source), and runpod_serverless_endpoint that REST v2 doesn’t report. Falls back to RUNPOD_GRAPHQL_URL, then https://api.runpod.io/graphql.
Set it only if you use the deprecated surfaces against a non-production environment. The 2.0.0 release candidates also had a rest_v1_url argument. It’s still accepted so a configuration that sets it validates, but it’s deprecated and ignored, and RUNPOD_REST_V1_URL isn’t read. Remove it. For the full list of calls that still leave REST v2, see Which Runpod APIs the provider uses.

Upgrade process

1

Pin the new version and initialize

Set the version in your provider block and run terraform init -upgrade:
~> 2.0 installs 2.0.0 and every later 2.x release.
2

Record your resource ids

Before editing anything, record the identifiers you will need to re-import. Run terraform state list and terraform show -json against the old state, or reuse the id outputs you already have. Do this while the 1.x provider is still in the lock file.
3

Rewrite the configuration resource by resource

Apply the mapping tables below, then:
  • Rename the three resource types that changed name: runpod_endpoint, runpod_container_registry_auth, and runpod_ecr_delegation.
  • Rename the two data sources that changed with them: runpod_container_registry_auths and runpod_ecr_delegations.
  • Delete the resources that no longer exist.
4

Run the state actions

2.0.0 ships no state upgraders, so a 1.x state entry whose attribute set changed cannot be decoded. Follow the state migration section to remove and re-import each affected resource. Those commands change state only. For a Pod, though, the first apply after them can replace it. Read Before importing a Pod you want to keep first.
5

Plan and review

Run terraform plan. Templates, network volumes, endpoints, machines, and account keys should show no changes when the rewritten configuration matches what the API reports. Imported Pods, registry credentials, and ECR delegations behave as the state migration section describes. Read every planned replacement before you apply it.
Expect genuine replacements where 1.x let you change something the API cannot change in place. Changing gpu_type_id, gpu_count, cloud, cpu_type_id, vcpu_count, template_id, the CUDA constraints, or the host-size floors forces a new Pod. Switching a Serverless endpoint between the GPU and CPU families replaces the endpoint.

Resources

runpod_pod

The resource type name and id format are unchanged. The attribute set changed substantially, and the two mount kinds moved into blocks. These attributes were renamed, reshaped, or moved: The container command now lives entirely in args as a single string. docker_entrypoint and docker_start_cmd still exist in 2.0.0 as read-only attributes, read back from the v2 Pod’s entrypoint and cmd. 1.0.8 accepted values for them but never sent those values. Remove them from your configuration and put the command in args. machine_id and volume_encrypted also still exist, as deprecated read-only values from the GraphQL Pod. machine_id reports the machine the Pod landed on. You can’t set it, because the v2 create has no machine pinning. volume_encrypted reads false for an unencrypted volume, not null as in 1.x, so a check such as volume_encrypted == null needs updating. These attributes keep their names and behavior: gpu_type_id, gpu_count, template_id, start_ssh, start_jupyter, memory_in_gb, id, status, and created_at. locked and cluster_ip also keep their names and are now populated from the v2 read, where 1.x declared them but never filled them. 2.0.0 adds these attributes:
  • cpu_type_id: creates a CPU-only Pod. Exactly one of gpu_type_id or cpu_type_id must be set.
  • desired_state: RUNNING or EXITED, reconciled on every apply.
  • data_center_ids: a placement preference. The scheduler’s pick lands in the read-only data_center_id.
  • registry: the registry credential id for a private image.
  • global_networking: a private cross-datacenter IP.
  • min_cuda_version and allowed_cuda_versions: a CUDA floor, or an exact set. These are mutually exclusive.
  • min_ram_per_gpu and min_vcpu_count_per_gpu: host-size placement filters, applied per requested GPU.
  • global_volumes: a list of { volume_id, path } objects that mounts global volumes wherever the Pod is placed.
Before, in 1.x:
After, in 2.0.0:
To attach a network volume instead of host-local storage, use the network_volumes block. The two mount kinds are mutually exclusive, and the volume must be in the same data center as the Pod:

runpod_endpoint

The 2.0.0 equivalent is runpod_serverless_endpoint: the resource type was renamed. The largest change is GPU selection. 1.x named individual GPU types; 2.0.0 names Serverless GPU pools and subtracts exceptions from them. These attributes were renamed, reshaped, or moved: These attributes keep their names and behavior: name, env, template_id (which must be a serverless template), gpu_count, workers_min, workers_max, idle_timeout, allowed_cuda_versions, min_cuda_version, data_center_ids, id, and created_at. gpu_type_priority and cpu_flavor_priority are still in the 2.0.0 schema as deprecated attributes, but they’re never applied. No API has a setting for the order in which the scheduler tries GPU types or CPU flavors, so a configured value stays in state, is never sent, and triggers a plan warning. Remove them from your configuration. template_version, users, version, and workers are also still available as deprecated read-only values:
  • template_version is always null. No API reports it. Use the runpod_endpoint_releases data source for releases.
  • users is the owning account as a one-element list, read from GraphQL. It was never an access list.
  • version and workers come from the REST v2 workers listing. In workers, pod_id is the worker’s id, uptime_ms has whole-second precision, and last_busy_ms is always null. The supported view is the runpod_endpoint_workers data source.
cloud_type is gone. It existed only in 1.0.9, which never ran, and the v2 Serverless create takes no cloud tier. 2.0.0 adds these attributes:
  • endpoint_type: required, either QUEUE or LOAD_BALANCER. Changing it replaces the endpoint.
  • ports: the worker HTTP ports a LOAD_BALANCER endpoint routes to.
  • excluded_types: GPU type ids subtracted from the selected pools.
  • registry: the registry credential id for a private worker image.
  • global_volumes: global volumes mounted on every worker of a GPU endpoint.
Before, in 1.x:
After, in 2.0.0:

runpod_network_volume

The resource type name and id format are unchanged. Two attributes were renamed: name, size (10 to 4096 GB, which can grow but never shrink), and id keep their names and behavior. Before, in 1.x:
After, in 2.0.0:

runpod_template

The resource type name and id format are unchanged. The container settings come from the v2 template object, docker_entrypoint included, and the single persistent mount moved into the persistent_volume block. A template that sets both docker_start_cmd and docker_entrypoint needs one extra edit. The API stores the entrypoint inside args, so args and docker_entrypoint can’t both be set. Write args in its JSON form instead, for example args = jsonencode({ entrypoint = ["/bin/bash", "-c"], cmd = ["start.sh"] }). These attributes were renamed, reshaped, or moved: name, category (CPU, NVIDIA, or AMD), env, ports, and id keep their names and behavior. Before, in 1.x:
After, in 2.0.0:

runpod_container_registry_auth

The 2.0.0 equivalent is runpod_registry: the resource type was renamed. Every attribute (name, username, password, and id) kept its name. The API has no update operation, so any change replaces the credential, and 2.0.0 cannot import one. Before, in 1.x:
After, in 2.0.0, the Pod references the credential explicitly through registry:

runpod_ecr_delegation

The 2.0.0 equivalent is runpod_registry_delegation: the resource type was renamed. Every attribute kept its name, and resource is now required. The API has no update operation, so any change replaces the delegation, and 2.0.0 cannot import one. Before, in 1.x:
After, in 2.0.0:

runpod_pod_action

The resource type name is unchanged, but the semantics are now explicit: the resource is imperative. It reconciles nothing and refreshes to nothing, and destroying it only forgets it, leaving the Pod as it is. The action runs on create and again whenever action or triggers change.
  • pod_id keeps its behavior. Pointing it at a different Pod replaces the resource and runs the action on the new Pod.
  • action keeps the names start, stop, restart, and terminate. 1.x also documented resume and reset; use start and restart instead.
  • status is read-only and reports the status at the moment the action was accepted, not a live value. A refresh does not update it, and terminate returns no body, so it leaves this null. Read live state from the runpod_pod data source.
  • triggers is new: a map of arbitrary values that re-runs the action when any of them changes.
  • id is new and read-only: the Pod this resource acts on, one action runner per Pod.
Do not combine runpod_pod_action with runpod_pod.desired_state on the same Pod. Both manage the same transitions, and each apply would undo the other. Use desired_state for a run state Terraform should keep, and runpod_pod_action for a one-off restart or a stop tied to something else changing.
Before, in 1.x:
After, in 2.0.0, a restart that re-runs when the image tag moves:
If what you wanted was a run state Terraform keeps, set desired_state on the Pod instead:

runpod_machine

The runpod_machine resource remains available on the GraphQL API as a deprecated shim. The resource type name, id format, and every attribute name are unchanged. No configuration change is needed beyond the state action. Only name and bid_price_per_gpu are settable, exactly as in 1.x; everything else reports what the API assigned. Terraform prints a deprecation warning on every plan that touches it.

Removed resources

Two 1.x resources have no 2.0.0 equivalent:
  • runpod_endpoint_job: jobs are runtime objects served by the Serverless runtime API, not infrastructure Terraform should own. Submit jobs from your application or a caller against the runtime API.
  • runpod_endpoint_worker: individual workers are not addressable. Use the runpod_endpoint_workers and runpod_endpoint_worker_logs data sources to observe workers, and the endpoint’s workers_min, workers_max, scaling_type, and scaling_value to control them.

Data sources

Data sources hold no managed state, so none of them needs a state action. Rename the two that changed name and delete the removed ones; the rest re-read on the next plan.

runpod_pod

The runpod_pod data source keeps its name and required id. It now reports far more than 1.x did, including live cost, runtime utilization, SSH details, mounts, and cluster membership. These attributes were renamed, reshaped, or moved: id, name, gpu_count, gpu_type_id, status, and created_at keep their names. The desired_status, machine_id, and machine_type attributes are gone; the 1.x data source could never populate them, so no configuration depended on them. 2.0.0 adds cloud, data_center_id, started_at, locked, registry, actions, cpu_type_id, cpu_vcpu_count, gpu_vcpu_count, cuda_version, the global_networking fields, mounts.network, runtime (CPU, memory, and per-GPU utilization), ssh.direct and ssh.proxy, and cluster.

runpod_machine and runpod_machines

Both data sources remain available on the GraphQL API as deprecated shims. Each keeps its name, its required inputs, and every attribute name. As in 1.x, data_center_id is always null on runpod_machine, because the underlying query does not select it; use runpod_machines when you need the data center.

runpod_gpu_types

The runpod_gpu_types data source is now read from the v2 catalog API. The list attribute is still gpu_types, and its nested fields were renamed to the catalog’s names: gpu_types[].id keeps its name. The cuda_cores and manufacturer fields are gone, because the v2 catalog does not carry them. 2.0.0 adds gpu_types[].community (availability on Community Cloud) and gpu_types[].pool (the Serverless pool id for runpod_serverless_endpoint.gpu_pools). A new single-item companion, runpod_gpu_type, looks up one entry by id.

runpod_data_centers

The runpod_data_centers data source is now read from the v2 catalog API. The list attribute is still data_centers: data_centers[].id, data_centers[].name, and data_centers[].global_network keep their names. 2.0.0 adds data_centers[].compliance (compliance certifications held) and data_centers[].network_volume_types (storage tiers offered). A new single-item companion, runpod_data_center, looks up one entry by id.

runpod_template

The runpod_template data source keeps its name and required id, and mirrors the resource’s renames. image_name becomes image, container_disk_in_gb becomes disk, is_public becomes public, is_serverless becomes serverless, and container_registry_auth_id becomes registry. docker_start_cmd becomes args, reshaped from a list to a single string. volume_in_gb and volume_mount_path move into mounts.persistent.size and mounts.persistent.path. docker_entrypoint keeps its name and is read from the v2 template. readme, earned, is_runpod, and runtime_in_min are deprecated read-only values from GraphQL. 2.0.0 adds allowed_cuda_versions, start_ssh, and start_jupyter.

runpod_container_registry_auths

The 2.0.0 equivalent is runpod_registries: the data source was renamed, and its list attribute container_registry_auths became registries. The id and name nested fields keep their names. registries[].username is deprecated and always null. REST v2 treats the username as write-only, and no other supported API reports it. The password, created_at, and updated_at fields are gone. They existed only in 1.0.9, which never ran, and the v2 list doesn’t return them.

runpod_ecr_delegations

The 2.0.0 equivalent is runpod_registry_delegations: the data source was renamed along with the resource, and its list attribute ecr_delegations became delegations. The nested id, name, aws_user, aws_region, repository, tag, docker_registry_uri, and created_at fields keep their names. The resource field is gone, because the API does not echo the delegated ARN; read it from your own configuration. 2.0.0 adds delegations[].delegator_user_id, the Runpod user that created the delegation.

runpod_user

The runpod_user data source is kept as a deprecated shim. It now reads the GraphQL myself query, because the REST v1 /user route is gone. Every attribute keeps its name, but only id and email have a source. The others read null.

runpod_endpoint_workers

The runpod_endpoint_workers data source keeps its name and required endpoint_id, with richer per-worker data and a status summary: workers[].id and workers[].status keep their names. The synthetic top-level id, along with workers[].pod_id and workers[].last_busy_ms, are gone, because the v2 worker list does not carry them. 2.0.0 adds per-worker data_center_id, gpu_type_id, gpu_count, image, and is_stale, plus a summary of counts by status and the endpoint’s current endpoint_version.

runpod_endpoint_worker_logs

The runpod_endpoint_worker_logs data source keeps its name and required endpoint_id and worker_id. The API serves logs as a live event stream. A read collects what the stream delivers and ends when the API closes it or the provider’s 60-second timeout elapses. The logs attribute (one string) became lines (a list of line strings); use join to get the old shape. The synthetic id is gone. 2.0.0 adds entries (per-event line, timestamp, and source) and the tail, since, last_event_id, and source arguments to bound the read.

Billing data sources

The three 1.x billing data sources still exist in 2.0.0. They’re deprecated and keep their 1.x names, arguments, and record fields, but they now read the v2 billing routes and map each record back into the 1.x shape, so some records differ from 1.x. See Deprecated shims. New configuration should use the v2-native equivalents below, which report cost components in USD. The record shape changed, so moving to them is a rewrite rather than a rename. In every case the billing_records list became records, billing_records[].amount became records[].amounts.total_amount, and the single time field became a start_time and end_time pair on each record. Each data source also adds a last_n argument and a metadata block. The last_n argument returns the last N buckets and is mutually exclusive with an explicit window. The metadata block describes the resolved window and its totals.
Watch the name on the endpoint billing move. 1.x runpod_billing_endpoint reported spend on your Serverless endpoints, and its 2.0.0 replacement is runpod_serverless_billing. The similarly named runpod_endpoint_billing in 2.0.0 is a different data source that reports spend on Runpod’s own Public Endpoints. Do not map to it by name.

Removed data sources

runpod_endpoint_jobs and runpod_endpoint_job_logs have no 2.0.0 equivalent, because jobs and their logs live on the Serverless runtime API. For worker-level output, use runpod_endpoint_worker_logs, and for Pod output, use the new runpod_pod_logs.

New in 2.0.0

2.0.0 adds capabilities that 1.x had no surface for. Clusters are multi-node groups of identical Pods on one private overlay network, with SLURM, Ray, training, and application topologies. Read them with runpod_cluster, runpod_clusters, and runpod_cluster_pods.
Global volumes are usage-billed storage with no data center. A Pod mounts one through global_volumes wherever it’s placed, and a GPU Serverless endpoint mounts one on every worker through its own global_volumes. Read one with the runpod_global_volume data source.
Account SSH keys manage the account’s registered public keys as a singleton. Every write replaces the whole document, so declare it once per account.
CPU Pods and CPU Serverless endpoints replace the GPU type with a CPU flavor, taking the vCPU count from the flavor’s catalog range. The flavors are in the new runpod_cpu_type and runpod_cpu_types catalog data sources.
CUDA and host-size constraints filter placement with an open-ended floor or an exact set, plus per-GPU RAM and vCPU floors on Pods.
2.0.0 also adds these data sources and settings:
  • Catalog templates: the publicly shared template catalog, read through runpod_catalog_templates.
  • Serverless builds and releases: runpod_endpoint_builds and runpod_endpoint_build report container builds from a Git repository, and runpod_endpoint_releases reports configuration releases with a field-level diff against the previous one.
  • Billing on the v2 routes: runpod_billing (account-wide), runpod_pod_billing, runpod_serverless_billing, runpod_endpoint_billing, runpod_network_volume_billing, and runpod_cluster_billing, all with the same window arguments and per-component totals.
  • List data sources: runpod_pods, runpod_templates, runpod_serverless_endpoints, and runpod_network_volumes read every resource of that kind on the account.
  • Pod logs: runpod_pod_logs, the Pod-level counterpart to worker logs, bounded by tail, since, or last_event_id.
  • Single-item catalog lookups: runpod_gpu_type, runpod_cpu_type, and runpod_data_center, so you no longer filter a whole list to read one entry.
  • FlashBoot tiers: cold-start acceleration is now a three-value setting (OFF, FLASHBOOT, or PRIORITY_FLASHBOOT) rather than a boolean.
  • Declarative Pod run state: runpod_pod.desired_state (RUNNING or EXITED) makes a Pod stopped outside Terraform show up as a plan diff and get started again on the next apply.

Removed in 2.0.0

Some 1.x attributes are gone in 2.0.0. Most of them were declared in the 1.x schema but never sent to the service, so removing them changes no behavior.
  • Spot Pods (type = "SPOT", interruptible, and bid_per_gpu) were retired by the platform. The APIs stopped accepting bids, so migrate these configurations to on-demand Pods.
  • stop_after, terminate_after, port, and volume_key on runpod_pod were schema-only in 1.x and have no v2 counterpart. Use desired_state or runpod_pod_action for a scheduled stop or terminate, declare ports as a list in ports, and note that the v2 API has no volume encryption key.
  • Machine pinning on Pods never worked in 1.x, and the v2 Pod create has no machine parameter. Constrain placement with data_center_ids and the per-GPU RAM and vCPU floors instead.
  • cloud_type on endpoints, and password, created_at, and updated_at on the registry list existed only in 1.0.9, which never ran. They were never in 1.0.8.

Deprecated shims

A shim is a small piece of code inside the provider that keeps a 1.x feature working when REST v2 has no equivalent yet. For a runnable example, see Legacy shims on the Terraform Registry. Everything a 1.0.8 configuration used that REST v2 has no field for still plans in 2.0.0, marked deprecated. Where only GraphQL has the value, the provider reads or writes it there through graphql_url. Where no API has the value anymore, the attribute is kept so the configuration still plans, and it reads null or isn’t applied. Terraform prints a deprecation warning on every plan that touches a shim, and each shim is removed in a later release once REST v2 covers it. 2.0.0 makes no REST v1 calls, so the REST v1 retirement on November 15, 2026 doesn’t affect any shim. The runpod_machine resource, the runpod_machine and runpod_machines data sources, and the runpod_user data source also run on GraphQL. Only id and email are populated on runpod_user. For the three billing data sources, end_time must be an RFC 3339 timestamp, a date, or a datetime without a zone (read as UTC). The window is the 30 days before end_time, or before the current time when it’s unset. When GraphQL fails, an unconfigured shim attribute reads null with a warning and the apply goes through. A shim attribute your configuration sets fails the apply. The billing data sources always fail on a bad read. compute_type on runpod_serverless_endpoint is deprecated for a different reason. It restates what gpu_pools or cpu already says, and it goes away once 1.x configurations have moved, not when an API changes. Don’t build new configuration on any shim.

State migration

2.0.0 ships no state upgraders. Every resource schema is at version 0 in both majors. Terraform does not rewrite a 1.x state entry into the 2.0.0 shape. Wherever the attribute set changed, the old entry cannot be decoded and must be removed and re-imported. terraform state rm and terraform import change state only: running them stops no Pod and deletes no volume. Do the state work after rewriting the configuration and before the first terraform apply.

Before importing a Pod you want to keep

The v2 Pod read does not return eight create-time attributes: template_id, start_ssh, start_jupyter, allowed_cuda_versions, min_cuda_version, min_ram_per_gpu, min_vcpu_count_per_gpu, and data_center_ids. A 2.0.0 Pod configuration can set all eight. After terraform import, each one the configuration sets shows as a diff on the first plan, and all eight force replacement. Applying that plan deletes the Pod permanently, along with everything not on a network volume, and creates a new Pod with a new id. The “after” Pod example in this guide sets start_ssh and start_jupyter, so a Pod migrated with it as written would be replaced.
There are two safe ways through:
  • Leave a running 1.x Pod on 1.x. Do not remove and import it. Keep it in a root module pinned to version = "<= 1.0.8". Don’t use ~> 1.0, which selects 1.0.9. That release can’t serve its own schema or configure most of its resources. Let that provider manage it until the Pod is due to be recreated anyway. Then create its successor under 2.0.0.
  • Adopt it with ignore_changes. If the Pod has to move to 2.0.0 now, add a lifecycle block before the first apply. Name every one of the eight attributes the configuration sets. Listing all eight is harmless if you are unsure which the Pod was created with.
The cost of ignore_changes is that Terraform never enforces those values on this Pod. State keeps them empty, so changing one later plans nothing at all. To apply a new value, take the attribute out of ignore_changes and accept the replacement. On a GPU Pod, also set cloud and gpu_count to the values the Pod already has. Leaving either out makes any other change plan as unknown, and both force replacement. Also, an import reads the Pod’s whole environment into state, so the first apply that sets env removes every key the configuration leaves out, including keys that came from a template. The plan lists those removals. Either way, read the first plan before applying it. It must not replace a Pod you mean to keep, and the # forces replacement marker names the attribute responsible.

Re-import with the same type name

The type name does not change, and the id is the one you already have. The attribute set still changed, though, so remove and import each resource. This applies to runpod_pod, runpod_template, runpod_network_volume, and runpod_machine. For runpod_machine, the attribute names are unchanged, but re-import anyway because the resource is a different implementation.

Re-import with a renamed type

The old address cannot be read once 2.0.0 is in the lock file, because the type no longer exists. terraform state mv does not help either, because the type is part of the address and the schemas differ. Remove the old address, then import the new one against the same id. This applies to runpod_endpoint, which becomes runpod_serverless_endpoint.

Recreate a renamed type that cannot be imported

The credential and delegation types were renamed, and neither can be imported, because the v2 API does not return the values needed to reconstruct them. Remove the old address and let the new resource be created; it gets a new id, so update every registry reference on Pods and endpoints. The 1.x resource stays on the account until you delete it in the console. This applies to runpod_container_registry_auth, which becomes runpod_registry, and runpod_ecr_delegation, which becomes runpod_registry_delegation.

Remove and re-declare

runpod_pod_action holds no Pod state and cannot be imported, so remove the old address and re-declare it.
Re-declaring runpod_pod_action runs the action again on create, so a terminate action you re-declare will terminate the Pod. If you wanted a persistent run state, drop the resource and set runpod_pod.desired_state instead. If you wanted a one-off, add a triggers map so future runs are deliberate.

Remove with nothing to import

The runpod_endpoint_job and runpod_endpoint_worker resource types are gone, so remove them from state:
The account SSH keys singleton, new in 2.0.0, imports by the literal id account.

Final check

After the state work, run terraform plan. Expect:
  • No changes for templates, network volumes, endpoints, and machines.
  • For each imported Pod, no replacement, and at most an in-place update for the env and desired_state that an import leaves empty.
  • A create for each registry credential and delegation.
  • A refresh on the log, worker, and billing data sources.
A planned Pod replacement has one of two causes. One is a create-time attribute the Pod guidance above says to cover. The other is a configuration mismatch against what the API reports, shown by the # forces replacement marker. Fix the configuration rather than applying it.

Next steps

Last modified on October 29, 2026