Accessing Neo4j using Kubernetes Ingress

The Neo4j Helm charts provide a Helm chart that allows you to use a Kubernetes Ingress to access Neo4j on port :80 or :443. The Helm chart is called neo4j/neo4j-reverse-proxy and is available on the Neo4j Helm repository from version 5.12.0. For more information about Kubernetes Ingress, see the Kubernetes official documentation → Ingress.

The Helm chart creates a reverse proxy that is configured to route traffic to the Neo4j service URL using the serviceName, namespace, and domain values. For example, if the serviceName is standalone-admin, the namespace is default, and the domain is cluster.local, then the Neo4j service URL is standalone-admin.default.svc.cluster.local.
For Neo4j clusters, the Neo4j headless service can be used to route the traffic to the cluster instances. For more information and a detailed example of how to install the neo4j/neo4j-cluster-headless-service Helm chart, see Access the Neo4j cluster using headless service.

reverse proxy
Figure 1. Reverse proxy flow diagram

The Reverse proxy Helm chart creates an HTTP server, which routes requests to either the Bolt reverse proxy or HTTP reverse proxy based on the request headers. Upon receiving a response, the Bolt reverse proxy updates the response to replace the Bolt port with either :80 or :443.

From version 5.17.0, the Reverse proxy Helm chart supports defining privilege and access control settings for a Container. Make sure that you do not run Neo4j as a root user.

Configuration options

To see all configurable options, run the following command:

helm show values neo4j/neo4j-reverse-proxy
# Default values for neo4j reverse proxy helm chart

## @param nameOverride String to partially override common.names.fullname
nameOverride: ""
## @param fullnameOverride String to fully override common.names.fullname
fullnameOverride: ""

# Parameters for reverse proxy
reverseProxy:
  image: "neo4j/helm-charts-reverse-proxy:5.17.0"
  # Name of the kubernetes service. This service should have the ports 7474 and 7687 open.
  # This could be the admin service ex: "standalone-admin" or the loadbalancer service ex: "standalone" created via the neo4j helm chart
  # serviceName , namespace , domain together will form the complete k8s service url. Ex: standalone-admin.default.svc.cluster.local
  # When used against a cluster ensure the service being used is pointing to all the cluster instances.
  # This could be the loadbalancer from neo4j helm chart or the headless service installed via neo4j-headless-service helm chart
  serviceName: ""
  # default is set to cluster.local
  domain: "cluster.local"

  # securityContext defines privilege and access control settings for a Container. Making sure that we dont run Neo4j as root user.
  containerSecurityContext:
    allowPrivilegeEscalation: false
    runAsNonRoot: true
    runAsUser: 7474
    runAsGroup: 7474
    capabilities:
      drop: [ "ALL" ]

  podSecurityContext:
    runAsNonRoot: true
    runAsUser: 7474
    runAsGroup: 7474
    fsGroup: 7474
    fsGroupChangePolicy: "Always"


  # This assumes ingress-nginx controller or haproxy-ingress-controller is already installed in your kubernetes cluster.
  # You can install ingress-nginx by following instructions on this link https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/index.md#quick-start
  # You can install haproxy-ingress by following instructions on this link https://haproxy-ingress.github.io/docs/getting-started/
  ingress:
    enabled: true
    #default value is nginx. It can be either nginx or haproxy
    className: nginx
    annotations: {}
#      "demo": "value"
#      "demo2": "value2"
    host: ""
    tls:
      enabled: false
      config: []
#      - secretName: "demo2"
#        hosts:
#          - localhost

The following steps assume that you have a Kubernetes cluster running and a standalone Neo4j Helm chart installed. The standalone Neo4j has a Neo4j service with the name standalone-admin, and it has :7474 an :7687 opened. To verify that, run:

kubectl get all, pvc, pv, configmaps, secrets

You also need to have an Ingress controller for the Kubernetes Ingress to work. The following steps use the Nginx Ingress Controller. See Ingress-Nginx Controller official documentation for more information.

If you do not have one, you can use the following command to install it:

helm upgrade --install ingress-nginx ingress-nginx \
      --repo https://kubernetes.github.io/ingress-nginx \
      --namespace ingress-nginx --create-namespace
helm upgrade --install ingress-nginx ingress-nginx \
      --repo https://kubernetes.github.io/ingress-nginx \
      --namespace ingress-nginx --create-namespace --set controller.service.externalTrafficPolicy=Local

Configure the Kubernetes Ingress

Configure the ingress-values.yaml file that you will use to install the Reverse proxy Helm chart.

Configure the ingress-values.yaml file to access Neo4j on port :443

The following example shows how to configure the ingress-values.yaml file to access Neo4j on port :443:

  1. Create a Kubernetes secret containing the Ingress self-signed certificates and then create the ingress-values.yaml file.

    1. Create a directory for the Ingress self-signed certificates:

      mkdir certs
      cd certs
    2. Create Ingress self-signed certificates:

      openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ingress.key -out ingress.cert -subj "/CN=localhost/O=neo4j" -addext "subjectAltName = DNS:localhost"
    3. Create Kubernetes secret using the Ingress self-signed certificates:

      kubectl create secret tls ingress-cert --key /path/to/your/certs/ingress.key --cert /path/to/your/certs/ingress.cert
  2. Configure the ingress-values.yaml file with the correct values for the serviceName and secretName. Ensure that the secretName is the same as the one created in the previous step. Enable TLS by setting tls.enabled to true.

    reverseProxy:
        image: neo4j/helm-charts-reverse-proxy:5.12.0
        serviceName: "standalone-admin"
        ingress:
            enabled: true
            tls:
                enabled: true
                config:
                    - secretName: ingress-cert
                      hosts:
                        - localhost

Configure the ingress-values.yaml file to access Neo4j on port :80

Alternatively, if you want to access Neo4j on port :80, leave tls.enabled with its default value false, and create the ingress-values.yaml file with the following content:

reverseProxy:
    #Use image only when need a specific version or using your internal artifactory.
    #Otherwise let it default to what is in the values.yaml
    #image: neo4j/helm-charts-reverse-proxy:5.12.0
    serviceName: "standalone-admin"
    ingress:
        enabled: true
        tls:
            enabled: false

Install the Reverse proxy Helm chart

Install the Reverse proxy Helm chart using the ingress-values.yaml file that you have created:

helm install rp neo4j/neo4j-reverse-proxy -f /path/to/your/ingress-values.yaml

Access your data via Neo4j Browser

  1. Get the Ingress LoadBalancer IP:

    kubectl get ingress/rp-reverseproxy-ingress -n default -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
  2. Open Neo4j Browser on https://INGRESS_IP:443 or http://INGRESS_IP:80 and log in with your credentials.

Access your data via Cypher Shell

Alternatively, if you want to use Cypher Shell to access your data via Nginx Ingress Controller only, you need to create a configmap, because Cypher Shell expects a TCP connection and Ingress is an HTTP connection. For more information about exposing TCP/UDP services, see Ingress-Nginx Controller official documentation → Exposing TCP and UDP services.

  1. Create a configmap with the following content:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: tcp-services
      namespace: ingress-nginx
    data:
      9000: "default/standalone-admin:7687"
  2. Apply the configmap:

    kubectl apply -f /path/to/your/nginx-tcp.yaml
  3. Update the Ingress controller LoadBalancer service to use the port :9000:

    1. Get the IP address of the Ingress controller:

      kubectl get svc -n ingress-nginx
    2. Open the Ingress controller service for editing:

      kubectl edit svc ingress-nginx-controller -n ingress-nginx -o yaml
    3. Add the following lines to the spec.ports section:

      - name: proxied-tcp-9000
        port: 9000
        protocol: TCP
        targetPort: 9000
    4. Save the changes and exit the editor.

  4. Update the Ingress controller deployment to use the configmap:

    1. Open the Ingress controller deployment for editing:

      kubectl edit deployment ingress-nginx-controller -n ingress-nginx
    2. Add the following lines to the spec.template.spec.containers.args section:

      - --tcp-services-configmap=ingress-nginx/tcp-services
    3. Save the changes and exit the editor.

    4. Verify that the changes are applied by running kubectl get all -n ingress-nginx. You should see the new port :9000 in the Ingress controller deployment.

  5. Get the IP address of the Ingress controller:

    kubectl get ingress
    NAME                     CLASS    HOSTS   ADDRESS        PORTS   AGE
    rp-reverseproxy-igress   nginx    *       34.89.91.112   80      2m
  6. Connect to the Neo4j database using Cypher Shell:

    cypher-shell -a neo4j://34.89.91.112:9000 -u neo4j -p <password>