Datalore On-Premises security considerations
Permissions
Runtime
Datalore notebook agent relies on two things which require elevated access to the runtime: CRI-U and FUSE mounts within the containers. Both of these things require at least SYS_ADMIN
capability granted to the runtime, otherwise Reactive mode and attached files won't work properly.
For the same reason, Datalore operational capacity is limited on environments with limited permission scope, like AWS Fargate.
We are looking into ways of reducing the scope of the permissions required. If Datalore is planned to be operated within the communal infrastructure, it's advised to provision a dedicated set of host machines specifically for Datalore compute agents.
Database
Make sure the Postgres' user for provisioning Datalore has CREATE privileges. This ensures proper execution of ALTER TABLE/COLUMN commands derived from Datalore SQL migrations. EXECUTE privilege is also required.
Configure TLS certificates for Datalore
Datalore does not provide any TLS-related options to its end users. Instead, it relies on third-party load balancers (or reverse proxies) to perform such a termination. As a consequence, the Datalore app itself is not normally expected to be user-faced directly without some intermediary proxy deployed next to Datalore.
This procedure describes creating another container with Nginx that will work as a reverse proxy with SSL termination.
Edit the docker-compose.yaml file as shown in the example below.
services: datalore: image: jetbrains/datalore-server:2025.2 expose: [ "8080", "8081", "5050", "4060" ] networks: - datalore-agents-network - datalore-backend-network volumes: - "datalore-storage:/opt/data" - "/var/run/docker.sock:/var/run/docker.sock" environment: # change to your domain name DATALORE_PUBLIC_URL: "https://datalore.example.com" # change to your password DB_PASSWORD: "changeme" # The following block is not required if the external database is used. postgresql: image: jetbrains/datalore-postgres:2025.2 expose: [ "5432" ] networks: - datalore-backend-network volumes: - "postgresql-data:/var/lib/postgresql/data" environment: # change to your password POSTGRES_PASSWORD: "changeme" DATABASES_COMMAND_IMAGE: "jetbrains/datalore-database-command:2025.2" nginx: image: nginx:1.26 networks: - datalore-backend-network volumes: # Adjust accordingly, as needed. - nginx-selfsigned.crt:/etc/ssl/certs/nginx-selfsigned.crt - dhparam.pem:/etc/nginx/dhparam.pem - nginx-selfsigned.key:/etc/ssl/private/nginx-selfsigned.key - ssl.conf:/etc/nginx/conf.d/ssl.conf ports: - 80:80 - 443:443 volumes: postgresql-data: { } datalore-storage: { } networks: datalore-agents-network: name: datalore-agents-network datalore-backend-network: name: datalore-backend-networkEdit the nginx ssl.conf file as shown in the example below.
server { listen 443 ssl; server_name datalore.example.com; # change to your cert and key, accordingly ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; ssl_protocols TLSv1.3; ssl_prefer_server_ciphers on; # If absent, can be generated with # openssl dhparam -out dhparam.pem 4096 ssl_dhparam /etc/nginx/dhparam.pem; ssl_ciphers EECDH+AESGCM:EDH+AESGCM; ssl_ecdh_curve secp384r1; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Comment the following two lines out # if the self-signed certificate is used. ssl_stapling on; ssl_stapling_verify on; location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-Proto "https"; proxy_pass http://datalore:8080; } } server { listen 80 default_server; server_name _; return 301 https://$host$request_uri; }
We advise to use either self-acquired certificate and private key (either self-generated or acquired from the trusted certificate authority), or Let's Encrypt as an alternative.
Perform the following steps based on a selected method:
Create a Kubernetes TLS secret, following the official Kubernetes guidance.
Adjust the
datalore.values.yaml
file, as follows, replacingdatalore.example.com
with your actual FQDN you're going to use with Datalore.ingress: enabled: true tls: - secretName: datalore-tls hosts: - datalore.example.com hosts: - host: datalore.example.com paths: - path: / pathType: Prefix annotations: nginx.ingress.kubernetes.io/proxy-body-size: 8m kubernetes.io/ingress.class: nginx
Install CertManager into your Kubernetes cluster.
Create a
letsencrypt.yaml
with the following content, replacing the placeholders as required:apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: letsencrypt-prod spec: acme: server: 'https://acme-v02.api.letsencrypt.org/directory' email: - PLACE YOUR EMAIL HERE privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: ingressClassName: nginxApply the manifest:
kubectl apply -f letsencrypt.yaml
Check the
kubectl get issuer
. Eventually, it should become as follows:kubectl get issuer 1 ↵ NAME READY AGE letsencrypt-prod True 14dAdjust the
datalore.values.yaml
file, as follows, replacingdatalore.example.com
with your actual FQDN you're going to use with Datalore.ingress: enabled: true tls: - secretName: datalore-tls hosts: - datalore.example.com hosts: - host: datalore.example.com paths: - path: / pathType: Prefix annotations: nginx.ingress.kubernetes.io/proxy-body-size: 8m kubernetes.io/ingress.class: nginx
Set the
DATALORE_PUBLIC_URL
parameter in the samedatalore.values.yaml
file. Use the same value you provided to replace"https://datalore.example.com"
in the step above.dataloreEnv: DATALORE_PUBLIC_URL: "https://datalore.example.com"Apply the configuration and restart Datalore.
Check whether the ingress controller registered the changes:
kubectl get ingress
. The expected result is adatalore
ingress with the 443 port exposed.Check whether the certificate is issued:
kubectl get certificates
. The expected output is similar to the one below.kubectl get certificates NAME READY SECRET AGE datalore-tls True datalore-tls 8m5s
Configuring the Datalore server database connection
Generate the password and store it in the Kubernetes secret, as described below. The
pwgen
tool is used here as an example. You can use any other tool or method to generate a password.PASSWORD=$(pwgen -N1 -y 32) kubectl create secret generic datalore-db-password --from-literal=DATALORE_DB_PASSWORD="$PASSWORD"Modify (or add, if not present yet) the
databaseSecret
block in yourdatalore.values.yaml
as follows:databaseSecret: create: false name: datalore-db-password key: DATALORE_DB_PASSWORDThe value of the name value is referring to a secret name defined at the previous step, while the key value is referring to the key within the secret that contains the password.
(Optional) If you are moving from plain text password storage to the secret reference: remove the
password
key with its value from thedatabaseSecret
block.Proceed based on whether this is your fresh deployment or Datalore is already installed.
Proceed with the installation. No further action is required.
Apply the configuration
helm upgrade --install -f datalore.values.yaml datalore datalore/datalore --version 0.2.28
Database password rotation
Datalore requires a permanent connection to a PostgreSQL database to operate properly. Once Datalore is deployed, the database password is saved within the environment so Datalore can re-use it later once restarted.
However, you might want to change this password later due to various compliance or operational reasons.
Locate the
values.yaml
file being used for the deployment.Depending on the method used: either replace the password within the
databaseSecret
block, OR update the secret value if the Kubernetes secret is used instead of the plain-text value.Update the Datalore deployment:
helm upgrade --install -f datalore.values.yaml datalore datalore/datalore --version 0.2.28
Locate the
docker-compose.yaml
file being used for the deployment.Update the
DB_PASSWORD
block inenvironment
block.
Configure TLS between server and agent
Perform the following procedures in the Configuration menu of the Admin panel.
Click the avatar in the upper right corner and select Admin panel from the menu.
From the Admin panel, select Configuration.
Select the Force agent SSL checkbox.
Click the avatar in the upper right corner and select Admin panel from the menu.
From the Admin panel, select Configuration.
Click the Reset secrets button.