coollabsio/coolify · error · RuntimeException

Failed to generate private key: {openssl_error_string()}

Error message

Failed to generate private key: {openssl_error_string()}

What it means

SslHelper::generateSslCertificate() calls openssl_pkey_new() requesting an EC key on curve secp521r1; the function returned false, meaning PHP's OpenSSL layer could not create the key. Typical causes: the OpenSSL extension is missing or misbuilt, no readable openssl.cnf (required even for key generation in many builds), or the OpenSSL build lacks EC/secp521r1 support. The appended openssl_error_string() output is the real diagnosis.

Source

Thrown at app/Helpers/SslHelper.php:42

        ?string $caCert = null,
        ?string $caKey = null,
        bool $isCaCertificate = false,
        ?string $configurationDir = null,
        ?string $mountPath = null,
        bool $isPemKeyFileRequired = false,
    ): SslCertificate {
        $organizationName = self::DEFAULT_ORGANIZATION_NAME;
        $countryName = self::DEFAULT_COUNTRY_NAME;
        $stateName = self::DEFAULT_STATE_NAME;

        try {
            $privateKey = openssl_pkey_new([
                'private_key_type' => OPENSSL_KEYTYPE_EC,
                'curve_name' => 'secp521r1',
            ]);

            if ($privateKey === false) {
                throw new \RuntimeException('Failed to generate private key: '.openssl_error_string());
            }

            if (! openssl_pkey_export($privateKey, $privateKeyStr)) {
                throw new \RuntimeException('Failed to export private key: '.openssl_error_string());
            }

            if (! is_null($serverId) && ! $isCaCertificate) {
                $server = Server::find($serverId);
                if ($server) {
                    $ip = $server->getIp;
                    if ($ip) {
                        $type = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)
                            ? 'IP'
                            : 'DNS';
                        $subjectAlternativeNames = array_unique(
                            array_merge($subjectAlternativeNames, ["$type:$ip"])
                        );
                    }

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Verify the extension: run php -m | grep openssl and check php -i | grep openssl.cnf shows a real, readable file.
  2. In Docker images, install openssl and ensure the default openssl.cnf is present (e.g. apk add openssl / apt-get install openssl) or set OPENSSL_CONF to a valid config.
  3. Read the appended openssl_error_string() — 'error:0E06D06C:...NCONF_get_string' points to config-file problems, 'unsupported curve' points to a restricted OpenSSL build.
  4. On FIPS/hardened hosts, enable an EC-capable OpenSSL or relax policy for secp521r1.

Example fix

// before: certificate generation throws on hosts without usable OpenSSL config
$cert = SslHelper::generateSslCertificate($commonName);

// after: probe OpenSSL availability once and fail with a clear message
if (! extension_loaded('openssl')) {
    throw new RuntimeException('OpenSSL extension is required for certificate generation.');
}
if (openssl_pkey_new(['private_key_type' => OPENSSL_KEYTYPE_EC, 'curve_name' => 'secp521r1']) === false) {
    throw new RuntimeException('OpenSSL cannot create secp521r1 keys: '.openssl_error_string());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Environment pre-flight before any certificate generation
if (! extension_loaded('openssl')) {
    throw new RuntimeException('The openssl extension is not loaded.');
}
$probe = @openssl_pkey_new(['private_key_type' => OPENSSL_KEYTYPE_EC, 'curve_name' => 'secp521r1']);
if ($probe === false) {
    throw new RuntimeException('OpenSSL EC/secp521r1 unavailable: '.openssl_error_string());
}
openssl_free_key($probe);

Try / catch

try {
    $cert = SslHelper::generateSslCertificate($commonName, $sans);
} catch (\RuntimeException $e) {
    if (str_starts_with($e->getMessage(), 'Failed to generate private key')) {
        // environment problem: log openssl_error_string, do not retry on this host
        report('OpenSSL key generation failed: '.$e->getMessage());
        return null;
    }
    throw $e;
}

Prevention

When it happens

Trigger: Generating any SSL certificate (app/service certificates, CA certificates) on a host where PHP has no OpenSSL extension, an invalid OPENSSL_CONF path, or a restricted OpenSSL (e.g., FIPS-mode or stripped distro/container builds).

Common situations: Slim Docker images (alpine/distroless) that ship no openssl.cnf; php:*-cli variants compiled --without-openssl; OPENSSL_CONF env var pointing to a deleted file; hardened/FIPS systems disabling non-approved curves.

Related errors


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/f6033d050f3de67b. Report an issue: GitHub.