All pages
Powered by GitBook
1 of 17

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Guides (Helm)

Guides for CARTO Self-hosted using Kubernetes and Helm

This section contains guides to configure specific aspects of your CARTO Self-hosted installation.

The content of this section applies only to using Kubernetes and Helm

Advanced Orchestrated container deployments

Enable BigQuery OAuth connections (Helm)

For CARTO Self-hosted using Kubernetes and Helm

This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

This document will walk you through the process of setting up OAuth connections in your CARTO Self-hosted installation, enabling secure and seamless authentication when creating your BigQuery connections from the CARTO platform.

Pre-requisites

1. Create an OAuth Consent Screen inside your Google Cloud Platform project

The first thing that has to be configured is an OAuth consent screen to allow the creation of OAuth connections. You'll have to navigate to APIs & Services > OAuth consent screen and enable this by filling up the application name, a support email for your consent screen, the authorized domain for your application and an email for developer contact. The authorized domain you choose should be the one used in the emails that will to use that feature..

The following are required to be able to create a BigQuery OAuth connection from CARTO platform.

  • https://www.googleapis.com/auth/userinfo.email

  • https://www.googleapis.com/auth/userinfo.profile

  • https://www.googleapis.com/auth/bigquery

Navigate to APIs & Services > Credentials > Create credentials to access the OAuth credentials creation form. The following details will be required to create the OAuth client ID:

  • Application type: Web application.

  • Authorized JavaScript origins: https://<your_selfhosted_domain>.

  • Authorized redirect URIs: https://<your_selfhosted_domain>/connections/bigquery/oauth.

Once the create button is clicked, you should be able to download the credentials generated for your application. These credentials will contain the required client_id and client_secret to enable OAuth connections in the CARTO installation.

Add the following lines to your customizations.yaml using the values you obtained from the credentials file:

Once you've configured your CARTO Self-Hosted platform to use the OAuth credentials created in GCP, the Sign in with Google button should be available from the Workspace

2. Create an OAuth credentials

Setup

creating a BigQuery connection
appConfigValues:
  bigqueryOauth2ClientId: "<value_from_credentials_web_client_id>"

appSecrets:
  bigqueryOauth2ClientSecret:
    value: "<value_from_credentials_web_client_secret>"

Enable Google Basemaps (Helm)

For CARTO Self-hosted using Kubernetes and Helm

This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

CARTO Self-hosted can be configured to use Google Basemaps in the builder, allowing you to choose between different Basemap styles provided by Google. All you need is a Google Maps API key and a few simple configuration steps.

Generate Google Maps API key

The CARTO Self-hosted deployment needs a Google Maps API key with the Google Maps JavaScript API enabled in order to use Google Basemaps from Builder. If you also want the Photorealistic 3D Tiles basemap, the Map Tiles API must be enabled on the same key. You can follow these steps to generate a new key:

  1. Enable the Google Maps JavaScript API:

    • In the , navigate to the APIs & Services section and go to the Library tab

    • Click on the Enable APIs & Services button

    • Search for Google Maps JavaScript API and enable it. This API powers all 2D Google Basemaps (Roadmap, Satellite, Hybrid, Terrain, and the Google Maps versions of Positron, Voyager, and Dark Matter).

    • (Optional) Search for Map Tiles API and enable it only if you want the Photorealistic 3D Tiles basemap. Without it, the 3D Tiles option will fail to load in Builder; all other basemaps work without it.

  1. Create Credentials:

  • After enabling the APIs, navigate to Credentials tab

  • Click on Create Credentials and pick API key. Your new API key should appear as soon as it's generated!

  1. Copy Your API Key: This is the API Key that the CARTO Selfhosted instance will use to load the different Google Basemaps in Builder.

In order to enable Google Maps basemaps inside CARTO Self Hosted, you need to own a Google Maps API key and add one of the options below to your customizations file.

  • Option 1: Automatically create the secret

Automatically create a secret based on the plain text value specified in your customizations.yaml file.

  • Option 2: Manually create a secret:

Create a secret running the command below, after replacing the <REDACTED> values with your key values:

Add the following lines to your customizations.yaml, without replacing any value:

Configure CARTO AI Prerequisites (Helm)

In this post you'll find all you need to do to enable the AI Features in Self-Hosted using Helm.

This guide provides instructions for enabling the necessary prerequisites to run CARTO AI features in a Self-Hosted environment managed via Helm. It covers configuration changes, deployment steps, and validation of the AI proxy resources.

Before modifying the Helm configuration, you must prepare your database and network environment.

To setup AI Features in CARTO Self-Hosted you need to already be using an external PostgreSQL metadata database. In legacy versions of CARTO Self-Hosted we provided an internal database that could be deployed as part of our Helm chart. If you're still using it, please get in touch with to plan the migration to an external database.

You can verify if you're using the internal database with the following command:

The AI Proxy service requires its own dedicated logical database within your PostgreSQL instance. The default recommended name is aiproxy

Enable the CARTO Data Warehouse (Helm)

For CARTO Self-hosted using Kubernetes and Helm

The is a default connection that will help you get started with our platform. It gives you access to some demo datasets in order to start using the platform from the very beginning in case you don't have your own data warehouse with spatial data yet. It will also allow using spatial datasets from CARTO’s Data Observatory without connecting your own data warehouse to get access to cloud resources.

By default, the CARTO Data Warehouse in CARTO Self-Hosted is disabled. In this state, certain functionalities are limited compared to when it's enabled. Understanding these limitations is essential for optimal use of CARTO's capabilities.

The CARTO platform has some demo tables, maps, and workflows powered by the CARTO Data Warehouse that can't be used when it is not enabled. Once it's enabled, you'll be able to complete the onboarding experience using these demo resources.

Without the CARTO Data Warehouse, you can still explore the , but you can’t subscribe or use the data it offers it in Workflows/Builder directly. Instead, you’ll need to contact our team, who can deploy a copy of the data in your Data Warehouse.

With the activation of the CARTO Data Warehouse, a dedicated connection is automatically established for every new created organization within your Self-Hosted installation. This seamlessly integrated connection allow users to import data and start using the platform's capabilities.

Already using Google Basemaps? If you previously configured a Google Maps API key that only has the Google Maps JavaScript API enabled, the Photorealistic 3D Tiles basemap will not work with it. You must additionally enable the Map Tiles API on the same key (or generate a new key with both APIs enabled and update your configuration).

Ensure the security of your API key by applying a restrictive usage policy. After setting up your API key, consider configuring key restrictions such as restricting it to the Google Maps JavaScript API (and the Map Tiles API, if you enabled it for 3D Tiles), and limiting its usage to your domain.

Setup

Google Cloud Console
.
  • Connect to your PostgreSQL instance and run:

You must identify the specific database user currently configured for your deployment to grant it permissions later.

  • Connect to your Kubernetes cluster where CARTO is deployed using kubectl cli tool .

  • Verify connection: check that you are in the correct cluster.

  • List namespaces to find your deployment:

  • Note the CARTO namespace <namespace>.

  • Make sure that you have helm cli tool installed .

  • Run the following Helm command to get the release name:

  • Note the CARTO release name <release-name> (first column named "NAME").

  1. Based on the previous information about the release name:

The database user identified in the previous step must have ownership permissions over the new AI database. Replace <carto_user> with the user you identified in step 1.2.

AI-generated responses often require longer processing times than standard HTTP requests. As those requests usually take less than 1 minute, but they can go up to 5 minutes, it's required to allow longer requests for the CARTO Self-Hosted platform.

Therefore, you'll have to increase the idle timeout on the Load Balancer exposing the CARTO service to allow requests taking up to 300 seconds (5 minutes).

CARTO already manages expected timeouts for each API at the service level to ensure that requests taking longer than expected don't block the operations performed by the platform, so it's not required to specify different timeout values depending on the request at your load balancer level.

Now that all prerequisites are met we can enable the AI Pre-requisites in the Helm Chart.

  • Add the following lines to your customization.yaml file:

  • If you used a different database name from the recommended aiproxy default, you need to set the following value:

1. Requirements

If your deployment restricts outbound network traffic (e.g., via a firewall or proxy), make sure the required AI provider domains are whitelisted. See the AI specific requirements section in Deployment Requirements.

Ensure your PostgreSQL password does not contain URI-special characters (@, #, %, etc.), as the AI Proxy builds database connection URLs internally. See Deployment Requirements for details.

1.1 Check that an external database is configured

1.2. Create 'aiproxy' database

CARTO Support team

1.3. Identify the database user

1.3.1 Connect to Kubernetes Cluster

1.3.2 Find your Helm Release

1.3.3 Get the Metadata Database user name:

1.4 Grant owner permissions

1.5 Increase load balancer timeout

Note: This configuration varies by provider (e.g., idle_timeout.timeout_seconds in AWS ALB, or keepalive_timeout in NGINX). You need to handle this configuration in your respective setup.

2. Modify 'customizations.yaml' file

appSecrets:
  googleMapsApiKey:
    value: "<REDACTED>"
kubectl create secret generic \
  [-n my-namespace] \
  mycarto-google-maps-api-key \
  --from-literal=googleMapsApiKey=<REDACTED>
appSecrets:
  googleMapsApiKey:
    existingSecret:
      name: mycarto-google-maps-api-key
      key: googleMapsApiKey
helm get values -n <namespace> <release-name> -o yaml | yq '.internalPostgresql.enabled'
CREATE DATABASE aiproxy;
kubectl cluster-info kubectl config current-context
kubectl get namespaces
helm list -A
helm get values -n <namespace> <release-name> -o yaml | yq '.externalPostgresql.user'
GRANT ALL PRIVILEGES ON DATABASE aiproxy TO <carto_user>;
ALTER DATABASE aiproxy OWNER TO <carto_user>;
appConfigValues:
  ## Enable CARTO AI Pre-requisites
  aiFeaturesEnabled: true
externalPostgresql:
  ## [... existing config...] 
  ## aiproxy database for AI functionalties
  aiProxyDatabaseName: "<aiproxy-custom-database-name>"

To take full advantage of the CARTO Data Warehouse in your organization, follow these steps:

  1. Update the CARTO Data Warehouse flag value:\

    The CARTO Data Warehouse can be enabled updating the customizations.yaml file. You'll have to add the following lines into the customizations file:\

    cartoConfigValues:
      cartoDataWarehouseEnabled: true
  2. Update your CARTO Self-Hosted installation to apply the change

Once the update process has finished, every CARTO organization created in your Self-Hosted deployment will have access to the CARTO Data Warehouse by default. Consequently, you'll be able to complete the onboarding process and access the Data Observatory subscriptions.

When enabling the CARTO Data Warehouse in a Self-Hosted installation, there are new requirements that should be accomplished as a new piece is added into the CARTO Self-Hosted architecture.

If you check the previous diagram, the CARTO Data Warehouse is a new external piece connected to your Self-Hosted installation. Consequently, your deployment should be able to perform requests to an external component that will be hosted on CARTO's side.

As it's explained in the deployment requirements, this data warehouse is powered by Google BigQuery, so you'll have to allow requests to BigQuery APIs in order to use this feature.

This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

Introduction

Default Behavior

Affected Functionality

Onboarding experience

Data Observatory

CARTO Data Warehouse connection

CARTO Data Warehouse
Spatial Data Catalog

How to Enable It

Update Requirements

Configure your custom service account (Helm)

For CARTO Self-hosted using Kubernetes and Helm

When deploying CARTO Self-Hosted, each installation is accompanied by a dedicated infrastructure, including a Service Account key necessary for utilizing certain deployed services. However, if you prefer to utilize your own Google Cloud Platform (GCP) Service Account, please follow these steps before initiating the Self-Hosted installation:

  1. Create a Dedicated Service Account: Generate a dedicated Service Account specifically for your CARTO Self-Hosted deployment within your Google Cloud Platform console.

  2. Contact CARTO Support: Reach out to our CARTO support team and provide them with the email associated with the Service Account you've created. This step ensures seamless integration of your Service Account with your CARTO Self-Hosted deployment. Email CARTO Support Team with the service account email.

For any queries or assistance regarding this process, feel free to contact our support team. Once the service account has the proper permissions on CARTO infrastructure, you'll be able to use your custom service account to deploy the CARTO Self-Hosted platform.

[email protected]

Enable Redshift imports (Helm)

For CARTO Self-hosted using Kubernetes and Helm

This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

To import data into Redshift through CARTO Self-Hosted, follow these step-by-step instructions.

This requires access to an AWS account and an existing accessible Redshift endpoint.

  1. Create an AWS IAM user with programmatic access. Take note of the user's ARN, Key ID and Key secret.

  2. Create an AWS S3 Bucket:

    • ACLs should be allowed.

    • If server-side encryption is enabled, the user must be granted with permissions over the KMS key following the .

  3. Create an AWS IAM role with the following settings:

    1. Trusted entity type: Custom trust policy.

    2. Custom trust policy: Make sure to replace <your_aws_user_arn>.

  4. Configure your CARTO Self-Hosted deployment:\

    Add the following lines to your customizations.yaml file:

  5. Update your installation to apply the changes.

  6. Configure Redshift Integration in CARTO:

    1. Log into your CARTO Self-Hosted, go to Data Explorer > Connections > Add new connection and create a new Redshift connection.

    2. Then go to Settings > Advanced > Integrations > Redshift > New, introduce your S3 Bucket name and region and copy the policy generated.

  7. Import Data to Redshift:

    1. Go to Data Explorer > Import data > Redshift connection. Now, you should be able to ! 🎉

Use EKS Pod Identity in AWS (Helm)

For CARTO Self-hosted using Kubernetes and Helm

allows Kubernetes pods in EKS clusters to securely assume specific AWS IAM roles, enabling secure, granular access to AWS resources without embedding credentials within the pods.

This approach enhances security by reducing the risk of exposed access keys and supports fine-grained access control by enabling distinct permissions for each workload. With EKS Pod Identity, managing access credentials becomes simpler and safer, allowing developers to control AWS resource permissions at the pod level.

Enabling EKS Pod Identity on a cluster allows assuming an IAM role from the pods deployed. When Amazon EKS starts a new pod that uses a service account with an EKS Pod Identity association it injects some environment variables in the pods that can be used to authenticate against AWS APIs.

In order to enable this feature in your EKS cluster, you can check the following .

CARTO Self-Hosted running on an EKS cluster can take advantage of EKS Pod Identity feature to connect to the PostgreSQL metadata database if it's deployed in RDS.

Configure Single Sign-On (SSO) (Helm)

For CARTO Self-hosted using Kubernetes and Helm

This guide outlines the steps to configure Single Sign-On (SSO) for your CARTO Self-Hosted instance. enhances security and user experience by allowing users to log in with a single set of credentials across multiple systems.

  1. Contact CARTO Support:

    • Initiate contact with the CARTO Support team to request assistance with SSO configuration.

Setup EKS Pod Identity following the documentation.

  • Enable IAM Authentication in your PostgreSQL RDS database.

  • Create a user with IAM Authentication enabled in your database:

    • USERNAME: Username that will be used to connect to your metadata database.

    1. Grant your Pod Identity IAM Role permissions to connect to your metadata database

    Assign the following policy to the role configured for EKS Pod Identity:

    • REGION: AWS region in which the metadata database is deployed.

    • AWS_ACCOUNT_ID: ID of the AWS account where the metadata database is deployed.

    • RDS_DATABASE_RESOURCE_ID: ID of the database in AWS. It should be a string matching the following format: db-Rxxxxxxxxxxxxxxxx

    • USERNAME: Username that will be used to connect to your metadata database. It should be the same that was created previously.

    1. Provide the following configuration in the customizations.yaml file:

    • EKS_POD_IDENTITY_SERVICE_ACCOUNT: Name of the service account you created when configuring EKS Pod Identity.

    • HOST: Address of the PostgreSQL RDS database.

    • USERNAME: Username that will be used to connect to your metadata database. It should be the same that was created previously.

    • PORT: Port used to connect to the PostgreSQL RDS database.

    • REGION: AWS region in which the metadata database is deployed.

    • CA_CERT: Content of the CA certificate used to connect to the database using SSL.

    Once you've applied the changes performed in your customizations.yaml file, your CARTO deployment will use the role you created to connect to the metadata database!

    CARTO Self-Hosted running on an EKS cluster can take advantage of EKS Pod Identity feature to connect to the S3 buckets if it's deployed in RDS.

    1. Setup EKS Pod Identity following the documentation.

    2. Grant your Pod Identity IAM Role permissions to connect to your S3 buckets. You can find the needed permissions in the guide to configure your own buckets.

    3. Provide the following configuration in the customizations.yaml file:

    You'll have to provide in your customizations.yaml file the changes explained in the guide to configure your own buckets and the following changes:

    • EKS_POD_IDENTITY_SERVICE_ACCOUNT: Name of the service account you created when configuring EKS Pod Identity.

    Once you've applied the changes performed in your customizations.yaml file, your CARTO deployment will use the role you created to connect to the S3 buckets!

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    What is EKS Pod Identity?

    Enabling EKS Pod Identity in your Self-Hosted installation is just available for the orchestrated container deployment of CARTO.

    How does EKS Pod Identity work?

    Use EKS Pod Identity to access the metadata database

    Configuration

    Amazon EKS Pod Identity
    documentation

    Use EKS Pod Identity to access the S3 buckets

    Configuration

    Work closely with the Support team to communicate your organization's specific requirements.

  • Obtain organization ID:

    • Once SSO is successfully configured from the CARTO side, CARTO Support team will provide you with a unique identifier known as the organization ID. This organization ID is required to continue with the SSO configuration in your CARTO Self-Hosted installation.

  • In order to configure the SSO in your orchestrated container deployment, the organization ID should be injected into your CARTO Self-Hosted instance. This value can be configured following these steps:

    • Inject the organization ID into your CARTO Self-hosted:

      • Add a new environment variable for the organization ID provided by CARTO Support in your customizations.yaml file.

    • Deploy Changes:

      • Deploy the updated configuration to apply the changes to your CARTO Self-Hosted instance.

    With the successful integration of SSO and the Organization ID, your CARTO Self-Hosted instance is now configured to provide a seamless and secure Single Sign-On experience for your users. You can now navigate to your CARTO deployment domain, and it should use your IdP to log into the platform.

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    Prerequisites

    Please get in touch at [email protected] to start configuring your SSO integration.

    SSO integration

    Setup

    Conclusion

    Tracking Activity Data from Public Maps (Helm)

    CARTO now supports tracking activity data from public maps, allowing administrators to measure the impact of their public maps by tracking interactions from unauthenticated visitors (e.g., views, exports, most active maps).

    For more details, see: https://docs.carto.com/whats-new#tracking-activity-data-from-public-maps

    This feature is not enabled by default. To enable it, add the following configuration in your customizations.yaml file:

    appConfigValues:
      publicEventsApiEnabled: true

    You'll have to deploy the new changes to you environment to ensure that the new component that will be handling the events triggered by your public maps is ready!

    Add permissions: Create a new permissions' policy, replacing <your_aws_s3_bucket_name>.

    From the AWS console, go to your S3 > Bucket > Permissions > Bucket policy and paste the policy obtained in the previous step in the policy editor.

  • Go back to the CARTO Self-Hosted (Redshift integration page) and check the I have already added the S3 bucket policy box and click on the Validate and save button.

  • Go to Data Exporer > Import data > Redshift connection and you should be able to import a local dataset to Redshift.

  • AWS documentation
    import a local dataset to Redshift
    CREATE USER {USERNAME};
    GRANT rds_iam TO {USERNAME};
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "rds-db:connect",
                "Resource": "arn:aws:rds-db:{REGION}:{AWS_ACCOUNT_ID}:dbuser:{RDS_DATABASE_RESOURCE_ID}/{USERNAME}"
            }
        ]
    }
    commonBackendServiceAccount:
      create: false
      name: '{EKS_POD_IDENTITY_SERVICE_ACCOUNT}'
    externalPostgresql:
      host: {HOST}
      user: {USERNAME}
      database: {DATABASE}
      port: {PORT}
      awsEksPodIdentityEnabled: true
      awsRdsRegion: {REGION}
      sslEnabled: true
      sslCA: |
      {CA_CERT}
    commonBackendServiceAccount:
      create: false
      name: '{EKS_POD_IDENTITY_SERVICE_ACCOUNT}'
    appConfigValues:
      awsEksPodIdentityBucketsEnabled: true
    appConfigValues:
      ssoOrganizationId: "<YOUR_ORGANIZATION_ID>"
    {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "AWS": "<your_aws_user_arn>"
              },
              "Action": [
                  "sts:AssumeRole",
                  "sts:TagSession"
              ]
          }
      ]
    }
    appConfigValues:
      importAwsRoleArn: "<your_aws_user_arn>"
    
    appSecrets:
      importAwsAccessKeyId:
        value: "<your_aws_user_access_key_id>"
      importAwsSecretAccessKey:
        value: "<your_aws_user_access_key_secret>"
    {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "s3:ListBucket",
               "Resource": "arn:aws:s3:::<your_aws_s3_bucket_name>"
           },
           {
               "Effect": "Allow",
               "Action": "s3:*Object",
               "Resource": "arn:aws:s3:::<your_aws_s3_bucket_name>/*"
           }
       ]
    }

    Configure an external proxy (Helm)

    For CARTO Self-hosted using Kubernetes and Helm

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    CARTO Self-hosted supports operating behind an HTTP or HTTPS proxy. The proxy acts as a gateway, enabling CARTO Self-hosted components to establish connections with essential external services like CARTO licensing system, or auth.carto.com. You can find detailed information about these components and services in the network requirements section.

    CARTO Self-hosted does not provide or install any proxy component; It's built to connect to an existing proxy software deployed on your side.

    A comprehensive list of domains that must be whitelisted by the proxy for the proper operation of CARTO Self-hosted can be found here. Such list includes domains for the core services of CARTO Self-hosted, as well as some optional domains that should be enabled to access specific features.

    HTTP

    In order to configure an external HTTP proxy on your CARTO Self-hosted installation, you'll have to:

    Add the following lines in your customizations.yaml file:

    The externalProxy.excludedDomains property contains a comma-separated list of domains to exclude from proxying. The .svc.cluster.local domain must be in the list to allow internal communication between components within your cluster.

    To configure an HTTPS proxy on CARTO Self-hosted, you'll have to change the following configuration:

    Add the following lines in your customizations.yaml file:

    • externalProxy.excludedDomains : obtains a comma-separated list of domains to exclude from proxying. The .svc.cluster.local domain must be in the list to allow internal communication between components.

    • externalProxy.sslRejectUnauthorized (optional): Specify if CARTO Self-hosted should check if the proxy certificate is valid or not. For instance, self-signed certificates validation must be skipped.

    While certain data warehouses can be configured to work with a proxy, there are some providers that will inherently bypass it. This means that the connection to these data warehouses won't be created through the proxy, so CARTO Self-hosted services will try to directly perform requests to the providers.

    • BigQuery: It supports both HTTP and HTTPs proxy.

    • PostgreSQL and Redshift: They use a TCP connection instead of HTTP(S), so the proxy is bypassed.

    • Databricks: Proxy is not supported, so the HTTPS connection will be bypassed.

    When no network policy is enforced, all outgoing traffic that does not pass through a proxy will be permitted.

    In restrictive environments, it is indispensable to maintain strict control over connections made by CARTO Self-hosted components. To achieve this, you should configure your proxy to allow only approved external services (whitelisting), while blocking any other outgoing traffic that does not go through the proxy.

    To accomplish this, you can apply a custom network policy, such as the one provided in this example:

    Password authentication is not supported for the proxy connection.

    using an HTTPS Proxy configured with a certificate signed by a Custom CA is not supported.

    Advanced customizations (Helm)

    For CARTO Self-hosted using Kubernetes and Helm

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    • Custom Analytics Toolbox location

    • Allow embedding CARTO into an iframe

    • Enabling/Disabling TrackJS

    The default location of the Analytics Toolbox can be customized for all connections in your CARTO Self-Hosted installation. If you edit this value, each new connection will have the AT location configured in the specified location:

    Update your config in the customizations.yaml file:

    CARTO Self-Hosted is prepared to be allowed into an iframe when needed. This way, custom applications using CARTO can work without any issue from an iframe. In order to allow your application using the platform through an iframe, you'll have to configure the allowed domains that can embed CARTO:

    Update your customizations.yaml file:

    TrackJS is a useful tool as it provides valuable insights into the performance and errors occurring within the CARTO platform.

    TrackJS is enabled by default in the frontend components, but you can disable adding the following config in the customizations.yaml file:

    The CARTO Self-Hosted deployment exposes the 443 port through a component called router, which is running a NGINX service under the hood. The following customization options are available for this service:

    CARTO Self-Hosted connects to your data warehouse to perform different operations with your data. When connecting it with Postgres or Redshift, it's important to understand how the connection pool works.

    Each node will have a connection pool controlled by the environment variables MAPS_API_V3_POSTGRES_POOL_SIZE and MAPS_API_V3_REDSHIFT_POOL_SIZE. The pool is per connection created from CARTO Self Hosted. If each user creates a different connection, each one will have its own pool. The maximum connections can be calculated with the following formula:

    When a request is sent to an external data warehouse, we're applying some limits on the amount of time that a query can take to finish. If you'd like to customize the timeout applied to the queries executed against your data warehouse, you'll have to edit the following environment variables:

    Their default value is set to 20 seconds. Please take into account that the updated value should be specified in milliseconds.

    Migrating CARTO Self-hosted installation to an external database (Helm)

    For CARTO Self-hosted using Kubernetes and Helm

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    This guide outlines the steps to migrate the internal database of a CARTO Self-Hosted installation to an external database. By following these steps, you can seamlessly transition your CARTO workspace to a new database environment.

    Prerequisites

    Before starting the migration process, ensure that you have the following:

    • Access to the CARTO Self-Hosted installation

    • Credentials for the external database (hostname, port, username, password)

    How to perform the migration to an external database

    Step 1: Dump the Container Database

    Use the following command to create a dump of the internal database:

    1. Obtain the PostgreSQL password generated by the CARTO installation from the secret created for postgresql:\

    1. Obtain the name of your workspace database pod. The following command should return a pod named postgresql

    2. Run the following command to perform a backup of the internal database located in your cluster:

    This command exports the database structure and data to a SQL file named dump.sql

    Run the following command to create the necessary user in the new external database:

    Execute the following commands to create the database in the external database:

    Restore the dumped data into the new external database. If you have access to the external database using psql you can directly restore the database using the following command:

    You have successfully migrated your CARTO Self-Hosted installation to an external database! 🎉 Ensure that you update your CARTO configuration files to reflect the changes in the database connection details. You can find more information about how to connect your Self-Hosted installation to an external database in our .

    Configure an external in-memory cache (Helm)

    For CARTO Self-hosted using Kubernetes and Helm

    CARTO Self-Hosted requires Valkey (version 6 or above) to work. This Valkey instance does not need persistence, as it is used solely as a cache.

    Both and come already with an internal Valkey deployment, but they lack any backups, autoscaling, or monitoring. Cloud vendors already offer Valkey deployments at scale as a service:

    • .

    • .

    externalProxy.sslCA (optional): Path to the proxy CA certificate. If the proxy certificate is signed by a custom CA, such CA must be included here, but if it's signed by a well known CA, there is no need to add it here. Well known CAs are usually part of the ca-certificates package.
    Snowflake: It supports HTTP proxy, but HTTPS is not supported and will have to be bypassed. In order to bypass it, you'll have to add snowflakecomputing.com to the list of excluded domains.
  • Oracle: It supports HTTP proxy, but HTTPS is not supported and will have to be bypassed. In order to bypass it, you'll have to add oraclecloud.com to the list of excluded domains.

  • Please, take into account that if you're configuring an external proxy in a CARTO Self-Hosted installation running in GKE with Workload Identity configured, you'll have to add the following excluded domains:

    169.254.169.254,metadata,metadata.google.internal

    These domains are required when authenticating the requests performed from an installation using Workload Identity.

    HTTPS

    Please, take into account that if you're configuring an external proxy in a CARTO Self-Hosted installation running in GKE with Workload Identity configured, you'll have to add the following excluded domains:

    169.254.169.254,metadata,metadata.google.internal

    These domains are required when authenticating the requests performed from an installation using Workload Identity.

    Support for data warehouses

    When the proxy is bypassed, and you have a restrictive network policy in place, you will need to explicitly allow this egress of non-proxied traffic.

    Enhanced control over non-proxied egress traffic

    The following configuration just applies for orchestrated container deployments of CARTO Self-Hosted, so if you're using the Single VM deployment this section must be skipped.

    Limitations

    Importing data

    Custom Analytics Toolbox location

    Allow embedding CARTO into an iframe

    Enabling/Disabling TrackJS

    Customizable values for NGINX router

    External Data warehouse tuning

    Customizable values for NGINX router
    External Data warehouse tuning

    You can obtain the name of your PostgreSQL secret running the following command:

    kubectl get secrets -n <namespace>

    Step 2: Create Workspace Admin User in External Database

    Step 3: Create Database in External Database

    Step 4: Restore the Dump

    quickstart guides
    externalProxy:
      enabled: true
      host: <Proxy IP/Hostname>
      port: <Proxy port>
      type: http
      excludedDomains: ["localhost,.svc.cluster.local"]
    externalProxy:
      enabled: true
      host: <Proxy IP/Hostname>
      port: <Proxy port>
      type: https
      excludedDomains: ["localhost,.svc.cluster.local"]
      ## NOTE: Please, carefully read CARTO Self-hosted proxy documentation to understand the  the current limitations with [custom CAs].
      sslRejectUnauthorized: true
      # sslCA: |
      #  -----BEGIN CERTIFICATE-----
      #  XXXXXXXXXXXXXXXXXXXXXXXXXXX
      #  -----END CERTIFICATE-----
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: carto-no-internet-access
      # Optional labels
      labels:
        app.kubernetes.io/instance: <instance-name>
        app.kubernetes.io/managed-by: <managed-by>
        app.kubernetes.io/name: <app-name>
    spec:
      # Match all Pods except the proxy Pod.
      # NOTE: Make sure your proxy pod has the label app.kubernetes.io/component: proxy
      # NOTE: Proxy pod is not deployed with the CARTO Self-hosted chart
      podSelector:
        matchExpressions:
          - key: app.kubernetes.io/component
            operator: NotIn
            values:
              - proxy
              - router
      policyTypes:
        - Ingress
        - Egress
      ingress:
        # Allow connections within the same namespace
        - from:
            - namespaceSelector:
                matchLabels:
                  kubernetes.io/metadata.name: <namespace>
      egress:
        # Allow connections within the same namespace
        - to:
            - namespaceSelector:
                matchLabels:
                  kubernetes.io/metadata.name: <namespace>
        # Allow DNS resolution
        - to:
            - namespaceSelector:
                matchLabels:
                  kubernetes.io/metadata.name: kube-system
            - podSelector:
                matchLabels:
                  k8s-app: kube-dns
          ports:
            - port: 53
              protocol: UDP
        # Allow connections to external datawarehouses
        - to:
            - ipBlock:
                cidr: 0.0.0.0/0
          ports:
            # Postgres
            - port: 5432
              protocol: TCP
            # Redshift
            - port: 5439
              protocol: TCP
            # Valkey
            - port: 6379
              protocol: TCP
        # Allow connections to other datawarehouses hosts on port 443
        - to:
            - ipBlock:
                cidr: <CIDR>
          ports:
            - port: 443
              protocol: TCP
    appConfigValues:
      defaultAtLocation:
        bigquery: "carto-un.carto"
        snowflake: "CARTO.CARTO"
        redshift: "carto"
        databricks: "carto"
        postgres: "carto"
    router:
      extraEnvVars:
        - name: IFRAME_ALLOWED_DOMAINS
          value: "https://mydomain1.com https://mydomain2.com:8080"
    appConfigValues:
        enableTrackJS: false
    router:
      extraEnvVars:
        - name: NGINX_CLIENT_MAX_BODY_SIZE
          value: "10M"
        - name: NGINX_GZIP_MIN_LENGTH
          value: "1100"
        - name: NGINX_GZIP_BUFFERS
          value: "16 8k"
        - name: NGINX_PROXY_BUFFERS
          value: "16 8k"
        - name: NGINX_PROXY_BUFFER_SIZE
          value: "8k"
        - name: NGINX_PROXY_BUSY_BUFFERS_SIZE
          value: "8k"
    max_connections = pool_size * number_connections * number_nodes;
    MAPS_API_V3_DYNAMIC_TILES_QUERY_TIMEOUT_POSTGRES_MS=20000
    MAPS_API_V3_DYNAMIC_TILES_QUERY_TIMEOUT_REDSHIFT_MS=20000
    MAPS_API_V3_DYNAMIC_TILES_QUERY_TIMEOUT_SNOWFLAKE_MS=20000
    MAPS_API_V3_DYNAMIC_TILES_QUERY_TIMEOUT_BIGQUERY_MS=20000
    MAPS_API_V3_DYNAMIC_TILES_QUERY_TIMEOUT_DATABRICKS_MS=20000
    kubectl get secret <postgresql_secret_name> \
     -n <namespace> \
     -ogo-template='{{ index .data "postgres-password" }}' | base64 -D
    kubectl get pods -n <namespace> | grep postgresql
    kubectl exec <postgresql_pod_name> \
     -n <namespace> \
     -- pg_dump --dbname=postgresql://postgres:<postgres_password>@localhost:5432/workspace > dump.sql
    CREATE USER workspace_admin with encrypted password '<password>';
    CREATE DATABASE workspace OWNER workspace_admin;
    psql -h <external_db_host> -p <external_db_port> -U workspace_admin -d workspace -f dump.sql

    Azure Cache for Redis.

    In this section, you will see how to configure the Self-hosted to use an external Valkey provided by your cloud vendor.

    1. Add the secret:

    kubectl create secret generic \
      -n
    
    1. Configure the package:

    Add the following lines to your customizations.yaml to connect to the external Valkey:

    internalRedis:
      # Disable the internal Valkey
      enabled: false
    
    1. Add the following lines to your customizations.yaml to connect to the external Valkey:

    Note: One kubernetes secret is going to be created automatically during the installation process with the externalRedis.password that you set in previous lines.

    By default, CARTO will try to connect to your Valkey without TLS enabled. In case you want to connect via TLS, you can configure it via the externalRedis.tlsEnabled parameter.

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    Valkey replaces Redis as of CARTO Self-Hosted 2026.04. Valkey is an open-source fork of Redis 7.2 and is fully wire-compatible: existing external Redis instances continue to work as a drop-in cache without configuration changes. For versions earlier than 2026.04, see the legacy documentation.

    Single VM deployment
    Orchestrated container deployment
    Google Memorystore for Redis
    Amazon ElastiCache for Redis
    externalRedis:
      ...
      tlsEnabled: true
    externalRedis:
      ...
      tlsEnabled: true
      tlsCA: |
        #   -----BEGIN CERTIFICATE-----
        #   ...
        #   -----END CERTIFICATE-----

    Setup

    Configuration

    Configure TLS

    In case you are connecting to a Valkey where the TLS certificate is selfsigned or from a custom CA you can configure it via the externalRedis.tlsCA parameter

    <
    namespac
    e
    >
    \
    mycarto-custom-redis-secret \
    --from-literal=password=<AUTH string password>
    externalRedis:
    host: <Valkey IP/Hostname>
    port: "6379"
    existingSecret: "mycarto-custom-redis-secret"
    existingSecretPasswordKey: "password"
    tlsEnabled: true
    # Only applies if your Valkey TLS certificate it's self-signed
    # tlsCA: |
    # -----BEGIN CERTIFICATE-----
    # ...
    # -----END CERTIFICATE-----
    internalRedis:
      # Disable the internal Valkey
      enabled: false
    externalRedis:
      host: <Valkey IP/Hostname>
      port: "6379"
      password: <Valkey password>
      tlsEnabled: true
      # Only applies if your Valkey TLS certificate it's self-signed
      # tlsCA: |
      #   -----BEGIN CERTIFICATE-----
      #   ...
      #   -----END CERTIFICATE-----

    Use Workload Identity in GCP (Helm)

    For CARTO Self-hosted using Kubernetes and Helm

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    What is Workload Identity?

    Applications running on Google Kubernetes Engine might need access to Google Cloud APIs such as Compute Engine API, BigQuery API, or Storage APIs.

    Workload Identity allows a Kubernetes service account in your GKE cluster to act as an IAM service account. Pods that use the configured Kubernetes service account automatically authenticate as the IAM service account when accessing Google Cloud APIs. Using Workload Identity allows you to assign distinct, fine-grained identities and authorization for each application in your cluster.

    Enabling Workload Identity in your Self-Hosted installation is just available for the orchestrated container deployment of CARTO.

    How does Workload Identity work?

    When you enable Workload Identity on a cluster, GKE automatically creates a fixed workload identity pool for the cluster's Google Cloud project. A workload identity pool allows IAM to understand and trust Kubernetes service account credentials. GKE uses this pool for all clusters in the project that use Workload Identity. The workload identity pool has the following format:

    PROJECT_ID.svc.id.goog

    When you configure a Kubernetes service account in a namespace to use Workload Identity, IAM authenticates the credentials using the following member name:

    serviceAccount:PROJECT_ID.svc.id.goog[KUBERNETES_NAMESPACE/KUBERNETES_SERVICE_ACCOUNT]

    In this member name:

    • PROJECT_ID: your Google Cloud project ID.

    • KUBERNETES_NAMESPACE: the namespace of the Kubernetes service account.

    • KUBERNETES_SERVICE_ACCOUNT: the name of the Kubernetes service account making the request.

    The process of configuring Workload Identity includes using an IAM policy binding to bind the Kubernetes service account member name to an IAM service account that has the permissions your workloads need. Any Google Cloud API calls from workloads that use this Kubernetes service account are authenticated as the bound IAM service account.

    In order to enable Workload Identity in your CARTO Self-Hosted installation, you'll have to follow these steps:

    1. Create an IAM service account for your application, or use an existing IAM service account instead.

    • IAM_SERVICE_ACCOUNT_NAME: name of the new service account.

    • PROJECT_ID: ID of the project where the GKE cluster is deployed.

    Service Account needs roles/iam.serviceAccountTokenCreator role to sign URLs, you can grant it with this command:

    1. Send email to CARTO Support Team with Service Account Contact CARTO Support to let us know the Service Account you want to use for Workload Identity. We will ensure that your Service Account is granted the required roles to run CARTO Self-Hosted.

    1. Add the following lines to your customizations.yaml file:

    • IAM_SERVICE_ACCOUNT_EMAIL: email of the service account generated in the first step.

    1. Allow the Kubernetes service account that is going to be created in your GKE cluster to impersonate the IAM service account by adding an IAM policy binding between the two service accounts. This binding allows the Kubernetes service account to act as the IAM service account.

    • IAM_SERVICE_ACCOUNT_EMAIL: email of the service account generated in the first step.

    • PROJECT_ID: ID of the project where the GKE cluster is deployed.

    • KUBERNETES_NAMESPACE

    CARTO Self-Hosted running on a GKE cluster can take advantage of GKE Workload Identity feature to create a connection between the CARTO Self-Hosted platform and BigQuery without any user action.

    1. Setup GKE Workload Identity for CARTO Self-Hosted following the .

    2. Grant your Workload Identity service account with BigQuery to your data warehouse project.

    3. Add the following environment variables in your customizations.yaml file:

    • WORKFLOWS_TEMP_LOCATION: BigQuery dataset ID used for storing temporary tables (i.e. my_gcp_project.my_dataset).

    • BILLING_PROJECT_ID: GCP project to be charged with the BigQuery costs.

    1. Follow the previous command output and grant the service account the following role:

    • WORKLOAD_IDENTITY_SA_EMAIL: Service account email configured for Workload Identity.

    • PROJECT_ID: ID of the project where the GKE cluster is deployed.

    • KUBERNETES_NAMESPACE

    Once you've applied the changes performed in your customizations.yaml file, your CARTO deployment will automatically create a new BigQuery connection using Workload Identity owned by the CARTO user specified in the deployment configuration!

    IAM_SERVICE_ACCOUNT_NAME: name of the new service account used in previous step

  • IAM_SERVICE_ACCOUNT_EMAIL: email of the service account generated with the previous command.

  • : namespace where CARTO application is deployed.
  • KUBERNETES_SERVICE_ACCOUNT: name of the kubernetes service account used by CARTO application. Default value is carto-common-backend.

  • WORKLOAD_IDENTITY_SA_EMAIL: Service account email configured for Workload Identity.
  • CARTO_OWNER_ID: ID of the CARTO user who will be the owner of the connection (i.e. "auth0|3idsj230990sj4wsddd10"). This can be obtained by running the following curl command:

  • : namespace where CARTO application is deployed.

    Configure CARTO deployment to use Workload Identity

    IMPORTANT: You cannot change the Service Account without contacting support.

    The chart gives the possibility of disabling commonBackendServiceAccount account creation with commonBackendServiceAccount.create: false but you'll have to provide the name of your service account with name: "{K8S_SERVICE_ACCOUNT_NAME}"

    Create a BigQuery connection managed using Workload Identity

    Configuration

    [email protected]
    documentation
    required permissions

    You can find the gcloud command with the KUBERNETES_NAMESPACE and KUBERNETES_SERVICE_ACCOUNT values in the helm output notes once you execute the installation process.

    curl -s 'https://accounts.app.carto.com/users/me' \
      -H 'Authorization: Bearer <your_carto_jwt_token>' \
      | jq '.user_id'
    gcloud iam service-accounts create {IAM_SERVICE_ACCOUNT_NAME} \
        --project={PROJECT_ID}
    gcloud iam service-accounts add-iam-policy-binding \
      {IAM_SERVICE_ACCOUNT_EMAIL} \
      --member=serviceAccount:{IAM_SERVICE_ACCOUNT_EMAIL} \
      --role=roles/iam.serviceAccountTokenCreator
    commonBackendServiceAccount:
      enableGCPWorkloadIdentity: true
      annotations:
        iam.gke.io/gcp-service-account: "{IAM_SERVICE_ACCOUNT_EMAIL}"
    gcloud iam service-accounts add-iam-policy-binding {IAM_SERVICE_ACCOUNT_EMAIL} \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:{PROJECT_ID}.svc.id.goog[{KUBERNETES_NAMESPACE}/{KUBERNETES_SERVICE_ACCOUNT}]"
    workspaceApi:
      extraEnvVars:
        - name: WORKSPACE_SYNC_DATA_ENABLED
          value: "true"
        - name: WORKSPACE_WORKLOAD_IDENTITY_WORKFLOWS_TEMP
          value: {WORKFLOWS_TEMP_LOCATION}
        - name: WORKSPACE_WORKLOAD_IDENTITY_BILLING_PROJECT
          value: {BILLING_PROJECT_ID}
        - name: WORKSPACE_WORKLOAD_IDENTITY_SERVICE_ACCOUNT_EMAIL
          value: {WORKLOAD_IDENTITY_SA_EMAIL}
        - name: WORKSPACE_WORKLOAD_IDENTITY_CONNECTION_OWNER_ID
          value: {CARTO_OWNER_ID}
    workspaceSubscriber:
      extraEnvVars:
        - name: WORKSPACE_SYNC_DATA_ENABLED
          value: "true"
        - name: WORKSPACE_WORKLOAD_IDENTITY_WORKFLOWS_TEMP
          value: {WORKFLOWS_TEMP_LOCATION}
        - name: WORKSPACE_WORKLOAD_IDENTITY_BILLING_PROJECT
          value: {BILLING_PROJECT_ID}
        - name: WORKSPACE_WORKLOAD_IDENTITY_SERVICE_ACCOUNT_EMAIL
          value: {WORKLOAD_IDENTITY_SA_EMAIL}
        - name: WORKSPACE_WORKLOAD_IDENTITY_CONNECTION_OWNER_ID
          value: {CARTO_OWNER_ID}
    gcloud iam service-accounts add-iam-policy-binding \
      {WORKLOAD_IDENTITY_SA_EMAIL} \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:{PROJECT_ID}.svc.id.goog[{KUBERNETES_NAMESPACE}/carto-common-backend]" \
      --project {PROJECT_ID}

    Load Balancing best practices (Helm)

    This guide provides best practices guidance for exposing CARTO Self-Hosted to users in production environments. It covers load balancing architectures, configuration patterns, and cloud provider-specific recommendations for Kubernetes deployments using Helm.

    1. Prerequisites

    • CARTO Self-Hosted deployed via Helm.

    • Kubernetes cluster running on a cloud provider (GCP, AWS, or Azure).

    • Understanding of Kubernetes Services and Ingress resources.

    • Domain name configured for your CARTO deployment.

    CARTO Self-Hosted uses a component called router-http as the main entry point for all HTTP/HTTPS traffic. You can see the details on Carto Self-hosted architecture here:

    This router service can be exposed through different Kubernetes networking patterns:

    Pattern
    Description
    Recommended For
    Helm Management

    Below you'll find in detail the two recommended patterns to publish your CARTO SelfHosted instance through a Load Balancer:

    • Cloud Load Balancer + Router LoadBalancer Service.

    • Ingress/GatewayAPI Layer + Router ClusterIP Service.

    In this pattern, you define the service type as LoadBalancer. The Kubernetes Cloud Controller Manager talks directly to your cloud provider (AWS, GCP, Azure) to automatically provision and configure a native Cloud Load Balancer. You handle your own Cloud Load Balancing layer on top of this K8s integration.

    Kubernetes requests a Load Balancer from the cloud provider. The cloud provider provisions it, assigns it a public/private IP, and automatically updates the backend target groups (nodes) as the cluster autoscales or nodes are replaced.

    When to use:

    • Simplicity: You want a dedicated Load Balancer for CARTO without the complexity of configuring an Ingress Controller.

    • Automation: You want Kubernetes to automatically manage the backend node registration (avoiding the risk of stale Node IPs).

    • Cloud-specific features: You need to utilize specific cloud features (like AWS NLB or Azure Internal LB) triggered via Service Annotations.

    To enable this pattern, simply update the router service type in your values file.

    You can customize the behavior of the cloud-provisioned Load Balancer (such as enabling SSL, setting timeouts, or making it internal-only) using annotations.

    These annotations are specific to your Cloud Provider (AWS, GCP, Azure) and are passed directly to the router.service.annotations field.

    Key configuration options:

    This example configures an AWS Load Balancer with SSL termination, specific timeouts, and an internet-facing scheme.

    • GCP Internal LB:

    • Azure Internal LB:

    • âś… Automated Lifecycle: Kubernetes automatically updates the Load Balancer when nodes change or die.

    • âś… Cloud Integration: Deep integration with cloud provider features via annotations.

    • âś… Reduced Maintenance: No need to manually track Node Ports or update target groups.

    The CARTO router service remains internal to the cluster (ClusterIP). A Kubernetes Ingress or GatewayAPI resource (managed separately from Helm) handles external access, SSL termination, and routing.

    When to use:

    • Standard Kubernetes deployments on cloud providers (GKE, EKS, AKS)

    • Teams familiar with Kubernetes networking patterns

    • Need for native Kubernetes certificate management (cert-manager, cloud-managed certs)

    • Multi-service deployments sharing the same ingress controller

    Configuration:

    Key characteristics:

    • âś… Kubernetes-native: Uses standard Ingress resources and controllers

    • âś… Ecosystem integration: Works seamlessly with cert-manager, external-dns, etc.

    • âś… Simpler architecture: No need to manage node IPs or port mappings

    CARTO Self-Hosted supports two primary SSL/TLS termination strategies. Your choice should align with your security requirements, compliance needs, and operational preferences:

    • TLS Offloading (recommended): Termination occurs at the external Load Balancer or Ingress.

    • End-to-End TLS: TLS traffic passes through to the CARTO Router, which handles termination.

    Use this table to quickly determine the best strategy for your TLS/SSL Configuration in CARTO deployment.

    In this recommended architecture, SSL/TLS is terminated at your Load Balancer or Ingress Controller. HTTP traffic is then forwarded internally to the CARTO Router.

    When to Use

    • Standard production deployments.

    • Requirement for automated certificate provisioning and renewal (zero manual intervention).

    • Integration with WAF or DDoS protection.

    • Simplified operations with no certificate expiration concerns.

    No explicit TLS configuration is needed within the CARTO Helm chart, the external component handles all SSL aspects.

    In this setup, SSL/TLS remains encrypted all the way to the CARTO Router, which is responsible for TLS termination.

    When to Use

    • Strict compliance requirements mandating encryption throughout the infrastructure.

    • Zero-trust architectures that require absolute end-to-end encryption.

    • Requirement for Client Certificate Authentication.

    Before configuring the Helm chart, you must obtain a valid SSL/TLS certificate from a Certificate Authority (CA).

    Certificate Requirements:

    • Valid SSL certificate for your CARTO domain

    • Full certificate chain (server certificate + intermediate CA certificates)

    • Private key corresponding to the certificate

    • PEM-encoded format for both certificate and key

    The Helm chart requires certificates to be base64-encoded without line breaks.

    You must explicitly enable TLS and reference a Kubernetes secret containing your certificate and key.

    âś… Ingress managed separately

    Cloud Load Balancer +

    Kubernetes creates cloud LB automatically (internal recommended). Exposed via user-managed Cloud Load Balancer.

    Production deployments in private/public clusters

    âś… Ingress managed separately

    Helm-managed

    Kubernetes automatically provisions a cloud load balancer, fully managed through Helm. This approach offers limited flexibility for advanced security customizations.

    Production with soft network security requirements

    âś… LB managed by Helm chart.

    + Cloud Load Balancer

    Service internal to cluster managed by helm chart. User-managed Cloud LB points to NodePorts

    Production deployments in private clusters

    ⚠️ Not recommended for production

    Helm-managed

    Service exposed on static port on each node

    Development/testing

    ⚠️ Not recommended for production

    Helm-managed

    Ingress Layer managed by Helm Chart

    Not recommended.

    ❌ To be deprecated.

    Helm-managed

    GatewayAPI usage managed by the Helm Chart.

    Not recommended for Helm deployments.

    ❌ To be deprecated.

    Firewall allow-list (CIDR ranges) for access control

    ⚠️ Cost: Typically provisions one dedicated Load Balancer per service (higher cost than Ingress) + the standalone load balancer you setup on your own.
    âś… Cloud provider integration: GKE Ingress, AWS ALB Controller, Azure AGIC available
  • ⚠️ Ingress/GatewayAPI controller required: Must install/configure if not pre-existing

  • ⚠️ Learning curve: Requires understanding of Ingress concepts and annotations

  • ⚠️ May suffice, check policy

    âś… Required by stricter policies

    Zero-trust architecture

    ⚠️ Not ideal

    âś… Required

  • For standard deployments, use TLS Offloading. It provides the best operational experience with zero certificate expiration risk.

  • ClusterIP + GatewayAPI

    Service internal to cluster managed by helm chart. Exposed via user-managed GatewayAPI controller

    Production deployments in private/public clusters

    âś… Ingress managed separately

    ClusterIP + Ingress Layer

    Service internal to cluster managed by helm chart. Exposed via user-managed Ingress controller

    router:
      service:
        type: LoadBalancer

    Parameter

    Description

    router.service.type

    Set to LoadBalancer

    router.service.annotations

    Key-value pairs for cloud-specific settings

    router.service.loadBalancerIP

    Request a specific static IP (if supported by provider)

    router:
      service:
        type: LoadBalancer
        annotations:
          # Use AWS Network Load Balancer (NLB) or Classic (CLB)
          service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
          # Reference an ACM Certificate ARN for SSL termination
          service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:us-east-1:123456789012:certificate/uuid"
          # Configure SSL ports
          service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
          # Connection settings
          service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "605"
          service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
    router:
      service:
        annotations:
          cloud.google.com/load-balancer-type: "Internal"
    router:
      service:
        annotations:
          service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    router:
      service:
        type: ClusterIP  # Default value

    Requirement

    Option A: TLS Offloading (recommended)

    Option B: End-to-End TLS

    Automatic certificate renewal

    âś… Yes (Managed by LB/Ingress or third party)

    ⚠️ Manual process or other integration required

    Zero operational overhead

    âś… Yes

    ❌ Regular maintenance needed

    ClusterIP + Ingress

    router.service.type: ClusterIP

    router.service.ports.http: 80

    The Ingress Controller performs TLS termination and forwards to ClusterIP port 80.

    ClusterIP + Cloud LB

    router.service.type: ClusterIP

    router.service.ports.http: 80

    The Cloud Load Balancer performs TLS termination and forwards to ClusterIP.

    # Example: Configuration for TLS Offloading
    ## Disable HTTPS and disable cert autogeneration.
    tlsCerts:
      httpsEnabled: false
      autoGenerate: false
    router:
      service:
        type: ClusterIP
        ports:
          http: 80
    # 1. Encode the full certificate chain (including intermediates)
    cat /path/to/fullchain.pem | base64 | tr -d '\n' > cert.b64
    
    # 2. Encode the private key
    cat /path/to/privkey.pem | base64 | tr -d '\n' > key.b64
    
    # 3. View the encoded values (you'll copy these into your values file)
    echo "Certificate (base64):"
    cat cert.b64
    echo ""
    echo "Private Key (base64):"
    cat key.b64
    # Example: Configuration for End-to-End TLS
    ## Enable HTTPS and disable cert autogeneration.
    tlsCerts:
      httpsEnabled: true
      autoGenerate: false
    
    router:
      service:
        type: ClusterIP
        ports:
          https: 443
          httpsTargetPort: "https"
    
      ## Add the base64 cert keys to the router. 
      tlsCertificates:
        certificateValueBase64: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZaRENDQk..."
        privateKeyValueBase64: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQU..."
        

    2. Load balancing and publishing architecture

    3. Recommended Load Balancing patterns:

    3.1 Load Balancer service + Cloud Load Balancer

    3.1.1 How it works:

    3.1.2 Configuration

    3.1.3 Advanced configuration: annotations

    3.1.4 Example: AWS Load Balancer configuration

    3.1.5 Common annotation cheatsheet:

    Key characteristics

    3.2 ClusterIP service + User-managed Ingress/GatewayAPI layer

    4. TLS/SSL configuration

    Certificates and private keys used in this process must not be encrypted or protected with a passphrase. CARTO Self-Hosted does not support encrypted certificates. This requirement applies to all components and configuration steps where TLS certificates are used.

    4.1 Decision guide

    4.2 Option A: TLS Offloading (recommended)

    Key Benefit: The entire certificate lifecycle is managed automatically at the load balancer or ingress level. This eliminates the operational burden of certificate rotation.

    4.2.1 Customizations.yaml for TLS Offloading

    4.3 Option B: End-to-End TLS

    Crucial Responsibility: You are fully responsible for the certificate lifecycle management (acquisition, renewal, and rotation).

    4.3.1 Certificate preparation

    4.3.2 Encode certificates to Base64

    Notes:

    • The tr -d '\n' command removes all line breaks, creating a single-line base64 string

    • On macOS, you can also use base64 -i /path/to/file without line breaks

    • Keep these base64 strings secure - they contain your private key

    4.3.3 Customizations.yaml for End-to-End TLS

    Architecture

    Production deployments in private/public clusters

    router.service.loadBalancerSourceRanges

    Compliance

    Configure your own buckets (Helm)

    For CARTO Self-hosted using Kubernetes and Helm

    This documentation only applies to advanced Orchestrated container deployments using Kubernetes and Helm

    1. Overview

    Every CARTO Self-Hosted installation requires two cloud storage buckets to handle data and assets used by the platform:

    Purpose
    Is Mandatory?
    Description
    Example contents

    1. Import Bucket

    Yes

    You can create and use your own storage buckets in any of the following supported storage providers:

    1. (Optional) Create the data export bucket. This bucket has to be created in different storage providers depending on your data warehouse:

      • BigQuery:

      • Snowflake:

    1. Import Bucket

    2. Thumbnails Bucket

    3. Export Bucket (optional)

    There are no naming constraints for these buckets.

    • Thumbnails objects (.png) can be public (default) or private.

    • To make them private, set:

    • ⚠️ Some features (branding, custom markers) require public access. To keep the bucket private while allowing these features:

    Data Warehouse
    Required Storage Provider

    Required for Import and Thumbnails Buckets

    Setting
    Value

    CORS configuration location:

    • GCS / S3: Bucket level

    • Azure Blob: Storage account level

    For more details, refer to:

    • Google Cloud Storage CORS Setup

    • AWS S3 CORS Setup

    • Azure Blob CORS Setup

    The buckets access from the Carto platform require authentication configuration. You'll find below the authentication methods available for each provider:

    Provider
    Auth Method

    In order to use Google Cloud Storage custom buckets you need to:

    1. Add the following lines to your customizations.yaml and replace the <values> with your own settings:

    Note that thumbnailsBucketExternalURL could be https://storage.googleapis.com/<thumbnails_bucket_name>/ for public access or https://storage.cloud.google.com/<thumbnails_bucket_name>/ for authenticated access.

    To enable exporting data from BigQuery on CARTO Self-Hosted platform these are the required steps:

    1. Grant read/write permissions to the service account used by your CARTO Self-Hosted installation on the GCS bucket created in the .

    2. Define the name the bucket that will be used for exporting data in your customizations.yaml file:

    Snowflake and Redshift require an AWS S3 bucket to export data from CARTO platform. These are the needed steps for allowing exporting data from CARTO Self-Hosted in these providers:

    1. Create an IAM user and generate a programmatic key ID and secret. If server-side encryption is enabled, the user must be granted with permissions over the KMS key used.

    1. Create an AWS IAM role with the following settings:

      1. Trusted entity type: Custom trust policy.

      2. Custom trust policy: Make sure to replace <your_aws_user_arn>.

    Pass your AWS credentials as secrets:

    • Option 1: Automatically create the secret:

    appSecrets.exportAwsSecretAccessKey.value and appSecrets.exportAwsAccessKeyId.value be in plain text, preserving the multiline and correctly tabulated.

    • Option 2: Using existing secret: Create a secret running the command below:

      Add the following lines to your customizations.yaml, without replacing any value:

    The bucket to export data from Amazon RDS for PostgreSQL can be configured from the CARTO platform UI. Once your Self-Hosted installation is finished, you can check in the following documentation .

    LoadBalancer Service
    LoadBalancer Service
    NodePort
    NodePort Service
    Ingress Layer
    GatewayAPI
    Redshift: AWS S3
  • Amazon RDS: AWS S3

  • Enable public objects

  • Allow ACLs (non-uniform permissions)

  • Disable server-side encryption

  • AWS S3

    Oracle

    AWS S3

    Azure extra headers

    Access-Control-Request-Headers, X-MS-Blob-Type

    Max age

    3600

    Select a Service Account that will be used by the application to interact with the buckets. There are two options:
    1. Using a custom Service Account, that will be used not only for the buckets, but for the services deployed by CARTO as well. If you are using Workload Identity, that's your option.

    2. Using a dedicated Service Account only for the buckets

  • Grant the selected Service Account with the role roles/iam.serviceAccountTokenCreator in the GCP project where it was created.

  • ⚠️ We don't recommend granting this role at project IAM level, but instead at the Service Account permissions level (IAM > Service Accounts > your_service_account > Permissions).

    1. Grant the selected Service Account with the role roles/storage.admin to the buckets created.

    2. [OPTIONAL] Pass your GCP credentials as secrets: This is only required if you are going to use a dedicated Service Account only for the buckets

      • Option 1: Automatically create the secret:

        appSecrets:
          googleCloudStorageServiceAccountKey:
            value: |
              <REDACTED>

      appSecrets.googleCloudStorageServiceAccountKey.value should be in plain text, preserving the multiline and correctly tabulated.

      • Option 2: Using existing secret: Create a secret running the command below, after replacing the <PATH_TO_YOUR_SECRET.json> value with the path to the file of the Service Account:

        Add the following lines to your customizations.yaml, without replacing any value:

    In order to use AWS S3 custom buckets you need to:

    1. Create an IAM user and generate a programmatic key ID and secret.

    2. Grant this user with read/write access permissions over the buckets. If server-side encryption is enabled, the user must be granted with permissions over the KMS key used.

    3. Add the following lines to your customizations.yaml and replace the <values> with your own settings:

    Note that thumbnailsBucketExternalURL should be https://<thumbnails_bucket_name>.s3.amazonaws.com/

    1. Pass your AWS credentials as secrets by using one of the options below:

      • Option1: Automatically create a secret

        Add the following lines to your customizations.yaml replacing it with your access key values:

        appSecrets.awsAccessKeyId.value and appSecrets.awsAccessKeySecret.value

    In order to use Azure Storage buckets you need to:

    1. Generate an Access Key, from the storage account's Security properties.

    2. Add the following lines to your customizations.yaml and replace the <values> with your own settings:

    appConfigValues:
      storageProvider: "azure-blob"
      azureStorageAccount: <storage_account_name>
      workspaceImportsBucket: <import_bucket_name>
      workspaceImportsPublic: <false|true>
      workspaceThumbnailsBucket: <thumbnails_bucket_name>
      thumbnailsBucketExternalURL: <external bucket URL>
      workspaceThumbnailsPublic: <false|true>

    Note that thumbnailsBucketExternalURL should be https://<azure_resource_group>.blob.core.windows.net/<thumbnails_bucket_name>/

    1. Pass your credentials as secrets by using one of the options below:

      • Option 1: Automatically create the secret: Add the following lines to your customizations.yaml replacing it with your access key value:

        appSecrets.azureStorageAccessKey.value should be in plain text

    Add permissions: Create a new permissions' policy, replacing <your_aws_s3_bucket_name>.

  • Update your customizations.yaml file with the following values:

  • Used to upload and import datasets into CARTO.

    .csv, .geojson, .zip

    2. Thumbnails Bucket

    Yes

    Stores generated map thumbnails and customization assets (logos, markers, etc.).

    .png images

    3. Export Bucket

    No, this bucket is optional

    Used for exporting data from your data warehouse (BigQuery, Snowflake, Redshift, or Amazon RDS). Create this only if you plan to use data export features.

    .csv, .json, .parquet

    WORKSPACE_THUMBNAILS_PUBLIC="false"

    BigQuery

    Google Cloud Storage

    Snowflake

    AWS S3

    Redshift

    AWS S3

    Allowed origins

    *

    Allowed methods

    GET, PUT, POST

    Allowed headers (common)

    Content-Type, Content-MD5, Content-Disposition, Cache-Control

    GCS extra headers

    GCS

    Service Account Key

    AWS S3

    Access Key ID + Secret Access Key

    Azure Blob

    Access Key

    appConfigValues:
      storageProvider: "gcp"
      workspaceImportsBucket: <import_bucket_name>
      workspaceImportsPublic: <false|true>
      workspaceThumbnailsBucket: <thumbnails_bucket_name>
      workspaceThumbnailsPublic: <false|true>
      thumbnailsBucketExternalURL: <public or authenticated external bucket URL>
      googleCloudStorageProjectId: <gcp_project_id>
    appConfigValues:
        workspaceExportsBucket: <YOUR_EXPORTS_BUCKET>
    {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "AWS": "<your_aws_user_arn>"
              },
              "Action": [
                  "sts:AssumeRole",
                  "sts:TagSession"
              ]
          }
      ]
    }
    appConfigValues:
        awsExportBucket: <BUCKET_NAME>
        awsExportBucketRegion: <REGION>
        exportAwsRoleArn: <ROLE_ARN>
    appSecrets:
      exportAwsSecretAccessKey:
        value: <REDACTED>
      exportAwsAccessKeyId:
        value: <REDACTED>
    kubectl create secret generic \
      [-n my-namespace] \
      mycarto-export-aws-access-key \
      --from-literal=key-id=<ACCESS_KEY_ID>
      --from-literal=key-secret=<ACCESS_KEY_SECRET>
    appSecrets:
      exportAwsSecretAccessKey:
        existingSecret:
          name: mycarto-export-aws-access-key
          key: key-id
      exportAwsAccessKeyId:
        existingSecret:
          name: mycarto-export-aws-access-key-id
          key: key-secret

    2. Pre-requisites

    2.1. Create the required buckets

    3. Configuration notes

    3.1. Thumbnails bucket access

    3.2. Export bucket provider requirements

    3.3. CORS Configuration

    3.4. Authentication requirements

    If you can't setup Service Account Keys, Access Keys or Secret Access Key due to security constraints or other reasons you can setup GCP Workload Identity or EKS Pod Identity using the following guides:

    • Use Workload Identity in GCP (Helm)

    • Use EKS Pod Identity in AWS (Helm)

    4. Setup per provider

    4.1 Import and Thumbnails buckets

    5. Data export bucket

    5.1 BigQuery

    5.2 Snowflake and Redshift

    If you've already configured the Import and Thumbnails buckets using AWS S3, you can use the same user you already created for these buckets.

    Configure data exports in Amazon RDS for PostgreSQL

    Google Cloud Storage
    AWS S3
    Azure Blob Storage
    Google Cloud Storage
    AWS S3
    pre-requisites
    how to configure your S3 bucket integration for Amazon RDS for PostgreSQL

    Amazon RDS (PostgreSQL)

    x-goog-content-length-range, x-goog-meta-filename

    {
       "Version": "2012-10-17",
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "s3:ListBucket",
               "Resource": "arn:aws:s3:::<your_aws_s3_bucket_name>"
           },
           {
               "Effect": "Allow",
               "Action": "s3:*Object",
               "Resource": "arn:aws:s3:::<your_aws_s3_bucket_name>/*"
           }
       ]
    }
    should be in plain text
  • Option 2: Using an existing secret

    Create a secret running the command below, after replacing the <REDACTED> values with your key values:

    Use the same namespace where you are installing the helm chart

    Add the following lines to your customizations.yaml, without replacing any value:

  • Option 2: Using existing secret: Create a secret running the command below, after replacing the <REDACTED> values with your key values:

    Use the same namespace where you are installing the helm chart

    Add the following lines to your customizations.yaml, without replacing any value:

    kubectl create secret generic \
      [-n my-namespace] \
      mycarto-custom-s3-secret \
      --from-literal=awsAccessKeyId=<REDACTED> \
      --from-literal=awsSecretAccessKey=<REDACTED>
    appSecrets:
      awsAccessKeyId:
        existingSecret:
          name: mycarto-custom-s3-secret
          key: awsAccessKeyId
      awsAccessKeySecret:
        existingSecret:
          name: mycarto-custom-s3-secret
          key: awsSecretAccessKey
    kubectl create secret generic \
      [-n my-namespace] \
      mycarto-custom-azure-secret \
      --from-literal=azureStorageAccessKey=<REDACTED>
    appSecrets:
      awsAccessKeyId:
        existingSecret:
          name: mycarto-custom-azure-secret
          key: azureStorageAccessKey
    kubectl create secret generic \
      [-n my-namespace] \
      mycarto-google-storage-service-account \
      --from-file=key=<PATH_TO_YOUR_SECRET.json>
    appSecrets:
      googleCloudStorageServiceAccountKey:
        existingSecret:
          name: mycarto-google-storage-service-account
          key: key
    appConfigValues:
      storageProvider: "s3"
      workspaceImportsBucket: <import_bucket_name>
      workspaceImportsPublic: <false|true>
      workspaceThumbnailsBucket: <thumbnails_bucket_name>
      workspaceThumbnailsPublic: <false|true>
      thumbnailsBucketExternalURL: <external bucket URL>
      awsS3Region: <s3_buckets_region>
    appSecrets:
      awsAccessKeyId:
        value: "<REDACTED>"
      awsAccessKeySecret:
        value: "<REDACTED>"
    appSecrets:
      azureStorageAccessKey:
        value: "<REDACTED>"