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_PATH—Path 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_PATH—Path 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.