Plugins

There are three recommended methods for adding Neo4j plugins to Neo4j Helm chart deployments. You can use:

Add plugins using an automatic plugin download

You can configure the Neo4j deployment to automatically download and install plugins. If licenses are required for the plugins, you must provide the licenses in a secret.

Install GDS Community Edition (CE)

GDS Community Edition does not require a license. To add the GDS CE, configure the Neo4j values.yaml and set the env to download the plugins:

neo4j:
  name: licenses
  acceptLicenseAgreement: "yes"
  edition: enterprise
volumes:
  data:
    mode: defaultStorageClass
env:
  NEO4J_PLUGINS: '["graph-data-science"]'
config:
  dbms.security.procedures.unrestricted: "gds.*"

Install GDS Enterprise Edition (EE) and Bloom plugins

To install GDS EE and Bloom, you must provide a license for each plugin. You provide the licenses in a Kubernetes secret.

  1. Create a secret containing the licenses:

    kubectl create secret  generic --from-file=gds.license,bloom.license gds-bloom-license
  2. Configure the Neo4j values.yaml file using the secret as the /licenses volume mount, and set the env to download the plugins:

    neo4j:
      name: licenses
      acceptLicenseAgreement: "yes"
      edition: enterprise
    volumes:
      data:
        mode: defaultStorageClass
      licenses:
        disableSubPathExpr: true
        mode: volume
        volume:
          secret:
            secretName: gds-bloom-license
            items:
              - key: gds.license
                path: gds.license
              - key: bloom.license
                path: bloom.license
    env:
      NEO4J_PLUGINS: '["graph-data-science", "bloom"]'
    config:
      gds.enterprise.license_file: "/licenses/gds.license"
      dbms.security.procedures.unrestricted: "gds.*,apoc.*,bloom.*"
      server.unmanaged_extension_classes: "com.neo4j.bloom.server=/bloom,semantics.extension=/rdf"
      dbms.security.http_auth_allowlist: "/,/browser.*,/bloom.*"
      dbms.bloom.license_file: "/licenses/bloom.license"

Add plugins using a custom container image

The best method for adding plugins to Neo4j running in Kubernetes is to create a new Docker container image that contains both Neo4j and the Neo4j plugins. This way, you can ensure when building the container that the correct plugin version for the Neo4j version of the container is used and that the resulting image encapsulates all Neo4j runtime dependencies.

The Neo4j Bloom plugin (https://neo4j.com/download-center/#bloom) requires a license activation key, which needs to be placed in a directory accessible by the Neo4j Docker container, for example, mounted to /licenses (default). To obtain a valid license, reach out to your Neo4j account representative or use the form Contact Neo4j.

Building a Docker container image that is based on the official Neo4j Docker image and does not override the official image’s ENTRYPOINT and COMMAND is the recommended method to use with the Neo4j Helm chart, as shown in this example Dockerfile:

ARG  NEO4J_VERSION
FROM neo4j:{NEO4J_VERSION}

# copy my-plugins into the Docker image
COPY my-plugins/ /var/lib/neo4j/plugins

# install the apoc core plugin that is shipped with Neo4j
RUN cp /var/lib/neo4j/labs/apoc-* /var/lib/neo4j/plugins

Once the docker image has been built, push it to a container repository that is accessible to your Kubernetes cluster.

CONTAINER_REPOSITORY="my-container-repository.io"
IMAGE_NAME="my-neo4j"

# export this so that it's accessible as a docker build arg
export NEO4J_VERSION=5.17.0-enterprise

docker build --build-arg NEO4J_VERSION --tag ${CONTAINER_REPOSITORY}/${IMAGE_NAME}:${NEO4J_VERSION} .
docker push ${CONTAINER_REPOSITORY}/${IMAGE_NAME}:${NEO4J_VERSION}

To use the image that you have created, in the Neo4j Helm deployment’s values.yaml file, set image.customImage to use the image. For more details, see Configure a custom container image.

Many plugins require additional Neo4j configuration to work correctly. Plugin configuration should be set on the config object in the Helm deployment’s values.yaml file. In some cases, plugin configuration can cause Neo4j’s strict config validation to fail. Strict config validation can be disabled by setting server.config.strict_validation.enabled: "false".

Add plugins using a plugins volume

An alternative method for adding Neo4j plugins to a Neo4j Helm deployment uses a plugins volume mount. With this method, the plugin jar files are stored on a Persistent Volume that is mounted to the /plugins directory of the Neo4j container.

The Neo4j Bloom plugin (https://neo4j.com/download-center/#bloom) requires a license activation key, which needs to be placed in a directory accessible by the Neo4j Docker container, for example, mounted to /licenses (default). To obtain a valid license, reach out to your Neo4j account representative or use the form Contact Neo4j.

The simplest way to set up a persistent plugins volume is to share the Persistent Volume that is used for storing Neo4j data. This example shows how to configure that in the Neo4j Helm deployment values.yaml file:

# neo4j-values.yaml
volumes:
  data:
    # your data volume configuration
    ...

  plugins:
    mode: "share"
    share:
      name: "data"

Details of different ways to configure volume mounts are covered in Mapping volume mounts to persistent volumes.

The Neo4j container now has an empty /plugins directory backed by a persistent volume. Plugin jar files can be copied onto the volume using kubectl cp. Because it is backed by a persistent volume, plugin files will persist even if the Neo4j pod is restarted or moved.

Neo4j loads plugins only on startup. Therefore, you must restart the Neo4j pod to load them once all plugins are in place.

For example:

# Copy plugin files into the Neo4j container
kubectl cp my-plugins/* <namespace>/<neo4j-pod-name>:/plugins/

# Restart Neo4j
kubectl rollout restart statefulset/<neo4j-statefulset-name>

# Verify plugins are still present after restart
kubectl exec <neo4j-pod-name> -- ls /plugins

Configure and install APOC core only

APOC core library is shipped with Neo4j and is located in the labs folder.

If APOC core is the only plugin that you want to add to Neo4j, it is not necessary to perform plugin installation as described above. Instead, you can configure the helm deployment to use APOC core by upgrading the deployment with these additional settings in the values.yaml file:

  1. Configure APOC core by directly pointing to the location of the APOC core library in the labs folder and by loading and unrestricting the functions and procedures you need (for more details see APOC installation guide). For example:

    config:
      server.directories.plugins: "/var/lib/neo4j/labs"
      dbms.security.procedures.unrestricted: "apoc.*"
      server.config.strict_validation.enabled: "false"
      dbms.security.procedures.allowlist: "apoc.math.*,apoc.cypher.*"
  2. Under apoc_config, configure the APOC settings that you want, for example:

    apoc_config:
      apoc.trigger.enabled: "true"
      apoc.jdbc.neo4j.url: "jdbc:foo:bar"
      apoc.import.file.enabled: "true"
  3. Run helm upgrade to apply the changes:

    helm upgrade <release-name> neo4j/neo4j -f values.yaml
  4. After the Helm upgrade rollout is complete, verify that APOC core has been configured by running the following Cypher query using cypher-shell or Neo4j Browser:

    RETURN apoc.version()

Configure credentials for the plugin’s aliases using APOC-extended

From 5.11, the Neo4j Helm chart supports configuring credentials for the plugin’s aliases using a Kubernetes secret mounted on the provided path. This feature is available apoc.jdbc.<aliasname>.url and apoc.es.<aliasname>.url via APOC-extended.

The secret must be created beforehand and must contain the key-named URL, otherwise, the Helm chart throws an error. For example: kubectl create secret generic jdbcsecret --from-literal=URL="jdbc:mysql://30.0.0.0:3306/Northwind?user=root&password=password"

Under apoc_credentials, configure aliasName, secretName, and secretMountPath. For example:

apoc_credentials: {}
#   jdbc:
#    aliasName: "jdbc"
#    secretName: "jdbcsecret"
#    secretMountPath: "/secret/jdbcCred"
#
#   elasticsearch:
#     aliasName: "es"
#     secretName: "essecret"
#     secretMountPath: "/secret/esCred"