OpenSearch Setup
Prerequisites
Section titled “Prerequisites”| Requirement | Version |
|---|---|
| Java (OpenJDK) | 21 (required for OpenSearch 3.x) |
| Node.js | 20+ |
| RAM | 8GB minimum (6GB available) |
| Disk | 70GB free |
CLI Tool: opensearch-mgr
Section titled “CLI Tool: opensearch-mgr”The opensearch-mgr CLI provides unified management for all OpenSearch services.
# Installation (already done on this server)# The CLI is symlinked globally from /root/opensearch/cli/opensearch-mgr.js
# Verifyopensearch-mgr --versionAll Commands
Section titled “All Commands”| Command | Description |
|---|---|
start [service] | Start opensearch, dashboards, or all |
stop [service] | Stop services |
restart [service] | Restart services |
status | Show status of all services |
health | Health check endpoints |
build [service] | Build from source |
deploy | Deploy built OpenSearch to /opt |
logs [service] | View logs (-f to follow) |
watch | Watchdog mode with auto-restart |
install-service | Install systemd services |
ui | Interactive menu mode |
ingest <path> | Bulk ingest log files |
watch-logs <path> | Continuous log file monitoring |
ingest-status | Show ingestion statistics |
Semantic Search Commands
Section titled “Semantic Search Commands”| Command | Description |
|---|---|
semantic-setup | Setup ML model and semantic indexes |
semantic-reindex [index] | Reindex data for semantic search |
semantic <query> | Perform semantic search |
semantic-status | Check ML model and index status |
model-ensure | Ensure ML model is loaded |
Output Modes
Section titled “Output Modes”opensearch-mgr status # Human-readableopensearch-mgr status --json # JSON for automationConfiguration Files
Section titled “Configuration Files”OpenSearch Config
Section titled “OpenSearch Config”/opt/opensearch/config/opensearch.yml:
cluster.name: opensearch-devnode.name: node-1network.host: 0.0.0.0discovery.type: single-nodeOpenSearch is exposed publicly at https://analyticsapi.logrite.ai (Cloudflare → :9200 direct). Because the browser-side client (OpenSearchContext.jsx) sends Authorization headers, http.cors.allow-credentials must be true — which means http.cors.allow-origin cannot be "*". When that combination is set, OpenSearch silently drops all Access-Control-Allow-* headers and every browser request fails CORS.
Use a regex allowlist instead:
http.cors.enabled: truehttp.cors.allow-origin: "/https?:\\/\\/(app|logriteiq|staging)\\.logrite\\.ai|https?:\\/\\/localhost(:[0-9]+)?/"http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETEhttp.cors.allow-headers: X-Requested-With, Content-Type, Content-Length, Authorizationhttp.cors.allow-credentials: trueRestart after editing: opensearch-mgr restart opensearch.
Verify:
curl -I -X OPTIONS https://analyticsapi.logrite.ai/_cluster/health \ -H "Origin: https://app.logrite.ai" \ -H "Access-Control-Request-Method: GET"# Expect: access-control-allow-origin: https://app.logrite.aiTo add a new browser origin, extend the regex — do not switch back to "*".
Dashboards Config
Section titled “Dashboards Config”/root/opensearch/OpenSearch-Dashboards/config/opensearch_dashboards.yml:
server.host: "127.0.0.1"server.basePath: "/pxe"server.rewriteBasePath: trueopensearch.hosts: ["http://localhost:9200"]opensearch.ssl.verificationMode: none
server.cors: origin: - "https://app.logrite.ai" - "https://logrite.deployd.io" - "https://analytics.logrite.ai" additionalHeaders: - osd-xsrf - osd-version - kbn-version - Content-Type - Authorization credentials: trueDashboards is bound to 127.0.0.1:5601 and fronted by Apache at analytics.logrite.ai — never expose it directly. credentials: true is required because the frontend calls /pxe/internal/search/* with cookies/Authorization; with credentials: false the browser rejects the response. allow-origin must be an explicit list (not *) when credentials is true.
Public Routing (Apache)
Section titled “Public Routing (Apache)”Dashboards is reached externally via https://analytics.logrite.ai/pxe/* → Cloudflare → Apache (:80) → 127.0.0.1:5601. The Apache vhost lives at /etc/apache2/sites-available/analytics.logrite.ai.conf (versioned in LogriteMasterControl at config/apache/analytics.logrite.ai.conf):
<VirtualHost *:80> ServerName analytics.logrite.ai ProxyPreserveHost On ProxyRequests Off ProxyPass / http://127.0.0.1:5601/ ProxyPassReverse / http://127.0.0.1:5601/
RewriteEngine On RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/?(.*) ws://127.0.0.1:5601/$1 [P,L]
RequestHeader set X-Forwarded-Proto "https" ProxyTimeout 300 ErrorLog ${APACHE_LOG_DIR}/analytics-error.log CustomLog ${APACHE_LOG_DIR}/analytics-access.log combined</VirtualHost>Enable with a2ensite analytics.logrite.ai && apache2ctl configtest && systemctl reload apache2. Cloudflare’s Tunnel / origin for analytics.logrite.ai must route to this host on :80 — check the Cloudflare Zero Trust dashboard if the edge returns 502 while curl -H 'Host: analytics.logrite.ai' http://127.0.0.1/pxe/api/status returns 200 locally.
Starting Services
Section titled “Starting Services”# Start everythingopensearch-mgr start all
# Start only OpenSearch (wait for green health)opensearch-mgr start opensearch
# Start only Dashboardsopensearch-mgr start dashboardsRebuilding from Source
Section titled “Rebuilding from Source”# Rebuild OpenSearch engineopensearch-mgr build opensearch
# Deploy to /opt/opensearchopensearch-mgr deploy
# Rebuild Dashboards (takes 5-15 minutes)opensearch-mgr build dashboardsSyncing with Upstream
Section titled “Syncing with Upstream”# Pull latest from official opensearch-projectgit fetch upstreamgit checkout maingit merge upstream/maingit push origin mainMigrating to a New Server
Section titled “Migrating to a New Server”For bootstrapping OpenSearch on a fresh server, an export bundle of live state lives at /root/opensearch/exports/:
| File | Contents |
|---|---|
kibana/saved-objects.ndjson | Dashboards index-patterns, visualizations, dashboards |
detectors/detectors.json | Anomaly detectors (production set) |
monitors/monitors.json | Alert monitors |
destinations/destinations.json | Notification channels (Discord webhooks) |
import.sh | Re-imports all four into a target cluster |
logrite-opensearch-bundle.tgz | Single tarball with all of the above + sample NDJSON + dashboard creator scripts |
Restore on the new server (after opensearch-mgr start all is healthy and source data is ingested):
scp logrite-opensearch-bundle.tgz newserver:/root/ssh newserver "cd /root/opensearch && tar xzf /root/logrite-opensearch-bundle.tgz && bash exports/import.sh"Production systemd Setup
Section titled “Production systemd Setup”# Install systemd servicesopensearch-mgr install-service
# Enable and startsudo systemctl enable opensearch opensearch-dashboardssudo systemctl start opensearchsudo systemctl start opensearch-dashboardsIndex Templates (Logrite Platform)
Section titled “Index Templates (Logrite Platform)”Logrite maintains 4 composable index templates for its own indices. These are managed by opensearch/scripts/create-warden-indexes.js in the LogriteOpenSearch repo.
Templates
Section titled “Templates”| Template | Pattern | Retention | Purpose |
|---|---|---|---|
log-analytics-template | log-analytics-* | 90 days | Collector agent log documents |
agent-flags | agent-flags-* | 90 days | Compliance & anomaly flag findings (Phase 3) |
warden-requests | warden-requests-* | 90 days | AI Warden request captures |
relay-compliance-events | relay-compliance-events-* | 180 days | Relay compliance violation events |
ISM Policies
Section titled “ISM Policies”Each template has a matching ISM policy (warden-requests-retention, relay-compliance-events-retention, agent-flags-retention, collector-logs-retention) attached via ism_template. Policies auto-attach to new indexes matching the pattern — no manual steps needed when a new workspace index is created.
Running the Script
Section titled “Running the Script”# Apply / update all 4 templates and ISM policies (idempotent — safe to re-run)OPENSEARCH_USERNAME=<user> OPENSEARCH_PASSWORD=<pass> \ node opensearch/scripts/create-warden-indexes.jsThe script is idempotent — all operations are PUT so re-running it is safe.
start-all runs this automatically as a pre-flight after OpenSearch is healthy (via the ensureIndexTemplates() module export). Manual runs are only needed to apply template changes outside of a full restart.
Credentials
Section titled “Credentials”The dashboards-svc user has permission to write index templates (PUT /_index_template/*) but not ISM policies (cluster:admin/opendistro/ism/policy/write). ISM policy writes require the admin user. Since policies rarely change, this is normally not an issue — templates are what need re-applying after field mapping changes.
Important Notes
Section titled “Important Notes”- Root user — OpenSearch refuses to start as root. The
opensearchsystem user is used. - First Dashboards start — Takes several minutes for bundle compilation.
- Security plugin — Not included in source builds (the legacy
opensearch-mgrinstall on/opt/opensearch/). The official Docker image used in Coolify (opensearchproject/opensearch:3.3.1) ships with it pre-installed. See Security Plugin for users/roles management via the Dashboards UI, and Security Hardening for the platform-wide checklist. - PID management — PIDs tracked in
/var/run/opensearch/. Always useopensearch-mgrfor lifecycle management.