# Best provider.tf (versions.tf) placement

**URL:** <https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581>\
**Category:** Terraform\
**Created:** [July 27, 2023, 5:02am UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581 "2023-07-27T05:02:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![zondi](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/zondi/32/27970_2.png) [@zondi](https://discuss.hashicorp.com/u/zondi)\
**Post date:** [July 27, 2023, 5:02am UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581/1 "2023-07-27T05:02:56Z")

</div>

Hi.

Newbish question.

This is what one of the projects (prod) looks like (_sorry, it is too long but hope it can help make the point_):

```auto
├── $projects
│ ├── 10800000000
│ │ ├── 10800000000
│ │ │ └── Project
│ │ │ └── LoggingLogSink
│ │ │ └── req.tf
│ │ └── Service
│ │ ├── admin-googleapis-com.tf
│ │ ├── analyticshub-googleapis-com.tf
│ │ ├── analyticsreporting-googleapis-com.tf
│ │ ├── appengine-googleapis-com.tf
│ │ ├── $others
│ ├── 7400000000
│ │ └── Project
│ │ ├── $projects-name.tf
│ │ └── terraform.tfstate
│ ├── $projects-name
│ │ ├── BigQueryDataset
│ │ │ ├── US
│ │ │ │ ├── $something.tf
│ │ │ │ └── terraform.tfstate
│ │ │ └── us-west1
│ │ │ ├── $server-name-ogs.tf
│ │ │ └── terraform.tfstate
│ │ └── ComputeDisk
│ │ ├── us-central1-f
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ └── $server-name-vm.tf
│ │ └── us-west1-b
│ │ ├── $disk2-name.tf
│ │ ├── $server-name.tf
│ │ ├── terraform.tfstate
│ │ ├── terraform.tfstate.backup
│ │          
│ ├── modules.tf
│ └── projects
│ ├── 10800000000
│ │ └── MonitoringAlertPolicy
│ └── $projects-name
│ ├── BigQueryTable
│ │ ├── apache-access.tf
│ │ ├── apache-error.tf
│ │ ├── syslog.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeAddress
│ │ ├── provider.tf
│ │ ├── us-central1
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ └── $server-name.tf
│ │ ├── us-west1
│ │ │ ├── $server-name2.tf
│ │ │ ├── $server-name.tf
│ │ │ ├── terraform.tfstate
│ │ │ └── terraform.tfstate.backup
│ │ └── us-west2
│ │ ├── $a-$server-name-ipv4.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeFirewall
│ │ ├── allow-ingress-from-iap.tf
│ │ ├── allow-ssh-ingress-from-iap-vpc-1-us-west1.tf
│ │ ├── allow-ssh-ingress-from-iap-vpc-2-us-west1.tf
│ │ ├── allow-ssh-ingress-from-iap-vpc-3.tf
│ │ ├── netdata.tf
│ │ ├── provider.tf
│ │ ├── railgun.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeHealthCheck
│ │ └── global
│ │ ├── httpd-80.tf
│ │ ├── https.tf
│ │ ├── provider.tf
│ │ ├── terraform.tfstate
│ │ ├── terraform.tfstate.backup
│ │ └── $ketch.tf
│ ├── ComputeImage
│ │ ├── centos-$os-name7.tf
│ │ ├── $os-name-7-$name3-name.tf
│ │ ├── $os-name-$name3-name-v2.tf
│ │ ├── provider.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeInstance
│ │ ├── us-central1-f
│ │ │ ├── OLD-terraform.tfstate.txt
│ │ │ ├── OLD-$server-name-vm.tf.txt
│ │ │ ├── provider.tf
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ └── $server-name-vm.tf
│ │ ├── us-west1-b
│ │ │ ├── $d.server
│ │ │ │ ├── $d.server.tf
│ │ │ │ └── provider.tf
│ │ │ ├── $server-name.tf
│ │ │ ├── provider.tf
│ │ │ └── terraform.tfstate
│ │ └── us-west2-a
│ ├── ComputeNetwork
│ │ ├── $name3-name-custom-network.tf
│ │ ├── $name3-name-custom-vpc-0.tf
│ │ ├── $name3-name-custom-vpc-1-us-west1.tf
│ │ ├── $name3-name-custom-vpc-2-us-west1.tf
│ │ ├── $name3-name-custom-vpc-3.tf
│ │ ├── $name3-name-custom-vpc-4.tf
│ │ ├── $name3-name-custom-vpc-5.tf
│ │ ├── provider.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeResourcePolicy
│ │ ├── us-central1
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ └── $server-name-schedule-1.tf
│ │ └── us-west1
│ │ ├── $server-name-auto-snapshots.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeRoute
│ │ ├── peering-route-1.tf
│ │ ├── peering-route-4.tf
│ │ ├── peering-route-7.tf
│ │ └── peering-route-bc.tf
│ ├── ComputeSnapshot
│ │ ├── $server-name-us-west1-b-20230326015001.tf
│ │ ├── $server-name-us-west1-b-20230402015009.tf
│ │ ├── terraform.tfstate
│ │ └── $server-name-vm-us-central1-f-20230402001335.tf
│ ├── ComputeSubnetwork
│ │ ├── us-west1
│ │ │ ├── $zeezee0-subnet-a.tf
│ │ │ ├── $zeezee1-subnet-b-us-west1.tf
│ │ │ ├── $zeezee1-subnet-c-us-west1.tf
│ │ │ ├── oregon-subnet-us-west1-a.tf
│ │ │ └── us-west1-$name3-name-custom.tf
│ ├── DNSManagedZone
│ │ ├── $name3-nameopensesame-zone.tf
│ │ ├── $toptop-dns-zone.tf
│ │ ├── $project-name.tf
│ │ ├── nomnom-com.tf
│ │ ├── $tonton-com.tf
│ │ ├── terraform.tfstate
│ │ ├── terraform.tfstate.backup
│ │ └── $tintin.tf
│ ├── IAMCustomRole
│ │ ├── bigquerycustomcreaterole.tf
│ │ └── computefirebasefulladminrole.tf
│ ├── IAMServiceAccount
│ │ ├── agent-service-account.tf
│ │ ├── aws-connector-ocs.tf
│ │ ├── compute-admin.tf
│ │ ├── firebase-adminsdk-a3ryh.tf
│ │ ├── firebase-adminsdk-ouogr.tf
│ │ ├── firebase-adminsdk.tf
│ │ ├── github-action-123456789.tf
│ │ ├── hashi-vault-dev.tf
│ │ ├── $projects-name.tf
│ │ ├── $tinton.tf
│ │ ├── $disk2-name.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── PubSubTopic
│ │ ├── cloud-builds.tf
│ │ ├── gcr.tf
│ │ ├── security-command-center.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ └── StorageBucket
│ └── US
│ ├── $owner-name.tf
│ ├── cloud-$name3-nameopensesame-com.tf
│ ├── $name3-nameopensesame-com.tf
│ ├── dataprep4047.tf
│ ├── $projects-name-appspot-com.tf
│ ├── $toptop.tf
│ ├── $disk2-name-s3.tf
│ ├── $projects-name-appspot-com.tf
│ ├── terraform.tfstate
│ ├── terraform.tfstate.backup
│ ├── $tintin.tf
│ └── www-$name3-nameopensesame-com.tf
├── $project-name
│ ├── 7400000000
│ │ └── Project
│ │ ├── $project-name.tf
│ │ └── terraform.tfstate
│ ├── 64000000000
│ │ ├── 64000000000
│ │ │ └── Project
│ │ │ └── LoggingLogSink
│ │ │ └── areq.tf
│ │ └── Service
│ │ ├── accessapproval-googleapis-com.tf
│ │ ├── appengine-googleapis-com.tf
│ │ ├── artifactregistry-googleapis-com.tf
│ │ ├── autoscaling-googleapis-com.tf
│ ├── $project-name
│ │ └── ComputeDisk
│ │ └── us-central1-c
│ │ └── cserver-disk.tf
│ ├── $project-name_import.sh
│ ├── $project-name-modules.tf
│ ├── projects
│ │ └── $project-name
│ │ ├── ComputeAddress
│ │ │ └── us-central1
│ │ │ ├── terraform.tfstate
│ │ │ ├── cserver-external-ipv4.tf
│ │ │ └── cserver-internal-ipv4.tf
│ │ ├── ComputeFirewall
│ │ │ ├── default-allow-icmp.tf
│ │ │ ├── default-allow-internal.tf
│ │ │ ├── default-allow-rdp.tf
│ │ │ ├── default-allow-ssh.tf
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ ├── cservervpc-allow-custom.tf
│ │ │ ├── cservervpc-allow-https.tf
│ │ │ ├── cservervpc-allow-http.tf
│ │ │ ├── cservervpc-allow-icmp.tf
│ │ │ └── cservervpc-allow-ssh.tf
│ │ ├── ComputeImage
│ │ │ └── cserver-image.tf
│ │ ├── ComputeInstance
│ │ │ └── us-central1-a
│ │ │ ├── outputs.tf
│ │ │ ├── provider.tf
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ ├── variables.tf
│ │ │ └── cserver-vm.tf
│ │ ├── ComputeNetwork
│ │ │ ├── default.tf
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ ├── versions.tf.txt
│ │ │ └── cserver-vpc.tf
│ │ ├── ComputeSubnetwork
│ │ │ ├── asia-east1
│ │ │ │ ├── $project-name-subnet-taiwan.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-east2
│ │ │ │ ├── $project-name-subnet-hongkong.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-northeast1
│ │ │ │ ├── $project-name-subnet-tokyo.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-northeast2
│ │ │ │ ├── $project-name-subnet-osaka.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-northeast3
│ │ │ │ ├── $project-name-subnet-seoul.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-south1
│ │ │ │ ├── $project-name-subnet-mumbai.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-south2
│ │ │ │ ├── $project-name-subnet-delhi.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-southeast1
│ │ │ │ ├── $project-name-subnet-singapore.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── asia-southeast2
│ │ │ │ ├── $project-name-subnet-jakarta.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── australia-southeast1
│ │ │ │ ├── $project-name-subnet-sydney.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── australia-southeast2
│ │ │ │ ├── $project-name-subnet-melbourne.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-central2
│ │ │ │ ├── $project-name-subnet-warsaw.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-north1
│ │ │ │ ├── $project-name-subnet-finland.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-west1
│ │ │ │ ├── $project-name-subnet-belgium.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-west2
│ │ │ │ ├── $project-name-subnet-london.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-west3
│ │ │ │ ├── $project-name-subnet-frankfurt.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-west4
│ │ │ │ ├── $project-name-subnet-netherlands.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── europe-west6
│ │ │ │ ├── $project-name-subnet-zurich.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── northamerica-northeast1
│ │ │ │ ├── $project-name-subnet-montreal.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── northamerica-northeast2
│ │ │ │ ├── $project-name-subnet-toronto.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── southamerica-east1
│ │ │ │ ├── $project-name-subnet-saopaulo.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── southamerica-west1
│ │ │ │ ├── $project-name-subnet-chile.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-central1
│ │ │ │ ├── $project-name-subnet-iowa.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-east1
│ │ │ │ ├── $project-name-subnet-southcarolina.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-east4
│ │ │ │ ├── $project-name-subnet-nvirginia.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-south1
│ │ │ │ ├── $project-name-subnet-dallas.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-west1
│ │ │ │ ├── $project-name-subnet-oregon.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-west2
│ │ │ │ ├── $project-name-subnet-losangeles.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ ├── us-west3
│ │ │ │ ├── $project-name-subnet-saltlake.tf
│ │ │ │ ├── provider.tf.txt
│ │ │ │ └── terraform.tfstate
│ │ │ └── us-west4
│ │ │ ├── $project-name-subnet-lasvegas.tf
│ │ │ ├── provider.tf.txt
│ │ │ └── terraform.tfstate
│ │ ├── IAMServiceAccount
│ │ │ ├── backend.tf
│ │ │ ├── $project-name.tf
│ │ │ ├── terraform.tfstate
│ │ │ └── terraform.tfstate.backup
│ │ ├── PubSubTopic
│ │ │ ├── backend.tf
│ │ │ ├── $project-name-gcp-pubsub-topic.tf
│ │ │ ├── terraform.tfstate
│ │ │ └── terraform.tfstate.backup
│ │ └── StorageBucket
│ │ ├── US
│ │ │ ├── $owner-name-tf-state.tf
│ │ │ ├── backend.tf
│ │ │ ├── terraform.tfstate
│ │ │ ├── terraform.tfstate.backup
│ │ │ └── us-artifacts-$project-name-appspot-com.tf
│ │ └── US-WEST2
│ │ ├── backend.tf
│ │ ├── $project-name-appspot-com.tf
│ │ ├── staging-$project-name-appspot-com.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ └── versions.tf
├── $project-name
│ ├── 8000001234
│ │ ├── 8000001234
│ │ │ └── Project
│ │ │ └── LoggingLogSink
│ │ │ └── areq.tf
│ │ └── Service
│ │ ├── accessapproval-googleapis-com.tf
│ │ ├── autoscaling-googleapis-com.tf
│ │ ├── bigquery-googleapis-com.tf
│ │ ├── bigquerymigration-googleapis-com.tf
│ │ ├── bigquerystorage-googleapis-com.tf
│ │ ├── cloudapis-googleapis-com.tf
│ │ ├── storage-googleapis-com.tf
│ │ ├── terraform.tfstate
│ │ ├── terraform.tfstate.backup
│ │ └── vpcaccess-googleapis-com.tf
│ ├── 8000000000
│ │ └── Project
│ │ ├── $project-name.tf
│ │ ├── provider.tf
│ │ └── terraform.tfstate
│ ├── $project-name
│ │ └── ComputeDisk
│ │ └── us-west2-a
│ │ ├── heyheys-1.tf
│ │ ├── heyheys-5.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── $project-name_import.sh
│ ├── $project-name-modules.tf
│ └── projects
│ ├── 8000001234
│ │ └── MonitoringAlertPolicy
│ └── $project-name
│ ├── ComputeAddress
│ │ └── us-west2
│ │ ├── heyheys1-external-ipv4.tf
│ │ ├── heyheys1-internal-ipv4.tf
│ │ ├── heyheys5-external-ipv4.tf
│ │ ├── heyheys5-internal-ipv4.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeFirewall
│ │ ├── $project-name-$name3-name-dualstackvpc-allow-custom-ipv6.tf
│ │ ├── $project-name-$name3-name-dualstackvpc-allow-custom.tf
│ │ ├── $project-name-$name3-name-dualstackvpc-allow-https.tf
│ │ ├── $project-name-$name3-name-dualstackvpc-allow-http.tf
│ │ ├── $project-name-$name3-name-dualstackvpc-allow-icmp.tf
│ │ ├── $project-name-$name3-name-dualstackvpc-allow-ssh.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeImage
│ │ ├── $owner-name-$name3-namedns-v1.tf
│ │ ├── $owner-name-$name3-namedns-v2.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeInstance
│ │ └── us-west2-a
│ │ ├── heyheys-1.tf
│ │ ├── heyheys-5.tf
│ │ ├── provider.tf
│ │ ├── terraform.tfstate
│ │ └── terraform.tfstate.backup
│ ├── ComputeNetwork
│ │ ├── $project-name-$name3-name-dualstackvpc.tf
│ │ ├── provider.tf
│ │ └── terraform.tfstate
│ ├── ComputeSubnetwork
│ │ ├── europe-west2
│ │ │ ├── dualstack-subnet-london.tf
│ │ │ ├── provider.tf
│ │ │ └── terraform.tfstate
│ │ ├── us-central1
│ │ │ ├── dualstack-subnet-iowa.tf
│ │ │ ├── provider.tf
│ │ │ └── terraform.tfstate
│ │ ├── us-east4
│ │ │ ├── dualstack-subnet-nvirginia.tf
│ │ │ ├── provider.tf
│ │ │ └── terraform.tfstate
│ │ ├── us-west1
│ │ │ ├── dualstack-subnet-oregon.tf
│ │ │ ├── provider.tf
│ │ │ └── terraform.tfstate
│ │ └── us-west2
│ │ ├── dualstack-subnet-losangeles.tf
│ │ ├── provider.tf
│ │ └── terraform.tfstate
│ └── IAMServiceAccount

```

**Issue** : As you can see, I have too many provider.tf (aka versions.tf).  
The thing is that each of these often runs a different TF or $provider version.  
I use the latest versions for dev before moving to prod.

**Goal** : Have a single provider.tf (aka versions.tf) for each project or provider and able to run “`terraform $command`” from any folder.

Please, can you advise me on this?

Thanks

---

<div class="post-metadata">

**Author:** ![maxb](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/maxb/32/26655_2.png) [@maxb](https://discuss.hashicorp.com/u/maxb)\
**Post date:** [July 27, 2023, 5:17am UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581/2 "2023-07-27T05:17:07Z")

</div>

> [@zondi](#):
>
> This is what one of the projects (prod) looks like (_sorry, it is too long but hope it can help make the point_):

This does not explain your setup, because it does not reveal which directories are intended to be used as a root module (have terraform run directly on them), and which exist to be included via `module` blocks.

> [@zondi](#):
>
> **Issue** : As you can see, I have too many provider.tf (aka versions.tf).

You can put any Terraform syntax in .tf files of any name. Terraform doesn’t care. You just telling us a couple of file names leaves too much doubt about what those files contain, to answer your question.

> [@zondi](#):
>
> able to run “`terraform $command`” from any folder.

You cannot do this. Terraform **requires** you to always run Terraform from the folder containing the root module you want it to operate on.

---

<div class="post-metadata">

**Author:** ![zondi](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/zondi/32/27970_2.png) [@zondi](https://discuss.hashicorp.com/u/zondi)\
**Post date:** [July 27, 2023, 5:55am UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581/3 "2023-07-27T05:55:25Z")

</div>

Hi, [maxb](https://discuss.hashicorp.com/u/maxb).

1. 

> This does not explain your setup, because it does not reveal which directories are intended to be used as a root module

I understand. Kinda assumed that each project’s root ( **$projects-name** ) is clear.

That is … each **$projects-name** represents a specific project.

There are many of these but I truncated most of the output.

1. 

> You can put any Terraform syntax in .tf files of any name.  
> I’m aware of that.  
> I shared the tree structure as a way of conveying what it looks like.

2. 

> Terraform **requires** you to always run Terraform from the folder containing the root module you want it to operate on.

I’m also aware of that.

I don’t use one root module (`.tf` file) for every project but make changes (_as needed_) per service to reduce the blast radius.

I was hoping that somehow I can have a single provider/version.tf without needing to have them per each $service\_dir or at $root/$main/$whatchamacallit.tf.

Hope this makes some sense.

---

<div class="post-metadata">

**Author:** ![maxb](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/maxb/32/26655_2.png) [@maxb](https://discuss.hashicorp.com/u/maxb)\
**Post date:** [July 27, 2023, 6:11am UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581/4 "2023-07-27T06:11:40Z")

</div>

> [@zondi](#):
>
> I understand. Kinda assumed that each project’s root ( **$projects-name** ) is clear.
> 
> That is … each **$projects-name** represents a specific project.

Except, you have `terraform.tfstate` files in various other places in your tree, disagreeing with this.

> [@zondi](#):
>
> You can put any Terraform syntax in .tf files of any name.  
> I’m aware of that.

You’re aware of that but you still haven’t explained whether you’re talking about `provider "name" {}` blocks or `terraform { required_providers {} }` blocks, both, or other stuff.

> [@zondi](#):
>
> I was hoping that somehow I can have a single provider/version.tf without needing to have them per each $service\_dir or at $root/$main/$whatchamacallit.tf.

You can’t. Terraform does not “look outside” the configuration you are running it on for additional configuration to merge in.

---

<div class="post-metadata">

**Author:** ![apparentlymart](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/apparentlymart/32/702_2.png) [@apparentlymart](https://discuss.hashicorp.com/u/apparentlymart)\
**Post date:** [July 27, 2023, 10:29pm UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581/5 "2023-07-27T22:29:24Z")

</div>

As @maxb noted, the answer here depends on what you are intending to place in each file, but for the sake of discussion let’s assume a relatively common convention:

- `versions.tf` contains a `terraform` block that contains a `required_providers` block that specifies the providers that the module uses and the earliest version of each provider the module is known to be compatible with.

- `providers.tf` contains one or more `provider` blocks that actually instantiate the providers, specifying the configuration to use for each.

If you are intending to follow that convention, then every one of your modules would have a `versions.tf` file, and each one should describe only what that one module needs. For example, if one of your modules uses a provider feature that is relatively new then it would probably specify a different minimum version than another module that uses provider features that have been available for a long time.

You should have `providers.tf` only in modules that you intend to use as _root_ modules. The others should inherit or be passed configurations from their callers.

Some exceptions to these guidelines:

- If you have a module that you know has been broken by a later major version of a provider and you aren’t yet ready to upgrade it, you would typically specify an upper limit on the version constraint in `required_providers` for that particular module, so Terraform won’t try to select a newer version that’s incompatible.
- Some legacy modules include `provider` blocks even though they aren’t root modules. I would not recommend writing any new modules like that, but it is technically still allowed – with various caveats – for backward compatibility.

When you run `terraform init` in a root module you will get one more file generated automatically: `.terraform.lock.hcl`. This file tracks Terraform’s decisions about which version of each provider to use to satisfy all of the modules’ version constraints, and so you should also add this to your version control to ensure that later provider releases with breaking changes can’t break your setup. Terraform will select a new version only if you explicitly ask it to by running `terraform init -upgrade`.

---

<div class="post-metadata">

**Author:** ![zondi](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/zondi/32/27970_2.png) [@zondi](https://discuss.hashicorp.com/u/zondi)\
**Post date:** [July 28, 2023, 1:02am UTC](https://discuss.hashicorp.com/t/best-provider-tf-versions-tf-placement/56581/7 "2023-07-28T01:02:57Z")

</div>

Thank you so much [apparentlymart](https://discuss.hashicorp.com/u/apparentlymart) for the detailed guide and Maxb for caring enough to respond.

Honestly, I sometimes wish TF would behave like Ansible where you can define configurations in home/working dir, /etc, or as an env variable and then call it from anywhere.

Anyway, your explanation is absolutely a great starting point in dealing with a multi-prod/cross-platform environment.

Thank you.
