Resolve cURL Error 60 on Local Windows Server (Laragon)
Budget: €30 – €250 EUR
I'm experiencing an SSL issue on a web application hosted on my local Windows machine. The specific error is cURL error 60: SSL certificate problem: unable to get local issuer certificate.
Ideal Skills and Experience:
- Expertise in Windows server administration
- Proficient in SSL certificate management
- Experienced with cURL and troubleshooting related issues
- Familiar with web application hosting on local machines
- Knowledge of network and security protocols.
Environment Specifications
Operating System: Windows 10
Development Environment: Laragon
Web Server: Apache/2.4.54 with OpenSSL/1.1.1q
PHP: Version 8.2.11 with OpenSSL 3.0.8 (February 7, 2023)
Framework: Laravel
Antivirus/Firewall: Norton (disabled during testing)
Issue Description
When making HTTPS requests from Laravel applications running in this Laragon environment, the following error occurs:
CopycURL error 60: SSL certificate problem: unable to get local issuer certificate
This error persists when making HTTP requests to external APIs (such as Mistral, Daxtra, etc.) and when using Composer. The issue remains even when explicitly using verify => false in HTTP request options.
Current Configuration
php.ini contains:
Copycurl.cainfo = "C:\laragon\etc\ssl\cacert.pem"
openssl.cafile = "C:\laragon\etc\ssl\cacert.pem"
openssl.capath = "C:\laragon\etc\ssl"
Environment variables:
CopySSL_CERT_DIR = "C:\laragon\etc\ssl"
SSL_CERT_FILE = "C:\laragon\etc\ssl\cacert.pem"
CURL_CA_BUNDLE = "C:\laragon\etc\ssl\cacert.pem"
Diagnostic Findings
Certificate file exists and is accessible:
The certificate file exists at the specified path
It contains 150 certificates
File size is 233,263 bytes
The file is accessible and readable by PHP
Environment variables are correctly set:
SSL_CERT_FILE, SSL_CERT_DIR, and CURL_CA_BUNDLE are all properly defined
PHP configuration appears correct:
curl.cainfo, openssl.cafile, and openssl.capath are properly set in php.ini
Inconsistent OpenSSL versions:
PHP is using OpenSSL 3.0.8
Apache is using OpenSSL 1.1.1q
This version mismatch may be contributing to the issue
Verbose cURL output:
Copy* CAfile: C:\laragon\etc\ssl\cacert.pem
* CApath: none
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
This indicates cURL finds the certificate file but still can't validate certificates
Windows certificate store:
Windows certificate revocation checking appears to be interfering with the cURL SSL verification process
Solutions Attempted
Certificate file updates:
Updated the cacert.pem file with the latest version from curl.se
Created copies of the certificate in all default OpenSSL locations
Verified the certificate file is properly formatted and accessible
Environment variables:
Set CURL_CA_BUNDLE, SSL_CERT_FILE, and SSL_CERT_DIR environment variables
Confirmed they are correctly configured and readable
PHP configuration:
Verified and updated php.ini settings for curl.cainfo and openssl.cafile
Confirmed PHP is loading these settings correctly
Path formatting tests:
Tested with backslashes, forward slashes, and double backslashes in paths
None of these path formatting differences resolved the issue
Attempted to disable certificate verification:
Tried setting verify => false in Guzzle options
Tried curl_setopt options CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
These solutions work for simple test scripts but not consistently in the Laravel application
Root Cause Analysis
The primary issue appears to be related to how cURL and OpenSSL interact with Windows certificate handling, particularly:
A mismatch between PHP's OpenSSL 3.0.8 and Apache's OpenSSL 1.1.1q
Windows certificate revocation checking interfering with SSL verification
cURL not properly using the specified certificate bundle despite configuration
Help Needed
Need assistance with implementing a system-level solution that does not modify the source code of the Laravel project. The ideal solution would fix the SSL certificate issue at the Windows/Laragon level so that all PHP applications (including Laravel and Composer) can make HTTPS requests without SSL verification errors.
Ideal Skills and Experience:
- Expertise in Windows server administration
- Proficient in SSL certificate management
- Experienced with cURL and troubleshooting related issues
- Familiar with web application hosting on local machines
- Knowledge of network and security protocols.
Environment Specifications
Operating System: Windows 10
Development Environment: Laragon
Web Server: Apache/2.4.54 with OpenSSL/1.1.1q
PHP: Version 8.2.11 with OpenSSL 3.0.8 (February 7, 2023)
Framework: Laravel
Antivirus/Firewall: Norton (disabled during testing)
Issue Description
When making HTTPS requests from Laravel applications running in this Laragon environment, the following error occurs:
CopycURL error 60: SSL certificate problem: unable to get local issuer certificate
This error persists when making HTTP requests to external APIs (such as Mistral, Daxtra, etc.) and when using Composer. The issue remains even when explicitly using verify => false in HTTP request options.
Current Configuration
php.ini contains:
Copycurl.cainfo = "C:\laragon\etc\ssl\cacert.pem"
openssl.cafile = "C:\laragon\etc\ssl\cacert.pem"
openssl.capath = "C:\laragon\etc\ssl"
Environment variables:
CopySSL_CERT_DIR = "C:\laragon\etc\ssl"
SSL_CERT_FILE = "C:\laragon\etc\ssl\cacert.pem"
CURL_CA_BUNDLE = "C:\laragon\etc\ssl\cacert.pem"
Diagnostic Findings
Certificate file exists and is accessible:
The certificate file exists at the specified path
It contains 150 certificates
File size is 233,263 bytes
The file is accessible and readable by PHP
Environment variables are correctly set:
SSL_CERT_FILE, SSL_CERT_DIR, and CURL_CA_BUNDLE are all properly defined
PHP configuration appears correct:
curl.cainfo, openssl.cafile, and openssl.capath are properly set in php.ini
Inconsistent OpenSSL versions:
PHP is using OpenSSL 3.0.8
Apache is using OpenSSL 1.1.1q
This version mismatch may be contributing to the issue
Verbose cURL output:
Copy* CAfile: C:\laragon\etc\ssl\cacert.pem
* CApath: none
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
This indicates cURL finds the certificate file but still can't validate certificates
Windows certificate store:
Windows certificate revocation checking appears to be interfering with the cURL SSL verification process
Solutions Attempted
Certificate file updates:
Updated the cacert.pem file with the latest version from curl.se
Created copies of the certificate in all default OpenSSL locations
Verified the certificate file is properly formatted and accessible
Environment variables:
Set CURL_CA_BUNDLE, SSL_CERT_FILE, and SSL_CERT_DIR environment variables
Confirmed they are correctly configured and readable
PHP configuration:
Verified and updated php.ini settings for curl.cainfo and openssl.cafile
Confirmed PHP is loading these settings correctly
Path formatting tests:
Tested with backslashes, forward slashes, and double backslashes in paths
None of these path formatting differences resolved the issue
Attempted to disable certificate verification:
Tried setting verify => false in Guzzle options
Tried curl_setopt options CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
These solutions work for simple test scripts but not consistently in the Laravel application
Root Cause Analysis
The primary issue appears to be related to how cURL and OpenSSL interact with Windows certificate handling, particularly:
A mismatch between PHP's OpenSSL 3.0.8 and Apache's OpenSSL 1.1.1q
Windows certificate revocation checking interfering with SSL verification
cURL not properly using the specified certificate bundle despite configuration
Help Needed
Need assistance with implementing a system-level solution that does not modify the source code of the Laravel project. The ideal solution would fix the SSL certificate issue at the Windows/Laragon level so that all PHP applications (including Laravel and Composer) can make HTTPS requests without SSL verification errors.