Skip to content
SSL
Visit SSL on GitHub
Set theme to dark (⇧+D)

Uploading

Custom Certificates can be uploaded in the Cloudflare Dashboard or using the Cloudflare API.


Certificate requirements

Certificates are parsed and checked for validity before being accepted. Each certificate uploaded must:

  • Be encoded in PEM format
  • Not have a key file password
  • 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.

Step 1 — Replace line endings with the string “\n” and build the payload

$ cat app_example_com.pem
-----BEGIN CERTIFICATE-----
MIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBN
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E
...
SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/O
OeH8gMJ+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.

Step 2 — 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"