An air-gapped environment ensures that all the applications, networks, and resources in the environment are physically isolated from external inputs to prevent potential security risks.

In this context, if you need to operate with artifacts that are not within your network, you have to mirror them to the air-gapped environment so that your teams are able to consume them under secure conditions.

VMware Tanzu Application Catalog (TAC) provides your enterprise with a customizable selection of open source software from Bitnami that is continuously maintained and verifiably tested for use in production environments.

To consume TAC content in an air-gapped enterprise environment, you can use a Harbor private repository installed in a private Kubernetes cluster and synchronize it with the TAC demo repository. This ensures that enterprise teams always have access to the most updated collection of Helm charts and container images without compromising the security of the air-gapped environment.

The best option to synchronize the TAC demo repository with a Harbor private repository in an air-gapped environment is to install the charts-syncer tool on the same Kubernetes cluster where Harbor is running. This tool is open source and therefore easily auditable. It is completely reliable and secure, since it is executed only within the air-gapped environment.

Understand the charts-syncer tool

In order to synchronize both repositories, the charts-syncer tool makes some changes in the migrated charts to ensure that the images present in your registry contain the right information. The main changes performed by the tool on each migrated chart are as follow:

  • It updates all Docker image references used by the chart. Thus, it uses images from the private container registry by default, instead of pulling Bitnami images from Docker Hub.
  • It changes the README file of each chart to update the chart repository location (in this case, your Harbor private registry).

TIP: Find more information about the changes that the charts-syncer tool performs in a chart in its README file.

This guide shows you step-by step how to use the charts-syncer tool to synchronize the TAC demo repository with your private Harbor repository in a Kubernetes cluster running on your secure network.

Assumptions and prerequisites

This guide assumes that:

  • You have access to the Tanzu Application Catalog (TAC) Demo environment. If you are a VMware employee, you can ask for access internally. For customer access, please reach out to your VMware sales representative.
  • You have administrator access to a pre-existing installation of Harbor, configured in line with existing enterprise requirements. If you don't already have Harbor, you can install it using Bitnami's Harbor Helm chart, and you can learn more about Harbor on its website.
  • You have a Docker environment installed and configured. Learn more about installing Docker.
  • You have a Kubernetes cluster. Check out our Getting Started with Kubernetes guide for an easy way to get started with one.
  • Tanzu Application Catalog container images are already pushed to a Harbor private repository accessible from the Kubernetes cluster where the charts are going to be installed. Learn more about consuming TAC container images using a private Harbor registry.

Step 1: Build the charts-syncer tool image

To get started, clone the charts-syncer tool repository which contains all the files needed to deploy the tool on a Kubernetes cluster. After cloning, build the charts-syncer container image.

To clone the charts-syncer tool repository, execute the following command:

$ git clone
$ cd charts-syncer

It will clone the entire charts-syncer repository. In this repository, you will find the following files amongst others:

  • deployment/configmap.yaml file: This is an example of the tool configuration file where the chart-syncer.yaml is present. Check out the specific Harbor example to learn more about how to configure the syncronization with a private Harbor repository.
  • deployment/cronjob.yaml file: This file contains the cron job information for configuring the job to be executed periodically.
  • Dockerfile: A text file that contains instructions on how to build the Docker image for the charts-syncer tool.

To build the charts-syncer image, follow these steps:

  1. Create a folder named dist:

    $ mkdir dist
  2. Download latest version of the binary into the dist folder (this example uses Linux, select the right binary according to your operating system replacing the X.Y.Z placeholder with the latest version of the binary):

    $ curl -lo dist/charts-syncer.tar.gz
  3. Uncompress the tarball:

    $ tar xzf dist/charts-syncer.tar.gz -C dist
  4. Run the docker build command to build the image from the Dockerfile. Add a tag to identify the application version. Remember to replace the USERNAME placeholder with your Docker ID and X.Y.Z with the current version of the application.

    $  docker build -t USERNAME/charts-syncer:X.Y.Z .

Step 2: Configure the charts-syncer tool

The next step is configuring the tool to sync both the source and the target repositories. This information should be specified in the deployment/configmap.yaml file where you will find the following values:

  • source: It refers to the repository from where the charts will be fetch. In this example, the TAC demo repository.
  • target: This is the repository where we want to push the charts. In this example, your Harbor private repository.
    • containerRegistry and containerRepository parameters will be used to replace the default values in the values.yaml file for populating the container images to that registry.

To configure the tool to synchronize the source repository with the target, edit the deployment/configmap.yaml file as shown below. Remember to replace the HARBOR_DOMAIN and HARBOR_PROJECT placeholders with the domain of your Harbor installation and the name of the project where you want to push the charts, respectively:

apiVersion: v1
kind: ConfigMap
  name: charts-syncer-config
  charts-syncer.yaml: |-
        kind: "HELM"
        url: ""
      containerRegistry: "HARBOR_DOMAIN"
      containerRepository: "HARBOR_PROJECT"
      repoName: "HARBOR_PROJECT"
        kind: "HARBOR"
        url: "https://HARBOR_DOMAIN/chartrepo/HARBOR_PROJECT"

IMPORTANT: If the source or the target repository needs any kind of authentication, you must specify these values in the auth section as follows:

        name: chart-syncer-credentials
        key: target-username
        name: chart-syncer-credentials
        key: target-password

Step 3: Configure the cron job

To deploy the tool as a cron job in your Kubernetes cluster, you need to edit the deployment/cronjob.yaml manifest file of the tool to specify the frequency of the job and the repository where the charts-syncer image is available.

In the example below, the environment variables of the source repository have been removed since there is no authentication method needed in this example.

Your deployment/cronjob.yaml manifest file should look like this:

apiVersion: batch/v1beta1
kind: CronJob
  name: charts-syncer
  schedule: "0 1 * * *"
  concurrencyPolicy: Forbid
          restartPolicy: OnFailure
          - name: c3styncer
            imagePullPolicy: Always
            image: bitnami-labs/charts-syncer
            args: ["sync", "--config", "/charts-syncer.yaml", "-v", "4", "--from-date", "YYYY-MM-DD"]
              - name: TARGET_AUTH_USERNAME
                    name: chart-syncer-credentials
                    key: target-username
              - name: TARGET_AUTH_PASSWORD
                    name: charts-syncer-credentials
                    key: target-password
              - name: config
                mountPath: /charts-syncer.yaml
                subPath: charts-syncer.yaml
          restartPolicy: OnFailure
            - name: config
                name: charts-syncer-config

In the above example, the frequency has been set to 0 1 * * * to execute the job on a daily basis. Remember to replace the YYYY-MM-DD placeholder with the date from which you want to synchronize the repository.

NOTE: The "--from-date" parameter is optional. Use this to save disk space by retrieving only the latest versions of the charts in the TAC repository.

Step 4: Create the charts-syncer secret with credentials

As you can see in the deployment/cronjob.yaml manifest file from the previous section, the target repository entry references a chart-syncer-credentials secret. This secret holds the credentials for the chart-syncer tool to use when pushing the charts catalog into the target repository.

The next step is to create a secret containing the TARGET_AUTH_USERNAME and TARGET_AUTH_PASSWORD keys. To do so, create a secret named chart-syncer-credentials by running the command below.

NOTE: In the example below, the * --from-literal=target-password='HARBOR_ROBOT_ACCOUNT'* is optional. You only need to add if you have enabled a Harbor Robot Account for your private repository. In that case, replace HARBOR_ROBOT_ACCOUNT with the token you obtained when creating a robot account for your project.

$  kubectl create secret generic chart-syncer-credentials --from-literal=target-username='robot$chart-syncer' --from-literal=target-password='HARBOR_ROBOT_ACCOUNT'

Step 5: Deploy the charts-syncer tool in your Kubernetes cluster

Now that you have the charts-syncer tool properly configured, deploy it in the same Kubernetes cluster as your Harbor installation. Follow these steps:

  1. Deploy the manifests files by executing:

    $ kubectl create -f deployment/
  2. Check that the cron job is working as expected:

    $ kubectl get cronjob
    charts-syncer   0 1 * * *   False     0        <none>          2m19s
  3. Check that the configMap configuration was correctly deployed:

    $ kubectl get configmaps
    NAME                   DATA   AGE
    charts-syncer-config   1      2m25s
  4. Check that the chart-syncer secret was created:

    $ kubectl get secret
    NAME                                  TYPE                                  DATA   AGE
    chart-syncer-credentials              Opaque                                2      4m10s

Since the cron job was configured to be executed on a daily basis, after one day you will be able to check that it is working smoothly. A new pod will be created when executing the tool, so you can check it by running the kubectl get pods command:

$ kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
charts-syncer-POD-NAME   1/1     Running   0          52s

For more detail, you can run kubectl logs POD-NAME to obtain more details about the status of the synchronization task. Remember to replace POD-NAME with the name of the pod running the charts-syncer tool. This pod name can be obtained from the kubectl get pods command, as shown above.

$ kubectl logs -f charts-syncer-POD-NAME

In addition, you can navigate to the Harbor UI and navigate to your project to see that all the TAC Helm charts are pushed to your registry.

TAC repository syncrhonized with a Harbor private repository

Useful links

check-circle-line exclamation-circle-line close-line
Scroll to top icon