Deploy to Kubernetes
This page covers installing Enterprise Studio with Helm, configuring values, managing secrets, and setting up TLS.
Prerequisites
-
helm(v3.8+): Install Helm -
kubectl: Install kubectl -
Access to a Kubernetes enviroment (cloud, on-prem, or local with a LoadBalancer resource implementation).
Configure Helm
Add the Enterprise Studio Helm chart repository.
helm repo add \
enterprise-studio https://dist.neo4j.org/enterprise-studio/helm
Update repository
helm repo update enterprise-studio
Check available versions of Enterprise Studio Helm charts
helm search repo enterprise-studio/ --versions
Export a values template to use as a starting point:
helm show values \
enterprise-studio/neo4j-enterprise-studio \
--version '<VERSION>' > values.yaml
Configure values
Edit values.yaml with your deployment settings.
At a minimum, you need to configure:
-
Asset storage connection (URI, database name, credentials)
-
At least one Neo4j deployment for users to connect to
See Reference for the full list of available settings.
Minimal example
Replace <ASSET-STORAGE-HOST>, <DEPLOYMENT-HOST>, <NEO4J-SERVICE-ACCOUNT>, and <NEO4J-SERVICE-ACCOUNT-PASSWORD> with values from your environment, and provide your Enterprise Studio license.
secrets:
licenseKey: | (1)
<contents of your nes.license file>
assetStorageCredentials:
username: "<NEO4J-SERVICE-ACCOUNT>"
password: "<NEO4J-SERVICE-ACCOUNT-PASSWORD>"
assetStorage:
uri: "neo4j://<ASSET-STORAGE-HOST>:7687"
database: tools-storage
neo4jDeployments: (2)
minexample:
name: "Minimal Example"
uri: "http://<DEPLOYMENT-HOST>:7474"
| 1 | A valid license is required to start. The chart writes this into a Secret and mounts it at license.path (default /app/nes.license). To reference an existing Secret instead, use secretsFromSecrets.licenseKey. |
| 2 | neo4jDeployments is a map keyed by deployment id (letters and digits only). Each entry needs at least name and uri. See Configuration → Neo4j deployments for the full schema. <DEPLOYMENT-HOST> — hostname or IP of the Neo4j deployment Studio users connect to (HTTP port 7474).
|
|
If a deployment |
After you install with the example release name my-enterprise-studio, you can reach Enterprise Studio from your machine in a local setup (without a load balancer or ingress) by port-forwarding the HTTP service and opening the app in your browser:
kubectl port-forward svc/my-enterprise-studio-http 8080:80
Open http://localhost:8080 in your browser while the port-forward command is running.
Install
helm install my-enterprise-studio \
enterprise-studio/neo4j-enterprise-studio \
--version '<VERSION>' \
--values values.yaml
Verify the release is running:
kubectl get pods -l app.kubernetes.io/instance=my-enterprise-studio
Ensure the service my-enterprise-studio-http on port 80 is reachable from outside the cluster.
Upgrade
To upgrade to a new version or apply configuration changes:
helm upgrade my-enterprise-studio \
enterprise-studio/neo4j-enterprise-studio \
--version '<VERSION>' \
--values values.yaml
To roll back to the previous release:
helm rollback my-enterprise-studio
Uninstall
helm uninstall my-enterprise-studio
|
This removes all Kubernetes resources created by the chart. It does not delete the asset storage database or any data in Neo4j. |
Managing secrets
For production, do not store credentials in values.yaml.
Use a cloud Secrets Manager when available (see Cloud Secrets Managers); otherwise use pre-created Kubernetes Secrets via secretsFromSecrets.
Using external Secrets
Reference existing Secrets by name:
secretsFromSecrets:
assetStorageCredentials: "nes-storage" (1)
tlsSecretName: "nes-tls" (2)
| 1 | Name of a kubernetes.io/basic-auth Secret containing username and password keys. |
| 2 | Name of a kubernetes.io/tls Secret (e.g. from cert-manager) containing tls.crt and tls.key. |
Chart behavior with external Secrets
-
Asset storage: When
secretsFromSecrets.assetStorageCredentialsis set, the chart does not create its own credentials Secret; the Deployment references your Secret directly. -
TLS: When
secretsFromSecrets.tlsSecretNameis set, the chart uses that existing TLS Secret for Ingress or in-pod HTTPS (depending on your TLS configuration). The inlinesecrets.ingressTlsCert/secrets.ingressTlsKeyvalues are ignored.
Install-time alternatives
If Helm lookup is disabled in your environment, inject secrets at install time:
helm install my-enterprise-studio \
enterprise-studio/neo4j-enterprise-studio \
--version '<VERSION>' \
--values values.yaml \
--set secrets.assetStorageCredentials.password="$(kubectl get secret nes-storage -o jsonpath='{.data.password}' | base64 -d)" \
--set-file secrets.ingressTlsCert=./certs/tls.crt \
--set-file secrets.ingressTlsKey=./certs/tls.key
Cloud Secrets Managers
If Helm values use Secrets Manager references (usernameFrom, passwordFrom, or clientSecretFrom), give the pod cloud credentials through workload identity — do not put access keys in values or config.yaml.
When passwordFrom or usernameFrom is set, the chart does not inject that field from a Kubernetes Secret; it only creates or references the ServiceAccount.
Secret shape and required permissions are covered under Configuration → Secrets Manager.
Wire identity into Helm via serviceAccount (and podLabels on AKS) as shown below.
| Provider | Recommended identity |
|---|---|
AWS (EKS) |
|
Azure (AKS) |
|
Google Cloud (GKE) |
AWS
Configure pod identity with IRSA (see also Assign IAM roles to Kubernetes service accounts). Ensure the role can read the secrets Enterprise Studio will resolve.
In Helm values, annotate the ServiceAccount, enable secretsManager.aws, and set usernameFrom / passwordFrom with secretRef type aws.
For secret shape and permissions, see Configuration → AWS Secrets Manager.
values-aws.yamlserviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT:role/nes-studio (1)
secretsManager:
aws:
enabled: true
region: eu-west-1
secrets:
licenseKey: |
<contents of your nes.license file>
assetStorage:
uri: neo4j://my-neo4j-host:7687
database: tools-storage
authentication:
basic:
usernameFrom:
secretRef:
type: aws
name: nes-assetstore-username (2)
passwordFrom:
secretRef:
type: aws
name: nes-assetstore-password
neo4jDeployments:
production:
name: Production Graph
uri: https://neo4j-prod:7473
| 1 | IAM role ARN for this ServiceAccount. Set according to the IRSA documentation linked above. |
| 2 | Secrets Manager secret name or ARN. See Configuration → AWS Secrets Manager. |
Azure
Configure pod identity with Microsoft Entra Workload ID (see also Deploy and configure workload identity on an AKS cluster). Ensure the identity can read the secrets Enterprise Studio will resolve.
In Helm values, set the ServiceAccount annotation and podLabels, enable secretsManager.azure, and set usernameFrom / passwordFrom with secretRef type azure.
For secret shape and permissions, see Configuration → Azure Key Vault.
values-azure.yamlserviceAccount:
create: true
annotations:
azure.workload.identity/client-id: <CLIENT_ID> (1)
podLabels:
azure.workload.identity/use: "true" (2)
secretsManager:
azure:
enabled: true
vaultUrl: https://contoso.vault.azure.net/
secrets:
licenseKey: |
<contents of your nes.license file>
assetStorage:
uri: neo4j://my-neo4j-host:7687
database: tools-storage
authentication:
basic:
usernameFrom:
secretRef:
type: azure
name: nes-assetstore-username (3)
passwordFrom:
secretRef:
type: azure
name: nes-assetstore-password
neo4jDeployments:
production:
name: Production Graph
uri: https://neo4j-prod:7473
| 1 | Managed identity client ID for this ServiceAccount. Set according to the Workload ID documentation linked above. |
| 2 | Required for Microsoft Entra Workload ID on the pod. See the Workload ID documentation linked above. |
| 3 | Key Vault secret name. See Configuration → Azure Key Vault. |
Google Cloud
Configure pod identity with Workload Identity Federation for GKE (see also Authenticate to Google Cloud APIs from GKE workloads). Ensure the identity can read the secrets Enterprise Studio will resolve.
In Helm values, annotate the ServiceAccount, enable secretsManager.gcp, and set usernameFrom / passwordFrom with secretRef type gcp.
For secret shape and permissions, see Configuration → Google Cloud Secret Manager.
values-gcp.yamlserviceAccount:
create: true
annotations:
iam.gke.io/gcp-service-account: [email protected] (1)
secretsManager:
gcp:
enabled: true
project: my-project
secrets:
licenseKey: |
<contents of your nes.license file>
assetStorage:
uri: neo4j://my-neo4j-host:7687
database: tools-storage
authentication:
basic:
usernameFrom:
secretRef:
type: gcp
name: nes-assetstore-username (2)
passwordFrom:
secretRef:
type: gcp
name: nes-assetstore-password
neo4jDeployments:
production:
name: Production Graph
uri: https://neo4j-prod:7473
| 1 | Google service account email for this ServiceAccount. Set according to the Workload Identity documentation linked above. |
| 2 | Secret Manager secret ID. See Configuration → Google Cloud Secret Manager. |
Ingress and inbound TLS
Enterprise Studio supports two inbound TLS termination models (browser → Enterprise Studio):
-
Ingress-terminated TLS: the Ingress controller handles TLS; the pod serves plain HTTP.
-
In-pod TLS (SSL passthrough): the pod terminates TLS; the Ingress just forwards encrypted traffic.
These configure Enterprise Studio as an HTTPS server only (server.https.enabled, server.https.certificates.*).
They do not affect outbound trust when Enterprise Studio calls Neo4j.
See Outbound TLS trust (private CAs) for private CA trust to Neo4j backends.
Ingress-terminated TLS
The Ingress controller handles TLS decryption.
The pod serves HTTP on server.port (default 8080).
Set ingress.httpHostName to the hostname clients use to reach Enterprise Studio.
ingress:
enabled: true
sslPassthrough: false
ingressClassName: nginx
httpHostName: studio.example.com
annotations: {}
server:
https:
enabled: false
# Provide cert inline or via secretsFromSecrets
secrets:
ingressTlsCert: '<PEM certificate>'
ingressTlsKey: '<PEM private key>'
For cert-manager, set secretsFromSecrets.ingressTlsCert.secretName to your kubernetes.io/tls Secret instead of inline PEM strings.
Use ingress.annotations to customize the Ingress controller (for example, nginx-specific settings like proxy timeouts or body size limits).
In-pod TLS (SSL passthrough)
The pod terminates TLS directly. Use this with a LoadBalancer Service, port-forwarding, or an Ingress with SSL passthrough.
server:
https:
enabled: true
certificates:
baseDirectory: certificates/https
privateKey: private.key
publicCertificate: public.crt
ingress:
enabled: true
sslPassthrough: true
ingressClassName: nginx
httpHostName: studio.example.com
secrets:
httpsTlsCert: '<PEM certificate>'
httpsTlsKey: '<unencrypted PKCS#8 private key>'
|
The nginx Ingress controller requires SSL passthrough to be enabled on the controller (e.g. |
In-pod TLS without Ingress (LoadBalancer)
If you do not need Ingress and want to expose Enterprise Studio directly via a LoadBalancer:
server:
https:
enabled: true
certificates:
baseDirectory: certificates/https
privateKey: private.key
publicCertificate: public.crt
secrets:
httpsTlsCert: '<PEM certificate>'
httpsTlsKey: '<unencrypted PKCS#8 private key>'
ingress:
enabled: false
service:
http:
type: LoadBalancer
The chart mounts the certificate and key at /app/certificates/https as public.crt and private.key.
For certificate format and key requirements, see Security → TLS encryption.
Outbound TLS trust (private CAs)
When Enterprise Studio connects to Neo4j over HTTPS or Bolt+TLS, it uses the system trust store inside the pod (/etc/ssl/certs).
There is no Enterprise Studio configuration setting for outbound TLS trust — install upstream CAs in the pod where Enterprise Studio runs.
Host OS trust does not apply inside Kubernetes pods.
Use this when:
-
deployments.*.uriuseshttps://with a private or self-signed CA -
assetStorage.uriusesneo4j+s://with a private CA
|
Outbound pod trust is independent of inbound TLS.
If TLS terminates at Ingress and Enterprise Studio serves HTTP in-pod, outbound trust is still required for HTTPS Neo4j backends and |
The Helm chart (0.2.1 and later) mounts a trusted upstream CA at /etc/ssl/certs/ca.crt in the Enterprise Studio pod when either value below is set.
| Helm value | Description |
|---|---|
|
PEM-encoded upstream CA; the chart creates an Opaque Secret and mounts it in the pod |
|
Reference an existing Secret ( |
Inline CA at install time
Pass the CA file when installing or upgrading:
helm upgrade --install my-enterprise-studio \
enterprise-studio/neo4j-enterprise-studio \
--version '<VERSION>' \
--values values.yaml \
--set-file secrets.trustedCaCert=./ca.crt
Or embed the PEM in values.yaml:
secrets:
trustedCaCert: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
Reference an existing Secret
For production, create the CA Secret separately and reference it by name:
secretsFromSecrets:
trustedCaCert:
secretName: neo4j-ca
key: ca.crt
See Security → TLS encryption for the trust model.
See Docker deployment for the equivalent procedure with docker run.
Setting up a new Neo4j instance for asset storage
If you don’t have an existing Neo4j instance for asset storage, you can deploy one alongside Enterprise Studio:
helm install nes-asset-storage neo4j/neo4j \
--set neo4j.name=nes-asset-storage \
--set neo4j.password=changeme \
--set neo4j.edition=enterprise \
--set neo4j.acceptLicenseAgreement=yes \
--set volumes.data.mode=defaultStorageClass
Find the cluster IP:
kubectl get svc nes-asset-storage
Then use that IP in your values.yaml:
assetStorage:
uri: "neo4j://<CLUSTER-IP>:7687"
database: tools-storage
Health probes
Enterprise Studio exposes a GET /health endpoint that returns 200 OK when the server is running.
It does not verify backend connectivity (for example to the asset storage database).
See Logging and monitoring → Health check endpoint for more details.
Running multiple replicas
Enterprise Studio is stateless (see Architecture → Scalability and high availability). The Helm chart supports configuring horizontal pod autoscaling. The default values are:
hpa:
spec:
targetCPUUtilizationPercentage: 70
maxReplicas: 2
Override these values in your values.yaml if needed.
|
When a deployment proxies queries to a Neo4j cluster, session affinity must be configured in front of the cluster regardless of the number of Enterprise Studio replicas. See Prerequisites → Set up communication to a Neo4j cluster. |