The "unknown certificate issuer" error occurs when Terraform cannot verify the SSL/TLS certificate of a remote endpoint because the certificate was signed by an untrusted or unrecognized Certificate Authority. This commonly happens with self-signed certificates, corporate proxies, or custom registries.
When Terraform connects to remote services (like Terraform Registry, provider endpoints, or backends), it validates the SSL/TLS certificates to ensure secure communication. The "unknown certificate issuer" error means that the certificate presented by the server was signed by a Certificate Authority (CA) that your system does not trust. This can occur in several scenarios: - The server uses a self-signed certificate (signed by itself, not a trusted CA) - A corporate proxy or firewall performs SSL inspection and re-signs certificates - The certificate is signed by a private/internal CA not installed on your system - Your system's certificate store is out of date or corrupted Unlike expired certificate errors, this issue is specifically about certificate validation, not time-based validity.
First, identify which server certificate cannot be verified. The error message usually includes the hostname or endpoint. For example:
Error: Failed to download module: unknown certificate issuer
Module source: registry.terraform.io/hashicorp/aws/latestOr for a backend:
Error: backend initialization required
Error: TLS verification failed: unknown certificate issuerNote the hostname or URL that is failing.
Use openssl to fetch the certificate chain from the server:
# Replace example.com with your server hostname
openssl s_client -connect example.com:443 -showcerts < /dev/null 2>/dev/null | openssl x509 -outform PEM > ca-cert.pem
# For private registries on non-standard ports
openssl s_client -connect registry.internal:8443 -showcerts < /dev/null 2>/dev/null | openssl x509 -outform PEM > ca-cert.pemThis creates a ca-cert.pem file with the server's certificate.
On Linux, copy the certificate to the system CA directory and update the trust database:
# Debian/Ubuntu
sudo cp ca-cert.pem /usr/local/share/ca-certificates/ca-cert.crt
sudo update-ca-certificates
# RHEL/CentOS/Fedora
sudo cp ca-cert.pem /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
# Alpine
sudo cp ca-cert.pem /usr/local/share/ca-certificates/
sudo update-ca-certificatesVerify with:
ls /etc/ssl/certs/ | grep -i ca-certOn macOS, use the Keychain to add the certificate:
# Add to system keychain
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca-cert.pem
# Or add to user keychain (no sudo needed)
security add-trusted-cert ca-cert.pemVerify:
security find-certificate -c ca-cert /Library/Keychains/System.keychainOn Windows, import the certificate using PowerShell or Certificate Manager:
# PowerShell (run as Administrator)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 "ca-cert.pem"
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store "Root", "LocalMachine"
$store.Open("ReadWrite")
$store.Add($cert)
$store.Close()Or use Certificate Manager:
1. Press Win+R, type certmgr.msc
2. Navigate to "Trusted Root Certification Authorities"
3. Right-click, select "Import..."
4. Browse and select ca-cert.pem
If adding to system store is not possible, set the environment variable to use a custom certificate:
# Linux/macOS
export SSL_CERT_FILE=/path/to/ca-cert.pem
terraform init
# Windows PowerShell
$env:SSL_CERT_FILE = "C:\path\to\ca-cert.pem"
terraform init
# Make persistent (Linux/macOS) - add to ~/.bashrc or ~/.zshrc
echo 'export SSL_CERT_FILE=/path/to/ca-cert.pem' >> ~/.bashrc
source ~/.bashrcThis tells Terraform and other Go-based tools to trust the specified certificate file.
If behind a corporate proxy that re-signs certificates:
1. Obtain your organization's root CA certificate
2. Use one of the methods above to add it to your trust store
3. For Go applications (Terraform is built in Go), you can also:
export SSL_CERT_FILE=/path/to/corporate-ca-bundle.pemThe root CA bundle should contain all certificates in the chain, from leaf to root.
Alternatively, create a combined certificate file:
# Concatenate all CA certs
cat corporate-root-ca.pem > ca-bundle.pem
cat intermediate-ca.pem >> ca-bundle.pem
export SSL_CERT_FILE=/path/to/ca-bundle.pemVerify that certificate verification now works:
# Test with curl
curl -v https://your-registry.example.com
# Test with openssl
openssl s_client -connect your-registry.example.com:443
# Then retry Terraform
terraform initBoth should complete without certificate verification errors.
Security Note: Only add certificates to your trust store if you fully trust their origin. Adding untrusted certificates bypasses security protections.
Docker/Kubernetes: In containerized environments, ensure the CA certificate is copied into the image:
COPY ca-cert.pem /usr/local/share/ca-certificates/
RUN update-ca-certificatesTerraform Cloud/Enterprise: If using private Terraform Enterprise installations with self-signed certificates, Terraform Cloud agents automatically handle this. For self-managed agents, add the CA certificate to the host system.
GitHub Actions / CI/CD: In CI/CD pipelines, add the certificate during the setup step.
Provider-specific options: Some providers support insecure mode (not recommended for production):
provider "http" {
insecure = true # Disables certificate verification
}Debugging: Enable verbose logging to see certificate chain details:
TF_LOG=DEBUG terraform initWSL2 / Virtual Machines: If running in WSL2 or VirtualBox, ensure the VM system clock is synchronized. Certificate validation fails if the system time is significantly off.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform