> ## Documentation Index
> Fetch the complete documentation index at: https://gcore-doc-1256a.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure secrets for HTTPS load balancer

export const MethodSection = ({children}) => children ?? null;

export const MethodSwitch = ({children}) => {
  const tabs = React.Children.toArray(children).filter(c => c && c.props && c.props.id);
  const firstId = tabs.length > 0 ? tabs[0].props.id : "";
  const [active, setActive] = React.useState(firstId);
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem("gcore_docs_method");
      if (saved && tabs.find(t => t.props.id === saved)) {
        setActive(saved);
      }
    } catch (_) {}
  }, []);
  React.useEffect(() => {
    try {
      document.querySelectorAll("h2[id], h3[id]").forEach(heading => {
        const visible = heading.offsetParent !== null;
        document.querySelectorAll(`a[href="#${heading.id}"]`).forEach(link => {
          if (link.closest("h1,h2,h3,h4,h5,h6")) return;
          const li = link.closest("li");
          if (li) li.style.display = visible ? "" : "none";
        });
      });
    } catch (_) {}
  }, [active]);
  const handleClick = id => {
    setActive(id);
    try {
      localStorage.setItem("gcore_docs_method", id);
    } catch (_) {}
  };
  return <div>
      <div className="not-prose flex gap-0 border-b border-zinc-200 dark:border-zinc-800 mb-8 mt-2" role="tablist">
        {tabs.map(tab => {
    const isActive = active === tab.props.id;
    return <button key={tab.props.id} role="tab" aria-selected={isActive} onClick={() => handleClick(tab.props.id)} className={["px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors cursor-pointer", isActive ? "border-primary text-primary" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"].join(" ")}>
              {tab.props.label}
            </button>;
  })}
      </div>

      {tabs.map(tab => <div key={tab.props.id} style={{
    display: active === tab.props.id ? "" : "none"
  }}>
          {tab.props.children}
        </div>)}
    </div>;
};

<MethodSwitch>
  <MethodSection id="portal" label="Customer Portal">
    Secrets Manager is a dedicated tab where you can manage SSL/TLS secrets required to create Load Balancers with HTTPS listeners. Depending on your setup, you can either upload a PKCS12 file or add certificate details manually.

    ## Upload a PKCS12 file

    If you already have a PKCS12 file containing your SSL/TLS certificate, certificate chain, and private key, you can quickly upload it to the Secrets Manager.

    To upload a secret as a PKCS12 file:

    1. In the Gcore Customer Portal, navigate to Cloud.

    2. Open the **Secrets Manager** page.

    3. Click **Create Secret**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/Ftf8UsbUnSYma37M/images/docs/cloud/secrets-manager/upload-a-pkcs12-file/secrets-manager-page.png?fit=max&auto=format&n=Ftf8UsbUnSYma37M&q=85&s=f82dc17e583ad12499be8cceec96dbf0" alt="Upload a PKCS12 file" width="3256" height="2164" data-path="images/docs/cloud/secrets-manager/upload-a-pkcs12-file/secrets-manager-page.png" />
    </Frame>

    4. Enable **Upload as PKCS12 file**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/Ftf8UsbUnSYma37M/images/docs/cloud/secrets-manager/upload-a-pkcs12-file/upload-as-pkcs12-file.png?fit=max&auto=format&n=Ftf8UsbUnSYma37M&q=85&s=2b63f6dd810645387ba15938514247ad" alt="Enable Upload as PKCS12 file" width="535" height="577" data-path="images/docs/cloud/secrets-manager/upload-a-pkcs12-file/upload-as-pkcs12-file.png" />
    </Frame>

    6. Enter a name for your secret and choose your file.

    7. Click **Save**.

    ## Add certificates directly

    If you don't have a PKCS12 file or prefer to add the certificate details individually, you can enter them directly in the Secrets Manager.

    To add a secret manually:

    1. In the Gcore Customer Portal, navigate to Cloud.

    2. Open the **Secrets Manager** page.

    3. Click **Create Secret**.

    <Frame>
      <img src="https://mintcdn.com/gcore-doc-1256a/Ftf8UsbUnSYma37M/images/docs/cloud/secrets-manager/upload-a-pkcs12-file/add-certificates-directly.png?fit=max&auto=format&n=Ftf8UsbUnSYma37M&q=85&s=90cb92a7a8174dc721b46f63ed1584ac" alt="Add certificates directly" width="537" height="841" data-path="images/docs/cloud/secrets-manager/upload-a-pkcs12-file/add-certificates-directly.png" />
    </Frame>

    4. In the form that opens, fill in the following fields:

       * Enter a name for your secret.
       * Paste the content of your private key file.
       * Paste the content of your main SSL/TLS certificate file.
       * If required, paste the content of the certificate chain file. This should include root and intermediate certificates in the correct order.
    5. Click **Save**.

    ## Create a PKCS12 file

    PKCS12 (Public-Key Cryptography Standards) is a binary format for storing SSL/TLS certificate, certificate chain, and private key in one encrypted file.

    Basically, you "pack" the main SSL/TLS certificate, the certificate chain, and the private key into the PKCS12 file to transfer them easily. Each element is essential for establishing an HTTPS connection:

    * The main certificate is a digital signature of the site, which confirms that the resource actually belongs to you and not to criminals who impersonate you.
    * The certificate chain is information about the CAs (certificate authorities) that participated in the issuance of your certificate and confirm its authenticity.
    * The private key is a unique set of letters and numbers (key), using which the cryptographic algorithm will encrypt all data exchanged between the resource and a user.

    After receiving the PKCS12 file, our system will be able to open an HTTPS connection. You only need to put the files associated with the certificate in base64 encoded PKCS12 file and upload it to the Secrets Manager.

    ### 1. Prepare certificate files

    You need the SSL/TLS certificate for the domain, the chain of certificates, and the private key. The domain must be configured with a DNS A record with the virtual IP address of the Load Balancer (the IP is specified in the Load Balancers tab). If you are using our DNS zone, you can create an A record according to the [instructions](/dns/dns-records/manage-dns-records-advanced-interface-mode-with-balancing). Your domain will send requests to the IP of the balancer and it will distribute them among the machines.

    CA does not always send a client a chain of certificates along with the main certificate — sometimes it only sends the main one, because often it is enough for browsers to confirm the domain name. In this case, you can get the certificate chain yourself:

    1. Download the root and intermediate certificates from the site of the CA that issued you the certificate.
    2. Create the file in any text editor.
    3. Inside the created file, place the contents of the certificates in the following order: root certificate, then intermediate certificates in order, the certificate for the domain in the end. Like this:

    * Content of the root certificate (for example, CARoot.crt)
    * Content of the intermediate certificate no. 1 (for example, Intermediate1.crt)
    * Content of the intermediate certificate no. 2 (for example, Intermediate2.crt)
    * Content of the certificate for the domain (for example, domain.crt)

    ### 2. Merge certificate files into PKCS12

    Now you have all the files needed. There are several ways to merge them into PKCS12 format. Below we describe a common case — creating PKCS12 from PEM files.

    1\. Install OpenSSL. This is a library containing tools for working with SSL/TLS protocols. You can find installation links and instructions for working with OpenSSL on its [official website](https://openssl.org). 2. Check if your certificate files are in PEM format. Such files must have the extension .pem, .crt, .cer or .key, begin with the line `----- BEGIN CERTIFICATE -----` and end with the line `----- END CERTIFICATE -----`. To see the beginning and the end of a file, open it in a text editor. 3. If some files are not in PEM, convert them using OpenSSL. Enter the command in OpenSSL, replacing the text in square brackets with your names:

    *For a .crt, .cer or .der file*

    ```sh theme={null}
    openssl x509 - inform der - in [name of your file, including extension] - out [name for the future generated PEM file].pem
    ```

    If your file is named "example.der" and you want to name the new PEM file "PEMcertificate", then the command would be: openssl x509 -inform der -in example.der -out PEMcertificate.pem

    *For a .p7b or .p7c file*

    ```sh theme={null}
    openssl pkcs7 -print_certs -in [name of your file, including extension] -out [name for the future generated PEM file].cer
    ```

    If your file is named "example.pb7" and you want to name the new PEM file "PEMcertificate", then the command would be:

    ```sh theme={null}
    openssl pkcs7 -print_certs -in example.pb7 -out PEMcertificate.cer
    ```

    4\. Place the main certificate, key, and intermediate certificate chain (three PEM files in total) in the current directory.

    5\. To merge files into PKCS12, open OpenSSL and enter the command:

    ```sh theme={null}
    openssl pkcs12 -export -inkey [name of the file with the private key, including the extension] -in [name of the file with the certificate, including the extension] -certfile [name of the file with the certificate chain, including the extension] -passout pass: -out [name for the future created file].p12
    ```

    If your files are server.crt (main certificate), server.key (private key) and ca-chain.crt (certificate chain), and you want to name the new PKCS 12 file "server", then the command would be:

    ```sh theme={null}
    openssl pkcs12 -export -inkey server.key -in server.crt -certfile ca-chain.crt -passout pass: -out server.p12
    ```

    As a result, you will merge the key, certificate, and intermediate certificate chain into one PKCS12 file.

    ### 3. Base64 encode

    Encode the contents of PKCS12 file to base64. This can be done by entering the command in the console:

    *For Windows OS*

    ```sh theme={null}
    certutil.exe -encode [full path to PKCS12 file] [new file name].b64
    ```

    If the path to your file is "C:\Users\Myname\server.p12" and you want to name the new file "code64", then the command will be: certutil.exe -encode C:\Users\Myname\server.p12 code64.b64

    A new base64 encoded file will be created. Open it in a text editor and delete the first and the last lines: `----- BEGIN CERTIFICATE -----` and `----- END CERTIFICATE -----`. They are generated automatically and you don't need them. The rest of the text will be the content of the Secret.

    *For Mac OS*

    ```sh theme={null}
    openssl base64 -in [full path to PKCS12 file] -out [new file name].txt
    ```

    If the path to your file is "Users/admin/Downloads/server.p12" and you want to name the new file "code64", then the command will be: openssl base64 -in Users/admin/Downloads/server.p12 -out code64.txt

    A new .txt file will be created with the base64 encoded contents of the PKCS12 file. This is the content of the Secret.

    *For Linux (must be executed in the directory of PKCS12 file)*

    ```sh theme={null}
    base64 [PKCS12 file name] > [new file name]
    ```

    If your file is named "server.p12" and you want to name the new file "code64" then the command will be: base64 server.p12 > code64

    A new code64 file with the contents of the base64 encoded PKCS12 file will be created. This is the content of the Secret. The file can be opened using the command: nano code64.

    ## How to create a load balancer with an HTTPS listener

    <Info>
      **Info**

      You cannot delete a secret that is currently used by a Load Balancer's listener. To remove a secret, first delete the associated listener, then remove the secret. If needed, recreate the listener afterward.
    </Info>

    For detailed instructions on configuring a Load Balancer with an HTTPS listener, including adding TLS certificates, refer to the documentation on [adding TLS certificates to a Load Balancer](/cloud/networking/load-balancers/add-certificates-to-load-balancer).
  </MethodSection>

  <MethodSection id="api" label="REST API">
    Use the Gcore API to create TLS certificate secrets for HTTPS load balancer listeners — PEM-formatted certificate files are accepted directly, without PKCS12 conversion.

    <Info>
      A permanent [API token](/account-settings/api-tokens) is required, along with a [project ID](https://api.gcore.com/docs/cloud#tag/Projects/operation/ProjectsListV1.get) and a [region ID](https://api.gcore.com/docs/cloud#tag/Regions/operation/RegionListV1.get).
    </Info>

    Set the following environment variables before running the examples:

    ```bash theme={null}
    export GCORE_API_KEY="{YOUR_API_KEY}"
    export GCORE_CLOUD_PROJECT_ID="{YOUR_PROJECT_ID}"
    export GCORE_CLOUD_REGION_ID="{YOUR_REGION_ID}"
    ```

    ## Quickstart

    The scripts below create a TLS certificate secret from PEM files and print the secret ID for use in a load balancer listener.

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        import os
        from gcore import Gcore

        client = Gcore()

        # Step 1. Load PEM certificate files.
        with open("certificate.pem") as f:
            certificate = f.read()
        with open("private_key.pem") as f:
            private_key = f.read()
        with open("certificate_chain.pem") as f:
            certificate_chain = f.read()

        # Step 2. Create the TLS certificate secret.
        secret = client.cloud.secrets.upload_tls_certificate_and_poll(
            name="my-tls-secret",
            payload={
                "certificate": certificate,
                "private_key": private_key,
                "certificate_chain": certificate_chain,
            },
        )
        print(f"Secret ID: {secret.id}")
        print(f"Status:    {secret.status}")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        package main

        import (
            "context"
            "fmt"
            "log"
            "os"

            gcore "github.com/G-Core/gcore-go"
            "github.com/G-Core/gcore-go/cloud"
        )

        func main() {
            client := gcore.NewClient()
            ctx := context.Background()

            // Step 1. Load PEM certificate files.
            certificate, err := os.ReadFile("certificate.pem")
            if err != nil {
                log.Fatal(err)
            }
            privateKey, err := os.ReadFile("private_key.pem")
            if err != nil {
                log.Fatal(err)
            }
            certChain, err := os.ReadFile("certificate_chain.pem")
            if err != nil {
                log.Fatal(err)
            }

            // Step 2. Create the TLS certificate secret.
            secret, err := client.Cloud.Secrets.UploadTlsCertificateAndPoll(ctx, cloud.SecretUploadTlsCertificateParams{
                Name: "my-tls-secret",
                Payload: cloud.SecretUploadTlsCertificateParamsPayload{
                    Certificate:      string(certificate),
                    PrivateKey:       string(privateKey),
                    CertificateChain: string(certChain),
                },
            })
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("Secret ID: %s\n", secret.ID)
            fmt.Printf("Status:    %s\n", secret.Status)
        }
        ```
      </Tab>
    </Tabs>

    ## Step-by-step

    <p>Each step below explains what the call does, which parameters matter, and what the response looks like.</p>

    <Accordion title="Show all steps">
      ### Step 1. Create a TLS certificate secret

      The [create secret](https://api.gcore.com/docs/cloud#tag/Secrets/operation/SecretsViewSetV2.post) endpoint accepts PEM-formatted certificate data directly — no PKCS12 packaging or base64 encoding required.

      | Parameter                   | Required | Description                                                      |
      | --------------------------- | -------- | ---------------------------------------------------------------- |
      | `name`                      | Yes      | Display name for the secret                                      |
      | `payload.certificate`       | Yes      | SSL/TLS certificate in PEM format                                |
      | `payload.private_key`       | Yes      | Private key in PEM format                                        |
      | `payload.certificate_chain` | Yes      | Chain of intermediate and root certificates in PEM format        |
      | `expiration`                | No       | ISO 8601 datetime when the secret expires; defaults to no expiry |

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          import os
          from gcore import Gcore

          client = Gcore()

          with open("certificate.pem") as f:
              certificate = f.read()
          with open("private_key.pem") as f:
              private_key = f.read()
          with open("certificate_chain.pem") as f:
              certificate_chain = f.read()

          secret = client.cloud.secrets.upload_tls_certificate_and_poll(
              name="my-tls-secret",
              payload={
                  "certificate": certificate,
                  "private_key": private_key,
                  "certificate_chain": certificate_chain,
              },
          )
          print(f"Secret ID: {secret.id}")   # save as SECRET_ID
          print(f"Status:    {secret.status}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          certificate, _ := os.ReadFile("certificate.pem")
          privateKey, _ := os.ReadFile("private_key.pem")
          certChain, _ := os.ReadFile("certificate_chain.pem")

          secret, err := client.Cloud.Secrets.UploadTlsCertificateAndPoll(ctx, cloud.SecretUploadTlsCertificateParams{
              Name: "my-tls-secret",
              Payload: cloud.SecretUploadTlsCertificateParamsPayload{
                  Certificate:      string(certificate),
                  PrivateKey:       string(privateKey),
                  CertificateChain: string(certChain),
              },
          })
          if err != nil {
              log.Fatal(err)
          }
          fmt.Printf("Secret ID: %s\n", secret.ID)   // save as SECRET_ID
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl -X POST "https://api.gcore.com/cloud/v2/secrets/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
              "name": "my-tls-secret",
              "payload": {
                "certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
                "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
                "certificate_chain": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
              }
            }'
          ```

          Response:

          ```json theme={null}
          {
            "tasks": ["b63f0fff-1234-5678-abcd-ef0123456789"]
          }
          ```

          Poll <code>GET [https://api.gcore.com/cloud/v1/tasks/\{task\_id}](https://api.gcore.com/cloud/v1/tasks/\{task_id})</code> every 5 seconds until `state` is `FINISHED`. The created secret ID is in `created_resources.secrets[0]`.
        </Tab>
      </Tabs>

      ### Step 2. List secrets

      The [list secrets](https://api.gcore.com/docs/cloud#tag/Secrets/operation/SecretsViewSet.get) endpoint returns all secrets in the region — useful for finding the ID of an existing secret before attaching it to a load balancer.

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          secrets = client.cloud.secrets.list()
          print(f"Total: {secrets.count}")
          for s in secrets.results:
              print(f"  {s.id}  {s.name}  {s.status}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          page, err := client.Cloud.Secrets.List(ctx, cloud.SecretListParams{})
          if err != nil {
              log.Fatal(err)
          }
          fmt.Printf("Total: %d\n", page.Count)
          for _, s := range page.Results {
              fmt.Printf("  %s  %s  %s\n", s.ID, s.Name, s.Status)
          }
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          curl "https://api.gcore.com/cloud/v1/secrets/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY"
          ```

          Response:

          ```json theme={null}
          {
            "count": 1,
            "results": [
              {
                "id": "8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa",
                "name": "my-tls-secret",
                "status": "ACTIVE",
                "secret_type": "certificate",
                "created": "2026-05-31T10:00:00+00:00",
                "expiration": null
              }
            ]
          }
          ```
        </Tab>
      </Tabs>

      ### Step 3. Get secret details

      The [get secret](https://api.gcore.com/docs/cloud#tag/Secrets/operation/SecretViewSet.get) endpoint returns full metadata for a single secret by ID, including its status, type, and expiration date.

      <Tabs>
        <Tab title="Python SDK">
          ```python theme={null}
          SECRET_ID = "8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa"   # from Step 1 or Step 2

          secret = client.cloud.secrets.get(SECRET_ID)
          print(f"Name:       {secret.name}")
          print(f"Status:     {secret.status}")
          print(f"Type:       {secret.secret_type}")
          print(f"Expiration: {secret.expiration}")
          ```
        </Tab>

        <Tab title="Go SDK">
          ```go theme={null}
          secretID := "8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa"   // from Step 1 or Step 2

          secret, err := client.Cloud.Secrets.Get(ctx, secretID, cloud.SecretGetParams{})
          if err != nil {
              log.Fatal(err)
          }
          fmt.Printf("Name:       %s\n", secret.Name)
          fmt.Printf("Status:     %s\n", secret.Status)
          fmt.Printf("Type:       %s\n", secret.SecretType)
          ```
        </Tab>

        <Tab title="curl">
          ```bash theme={null}
          SECRET_ID="8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa"   # from Step 1 or Step 2

          curl "https://api.gcore.com/cloud/v1/secrets/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$SECRET_ID" \
            -H "Authorization: APIKey $GCORE_API_KEY"
          ```

          Response:

          ```json theme={null}
          {
            "id": "8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa",
            "name": "my-tls-secret",
            "status": "ACTIVE",
            "secret_type": "certificate",
            "created": "2026-05-31T10:00:00+00:00",
            "expiration": null,
            "content_types": {
              "default": "application/octet-stream"
            }
          }
          ```
        </Tab>
      </Tabs>
    </Accordion>

    ## Clean up

    The [delete secret](https://api.gcore.com/docs/cloud#tag/Secrets/operation/SecretViewSet.delete) endpoint removes a secret permanently. A secret attached to a load balancer listener cannot be deleted — remove the listener first, then delete the secret.

    <Tabs>
      <Tab title="Python SDK">
        ```python theme={null}
        SECRET_ID = "8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa"

        task_ids = client.cloud.secrets.delete(SECRET_ID)
        client.cloud.tasks.poll(task_ids.tasks[0])
        print("Secret deleted.")
        ```
      </Tab>

      <Tab title="Go SDK">
        ```go theme={null}
        secretID := "8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa"

        if err := client.Cloud.Secrets.DeleteAndPoll(ctx, secretID, cloud.SecretDeleteParams{}); err != nil {
            log.Fatal(err)
        }
        fmt.Println("Secret deleted.")
        ```
      </Tab>

      <Tab title="curl">
        ```bash theme={null}
        SECRET_ID="8f9a1dcd-09cb-4e39-9f6a-a4613f3a63aa"

        curl -X DELETE "https://api.gcore.com/cloud/v1/secrets/$GCORE_CLOUD_PROJECT_ID/$GCORE_CLOUD_REGION_ID/$SECRET_ID" \
          -H "Authorization: APIKey $GCORE_API_KEY"
        ```

        Response:

        ```json theme={null}
        {
          "tasks": ["b63f0fff-1234-5678-abcd-ef0123456789"]
        }
        ```

        Poll <code>GET [https://api.gcore.com/cloud/v1/tasks/\{task\_id}](https://api.gcore.com/cloud/v1/tasks/\{task_id})</code> until `state` is `FINISHED`.
      </Tab>
    </Tabs>
  </MethodSection>
</MethodSwitch>
