1---
2layout: "docs"
3page_title: "Provider Network Mirror Protocol"
4sidebar_current: "docs-internals-provider-network-mirror-protocol"
5description: |-
6  The provider network mirror protocol is implemented by a server intending
7  to provide a mirror or read-through caching proxy for Terraform providers,
8  as an alternative distribution source from the provider's origin provider
9  registry.
10---
11
12# Provider Network Mirror Protocol
13
14-> Provider network mirrors are supported only in Terraform CLI v0.13.2 and later. Prior versions do not support this protocol.
15
16The provider network mirror protocol is an optional protocol which you can
17implement to provide an alternative installation source for Terraform providers,
18regardless of their origin registries.
19
20Terraform uses network mirrors only if you activate them explicitly in
21[the CLI configuration's `provider_installation` block](/docs/cli/config/config-file.html#provider-installation).
22When enabled, a network mirror can serve providers belonging to any registry
23hostname, which can allow an organization to serve all of the Terraform
24providers they intend to use from an internal server, rather than from each
25provider's origin registry.
26
27This is _not_ the protocol that should be implemented by a host intending to
28serve as an origin registry for Terraform Providers. To provide an origin
29registry (whose hostname would then be included in the source addresses of the
30providers it hosts), implement
31[the provider registry protocol](./provider-registry-protocol.html)
32instead.
33
34## Provider Addresses
35
36Each Terraform provider has an associated address which uniquely identifies it
37within Terraform. A provider address has the syntax `hostname/namespace/type`,
38which is described in more detail in
39[the Provider Requirements documentation](/docs/language/providers/requirements.html).
40
41By default, the `hostname` portion of a provider address serves both as part
42of its unique identifier _and_ as the location of the registry to retrieve it
43from. However, when you configure Terraform to install providers from a network
44mirror, the `hostname` serves _only_ as an identifier and no longer as
45an installation source. A provider mirror can therefore serve providers
46belonging to a variety of different provider registry hostnames, including
47providers from the public Terraform Registry at `registry.terraform.io`, from a
48single server.
49
50In the relative URL patterns later in this document, the placeholder `:hostname`
51refers to the hostname from the address of the provider being requested, not
52the hostname where the provider network mirror is deployed.
53
54## Protocol Base URL
55
56Most Terraform-native services use
57[the remote service discovery protocol](./remote-service-discovery.html) so
58that the physical location of the endpoints can potentially be separated from
59the hostname used in identifiers. The Provider Network Mirror protocol does
60_not_ use the service discovery indirection, because a network mirror location
61is only a physical location and is never used as part of the identifier of a
62dependency in a Terraform configuration.
63
64Instead, the provider installation section of the CLI configuration accepts
65a base URL directly. The given URL must use the scheme `https:`, and should
66end with a trailing slash so that the relative URLs of the individual operation
67endpoints will be resolved beneath it.
68
69```hcl
70provider_installation {
71  network_mirror {
72    url = "https://terraform.example.com/providers/"
73  }
74}
75```
76
77Terraform uses the base URL only as a stem to resolve the operation endpoint
78URLs against, and so it will never access the base URL directly. You can
79therefore, if desired, publish human-readable usage documentation for your
80network mirror at that URL.
81
82The following sections describe the various operations that a provider
83network mirror server must implement to be compatible with Terraform CLI's
84provider installer. The indicated URLs are all relative to the given base URL,
85as described above.
86
87The URLs are shown with the convention that a path portion with a colon `:`
88prefix is a placeholder for a dynamically-selected value, while all other
89path portions are literal. For example, in `:hostname/:namespace/:type/index.json`,
90the first three path portions are placeholders while the third is literally
91the string "index.json".
92
93The example requests in the following sections will assume the example mirror
94base URL from the above CLI configuration example.
95
96### Authentication
97
98If the CLI configuration includes
99[credentials](/docs/cli/config/config-file.html#credentials) for the hostname
100given in the network mirror base URL, Terraform will include those credentials
101in its requests for operations described below.
102
103If the given URL uses a non-standard port number (other than 443) then the
104credentials must be associated with a hostname that includes the port number,
105such as `terraform.example.com:8443`.
106
107Terraform does _not_ send credentials when retrieving the archives whose
108URLs are given in the "List Available Installation Packages" response below.
109If a particular mirror considers the distribution packages themselves to be
110sensitive then it must use cryptographically-secure, user-specific, and
111time-limited URLs in the metadata response. Strategies for doing so are out
112of scope of this protocol documentation.
113
114## List Available Versions
115
116This operation determines which versions are currently available for a
117particular provider.
118
119| Method | Path                                    | Produces           |
120|--------|-----------------------------------------|--------------------|
121| `GET`  | `:hostname/:namespace/:type/index.json` | `application/json` |
122
123### Parameters
124
125* `hostname` (required): the hostname portion of the address of the requested
126  provider.
127* `namespace` (required): the namespace portion of the address of the requested
128  provider.
129* `type` (required): the type portion of the address of the requested provider.
130
131### Sample Request
132
133```
134curl 'https://terraform.example.com/providers/registry.terraform.io/hashicorp/random/index.json'
135```
136
137### Sample Response
138
139```json
140{
141  "versions": {
142    "2.0.0": {},
143    "2.0.1": {}
144  }
145}
146```
147
148### Response Properties
149
150A successful result is a JSON object containing a single property `versions`,
151which must be a JSON object.
152
153Each of the property names of the `versions` object represents an available
154version number. The property values must be objects, but no properties are
155currently defined for those objects. Future versions of this protocol may
156define optional per-version properties for Terraform to use as installation
157hints, so implementations of the current version should leave those objects
158empty.
159
160Return `404 Not Found` to signal that the mirror does not have a provider
161with the given address.
162
163## List Available Installation Packages
164
165This operation returns download URLs and associated metadata for the
166distribution packages for a particular version of a provider.
167
168Each distribution package is associated with a particular operating system
169and architecture. A network mirror may host only a subset of the available
170packages for a provider version, if the users of the mirror are known to all
171use only a subset of the target platforms that Terraform supports.
172
173Terraform CLI uses this operation after it has selected the newest available
174version matching the configured version constraints, in order to find a zip
175archive containing the plugin itself.
176
177| Method | Path                                       | Produces           |
178|--------|--------------------------------------------|--------------------|
179| `GET`  | `:hostname/:namespace/:type/:version.json` | `application/json` |
180
181### Parameters
182
183* `hostname` (required): the hostname portion of the address of the requested
184  provider.
185* `namespace` (required): the namespace portion of the address of the requested
186  provider.
187* `type` (required): the type portion of the address of the requested provider.
188* `version` (required): the version selected to download. This will exactly
189  match one of the version strings returned from a previous call to
190  [List Available Versions](#list-available-versions).
191
192### Sample Request
193
194```
195curl 'https://terraform.example.com/providers/registry.terraform.io/hashicorp/random/2.0.0.json'
196```
197
198### Sample Response
199
200```json
201{
202  "archives": {
203    "darwin_amd64": {
204      "url": "terraform-provider-random_2.0.0_darwin_amd64.zip",
205      "hashes": [
206        "h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs="
207      ]
208    },
209    "linux_amd64": {
210      "url": "terraform-provider-random_2.0.0_linux_amd64.zip",
211      "hashes": [
212        "h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ="
213      ]
214    }
215  }
216}
217```
218
219### Response Properties
220
221A successful result is a JSON object with a property called `archives`, which
222must be a JSON object.
223
224Each of the property names of the `archives` object is a target platform
225identifier, which consists of an operating system and architecture concatenated
226with an underscore (`_`).
227
228Each property value in the `archives` object is itself a nested object with
229the following properties:
230
231* `url` (required): a string specifying the URL from which Terraform should
232  download the `.zip` archive containing the requested provider plugin version.
233
234    Terraform resolves the URL relative to the URL from which the current
235    JSON document was returned, so the examples above containing only a
236    filename would cause Terraform to construct a URL like:
237
238    ```
239    https://terraform.example.com/providers/registry.terraform.io/hashicorp/random/terraform-provider-random_2.0.0_darwin_amd64.zip
240    ```
241
242* `hashes` (optional): a JSON array of strings containing one or more hash
243  values for the indicated archive. These hashes use Terraform's provider
244  package hashing algorithm. At present, the easiest way to populate these
245  is to construct a mirror's JSON indices using the `terraform providers mirror`
246  command, as described in a later section, which will include the calculated
247  hashes of each provider.
248
249    If the response includes at least one hash, Terraform will select the hash
250    whose algorithm it considers to be strongest and verify that the downloaded
251    package matches that hash. If the response does not include a `hashes`
252    property then Terraform will install the indicated archive with no
253    verification.
254
255Terraform CLI will only attempt to download versions that it has previously
256seen in response to [List Available Versions](#list-available-versions).
257
258## Provider Mirror as a Static Website
259
260The provider mirror protocol is designed so that it can potentially be implemented
261by placing files on typical static website hosting services. When using this
262strategy, implement the JSON index responses described above as `.json` files
263in the appropriate nested subdirectories, and ensure that your system is
264configured to serve `.json` files with the `application/json` media type.
265
266As a convenience, Terraform CLI includes
267[the `terraform providers mirror` subcommand](https://www.terraform.io/docs/cli/commands/providers/mirror.html),
268which will analyze the current configuration for the providers it requires,
269download the packages for those providers from their origin registries, and
270place them into a local directory suitable for use as a mirror.
271
272The `terraform providers mirror` subcommand also generates `index.json` and
273version-specific `.json` files that can, when placed in a static website hosting
274system, produce responses compatible with the provider mirror protocol.
275
276If you wish to create a mirror with providers for a number of different
277Terraform configurations, run `terraform providers mirror` in each configuration
278in turn while providing the same output directory each time. Terraform will
279then merge together all of the requirements into a single set of JSON indices.
280