June 24, 2025·6 min read·engineeringterraformregistriesstateobservability

OpenTofu 1.10 distributes modules and providers through OCI registries

OpenTofu 1.10 gives modules and provider mirrors distinct OCI artifact formats. Native S3 locking and experimental tracing address separate operational dependencies.

An organization can already operate a registry for container artifacts while needing a separate distribution arrangement for infrastructure modules and provider binaries. OpenTofu 1.10.0, released on June 24, allows that existing registry protocol to carry both kinds of infrastructure dependency. The module and provider integrations use different artifact structures because source packages and platform-specific executables have different installation requirements.

I value the reusable abstractions in Terraform and the licensing direction of OpenTofu. This release interests me because it extends reuse to distribution infrastructure. A registry can supply an established administrative boundary for publishing dependencies, provided the configuration still makes clear which package is being installed and how its identity is verified.

A module package is a source archive

The module-package documentation defines an OCI image manifest with the artifact type application/vnd.opentofu.modulepkg. It requires exactly one ZIP layer, identified by the media type archive/zip. The archive root represents the module package root. This is a source distribution contract expressed through OCI metadata, without requiring the module to become a runnable container image.

An existing package can be referenced in configuration with the new source scheme. This example selects an illustrative release tag in a repository that must already contain a correctly constructed module artifact.

module "network" {
  source = "oci://registry.example.com/modules/network?tag=v1.0.0"
}

The documentation also permits digest selection. Without an explicit tag or digest, OpenTofu resolves latest. That default is convenient for a demonstration, but it communicates a different dependency selection policy from an explicit artifact identifier. A configuration review needs to read the source address as a dependency reference, not simply as a location containing some interchangeable source files.

The packaging contract gives publishers a precise responsibility. A repository containing an arbitrary ZIP blob does not establish that it is a valid OpenTofu module package. Manifest metadata identifies the intended artifact, and the archive layout determines which files become the module root after installation. Those details are part of the publication interface.

The OCI image manifest specification explicitly supports artifacts through its artifactType field. That is why using the distribution protocol does not require inventing container execution semantics for a module. A client can recognize a particular artifact contract while using the registry's existing storage and retrieval model. For the publisher, the useful consequence is reuse of a protocol with typed content. For the consumer, the essential question remains whether the selected artifact matches the package format OpenTofu expects. Registry compatibility and module-package validity are separate properties, even when the same upload establishes both in a working example.

A provider mirror preserves the provider's identity

The provider-mirror documentation describes a secondary distribution location for an existing provider. CLI configuration maps the provider source address to an OCI repository. The provider's identity in a module remains its provider source address, while the mirror supplies the package bytes through another service.

The example below belongs in CLI configuration, rather than a module's infrastructure configuration. Its template maps provider namespaces and types into repository paths.

provider_installation {
  oci_mirror {
    repository_template = "registry.example.com/providers/${namespace}/${type}"
    include             = ["registry.opentofu.org/*/*"]
  }
}

Provider distribution needs a platform dimension that module source packages do not. A version tag refers to an OCI image index, which identifies the manifests for supported operating systems and architectures. OpenTofu selects the platform manifest and retrieves its ZIP package. The index and platform manifests have OpenTofu-specific artifact types, so the client can distinguish their purposes.

This is a useful separation for module authors. Infrastructure configuration can continue declaring a provider dependency while an execution environment chooses how to obtain it. The mirror arrangement should therefore be reviewed alongside the environment that executes initialization. It is not fully described by the module source alone.

Installation rules determine whether a mirror is exclusive

The released CLI configuration reference explains that matching installation methods participate in provider selection together. Configuring a mirror alongside a matching direct method does not inherently make the mirror exclusive. An installation policy that requires the mirror must remove the relevant direct path or exclude those providers from it.

That behavior matters for restricted environments. A configuration intended to use an internal registry should express whether public retrieval remains acceptable. Otherwise, a successful installation may prove that one of several methods worked without proving which administrative policy supplied the package. An explicit rule makes the dependency path assessable by someone reading the CLI configuration.

The same reference describes the provider cache's relationship to dependency-lock checksums. Cached packages normally need to match a recorded checksum. The cache helps reuse installed material, while the lock file records the dependency choice and verification information. Moving distribution to OCI does not make those responsibilities unnecessary or make a cached executable trustworthy merely because it is already present.

As a provider author, I find preserving that distinction more useful than renaming dependencies to match each distribution service. A provider can retain its identity while the organization changes where installation obtains it. This keeps packaging policy separate from the resource names and requirements that modules expose to their callers.

Registry credentials use a common lookup mechanism

The OCI credentials documentation defines a shared mechanism for the OCI integrations. By default, OpenTofu searches Docker-style credential configuration locations used by existing registry tools. More specific repository-prefix matches take precedence over broader registry matches. Explicit OpenTofu credential configuration can refine or replace that discovery.

That makes the execution environment relevant to authentication as well as installation routing. A developer shell and an automation worker may discover different credentials for the same repository. A successful local initialization does not establish that the worker has the same registry authority. The useful property is a documented lookup process that can be configured deliberately for each environment.

Credential helpers also require explicit configuration. OpenTofu reads credentials through those helpers, while another tool first populates the underlying store. This avoids treating a helper as an unspecified platform convention and makes the dependency on that executable visible. Registry access consequently remains a separate concern from the permissions a provider later uses to manage infrastructure.

Native S3 locking removes a separate coordination service

The S3 backend documentation describes native locking through conditional writes with If-None-Match. Setting use_lockfile = true enables it. This lets the storage service coordinate exclusive access through a lock object instead of requiring a DynamoDB table for that purpose.

For a new state location with a suitable bucket and permissions, the configuration can declare that choice directly. Existing clients sharing a state need a coordinated transition between locking mechanisms.

terraform {
  backend "s3" {
    bucket       = "example-infrastructure-state"
    key          = "network/terraform.tfstate"
    region       = "us-east-1"
    use_lockfile = true
  }
}

The documentation explains why switching mechanisms is more than replacing a setting in one checkout. An old client using DynamoDB and a new client using only S3 locks would not necessarily contend on the same lock. Configuring both during migration allows updated clients to participate in both mechanisms while older configurations are still in use. The shared state requires a shared exclusion protocol throughout that transition.

Tracing starts with initialization

The release changelog describes experimental, partial OpenTelemetry tracing for tofu init, exported to a collector endpoint controlled by the operator. The scope matters. It provides an initial way to examine work during initialization, not a claim of complete tracing for every plan and apply operation.

Initialization is an appropriate place to investigate the new distribution behavior. Registry requests and provider installation can contribute work before any infrastructure change begins. Trace information can help locate where initialization spends time without requiring that all such delays be inferred from a final command duration. The collector and exporter configuration determine where those observations go.

The changelog also makes the global provider cache safe for concurrent OpenTofu processes on filesystems supporting the required locking. That is another distinct lock from the backend lock. Cache coordination protects shared installation material, while backend coordination protects shared infrastructure state. Both are relevant to multiple automation jobs, but they protect different objects and cannot substitute for each other.

The release announcement places these changes alongside support for deprecating module inputs and outputs. Together they make more of a module's operational environment explicit. Distribution has a package format and an installation policy, while callers can receive warnings about an evolving module interface. This gives maintainers concrete mechanisms for publishing reusable infrastructure components and communicating how those components should be consumed.