Install the data platform on-premises offline
How to set up the Contextual Data Platform on your own hardware in an environment without internet access, including air-gapped environments
For offline installation and the special case of a fully air-gapped environment, you need another environment with internet access to download data and for generating license keys. Data needs to be transferred in both directions between the offline and the online environment at different steps, but mainly from the online to offline system and only small amounts from the offline to the online system (for the licensing).
What needs to be done in which environment is indicated by each step:
- Air-gapped system: The offline environment.
- Internet-connected system: The online environment.
Step 1: Download the installation files and information
Internet-connected system
In case of an installation on hardware without internet access, everything needed to install the services of the data platform has to be downloaded on a system with internet access and needs to be transferred to the offline or air-gapped system before the setup.
You receive license credentials from the Arango team. Store them securely on the system with internet access for repeated use.
The license credentials are composed of a client ID and client secret that you need to activate a deployment online or to generate license keys for offline deployments (e.g. air-gapped).
You either receive a package configuration file or a pre-made package for download.
A platform package is a zipped file that contains manifests and container images of various services for installing the Contextual Data Platform. You can import the platform package into your container registry from where Kubernetes can pull the images.
A Contextual Data Platform package configuration is a YAML file that defines which services to install and their configurations. You can use it to create a platform package yourself by exporting from Arango’s container registry.
Download the latest enterprise version of the ArangoDB Kubernetes Operator
kube-arangodbfrom https://github.com/arangodb/kube-arangodb/releases .Look for the file called
kube-arangodb-enterprise-x.x.x.tgz(wherex.x.xis the version number). It is the operator for x86-64 CPUs. You may need to click Show all # assets to reveal all files.Download the Arango Contextual Data Platform CLI tool
arangodb_operator_platformfrom https://github.com/arangodb/kube-arangodb/releases . It is available for Linux, macOS, and Windows for the x86-64 as well as 64-bit ARM architecture, for example:arangodb_operator_platform_darwin_arm64for macOS with Apple M1 and later CPUsarangodb_operator_platform_linux_amd64for Linux-based systems with x86-64 CPUarangodb_operator_platform_linux_arm64for Linux-based systems with 64-bit ARM CPUarangodb_operator_platform_windows_amd64for Windows with 64-bit x86-64 CPU
The Platform CLI tool simplifies the further setup and later management of the Platform’s Kubernetes services. You also need it on the system with internet access for generating license keys.
It is recommended to rename the downloaded executable to
arangodb_operator_platform(with an.exeextension on Windows) and add it to thePATHenvironment variable to make it available as a command in the system.On Linux and macOS, you need to make the file executable. Your file manager may allow that in a visual way, or you can use a command-line to run
chmod +x arangodb_operator_platform.On macOS, you may additionally need to run
xattr -r -d com.apple.quarantine arangodb_operator_platformin a command-line to remove the flag that marks it as downloaded from the internet to be able to run it.Pull the necessary images from the internet and save them to files in order to copy them to the air-gapped system.
You can use container management tool like Docker but you can also use a dedicated tool like
regctlinstead. Keep in mind that you also need this tool in the air-gapped environment to load the images into the container registry.You need at least the image of the ArangoDB Kubernetes Operator (
arangodb/kube-arangodb-enterprise). If you want to use a local MinIO instance for blob storage, make sure to also get this image (e.g.minio/minio:latest). The process is the same for any image.docker pull docker.io/arangodb/kube-arangodb-enterprise:1.4.2 docker save docker.io/arangodb/kube-arangodb-enterprise:1.4.2 -o kube-arangodb-enterprise.tarDownload the
regctlexecutables that match your systems from https://github.com/regclient/regclient/releases/ .In the following, the assumed name of the executable is
regctl.On Linux and macOS, you need to make the file executable. Your file manager may allow that in a visual way, or you can use a command-line to run
chmod +x regctl.On macOS, you may additionally need to run
xattr -r -d com.apple.quarantine regctlin a command-line to remove the flag that marks it as downloaded from the internet to be able to run it.To pull the image and save it to a file as follows:
regctl image export docker.io/arangodb/kube-arangodb-enterprise:1.4.2 kube-arangodb-enterprise.tar
Step 2: Import the images
Air-gapped system
You need to import at least the image of the ArangoDB Kubernetes Operator into your local container registry. The operator can then pull this and any other image you may need from there without internet access.
docker load -i kube-arangodb-enterprise.tar
docker tag arangodb/kube-arangodb-enterprise:1.4.2 \
<YOUR_REGISTRY_ADDRESS:5000>/arangodb/kube-arangodb-enterprise:1.4.2
docker push <YOUR_REGISTRY_ADDRESS:5000>/arangodb/kube-arangodb-enterprise:1.4.2
The --host parameter is only needed if your container registry uses HTTP as
opposed to HTTPS:
regctl image import \
<YOUR_REGISTRY_ADDRESS:5000>/arangodb/kube-arangodb-enterprise:1.4.2 \
kube-arangodb-enterprise.tar \
--host "reg=<YOUR_REGISTRY_ADDRESS:5000>,tls=disabled"
Step 3: Create a namespace
Air-gapped system
Ensure kubectl is properly configured and can communicate with your
Kubernetes cluster, e.g. by running the following commands:
kubectl cluster-info
kubectl get nodes
Create a Kubernetes namespace for ArangoDB and the data platform resources.
The namespace used throughout this guide is called arango, but you can use
a different name.
kubectl create namespace arango
When you specify the namespace for a command, you can do that in two ways:
--namespace arango(long-form option)-n arango(short-form option)
This guide uses long-form options for clarity.
Step 4: Install the Operator
Air-gapped system
Install the ArangoDB Kubernetes Operator
(kube-arangodb) from the downloaded .tgz file with Helm.
This operator is the core component that manages ArangoDB deployments and the Contextual Data Platform. It watches for custom resources and creates the necessary Kubernetes resources.
Make sure to set the options as shown below to enable the gateway feature and machine learning feature:
VERSION_OPERATOR='1.4.2' # Use a newer version if available
helm upgrade --install operator \
--namespace arango \
"kube-arangodb-enterprise-${VERSION_OPERATOR}.tgz" \
--set "webhooks.enabled=true" \
--set "operator.args[0]=--deployment.feature.gateway=true" \
--set "operator.architectures={amd64}"
The output looks similar to the following on success:
Release "operator" does not exist. Installing it now.
NAME: operator
LAST DEPLOYED: Thu Feb 5 16:12:21 2026
NAMESPACE: arango
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None
NOTES:
You have installed Kubernetes ArangoDB Operator in version 1.4.2
To access ArangoDeployments you can use:
kubectl --namespace "arango" get arangodeployments
More details can be found on https://github.com/arangodb/kube-arangodb/tree/1.4.2/docs
You may use the following commands to wait for the operator to be ready and verify it is running:
kubectl wait --for=condition=ready pod --selector app.kubernetes.io/name=kube-arangodb-enterprise --namespace arango --timeout=120s
kubectl get deployment --namespace arango --selector app.kubernetes.io/name=kube-arangodb-enterprise
kubectl get pods --namespace arango --selector app.kubernetes.io/name=kube-arangodb-enterprise
Expected output (x stands for varying letter or digit):
pod/arango-operator-operator-xxxxxxxxxx-xxxxx condition met
NAME READY UP-TO-DATE AVAILABLE AGE
arango-operator-operator 1/1 1 1 45s
NAME READY STATUS RESTARTS AGE
arango-operator-operator-xxxxxxxxxx-xxxxx 2/2 Running 0 45s
Step 5: Create a deployment
Air-gapped system
Create an ArangoDeployment specification for ArangoDB. See the
ArangoDeployment Custom Resource Overview
and the linked reference. The example below is a minimal specification
You need to enable the gateway feature by setting spec.gateway.enabled and
spec.gateway.dynamic to true in the specification. Enable vector indexes
(on DB-Servers and Coordinators respectively on single server) because they are
required by features such as GraphRAG. You also need to set spec.license to
a secret that you will create later.
Example for an ArangoDB cluster deployment using version 3.12.9 with three
DB-Servers and two Coordinators with the name deployment-example:
apiVersion: "database.arangodb.com/v1"
kind: "ArangoDeployment"
metadata:
name: "deployment-example"
spec:
mode: Cluster
image: "arangodb/enterprise:3.12.9"
gateway:
enabled: true
dynamic: true
gateways:
count: 1
dbservers:
count: 3
args:
- --vector-index # For ArangoDB versions before 4.0.0
coordinators:
count: 2
args:
- --vector-index # For ArangoDB versions before 4.0.0
license:
secretName: arango-license-key
# ...
You can save the specification as a YAML file, e.g. deployment.yaml.
Apply the specification using the previously created name (here: arango)
and wait for the pods to be ready:
kubectl apply --namespace arango -f deployment.yaml
kubectl get pods --namespace arango --watch # Ctrl+C to stop watching
Given the above specification using the name deployment-example, you should
eventually see pods with the following names with a status of Running:
deployment-example-agnt-*(3 Agents)deployment-example-crdn-*(2 Coordinators)deployment-example-prmr-*(3 DB-Servers)deployment-example-gway-*(1 Gateway)
Step 6: Collect information for the licensing
Air-gapped system
Before you can create a license key that you can apply on the air-gapped system, you need to get some information about the ArangoDB deployment. For an overview of how licensing works end-to-end in Kubernetes-managed deployments, including air-gapped environments, see License Management.
Use the Platform CLI tool to create an inventory file. You need to specify the
authentication method for ArangoDB (Disabled, Basic, Token), additional
authentication details depending on the selected authentication method, where the
ArangoDB instance can be reached, as well as a file path for the inventory file:
arangodb_operator_platform license inventory \
--arango.authentication <auth-method> \
... # See below
--arango.endpoint <arangodb-endpoint> \
inventory.json
The required authentication options per authentication method:
Disabled:
If the ArangoDB instance has authentication disabled, then you don’t need to specify any additional authentication details. You can also leave out--arango.authentication DisabledbecauseDisabledis the default value.Basic:
If you want to use ArangoDB user credentials, you need to specify that you want to use HTTP Basic Authentication together with a user name and their password:--arango.authentication Basic \ --arango.basic.username "<user-name>" \ --arango.basic.password "<password>" \Token:
If you want to use a JWT session token, you need to specify that you want to use a token as well as the JWT itself:--arango.authentication Token \ --arango.token <jwt> \
If the ArangoDB instance uses a self-signed certificate, you need to specify the following additional option to skip TLS certificate validation:
--arango.insecure \
Full command example:
arangodb_operator_platform license inventory \
--arango.authentication Basic \
--arango.basic.username root \
--arango.basic.password "" \
--arango.insecure \
--arango.endpoint https://127.0.0.1:8529 \
inventory.json
Expected output:
2026-02-05T17:03:07+01:00 INF Connecting to the server...
2026-02-05T17:03:07+01:00 INF Discovered Arango 3.12.9 (enterprise)
2026-02-05T17:03:07+01:00 INF Starting executor name=server.mode thread=0
2026-02-05T17:03:07+01:00 INF Starting executor name=server.info thread=0
2026-02-05T17:03:07+01:00 INF Starting executor name=aql.timestamp thread=0
2026-02-05T17:03:07+01:00 INF Starting executor name=deployment.id thread=0
Finally, get the deployment ID using an endpoint of ArangoDB’s HTTP API.
Substitute https://127.0.0.1:8529 with the endpoint at which ArangoDB can be
reached. You may need to specify additional options for authentication in place
of ...:
curl ... https://127.0.0.1:8529/_admin/deployment/id
The authentication options:
Disabled:
If the ArangoDB instance has authentication disabled, then you don’t need to specify any additional authentication options.Username and password:
If you want to use ArangoDB user credentials, set cURL’s-uoption and provide the user name and password separated by a colon:curl -u "<user-name>:<password>" https://...Token:
If you want to use a JWT session token, use cURL’s-Hoption to set an HTTP header with the token:curl -H "Authorization: bearer <token>" https://...
If the ArangoDB instance uses self-signed certificates, you additionally need to
set the --insecure / -k option to skip TLS certificate validation:
curl --insecure ...
Full command example:
curl -u "root:" --insecure https://127.0.0.1:8529/_admin/deployment/id
Expected output (x stands for varying letter or digit):
{"id":"xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx"}
The UUID wrapped in quote marks is the deployment ID.
Step 7: Generate a license key
Internet-connected system
Use your license credentials together with the inventory file and deployment ID from the previous step to obtain a license key. You can do this with the License Activation portal or with the Platform CLI tool — both produce an equivalent license key.
- Open https://activate.license.arango.ai/ in a browser.
- Enter your License Client ID and License Client Secret.
- Choose how to identify the deployment:
- Inventory (default): drop the
inventory.jsonfile into the upload area, or click to select it. Captures the full deployment shape and is recommended for air-gapped deployments. - Managed — Deployment ID only: enter the deployment ID from the previous step. No inventory file is needed. Available only if Managed activation is enabled for your license — check your contract or with your Arango contact. If it is not enabled, use Inventory mode instead.
- Inventory (default): drop the
- Optionally enable Custom TTL to override the default license duration.
Accepts values like
24h,168h,7d, or3600s. - Click Activate and copy the generated license key (e.g. into a local
license.txtfile). You will use it in the next step to create the Kubernetes secret on the air-gapped system.
The activation portal is a convenient alternative for users who would otherwise
run arangodb_operator_platform license generate. Inventory mode still requires
the Platform CLI tool to produce inventory.json in the previous step;
Managed mode skips that step entirely.
Substitute <license-client-id> and <license-client-secret> with the actual
license credentials. Specify the path to the inventory file inventory.json
and replace <deployment-id> with the deployment ID from the previous step.
arangodb_operator_platform license generate \
--license.client.id <license-client-id> \
--license.client.secret <license-client-secret> \
--inventory ./inventory.json \
--deployment.id <deployment-id>
The command logs information to the standard output (also known as stdout)
and writes the license key to the standard error stream (also known as stderr).
You may want to redirect stderr and thus the license key to a file by appending
2> license.txt to the above command (with a leading space).
You can also set the license credentials as environment variables
LICENSE_CLIENT_ID and LICENSE_CLIENT_SECRET. You can then leave out the
--license.client.id and --license.client.secret command-line options.
export LICENSE_CLIENT_ID=<license-client-id>
export LICENSE_CLIENT_SECRET=<license-client-secret>
arangodb_operator_platform license generate \
--inventory ./inventory.json \
--deployment.id <deployment-id>
Expected output (stdout, x stands for varying letter or digit):
2026-02-05T17:27:28+01:00 INF Using identity for client identity={}
2026-02-05T17:27:28+01:00 INF Generating License ClusterID=<deployment-id> Inventory=true
2026-02-05T17:27:28+01:00 INF License Generated and printed to STDERR ClusterID=<deployment-id> Inventory=true LicenseID=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Step 8: Create a secret for the license
Create a Kubernetes secret with your license credentials.
Substitute <license-string> with the license key you generated:
kubectl create secret generic arango-license-key \
--namespace arango \
--from-literal=token-v2="<license-string>"
You may run the following command to verify that the secret was created:
kubectl get secret arango-license-key --namespace arango
Expected output:
NAME TYPE DATA AGE
arango-license-key Opaque 2 10s
Step 9: Create a Contextual Data Platform package
Internet-connected system
If the Arango team provided you a pre-made platform package, download it and continue with the next step. Otherwise, create a platform package yourself as described below.
Use the Platform CLI tool to download the manifests and container images of the
data platform from Arango’s public container registry. This requires
license credentials and internet access to *.license.arango.ai.
What to download is defined by the package configuration file that you received
from the Arango team. The Platform CLI tool creates a single .zip file out of
the downloaded data. Depending on the configuration, it can be over 40 GiB.
Substitute <license-client-id> and <license-client-secret>
with the actual license credentials and ./platform.yaml with the path to the
package configuration file. Specify the path and a file name for the output file,
e.g. platform.zip:
arangodb_operator_platform package export \
--license.client.id "<license-client-id>" \
--license.client.secret "<license-client-secret>" \
./platform.yaml \
platform.zip
It can take a while to download everything. If you get errors because of
internet connection issues or timeouts, re-run the command. The Platform CLI tool
caches what it downloads in a cache folder in the current working directory. You can therefore retry and continue the download where it left off.
Step 10: Import the Contextual Data Platform package
Load the manifests and container images stored in the zipped package into your container registry using the Platform CLI tool.
Specify the address under which the container registry is available and the
path to the platform.zip file. Furthermore, provide a file path for the
Platform CLI tool to write the package configuration to. This file will be used
in the next step:
arangodb_operator_platform package import \
<YOUR_REGISTRY_ADDRESS:5000> \
./platform.zip \
platform.imported.yaml
If the container registry uses the HTTP protocol instead of HTTPS, you need to specify the following option in addition:
--registry.docker.insecure <YOUR_REGISTRY_ADDRESS:5000>
Step 11: Install the Contextual Data Platform package
Air-gapped system
Install the platform package using the Platform CLI tool.
The package installation creates and enables various services, including the unified web interface of the Contextual Data Platform.
The platform name (deployment-example) needs to match the name as specified in
the ArangoDeployment configuration. Substitute ./platform.imported.yaml with the
path to the package configuration file from the previous step:
arangodb_operator_platform --namespace arango package install \
--platform.name deployment-example \
./platform.imported.yaml
It can take a while to import everything into the container registry.
Step 12: Set up object storage
Air-gapped system
Features like MLflow and GraphML require an additional storage system to save model training data, for instance.
The following example shows how to set up a local MinIO and integrate it with
the Arango Contextual Data Platform, but you can also use a remote object storage like S3.
For the supported storage systems, see the
kube-arangodb documentation .
Create a Kubernetes namespace for MinIO, then create a secret in this namespace
with the username and password to use for the MinIO root user (replace minioadmin
and miniopassword with the credentials you actually want to use). Create another
secret with the same credentials but in the namespace of your ArangoDeployment,
which is arango in this example:
kubectl create namespace minio
kubectl create secret generic minio-root \
--namespace minio \
--from-literal=MINIO_ROOT_USER=minioadmin \
--from-literal=MINIO_ROOT_PASSWORD=miniopassword
kubectl create secret generic minio-credentials \
--namespace arango \
--from-literal=accessKey=minioadmin \
--from-literal=secretKey=miniopassword
Create a file to configure MinIO service and call it e.g. minio.yaml.
Example using a Persistent Volume Claim (PVC) of five gibibytes:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minio-data-pvc
namespace: minio
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio
namespace: minio
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio:latest
args:
- server
- /data
envFrom:
- secretRef:
name: minio-root
ports:
- containerPort: 9000
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: minio-data-pvc
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: minio
spec:
selector:
app: minio
ports:
- port: 9000
targetPort: 9000
---
apiVersion: batch/v1
kind: Job
metadata:
name: minio-create-bucket
namespace: minio
spec:
backoffLimit: 1
template:
spec:
restartPolicy: Never
containers:
- name: mc
image: minio/mc
env:
- name: MINIO_ENDPOINT
value: http://minio.minio.svc.cluster.local:9000
- name: MINIO_ACCESS_KEY
valueFrom:
secretKeyRef:
name: minio-root
key: MINIO_ROOT_USER
- name: MINIO_SECRET_KEY
valueFrom:
secretKeyRef:
name: minio-root
key: MINIO_ROOT_PASSWORD
command:
- sh
- -c
- |
mc alias set local $MINIO_ENDPOINT $MINIO_ACCESS_KEY $MINIO_SECRET_KEY
mc mb local/arango-platform-storage || true
Set up the MinIO service by applying the configuration file:
kubectl apply -f ./minio.yaml
Create another file to configure the storage for the Contextual Data Platform and call the
file e.g. platform-storage.yaml. Note that the name of the ArangoPlatformStorage
must be the same as for the ArangoDeployment:
apiVersion: platform.arangodb.com/v1beta1
kind: ArangoPlatformStorage
metadata:
name: deployment-example
namespace: arango
spec:
backend:
s3:
bucketName: arango-platform-storage
credentialsSecret:
name: minio-credentials
endpoint: http://minio.minio.svc.cluster.local:9000
Integrate the object storage with the Contextual Data Platform by applying the file:
kubectl apply -f ./platform-storage.yaml
