Deploying the WDS API Server with a Helm Chart

Deploy to Kubernetes using the WDS Helm Chart — suitable for staging and production with scaling and resilience.

By default, the chart uses SingleService mode: it deploys one Solidstack pod, plus the Docs and Playground auxiliary services. Supply MongoDB through either a direct connection string or a Kubernetes Secret reference. Review the server runtime dependencies before deployment.

MultiService mode deploys Dapi, Datakeeper, Crawler, Scraper, Idealer, and Jober. Retriever is also deployed when search is enabled. This mode requires a license key and is available with the Business plan. Contact us for a license key.
If you find an error in the Helm chart (or in the WDS API Server itself), or if you have specific requirements that need to be added to the Helm chart, kindly use the Issues.

Deployment options

There are several ways to deploy the WDS Helm Chart.

Deploying using Helm CLI

To deploy the WDS API Server using the Helm CLI, run the following commands:

IMPORTANT! Ensure you have access to a Kubernetes cluster.

# Add a repository
helm repo add webdatasource https://webdatasource.github.io/wds.helm

# Update your local repository cache
helm repo update

# Search for the chart to verify it's available
helm search repo webdatasource --version 1.4.0

# Install the chart
helm install wds-server --version 1.4.0 webdatasource/wds-helm-chart \
    --namespace webdatasource --create-namespace \
    --set global.registry="docker.io" \
    --set global.coreServices.databases.mongodb.connectionString="mongodb+srv://<user>:<password>@<host>/WebDataSource?appName=<cluster>&readPreference=secondary"

Deploying using Terraform

IMPORTANT! Ensure you have helm provider configured in your terraform project.

Minimal Terraform configuration to deploy WDS API Server:

variable "mongodb_connection_string" {
  description = "MongoDB connection string"
  type        = string
  sensitive   = true
}

variable "registry" {
  description = "Docker registry of WDS API Server service images"
  type        = string
  default     = "docker.io"
}

variable "helm_chart_version" {
  description = "Helm chart version for WDS API Server deployment"
  type        = string
  default     = "1.4.0"
}

variable "create_namespace" {
  description = "Namespace and ingress configuration for WDS API Server deployment. Set `create_namespace` to false to deploy in an existing namespace"
  type        = bool
  default     = true
}

variable "namespace" {
  description = "Namespace for WDS API Server deployment"
  type        = string
  default     = "webdatasource"
}

variable "enable_ingress" {
  description = "Enable or disable ingress for WDS API Server deployment"
  type        = bool
  default     = true
}

# Kubernetes namespace resource
resource "kubernetes_namespace" "webdatasource" {
  count = var.create_namespace ? 1 : 0
  metadata {
    name = var.namespace
  }
}

# Helm release resource
resource "helm_release" "wds-server" {
  name       = "wds-server"
  repository = "https://webdatasource.github.io/wds.helm"
  chart      = "wds-helm-chart"
  version    = var.helm_chart_version

  namespace        = var.namespace
  create_namespace = false

  values = [
    yamlencode({
      global = {
        registry = var.registry
        ingress = {
          enabled = var.enable_ingress
        }
      }
    }),
    sensitive(yamlencode({
      global = {
        coreServices = {
          databases = {
            mongodb = {
              connectionString = var.mongodb_connection_string
            }
          }
        }
      }
    }))
  ]

  depends_on = [
    kubernetes_namespace.webdatasource
  ]
}

Terraform configuration to deploy WDS API Server in the MultiService mode with Retrieval:

variable "license_key" {
  description = "WebDataSource license key"
  type        = string
  sensitive   = true
}

variable "embedding_service_url" {
  description = "Embedding service URL"
  type        = string
}

variable "embedding_service_api_key" {
  description = "Embedding service API key"
  type        = string
  sensitive   = true
  default     = ""
}

variable "mongodb_connection_string" {
  description = "MongoDB connection string"
  type        = string
  sensitive   = true
}

variable "registry" {
  description = "Docker registry of WDS API Server service images"
  type        = string
  default     = "docker.io"
}

variable "helm_chart_version" {
  description = "Helm chart version for WDS API Server deployment"
  type        = string
  default     = "1.4.0"
}

variable "create_namespace" {
  description = "Namespace and ingress configuration for WDS API Server deployment. Set `create_namespace` to false to deploy in an existing namespace"
  type        = bool
  default     = true
}

variable "namespace" {
  description = "Namespace for WDS API Server deployment"
  type        = string
  default     = "webdatasource"
}

variable "enable_ingress" {
  description = "Enable or disable ingress for WDS API Server deployment"
  type        = bool
  default     = true
}

# Kubernetes namespace resource
resource "kubernetes_namespace" "webdatasource" {
  count = var.create_namespace ? 1 : 0
  metadata {
    name = var.namespace
  }
}

# Helm release resource
resource "helm_release" "wds-server" {
  name       = "wds-server"
  repository = "https://webdatasource.github.io/wds.helm"
  chart      = "wds-helm-chart"
  version    = var.helm_chart_version

  namespace        = var.namespace
  create_namespace = false

  values = [
    yamlencode({
      global = {
        registry = var.registry
        ingress = {
          enabled = var.enable_ingress
        }
        coreServices = {
          mode = "MultiService"
          search = {
            enabled = true
            mode    = "FullTextAndVector"
            embeddingService = {
              url = var.embedding_service_url
            }
          }
        }
      }
    }),
    sensitive(yamlencode({
      global = {
        coreServices = {
          license = {
            key = var.license_key
          }
          databases = {
            mongodb = {
              connectionString = var.mongodb_connection_string
            }
          }
          search = {
            embeddingService = {
              apiKey = var.embedding_service_api_key
            }
          }
        }
      }
    }))
  ]

  depends_on = [
    kubernetes_namespace.webdatasource
  ]
}

NOTE This code can be used to create a dedicated Terraform Module for WDS API Server.

Configuration

Set chart configuration in values.yaml or with the equivalent Helm --set paths. Empty Secret-reference maps accept name and key children. For the license, MongoDB, cache, and search database, a non-empty direct value takes precedence over its Secret reference. For the embedding service URL and API key, a complete Secret reference takes precedence over the direct value.

Global values

Path Default or fallback Description
global.registry docker.io Registry prefix for every image.
global.resources.requests.cpu 100m Default CPU request for each container.
global.resources.requests.memory 256Mi Default memory request for each container.
global.deploymentExtraLabels {} Labels merged into every Deployment; a service override wins on duplicate keys.
global.serviceExtraLabels {} Labels merged into every Service; a service override wins on duplicate keys.
global.nodeSelector {} Default pod node selector.
global.tolerations [] Default pod tolerations.
global.affinity {} Default pod affinity rules.
global.coreServices.mode SingleService SingleService deploys Solidstack. MultiService deploys the distributed services and requires a Business-plan license.
global.coreServices.license.key Empty Direct license key used in MultiService mode. Use a placeholder or secret integration rather than committing a real key.
global.coreServices.license.keySecretRef {} Kubernetes Secret reference with name and key; used when the direct license key is empty.
global.coreServices.cache.connectionString Empty; primary MongoDB is used Optional Datakeeper cache connection string in MultiService mode.
global.coreServices.cache.connectionStringSecretRef {} Kubernetes Secret reference with name and key; used when the direct cache connection string is empty.
global.coreServices.cache.databaseName Empty; connection-string database Optional cache database name.
global.coreServices.databases.mongodb.connectionString Empty; required unless a Secret reference is set Direct MongoDB connection string.
global.coreServices.databases.mongodb.connectionStringSecretRef {} Kubernetes Secret reference with name and key; used when the direct MongoDB connection string is empty.
global.coreServices.databases.mongodb.databaseName WebDataSource Default MongoDB database name; an empty value lets the application use the name from the connection string.
global.coreServices.search.enabled false Enables search and retrieval. In MultiService mode this also deploys Retriever.
global.coreServices.search.mode FullText FullText, Vector, or FullTextAndVector. Vector modes require an embedding service.
global.coreServices.search.database.connectionString Empty; Retriever MongoDB connection Optional MongoDB Atlas or Enterprise search-database connection for Retriever.
global.coreServices.search.database.connectionStringSecretRef {} Kubernetes Secret reference with name and key; used when the direct search connection string is empty.
global.coreServices.search.database.databaseName WebDataSource Search database name, used when a separate search connection is configured.
global.coreServices.search.embeddingService.url Empty Direct external embedding-service URL.
global.coreServices.search.embeddingService.apiKey Empty Direct external embedding-service API key.
global.coreServices.search.embeddingService.urlSecretRef {} Kubernetes Secret reference with name and key; when complete, it overrides the direct URL.
global.coreServices.search.embeddingService.apiKeySecretRef {} Kubernetes Secret reference with name and key; when complete, it overrides the direct API key.
global.coreServices.search.embeddingService.dimentionsCount 768 Embedding-vector dimension count. The misspelled dimentionsCount is the chart’s public value name.
global.coreServices.search.embeddingService.requestTemplate Empty; internal fallback { 'model': 'embeddinggemma', 'input': null } JSON request template for an external embedding service.
global.coreServices.search.embeddingService.contentJsonPath Empty; internal fallback $.input JSONPath where the input string array is written in the embedding request.
global.coreServices.search.embeddingService.resultJsonPath Empty; internal fallback $.embeddings JSONPath used to read embedding arrays from the response.
global.coreServices.jobTypes [intranet, internet] Enabled job types.
global.coreServices.externalIpConfigs [intranet, amazon] Enabled external IP configurations.
global.coreServices.exceptionResponseDelayMs Empty; application fallback 1000 ms Delay before an HTTP error response; applies to the MSSQL API.
global.coreServices.maxInactiveSecToReregistrar Empty; application fallback 60 seconds Maximum Crawler inactivity before re-registration.
global.auxiliaryServices.docs.enabled true Deploys the Docs auxiliary service.
global.auxiliaryServices.docs.defaultTag v3.0 Docs image tag used when auxiliaryServices.docs.image.tag is empty.
global.auxiliaryServices.playground.enabled true Deploys the Playground auxiliary service.
global.minLogLevel Information Minimum log level: Trace, Debug, Information, Warning, Error, or Critical.
global.ingress.enabled false Creates the chart Ingress.
global.ingress.className nginx Ingress class; set an empty value to use the cluster’s default class.
global.ingress.annotations {} Additional Ingress annotations.
global.ingress.basePath / Prefix for all routes. It must be / or end with /.
global.hpa.enabled true Default HorizontalPodAutoscaler state. Core HPAs apply in MultiService; enabled auxiliary services also inherit this default.
global.hpa.minReplicas 1 Default HPA minimum replica count.
global.hpa.maxReplicas 3 Default HPA maximum replica count.
global.hpa.targetCPUUtilizationPercentage 80 Default average CPU utilization target.
global.hpa.targetMemoryUtilizationPercentage null Optional average memory utilization target; null disables the memory metric.
global.pdb.enabled true Default PodDisruptionBudget state. Core PDBs apply in MultiService; auxiliary services override this to false by default.
global.pdb.minAvailable 1 Default minimum available pods. If both availability fields are set, minAvailable wins.
global.pdb.maxUnavailable null Optional maximum unavailable pods.

Core service overrides

In the table below, <service> means exactly solidstack, dapi, datakeeper, crawler, scraper, idealer, jober, or retriever, except where a narrower list is stated.

Path Applies to Default or fallback Description
coreServices.<service>.image.name All eight core services Empty; webdatasource/<service> Overrides the image name.
coreServices.<service>.image.tag All eight core services Empty; .Chart.AppVersion Overrides the image tag.
coreServices.<service>.image.pullPolicy All eight core services Empty; IfNotPresent Overrides the image pull policy.
coreServices.<service>.resourcesOverride All eight core services {}; global.resources Replaces the global resource map when non-empty.
coreServices.<service>.deploymentExtraLabelsOverride All eight core services {} Merges with global Deployment labels and wins on duplicate keys.
coreServices.<service>.serviceExtraLabelsOverride All eight core services {} Merges with global Service labels and wins on duplicate keys.
coreServices.<service>.nodeSelectorOverride All eight core services {}; global.nodeSelector Replaces the global node selector when non-empty.
coreServices.<service>.tolerationsOverride All eight core services []; global.tolerations Replaces global tolerations when non-empty.
coreServices.<service>.affinityOverride All eight core services {}; global.affinity Replaces global affinity when non-empty.
coreServices.<service>.replicaCount dapi, datakeeper, crawler, scraper, idealer, jober, retriever 2 Deployment replica count. Solidstack always uses one replica and has no value at this path.
coreServices.<service>.databases.mongodb.databaseName dapi, datakeeper, scraper, idealer, jober, retriever Empty; global MongoDB database name Per-service MongoDB database-name override. Crawler and Solidstack do not expose this override.
coreServices.<service>.hpa dapi, datakeeper, crawler, scraper, idealer, jober, retriever {}; missing keys inherit global.hpa Per-service HPA map.
coreServices.<service>.pdb dapi, datakeeper, crawler, scraper, idealer, jober, retriever {}; missing keys inherit global.pdb Per-service PDB map.

Auxiliary service overrides

Here, <service> means exactly playground or docs.

Path Applies to Default or fallback Description
auxiliaryServices.<service>.replicaCount Both services 1 Deployment replica count.
auxiliaryServices.<service>.image.name Both services Empty; webdatasource/<service> Overrides the image name.
auxiliaryServices.playground.image.tag Playground Empty; .Chart.AppVersion Overrides the Playground image tag.
auxiliaryServices.docs.image.tag Docs Empty; global.auxiliaryServices.docs.defaultTag Overrides the Docs image tag.
auxiliaryServices.playground.image.pullPolicy Playground Empty; IfNotPresent Overrides the Playground image pull policy.
auxiliaryServices.docs.image.pullPolicy Docs Empty; Always Overrides the Docs image pull policy.
auxiliaryServices.<service>.resourcesOverride Both services {}; global.resources Replaces the global resource map when non-empty.
auxiliaryServices.<service>.deploymentExtraLabelsOverride Both services {} Merges with global Deployment labels and wins on duplicate keys.
auxiliaryServices.<service>.serviceExtraLabelsOverride Both services {} Merges with global Service labels and wins on duplicate keys.
auxiliaryServices.<service>.nodeSelectorOverride Both services {}; global.nodeSelector Replaces the global node selector when non-empty.
auxiliaryServices.<service>.tolerationsOverride Both services []; global.tolerations Replaces global tolerations when non-empty.
auxiliaryServices.<service>.affinityOverride Both services {}; global.affinity Replaces global affinity when non-empty.
auxiliaryServices.<service>.hpa Both services {}; missing keys inherit global.hpa Per-service HPA map.
auxiliaryServices.<service>.pdb.enabled Both services false Disables the auxiliary-service PDB by default; enable it when running more than one replica. Other PDB settings inherit the global map.

Accessing the WDS API Server instance

When the helm release has been deployed to a Kubernetes cluster, use the following command to get access URLs:

NAMESPACE=webdatasource # Change the namespace if necessary
SCHEME=$(kubectl get ing webdatasource -n $NAMESPACE -o jsonpath='{.spec.tls[0].hosts[0]}')
SCHEME=$([ -n "$SCHEME" ] && echo https || echo http)
HOST=$(kubectl get ing webdatasource -n $NAMESPACE -o jsonpath='{.spec.rules[0].host}')
if [ -z "$HOST" ]; then
  HOST=$(kubectl get ing webdatasource -n $NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
  [ -z "$HOST" ] && HOST=$(kubectl get ing webdatasource -n $NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  [ -z "$HOST" ] && HOST=localhost
fi
echo
kubectl get ing webdatasource -n $NAMESPACE -o jsonpath='{range .spec.rules[*].http.paths[*]}{.path}/{"\n"}{end}' | awk -v s="$SCHEME" -v h="$HOST" '{print s"://"h $0}'

The result should look like this:

http(s)://[your-host]/playground/
http(s)://[your-host]/docs/
http(s)://[your-host]/api/
http(s)://[your-host]/mcp/

Please rotate your device to landscape mode

This documentation is specifically designed with a wider layout to provide a better reading experience for code examples, tables, and diagrams.
Rotating your device horizontally ensures you can see everything clearly without excessive scrolling or resizing.

Return to Web Data Source Home