---
title: Deploy custom certificate · Cloudflare Zero Trust docs
description: Configure WARP to use a custom root certificate instead of the Cloudflare certificate.
lastUpdated: 2025-04-18T17:28:28.000Z
source_url:
  html: https://9d8cd229.preview.developers.cloudflare.com/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/index.md
  md: https://9d8cd229.preview.developers.cloudflare.com/cloudflare-one/connections/connect-devices/user-side-certificates/custom-certificate/
---

Note

Only available on Enterprise plans.

Enterprise customers who do not wish to install a [Cloudflare certificate](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment/) have the option to upload their own root certificate to Cloudflare. This feature is sometimes referred to as Bring Your Own Public Key Infrastructure (BYOPKI). Gateway will use your uploaded certificate to encrypt all sessions between the end user and Gateway, enabling all HTTPS inspection features that previously required a Cloudflare certificate. You can upload multiple certificates to your account, but only one can be active at any given time. You also need to upload a private key to intercept domains with JIT certificates and to enable the [block page](https://developers.cloudflare.com/cloudflare-one/policies/gateway/block-page/).

You can upload up to five custom root certificates. If your organization requires more than five certificates, contact your account team.

Warning

Custom certificates are limited to use between your users and the Gateway proxy. Gateway connects to origin servers using publicly trusted certificates, similar to how a browser validates secure websites.

If your users need to connect to self-signed origin servers, create an HTTP Allow policy for the origin server with the [untrusted certificate action](https://developers.cloudflare.com/cloudflare-one/policies/gateway/http-policies/#untrusted-certificates) set to *Pass through*.

## Generate a custom root CA

Before you generate a custom root CA, make sure you have [OpenSSL](https://www.openssl.org/) installed.

1. Open a terminal.

2. Create a directory for the root CA and change into it.

   ```sh
   mkdir -p /root/customca
   cd /root/customca
   ```

3. Generate a private key for the root CA.

   ```sh
   openssl genrsa -out <CUSTOM-ROOT-PRIVATE-KEY>.pem 2048
   ```

4. Generate a self-signed root certificate.

   ```sh
   openssl req -x509 -sha256 -new -nodes -key <CUSTOM-ROOT-PRIVATE-KEY>.pem -days 365 -out <CUSTOM-ROOT-CERT>.pem
   ```

When preparing your certificate and private key for upload, be sure to remove any unwanted characters, such as mismatching subdomains in the certificate's common name. To review the private key, run the following command:

```sh
openssl rsa -in <CUSTOM-ROOT-PRIVATE-KEY>.pem -text
```

To review the certificate, run the following command:

```sh
openssl x509 -in <CUSTOM-ROOT-CERT>.pem -text
```

## Deploy a custom root certificate

* Dashboard

  1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Settings** > **Resources**.

  2. In **Certificates**, select **Manage**.

  3. Select **Upload certificate**.

  4. Enter the private key and SSL certificate you generated or select **Paste certificate from file** to upload them from a file.

  5. Select **Generate certificate**.

     You can now [use the generated custom root certificate](#use-a-custom-root-certificate) for inspection.

* API

  1. Use the [Upload mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls_certificates/methods/create/) to upload the certificate and private key to Cloudflare. The certificate must be a root CA, formatted as a single string with `\n` replacing the line breaks.

     ```sh
     curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/mtls_certificates" \
     --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
     --header "Content-Type: application/json" \
     --data '{
       "name": "example_ca_cert",
       "certificates": "-----BEGIN CERTIFICATE-----\nXXXXX\n-----END CERTIFICATE-----",
       "private_key": "-----BEGIN PRIVATE KEY-----\nXXXXX\n-----END PRIVATE KEY-----",
       "ca": true
     }'
     ```

     The response will return a UUID for the certificate. For example:

     ```json
     {
       "success": true,
       "errors": [],
       "messages": [],
       "result": {
         "id": "2458ce5a-0c35-4c7f-82c7-8e9487d3ff60",
         "name": "example_ca_cert",
         "issuer": "O=Example Inc.,L=California,ST=San Francisco,C=US",
         "signature": "SHA256WithRSA",
         ...
       }
     }
     ```

  2. Set the certificate as available for use in inspection with the [Activate a Zero Trust certificate endpoint](https://developers.cloudflare.com/api/resources/zero_trust/subresources/gateway/subresources/certificates/methods/activate/). This will deploy the certificate across the Cloudflare global network.

     ```sh
     curl --request POST \
     "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/certificates/$CERTIFICATE_ID/activate" \
     --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
     ```

     The response will return the certificate and a `pending_deployment` binding status. For example:

     ```json
     {
       "errors": [],
       "messages": [],
       "success": true,
       "result": {
         "in_use": false,
         "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
         "certificate": "-----BEGIN CERTIFICATE-----\\n ... \\n-----END CERTIFICATE-----\\n",
         "issuer_org": "Example Inc.",
         "issuer_raw": "O=Example Inc.,L=California,ST=San Francisco,C=US",
         "fingerprint": "E9:19:49:AA:DD:D8:1E:C1:20:2A:D8:22:BF:A5:F8:FC:1A:F7:10:9F:C7:5B:69:AB:0:31:91:8B:61:B4:BF:1C",
         "binding_status": "pending_deployment",
         "type": "custom",
         "updated_at": "2014-01-01T05:20:00.12345Z",
         "uploaded_on": "2014-01-01T05:20:00.12345Z",
         "created_at": "2014-01-01T05:20:00.12345Z",
         "expires_on": "2014-01-01T05:20:00.12345Z"
       }
     }
     ```

  3. Use the [Get Zero Trust certificate details endpoint](https://developers.cloudflare.com/api/resources/zero_trust/subresources/gateway/subresources/certificates/methods/get/) to verify the certificate's binding status is set to `available`.

     ```sh
     curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/certificates/$CERTIFICATE_ID \
     --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
     ```

     ```json
     {
       "errors": [],
       "messages": [],
       "success": true,
       "result": {
         "in_use": false,
         "id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
         "certificate": "-----BEGIN CERTIFICATE-----\\n ... \\n-----END CERTIFICATE-----\\n",
         "issuer_org": "Example Inc.",
         "issuer_raw": "O=Example Inc.,L=California,ST=San Francisco,C=US",
         "fingerprint": "E9:19:49:AA:DD:D8:1E:C1:20:2A:D8:22:BF:A5:F8:FC:1A:F7:10:9F:C7:5B:69:AB:0:31:91:8B:61:B4:BF:1C",
         "binding_status": "available",
         "type": "custom",
         "updated_at": "2014-01-01T05:20:00.12345Z",
         "uploaded_on": "2014-01-01T05:20:00.12345Z",
         "created_at": "2014-01-01T05:20:00.12345Z",
         "expires_on": "2014-01-01T05:20:00.12345Z"
       }
     }
     ```

  4. (Optional) Verify the certificate is installed on your user's devices either [with WARP](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/user-side-certificates/automated-deployment/) or [manually](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/user-side-certificates/manual-deployment/).

  5. Use the [Patch Zero Trust account configuration endpoint](https://developers.cloudflare.com/api/resources/zero_trust/subresources/gateway/subresources/configurations/methods/edit/) to turn on the certificate for use in inspection. For example:

     ```sh
     curl --request PATCH \
     "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/gateway/configuration" \
     --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
     --header "Content-Type: application/json" \
     --data '{
       "settings": {
         "certificate": {
           "id": "$CERTIFICATE_ID",
          "in_use": true
         }
       }
     }'
     ```

  Once `in-use` is set to `true`, Gateway will sign your traffic using the custom root certificate and private key. If you turn off or deactivate the custom certificate, Gateway will revert to the next available Cloudflare certificate generated for your Zero Trust account.

Private key visibility

When you upload a private key to Zero Trust, Cloudflare encrypts the key and stores it at rest. Only your delegated apps have the necessary decryption keys to decrypt the private key. You will not be able to retrieve the private key after upload.

## Use a custom root certificate

To use a custom root certificate you generated and uploaded to Cloudflare, refer to [Activate a root certificate](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/user-side-certificates/#activate-a-root-certificate).

## Troubleshoot HTTP errors

If Gateway returns an **HTTP Response Code: 526** after deploying a custom certificate, you can [troubleshoot errors with our FAQ](https://developers.cloudflare.com/cloudflare-one/faq/troubleshooting/#i-see-error-526-when-browsing-to-a-website).
