I recently had to run a Terraform build in an air gapped network (no internet access) and these are the steps I took to locally host the Terraform provider I needed (vsphere). This was tested on Terraform v1.0.4 on CentOS 7.9 servers.
Local file mirror
Start by download the latest version of the desired plugin from https://releases.hashicorp.com/.
In this example I wanted the vsphere provider (terraform-provider-vsphere_2.0.2_linux_amd64.zip) so I grabbed it from https://releases.hashicorp.com/terraform-provider-vsphere/
Unzip the executable to the following directory on your Terraform machine: ~/.terraform.d/plugins/registry.terraform.io/hashicorp/vsphere/2.0.2/linux_amd64
For example: mkdir -p ~/.terraform.d/plugins/registry.terraform.io/hashicorp/vsphere/2.0.2/linux_amd64
unzip terraform-provider-vsphere_2.0.2_linux_amd64.zip -d ~/.terraform.d/plugins/registry.terraform.io/hashicorp/vsphere/2.0.2/linux_amd64
Keep in mind, your file path will be different depending on which provider you use, so please adjust accordingly!
Further information available here: https://www.terraform.io/docs/cli/config/config-file.html#implied-local-mirror-directories
Network mirror
This method is a bit tricky if you are using a self-signed certificate because Terraform enforces strict TLS checking. There is no command line option that I could find that allows you to turn off TLS enforcement.
To start, use an internet connected machine and run the  terraform providers mirror command as described here (https://www.terraform.io/docs/cli/commands/providers/mirror.html). Then dump the resultant files to the local apache/nginx webserver in your offline environment.
Web Server Configuration
I had to mess around quite a bit with the self signed certificate creation on my apache server in order for it to work.
To generate my self signed cert, I executed:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout self.key -out self.crt -config /etc/ssl/openssl.cnf
I had to make sure my basicConstraints setting in my SSL.cnf file was set to basicConstraints = CA:TRUE. In case it helps anyone, here’s an example of the openssl.cnf file I used:
[req]
default_bits = 2048
prompt = no
distinguished_name = dn
req_extensions = req_ext
x509_extensions = v3_req
[dn]
C = US
ST = MD
L = Annapolis
O = MyOrg
CN = yum01.mydomain.net
[req_ext]
subjectAltName = @alt_names
basicConstraints = CA:TRUE
[v3_req]
subjectAltName = @alt_names
basicConstraints = CA:TRUE
[alt_names]
DNS.1 = yum01.mydomain.net
IP.1 = 192.168.1.20
Then copy the cert and key to the /etc/pki/tls locations referenced by your /etc/httpd/conf.d/ssl.conf file (again, using apache as the example here).
For example:
SSLCertificateFile /etc/pki/tls/certs/self.crt
SSLCertificateKeyFile /etc/pki/tls/private/self.keyTerraform CLI configuration
Make sure to add your web server’s self signed certificate to your Terraform servers trust store. This stackoverflow thread shows you how to do that (https://stackoverflow.com/questions/22509271/import-self-signed-certificate-in-redhat) on CentOS/Red Hat with the following steps:
- Copy the CA cert to /etc/pki/ca-trust/source/anchors/
- update-ca-trust extract
Create a .terraformrc file to the HOME directory of your Terraform machine, if it doesn’t already exist, with the following inside:
provider_installation {
  network_mirror {
    url = "https://fileserver.yourdomain.com/terraform/"
  }
}
In my case, the top level directory /terraform/ contained the registry.terraform.io folder.
That should be it! Try it out by going to your terraform directory and running terraform init.