Skip to main content
Version: 6.0

Installation and Configuration of sa-ai

Overview

sa-ai is an LLM inference service for Search Anywhere (prefix sa). The installer deploys the service as a systemd unit, generates runtime configuration, prepares TLS materials, and optionally configures an account and keystore entry in local OpenSearch.


Conditional Designations

  • SA_AI_HOME — service installation directory (default /app/sa-ai)
  • SA_AI_LOGS — logs directory (default /app/logs/sa-ai)
  • OS_HOME — OpenSearch installation directory

Prerequisites

Before running the installer, ensure the following conditions are met on the host.

Required Dependencies

  • openssl — for working with certificates
  • curl — for OpenSearch API requests
  • systemd — for service management
  • Java 21 or newer — if not using the bundled JDK from the package (more details in section JDK Selection)

Installation Package Contents

Before running, check for the following files:

sa-ai-installer/
├── setup.sh ← entry point
├── artifacts/
│ ├── jar/
│ │ └── sa-ai-<version>.jar ← service JAR (required)
│ └── source/
│ └── jdk-*.tar.gz ← bundled JDK (needed if JDK_SOURCE: bundled)
├── configs/
│ └── model_registry.json
├── defaults/
├── lib/
├── templates/
└── example_config_sa-ai.yaml
note

The file artifacts/jar/sa-ai-<version>.jar must be present before starting installation. Without it, the installer will fail at the pre-flight step.

TLS Certificates

If planning to use existing certificates (CERT_MODE: provided), check for:

  • HTTPS certificate for the sa-ai service (sa-ai-cert.pem)
  • Private key (sa-ai-key.pem)
  • OpenSearch CA certificate (ca-cert.pem) — needed even with HTTPS disabled, since sa-ai always verifies OpenSearch's TLS certificate

If planning to generate a certificate (CERT_MODE: generate), check for:

  • OpenSearch CA certificate (ca-cert.pem)
  • CA private key (ca-key.pem)

Installation Package Structure

PathPurpose
setup.shSingle entry point
lib/cmd_install.shInstallation logic
lib/cmd_update.shUpdate logic
lib/cmd_uninstall.shUninstallation logic
defaults/functions.shCommon shell functions library
defaults/default.envDefault values (documentation etc.)
templates/application.propertiesRuntime configuration template
templates/sa-ai.serviceSystemd unit template
configs/model_registry.jsonBase model registry
example_config_sa-ai.yamlSample YAML configuration
artifacts/jar/Directory for sa-ai-<version>.jar
artifacts/source/Directory for JDK archive

Installation Methods

The installer supports three modes:

ModeCommandWhen to Use
Interactivesudo ./setup.sh installOne-time deployment
YAML Configurationsudo ./setup.sh install -c config.yamlAutomation
Rootless./setup.sh install --no-rootLimited sudo access

Interactive Installation

Launch

sudo ./setup.sh install

1. Pre-flight Checks

The installer automatically checks:

  • JAR presence in artifacts/jar/
  • Run permissions (root or sudo)
  • Presence of openssl, curl, systemd

No intervention required. If an error occurs, the installer displays the reason and exits.

2–3. Environment Detection

The installer automatically detects:

  • Presence of local OpenSearch (opensearch.service)
  • Availability of OpenSearch JDK
  • System Java in PATH
  • Bundled JDK in artifacts/source/

Then displays a summary and offers to select a mode:

Run in no-root mode? (print root commands) [y/N; default N]:

Enter y if you have limited sudo, or press Enter to continue in normal mode.

4. Deployment Parameters

The installer requests paths and service settings. Default values are shown in brackets — press Enter to accept.

sa-ai home directory [/app/sa-ai]:
sa-ai logs directory [/app/logs/sa-ai]:
Service port [8010]:
Linux service user [opensearch]:

If OpenSearch is not installed on this host, additional information is requested:

OpenSearch host (for sa-ai application config) [localhost]:
OpenSearch port [9200]:

TLS Configuration

TLS certificate setup:
1) Use existing certificate files
2) Generate sa-ai TLS certificate signed by an existing CA
Choose [1-2] [1]:

Option 1 — existing certificates:

Copy/generate certificates into /app/sa-ai/certs? [Y/n]:
HTTPS certificate path (sa-ai) [/path/to/sa-ai-cert.pem]:
HTTPS key path (sa-ai) [/path/to/sa-ai-key.pem]:
OpenSearch CA certificate path [/path/to/ca-cert.pem]:

Option 2 — certificate generation:

Copy/generate certificates into /app/sa-ai/certs? [Y/n]:
Common Name (CN) for sa-ai certificate [hostname.example.com]:
Country for sa-ai certificate [RU]:
State for sa-ai certificate [Moscow]:
Locality for sa-ai certificate [Moscow]:
Organization for sa-ai certificate [Search Anywhere]:
Subject Alternative Names (comma-separated DNS/IP) [127.0.0.1,localhost,hostname]:
CA certificate path (signs sa-ai cert) [/path/to/ca-cert.pem]:
CA private key path (signs sa-ai cert) [/path/to/ca-key.pem]:

5. JDK Selection

Choose Java runtime:
1) OpenSearch JDK [/app/opensearch/jdk/bin/java, version 21]
2) Bundled JDK [jdk-21.0.5-linux-x64.tar.gz -> /app/sa-ai/jdk]
3) System Java [/usr/bin/java, version 21]
4) Custom path [enter path to java binary or JDK home]
Choose [1-4] [1]:
OptionDescription
opensearchJDK from OpenSearch installation. Offered only if opensearch.service is detected and JDK is running.
bundledJDK from artifacts/source/jdk-*.tar.gz. Extracted to SA_AI_HOME/jdk.
systemjava from PATH. Must be version 21+.
customPath to java binary or JDK directory.

6. OpenSearch Configuration

Create or update OpenSearch internal user (sa_ai_user) on this host? [Y/n]:
Store sa-ai service password in OpenSearch keystore (_core/keystore)? [Y/n]:
OpenSearch API URL [https://localhost:9200]:
OpenSearch admin user (basic auth) [admin]:
OpenSearch admin password (admin): ← input hidden
Password for OpenSearch internal user (sa_ai_user): ← input hidden, confirmation required

7. Confirmation

The installer prints final parameters:

  Local OpenSearch: yes
Home: /app/sa-ai
Logs: /app/logs/sa-ai
Port: 8010
HTTPS enabled: true
Service user: opensearch
JDK source: opensearch
Java binary: /app/opensearch/jdk/bin/java
OpenSearch host: localhost:9200
Cert mode: provided
...

!!! AT THIS POINT WE START TO MAKE CHANGES IN OPERATING SYSTEM !!!

Continue installation? [y/N]:

After entering y, installation proceeds without stops.

8–14. Automatic

Remaining steps are executed automatically:

StepWhat Happens
8. Pre-install preparationCreating Linux user, directories, setting permissions
9. Backup & prepareBackup current config to SA_AI_HOME.bak.<timestamp>/, stopping service
10. Deploy filesCopying JAR, JDK, model_registry.json, TLS files
11. Render templatesGenerating application.properties and systemd unit file
12. Set ownershipSetting owner for SA_AI_HOME and SA_AI_LOGS
13. OpenSearch user & keystoreAPI calls to OpenSearch for creating user and keystore
14. Register & startRegistering systemd unit, daemon-reload, enable, start, health-check

Installation from YAML Configuration

Configuration Preparation

Copy the example and fill in for your environment:

cp example_config_sa-ai.yaml my-config.yaml

Launch

sudo ./setup.sh install -c my-config.yaml

Configuration Example

SaAi:

runtime:
noRoot: n # y — rootless mode

saAiLocation:
OVERWRITE_EXISTING: n # y — allow overwriting existing installation
SA_AI_HOME: /app/sa-ai
SA_AI_LOGS: /app/logs/sa-ai
SA_AI_PORT: 8010
SA_AI_USER: opensearch

jdkSelection:
JDK_SOURCE: opensearch # opensearch | bundled | system | custom
JDK_CUSTOM_PATH: "" # filled only when JDK_SOURCE: custom

prereqConfiguration:
CONFIGURE_USER: y
CONFIGURE_KEYSTORE: y
OS_API_URL: https://localhost:9200
OS_ADMIN_USER: admin
# Passwords not specified — entered interactively

# Needed only when local OpenSearch is absent
openSearchConnection:
HOST: opensearch.example.com
PORT: 9200
CERT_PATH: /app/sa-ai/certs

certManagement:
CERT_MODE: provided # provided | generate
COPY_TO_HOME: y
# Parameters below are relevant only when CERT_MODE: generate
CERT_CN: sa-ai.local
CERT_COUNTRY: RU
CERT_STATE: Moscow
CERT_CITY: Moscow
CERT_ORG: Search Anywhere
CERT_ALT_NAMES: 127.0.0.1,localhost,sa-ai.local
OS_CA_KEY_PATH: "" # path to CA key when CERT_MODE: generate

certFiles:
TLS_CERT_PATH: "" # HTTPS certificate when CERT_MODE: provided
TLS_KEY_PATH: "" # HTTPS key when CERT_MODE: provided
OS_CA_CERT_PATH: "" # OpenSearch CA certificate (always needed)

tls:
SERVER_SSL_ENABLED: y # y — enable HTTPS; n — for debugging only

updateOptions:
UPDATE_SERVICE_FILE: n # y — regenerate systemd unit during update
UPDATE_APPLICATION_PROPERTIES: n # y — regenerate application.properties during update

YAML Parameters Reference

SaAi.runtime

ParameterValuesDescription
noRooty / nRootless mode: output privileged commands instead of executing them

SaAi.saAiLocation

ParameterDefaultDescription
OVERWRITE_EXISTINGnAllow overwriting existing installation
SA_AI_HOME/app/sa-aiService installation directory
SA_AI_LOGS/app/logs/sa-aiLogs directory
SA_AI_PORT8010Service port
SA_AI_USERopensearchLinux service user. Created automatically if absent.

SaAi.jdkSelection

ParameterValuesDescription
JDK_SOURCEopensearchJDK from local OpenSearch installation
bundledJDK from artifacts/source/jdk-*.tar.gz
systemJava from PATH (version 21+)
customPath specified in JDK_CUSTOM_PATH
JDK_CUSTOM_PATHPath to java binary or JDK root directory (when JDK_SOURCE: custom)

SaAi.prereqConfiguration

Applied only when local OpenSearch is present (opensearch.service).

ParameterDefaultDescription
CONFIGURE_USERyCreate or update internal user sa_ai_user in OpenSearch Security
CONFIGURE_KEYSTOREyStore service password in keystore (sm.core.ai.password)
OS_API_URLhttps://localhost:9200OpenSearch API URL
OS_ADMIN_USERadminOpenSearch administrator (basic auth)
note

Passwords (OS_ADMIN_PASSWORD and sa_ai_user password) are not specified in YAML. They are requested by the installer from the keyboard.

SaAi.openSearchConnection

Filled only when OpenSearch is not installed on the host.

ParameterDescription
HOSTRemote OpenSearch host
PORTRemote OpenSearch port
CERT_PATHDirectory where TLS materials for connection are placed

SaAi.certManagement

ParameterValuesDescription
CERT_MODEprovidedUse existing files from certFiles
generateGenerate certificate signed by CA from OS_CA_CERT_PATH / OS_CA_KEY_PATH
COPY_TO_HOMEy / nCopy files to SA_AI_HOME/certs. When CERT_MODE: generate — always y
CERT_CNhostnameCommon Name for generated certificate
CERT_COUNTRYRUCountry
CERT_STATEMoscowState
CERT_CITYMoscowLocality
CERT_ORGSearch AnywhereOrganization
CERT_ALT_NAMEShostname, localhost, 127.0.0.1Subject Alternative Names (DNS and IP separated by commas)
OS_CA_KEY_PATHPath to CA private key (only when CERT_MODE: generate)

SaAi.certFiles

ParameterDescription
TLS_CERT_PATHHTTPS certificate for sa-ai service (when CERT_MODE: provided)
TLS_KEY_PATHHTTPS private key (when CERT_MODE: provided)
OS_CA_CERT_PATHOpenSearch CA certificate. Always needed: sa-ai verifies OpenSearch TLS with it

SaAi.tls

ParameterDefaultDescription
SERVER_SSL_ENABLEDyEnable incoming HTTPS. Disable only for local debugging

SaAi.updateOptions

ParameterDefaultDescription
UPDATE_SERVICE_FILEnRegenerate systemd unit during update command
UPDATE_APPLICATION_PROPERTIESnRegenerate application.properties during update command

Post-Installation Verification

# Service status
sudo systemctl status sa-ai

# Port listening
sudo ss -tlnp | grep :8010

# Health endpoint
curl -k -s https://localhost:8010/health

# List of available models
curl -k -s -u sa_ai_user:'<PASSWORD>' https://localhost:8010/models

Test LLM request:

curl -k -s -u sa_ai_user:'<PASSWORD>' \
-X POST https://localhost:8010/llm-run \
-H 'Content-Type: application/json' \
-d '{
"model": "qwen-mini",
"mode": "summary",
"rows": [{"message": "test"}],
"input": "message",
"output": "summary",
"systemMessage": "You are concise",
"userMessage": "Return one short sentence",
"maxTokens": 32
}'

Model Registry

File: ${SA_AI_HOME}/configs/model_registry.json

The registry describes available LLMs. The service re-reads it without restart, but restart is allowed:

sudo systemctl restart sa-ai

Example entry:

[
{
"name": "qwen-mini",
"provider": "vllm",
"endpoint": "http://127.0.0.1:11434/v1",
"model_id": "qwen2.5:0.5b",
"type": "chat",
"max_context": 32768,
"default_temperature": 0.2,
"default_max_tokens": 512
}
]
FieldDescription
nameModel identifier in API
providervllm, ollama or other OpenAI-compatible provider
endpointProvider URL
model_idModel identifier on provider side
typechat or completion
max_contextContext window size
default_temperatureDefault temperature
default_max_tokensMaximum number of tokens in response

Application Configuration

File: ${SA_AI_HOME}/application.properties

File is generated by installer from template. Key parameters:

FieldDescription
server.portService port
server.ssl.enabledEnable HTTPS
server.ssl.certificatePath to SSL certificate
server.ssl.certificate-private-keyPath to private key
llm.model-registry-pathPath to model registry
llm.auth.opensearch-hostOpenSearch host for authentication
llm.auth.opensearch-portOpenSearch port
llm.auth.ca-cert-pathPath to OpenSearch CA certificate
logging.file.pathLogs directory

OpenSearch Integration

sa-ai creates in OpenSearch:

  • Internal user: sa_ai_user
  • Keystore key: sm.core.ai.password

These names are hardcoded in the application.

Two independent flags are available:

  • CONFIGURE_USER — creates or updates sa_ai_user
  • CONFIGURE_KEYSTORE — writes password via API:
PUT /_core/keystore/sm.core.ai.password
{ "value": "<SA_AI_USER_PASSWORD>" }

Update

sudo ./setup.sh update
sudo ./setup.sh update -c my-config.yaml

Update steps:

  1. Stop service
  2. Replace JAR
  3. Optionally — regenerate unit file and application.properties (controlled by updateOptions in YAML)
  4. Start service and health-check

Uninstall

sudo ./setup.sh uninstall                  # interactive
sudo ./setup.sh uninstall -y # no questions; removes unit, home, logs
sudo ./setup.sh uninstall -y --keep-data # no questions; removes only unit
sudo ./setup.sh uninstall -y --remove-user # also removes service user
FlagBehavior
(no flags)Interactively offers to delete SA_AI_HOME, SA_AI_LOGS and Linux user
-yNo questions; removes unit, SA_AI_HOME, SA_AI_LOGS
-y --keep-dataRemoves only systemd unit
-y --remove-userAlso removes service Linux user

Rootless Mode

In this mode, the installer does not execute privileged commands on its own. Instead, it outputs blocks of commands that the operator executes manually, then confirms.

./setup.sh install --no-root

After each block of privileged commands, the installer requests:

Execute the commands above, then press Enter to continue...

After confirmation, the installer checks that the expected state has been reached. When SA_AI_USER differs from the current user, the username must be explicitly set via YAML or entered in interactive mode.