Skip to content

Kubernetes Installation & Deployment

🎯 Prerequisites

ResourceMinimumRecommended
CPU4 cores8 cores
RAM16 GiB64 GiB
Disk100 GiB200 GiB
Architecturex86_64 / ARM64x86_64
SoftwareKubernetes 1.24+, Helm 3+, kubectl configuredKubernetes 1.28+

💡 Note: The recommended configuration of 8 cores and 64 GiB RAM provides optimal performance for production workloads.

🚀 Quick Start

1. Prepare Kubernetes Cluster

Ensure your Kubernetes cluster is running and kubectl is configured with cluster access:

bash
kubectl cluster-info
kubectl get nodes

2. Clone and Navigate

bash
git clone https://github.com/ModelEngine-Group/nexent.git
cd nexent

3. Deployment

Run the deployment script:

bash
bash deploy.sh k8s

After running the command, the script opens Bash TUI menus for configuration. Use arrow keys or j/k to move, Space to toggle multi-select items, Enter to confirm, b/Backspace to go back, and q to quit.

Deployment Components:

  • infrastructure (required): Elasticsearch, PostgreSQL, Redis, MinIO
  • application (selected by default, optional): config, runtime, mcp, northbound, web
  • data-process (selected by default, optional): data processing service
  • supabase (selected by default, optional): enables user, tenant, and authentication features
  • terminal (optional): enables the OpenSSH terminal tool
  • monitoring (optional): enables observability components and then prompts for a provider

Port Policy:

  • development (default): uses NodePort for Web and selected debug/internal services
  • production: keeps internal services as ClusterIP and exposes only production entrypoints

Image Source:

  • general (default): uses standard public registries
  • mainland: uses mainland China mirrors
  • local-latest: uses local latest images and local-friendly pull policies for Nexent application images

Kubernetes uses the same deploy/env/.env file as Docker. Existing deploy/env/.env is kept as-is. If it does not exist, the deploy scripts first reuse docker/.env, then fall back to deploy/env/.env.example.

After a successful deployment, non-sensitive choices are saved to deploy/k8s/deploy.options. The next interactive deployment can reuse the local config or run a full reconfiguration.

⚠️ Important Notes

1️⃣ When deploying v1.8.0 or later for the first time, you will be prompted to set a password for the suadmin super administrator account during the deployment process. This account has the highest system privileges. Please enter your desired password and save it securely after creation - it cannot be retrieved later.

2️⃣ Forgot to note the suadmin account password? Follow these steps:

bash
# Step 1: Delete su account record in Supabase database
kubectl exec -it -n nexent deploy/nexent-supabase-db -- psql -U postgres -c \
  "SELECT id, email FROM auth.users WHERE email='suadmin@nexent.com';"
# Get the user_id and delete
kubectl exec -it -n nexent deploy/nexent-supabase-db -- psql -U postgres -c \
  "DELETE FROM auth.identities WHERE user_id='your_user_id';"
kubectl exec -it -n nexent deploy/nexent-supabase-db -- psql -U postgres -c \
  "DELETE FROM auth.users WHERE id='your_user_id';"

# Step 2: Delete su account record in nexent database
kubectl exec -it -n nexent deploy/nexent-postgresql -- psql -U root -d nexent -c \
  "DELETE FROM nexent.user_tenant_t WHERE user_id='your_user_id';"

# Step 3: Re-deploy and record the su account password
bash deploy.sh k8s

4. Access Your Installation

When deployment completes successfully:

ServiceDefault Address
Web Applicationhttp://localhost:30000
SSH Terminallocalhost:30022 (if enabled)

Access steps:

  1. Open http://localhost:30000 in your browser
  2. Log in with the super administrator account
  3. Access tenant resources → Create tenant and tenant administrator
  4. Log in with the tenant administrator account
  5. Refer to the User Guide to develop agents

🏗️ Service Architecture

Nexent uses a microservices architecture deployed via Helm charts:

Application Services:

ServiceDescriptionDefault Port
nexent-configConfiguration service5010
nexent-runtimeRuntime service5010
nexent-mcpMCP container service5010
nexent-northboundNorthbound API service5010
nexent-webWeb frontend3000
nexent-data-processData processing service5012

Infrastructure Services:

ServiceDescription
nexent-elasticsearchSearch and indexing engine
nexent-postgresqlRelational database
nexent-redisCaching layer
nexent-minioS3-compatible object storage

Supabase Services (when supabase is selected):

ServiceDescription
nexent-supabase-kongAPI Gateway
nexent-supabase-authAuthentication service
nexent-supabase-dbDatabase service

Optional Services:

ServiceDescription
nexent-openssh-serverSSH terminal for AI agents
nexent-monitoringOptional observability stack

🔌 Port Mapping

ServiceInternal PortNodePortDescription
Web Interface300030000Main application access
Northbound API501330013Northbound API service
SSH Server2230022Terminal tool access

For internal service communication, services use Kubernetes internal DNS (e.g., http://nexent-config:5010).

💾 Data Persistence

Nexent uses PersistentVolumes for data persistence:

Data TypePersistentVolumeDefault Host Path
Elasticsearchnexent-elasticsearch-pv/var/lib/nexent-data/nexent-elasticsearch
PostgreSQLnexent-postgresql-pv/var/lib/nexent-data/nexent-postgresql
Redisnexent-redis-pv/var/lib/nexent-data/nexent-redis
MinIOnexent-minio-pv/var/lib/nexent-data/nexent-minio
Supabase DB (when supabase is selected)nexent-supabase-db-pv/var/lib/nexent-data/nexent-supabase-db
Shared workspacenexent-workspace-pv/var/lib/nexent
Shared skillsnexent-skills-pv/var/lib/nexent-data/skills

Helm uninstall does not delete local hostPath data by default. Use bash deploy/k8s/uninstall.sh --delete-local-data true or bash uninstall.sh k8s --delete-local-data true to delete known Nexent local volume contents under /var/lib/nexent, /var/lib/nexent-data/skills, and /var/lib/nexent-data/nexent-*; use --keep-local-data to preserve them explicitly.

Uninstall Kubernetes Deployment

Use the root uninstall entrypoint from the repository root:

bash
# Remove Helm release; prompts before deleting namespace or local data in interactive shells
bash uninstall.sh k8s

# Clean only Helm release state, useful for stuck releases
bash uninstall.sh k8s clean

# Remove Helm release and namespace, but keep local hostPath data
bash uninstall.sh k8s delete --keep-local-data

# Delete known local hostPath data after uninstall
bash uninstall.sh k8s --delete-local-data true

# Full cleanup: Helm release, namespace, and local hostPath data
bash uninstall.sh k8s delete-all

--delete-data and --delete-volumes are compatibility options for Helm-managed resources. For local disks, use --delete-local-data or --keep-local-data; delete-all --keep-local-data removes the namespace while preserving local volume contents.

Offline Image Package

Build a Kubernetes offline package from the repository root:

bash
bash deploy/offline/build_offline_package.sh \
  --target k8s \
  --version v2.2.1 \
  --platform amd64 \
  --components infrastructure,application,data-process,supabase \
  --image-source general \
  --compress true \
  --output-dir offline-package

The package includes image tar files, load-images.sh, root deploy/uninstall entrypoints, Kubernetes Helm assets, SQL files, manifest.yaml, and checksums.txt. With --compress true, a nexent-offline-<target>-<platform>-<version>.zip archive is created next to the output directory. On a single-node Docker-backed cluster, you can load and deploy directly:

bash
cd offline-package
bash deploy.sh --load-images k8s

For multi-node clusters, load the images on every node that may run Nexent Pods, or push the loaded images to an internal registry and deploy with matching image settings.

🔧 Deployment Commands

bash
# Deploy with interactive prompts
bash deploy.sh k8s

# Non-interactive deployment with the default component set
bash deploy.sh k8s --components infrastructure,application,data-process,supabase --port-policy development --image-source general

# Add the terminal tool to the default component set
bash deploy.sh k8s --components infrastructure,application,data-process,supabase,terminal

# Deploy with mainland China image sources
bash deploy.sh k8s --image-source mainland

# Use local latest images
bash deploy.sh k8s --image-source local-latest

# Clean helm state only (fixes stuck releases)
bash uninstall.sh k8s clean

# Uninstall; local data is preserved by default, with interactive prompts for namespace and local data deletion
bash uninstall.sh k8s

# Uninstall and delete the namespace
bash uninstall.sh k8s --delete-namespace true

# Uninstall and delete local hostPath data
bash uninstall.sh k8s --delete-local-data true

# Complete uninstall including namespace and local hostPath data
bash uninstall.sh k8s delete-all

# Complete uninstall but preserve local hostPath data
bash uninstall.sh k8s delete-all --keep-local-data

🔧 Advanced Configuration

Monitoring Configuration

Kubernetes deployments enable monitoring through the monitoring component in the deployment script UI. The deployment script renders runtime Helm values for global.monitoring.enabled, global.monitoring.provider, and global.monitoring.dashboardUrl, and enables the nexent-monitoring subchart.

bash
cd nexent
bash deploy.sh k8s

If deploy/k8s/deploy.options already exists, the script asks whether to reuse local configuration. Choose to reconfigure/overwrite local configuration, then select monitoring in the component menu and manually choose grafana, phoenix, langfuse, langsmith, zipkin, or otlp in the provider menu.

Supported providers:

ProviderPurposeDefault URL
otlpOpenTelemetry Collector only, useful for forwarding to an external platformNo dashboard
phoenixLocal Phoenix trace analysishttp://localhost:30006
langfuseLocal Langfuse observability stackhttp://localhost:30001
langsmithForwarding to hosted LangSmithhttps://smith.langchain.com/
grafanaLocal Grafana + Tempohttp://localhost:30002/d/nexent-llm-agent/nexent-agent-trace-monitoring?orgId=1
zipkinLocal Zipkinhttp://localhost:30011

Before choosing the langsmith provider, configure global.monitoring.langsmithApiKey and global.monitoring.langsmithProject in deploy/deploy/k8s/helm/nexent/values.yaml. To change local Grafana, Langfuse, or dashboard ports, adjust the values file first, then re-run the deployment script, choose to reconfigure, and manually select monitoring.

Common Helm values:

ValueDescription
global.monitoring.enabledEnables OpenTelemetry export in the Nexent backend
global.monitoring.providerBackend provider label: otlp, phoenix, langfuse, langsmith, grafana, zipkin
global.monitoring.otlpEndpointBackend OTLP HTTP endpoint, default http://nexent-otel-collector:4318
global.monitoring.dashboardUrlFrontend monitoring entry URL; leave empty to hide the entry
global.monitoring.traceContentModeTrace content capture mode: summary, metrics, or full
nexent-monitoring.<provider>.service.nodePortNodePort override for provider dashboards
nexent-monitoring.langfuse.init.*Local Langfuse bootstrap organization, project, and admin account
nexent-monitoring.grafana.adminUser / adminPasswordLocal Grafana admin credentials

Check monitoring status:

bash
kubectl get pods -n nexent | grep -E 'otel|phoenix|grafana|tempo|zipkin|langfuse'
kubectl get svc -n nexent | grep -E 'otel|phoenix|grafana|zipkin|langfuse'

Production note: Replace default passwords, secrets, and the Langfuse encryptionKey. Prefer ClusterIP services or a controlled Ingress for dashboards.

OAuth Login Configuration

OAuth login requires the supabase component. When enabling third-party login, deploy supabase and set config.oauth.callbackBaseUrl to the browser-accessible Nexent Web URL.

bash
bash deploy.sh k8s --components infrastructure,application,supabase

Kubernetes writes OAuth settings into backend environment variables through nexent-common config.oauth.* values:

bash
helm upgrade --install nexent nexent \
  --namespace nexent --create-namespace \
  --set global.deploymentComponents.supabase=true \
  --set nexent-supabase-kong.enabled=true \
  --set nexent-supabase-auth.enabled=true \
  --set nexent-supabase-db.enabled=true \
  --set nexent-common.config.oauth.callbackBaseUrl=https://nexent.example.com \
  --set nexent-common.config.oauth.githubClientId=your_github_client_id \
  --set nexent-common.config.oauth.githubClientSecret=your_github_client_secret

Configurable OAuth values:

ValueEnvironment variableDescription
nexent-common.config.oauth.callbackBaseUrlOAUTH_CALLBACK_BASE_URLWeb entry URL; the callback path is appended automatically
nexent-common.config.oauth.githubClientIdGITHUB_OAUTH_CLIENT_IDGitHub OAuth Client ID
nexent-common.config.oauth.githubClientSecretGITHUB_OAUTH_CLIENT_SECRETGitHub OAuth Client Secret
nexent-common.config.oauth.gdeUrlGDE_URLGDE OAuth service URL
nexent-common.config.oauth.gdeClientIdGDE_OAUTH_CLIENT_IDGDE OAuth Client ID
nexent-common.config.oauth.gdeClientSecretGDE_OAUTH_CLIENT_SECRETGDE OAuth Client Secret
nexent-common.config.oauth.enableWechatENABLE_WECHAT_OAUTHEnables WeChat OAuth
nexent-common.config.oauth.wechatClientIdWECHAT_OAUTH_APP_IDWeChat App ID
nexent-common.config.oauth.wechatClientSecretWECHAT_OAUTH_APP_SECRETWeChat App Secret
nexent-common.config.oauth.sslVerifyOAUTH_SSL_VERIFYWhether to verify provider TLS certificates
nexent-common.config.oauth.caBundleOAUTH_CA_BUNDLECustom CA bundle path

Provider callback URLs:

ProviderCallback URL
GitHub{OAUTH_CALLBACK_BASE_URL}/api/user/oauth/callback?provider=github
GDE{OAUTH_CALLBACK_BASE_URL}/api/user/oauth/callback?provider=gde
WeChat{OAUTH_CALLBACK_BASE_URL}/api/user/oauth/callback?provider=wechat

For local NodePort, a GitHub callback example is http://localhost:30000/api/user/oauth/callback?provider=github. In production, use a public HTTPS domain and register the exact same URL in the OAuth provider console.

CAS Login Configuration

CAS SSO does not require the supabase component. Set nexent-common.config.cas.callbackBaseUrl to the browser-accessible Nexent Web URL without a trailing /. nexent-common.config.cas.serverUrl is the CAS Server root URL and should also not include a trailing /.

Kubernetes writes CAS settings into backend environment variables through nexent-common config.cas.* values:

bash
helm upgrade --install nexent nexent \
  --namespace nexent --create-namespace \
  --set nexent-common.config.cas.enabled=true \
  --set nexent-common.config.cas.serverUrl=https://cas.example.com/cas \
  --set nexent-common.config.cas.callbackBaseUrl=https://nexent.example.com \
  --set nexent-common.config.cas.loginMode=force \
  --set nexent-common.config.cas.logoutUrl=/logout

Configurable CAS values:

ValueEnvironment variableDescription
nexent-common.config.cas.enabledCAS_ENABLEDEnables CAS
nexent-common.config.cas.serverUrlCAS_SERVER_URLCAS Server root URL
nexent-common.config.cas.validatePathCAS_VALIDATE_PATHserviceValidate path, default /p3/serviceValidate
nexent-common.config.cas.callbackBaseUrlCAS_CALLBACK_BASE_URLWeb entry URL; CAS callback paths are appended automatically
nexent-common.config.cas.loginModeCAS_LOGIN_MODEdisabled, button, or force
nexent-common.config.cas.userAttributeCAS_USER_ATTRIBUTEUser identifier attribute. Empty means use <cas:user>
nexent-common.config.cas.emailAttributeCAS_EMAIL_ATTRIBUTEEmail attribute
nexent-common.config.cas.roleAttributeCAS_ROLE_ATTRIBUTERole attribute
nexent-common.config.cas.tenantAttributeCAS_TENANT_ATTRIBUTETenant attribute
nexent-common.config.cas.roleMapJsonCAS_ROLE_MAP_JSONJSON mapping from CAS roles to Nexent roles
nexent-common.config.cas.sessionMaxAgeSecondsCAS_SESSION_MAX_AGE_SECONDSMaximum local CAS session lifetime
nexent-common.config.cas.localSessionMaxAgeSecondsLOCAL_SESSION_MAX_AGE_SECONDSNexent local session lifetime
nexent-common.config.cas.renewBeforeSecondsCAS_RENEW_BEFORE_SECONDSTrigger silent renewal within this many seconds before expiry
nexent-common.config.cas.renewTimeoutSecondsCAS_RENEW_TIMEOUT_SECONDSSilent renewal timeout
nexent-common.config.cas.syntheticEmailDomainCAS_SYNTHETIC_EMAIL_DOMAINDomain used when CAS does not return an email
nexent-common.config.cas.logoutUrlCAS_LOGOUT_URLCAS logout URL. Empty means Nexent logout will not call the CAS Server logout endpoint
nexent-common.config.cas.sslVerifyCAS_SSL_VERIFYWhether to verify CAS Server TLS certificates
nexent-common.config.cas.caBundleCAS_CA_BUNDLECustom CA bundle path

Common CAS URLs:

PurposeURL
Nexent login entry{CAS_CALLBACK_BASE_URL}/api/user/cas/login?redirect=/
CAS service callback{CAS_CALLBACK_BASE_URL}/api/user/cas/callback
CAS silent renewal callback{CAS_CALLBACK_BASE_URL}/api/user/cas/renew_callback
CAS single logout callbackPOST {CAS_CALLBACK_BASE_URL}/api/user/cas/logout_callback

For Apereo CAS JSON Service Registry, create a service registration file such as Nexent-10001.json in the service registry directory configured by your CAS deployment. The id must be globally unique. This is a local NodePort example:

json
{
  "@class": "org.apereo.cas.services.RegexRegisteredService",
  "serviceId": "http://localhost:30000.*",
  "name": "Nexent CAS Client",
  "id": 10001,
  "description": "Nexent CAS SSO client",
  "evaluationOrder": 1,
  "logoutType": "BACK_CHANNEL",
  "logoutUrl": "http://localhost:30000/api/user/cas/logout_callback"
}

In production, keep CAS_SSL_VERIFY=true; for self-signed certificates, prefer CAS_CA_BUNDLE and only use CAS_SSL_VERIFY=false for local testing.

CAS Integration with ModelEngine

When integrating with ModelEngine through the CAS protocol, use a values file to configure Nexent. This avoids complex command-line escaping for CAS_ROLE_MAP_JSON.

Create cas-modelengine-values.yaml:

yaml
nexent-common:
  config:
    cas:
      enabled: true
      serverUrl: "https://<ModelEngine IP>:5443/SSOSvr"
      validatePath: "/p3/serviceValidate"
      callbackBaseUrl: "http://<Nexent IP>:30000"
      loginMode: "force"
      userAttribute: "userName"
      emailAttribute: "email"
      roleAttribute: "userType"
      tenantAttribute: "tenant_id"
      roleMapJson: '{"1":"ADMIN","3":"DEV"}'
      sessionMaxAgeSeconds: 3600
      localSessionMaxAgeSeconds: 3600
      renewBeforeSeconds: 300
      renewTimeoutSeconds: 10
      syntheticEmailDomain: "cas.local"
      logoutUrl: "/logout?service=http://<Nexent IP>:30000"
      sslVerify: false
      caBundle: ""

You also need to add a CAS client service registration file in the OMS container. Use the following steps as a reference:

bash
# Create the registration file, paste the JSON content into it, and save it.
vim Nexent-10000001.json
{
  "@class": "org.apereo.cas.services.CasRegisteredService",
  "serviceId": "http://<Nexent IP>:30000.*",
  "name": "Nexent CAS Client",
  "id": 1000001,
  "description": "Nexent CAS SSO client",
  "evaluationOrder": 1,
  "logoutType": "BACK_CHANNEL",
  "logoutUrl": "http://<Nexent IP>:30000/api/user/cas/logout_callback"
}

# Run the following command to copy the registration file into the container.
kubectl cp Nexent-10000001.json model-engine/$(kubectl get pods -n model-engine -l app=oms --no-headers | awk '{print $1}'):/opt/huawei/fce/apps/platform/webapps/SSOSvr/WEB-INF/classes/services/Nexent-10000001.json
kubectl exec -i -n model-engine $(kubectl get pods -n model-engine -l app=oms --no-headers | awk '{print $1}') -- chown tomcat:fusioncube /opt/huawei/fce/apps/platform/webapps/SSOSvr/WEB-INF/classes/services/Nexent-10000001.json

🔍 Troubleshooting

Check Pod Status

bash
kubectl get pods -n nexent
kubectl describe pod <pod-name> -n nexent

View Logs

bash
kubectl logs -n nexent -l app=nexent-config
kubectl logs -n nexent -l app=nexent-web
kubectl logs -n nexent -l app=nexent-elasticsearch

Restart Services

bash
kubectl rollout restart deployment/nexent-config -n nexent
kubectl rollout restart deployment/nexent-runtime -n nexent

Re-initialize Elasticsearch

If Elasticsearch initialization failed:

bash
bash init-elasticsearch.sh

Clean Up Stale PersistentVolumes

bash
kubectl delete pv nexent-elasticsearch-pv nexent-postgresql-pv nexent-redis-pv nexent-minio-pv

💡 Need Help