Uploading
Custom Certificates can be uploaded in the Cloudflare Dashboard or using the Cloudflare API.
Certificate packs
Certificates uploaded to Cloudflare will be automatically grouped together into a Certificate Pack before being deployed to the global edge. A Certificate Pack is a group of certificates that share the same set of hostnames, e.g., example.com
and *.example.com
, but use different signature algorithms. Each pack can include up to three certificates, with one from each of the following signature algorithms: SHA-2/RSA
, SHA-2/ECDSA
, and SHA-1/RSA
.
Certificate requirements
Certificates are parsed and checked for validity before being accepted. Each certificate uploaded must:
- Be encoded in PEM format
- Not be expiring in less than 14 days from time of upload
- Have a subject alternative name (SAN) matching at least one hostname in the zone where it’s being uploaded
- Use a private key greater than or equal to a minimum length (currently 2048 bit for RSA and 225 bit for ECDSA)
- Be publicly trusted by a major browser, unless the
User Defined
bundling method is used
Using the Cloudflare API
The call below will upload a certificate for use with www.example.com. Cloudflare will automatically bundle the certificate with a certificate chain optimized for maximum compatibility with browsers.
Note that if you are using an ECC key generated by OpenSSL, you will need to first remove the -----BEGIN EC PARAMETERS-----...-----END EC PARAMETERS-----
section of the file.
1. Prior to uploading your certificate, you will need to replace line endings with the string “\n” and build the payload
$ cat app_example_com.pem-----BEGIN CERTIFICATE-----MIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E...SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/OOeH8gMJ+FuwtXYEPa4hBf38M5eU5xWG7-----END CERTIFICATE-----
$ MYCERT="$(cat www_example_com.pem|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"$ MYKEY="$(cat www_example_com.key|perl -pe 's/\r?\n/\\n/'|sed -e's/..$//')"
With the certificate and key saved to environment variables (using escaped newlines), we build the payload:
$ request_body=$(< <(cat <<EOF{ "certificate": "$MYCERT", "private_key": "$MYKEY", "bundle_method":"ubiquitous"}EOF))
You can optionally add geographic restrictions that specify where your private key can physically be decrypted:
$ request_body=$(< <(cat <<EOF{ "certificate": "$MYCERT", "private_key": "$MYKEY", "bundle_method":"ubiquitous", "geo_restrictions":{"label":"us"}}'}
You can also enable support for legacy clients which do not include SNI in the TLS handshake.
$ request_body=$(< <(cat <<EOF{ "certificate": "$MYCERT", "private_key": "$MYKEY", "bundle_method":"ubiquitous", "geo_restrictions":{"label":"us"}}', "type":"sni_custom"}
sni_custom
is recommended by Cloudflare. Use legacy_custom
when a specific client requires non-SNI support. The Cloudflare API treats all Custom SSL certificates as Legacy by default.
2. With the payload built, make the API call to upload your certificate and key
$ curl -sX POST https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_certificates \ -H "X-Auth-Email: {email}" -H "X-Auth-Key: {key}" \ -H "Content-Type: application/json" -d "$request_body"