Quick start
The shortest path from the delivery archive to a working login: one Linux host, Docker, an existing Elasticsearch, one run of deploy.sh.
Prerequisites
| Item | Requirement |
|---|---|
| Host | Ubuntu 20.04 / 22.04 / 24.04 or equivalent Linux, 2 vCPU / 4 GB / 20 GB+ |
| Runtime | Docker Engine 24+ and Docker Compose v2 |
| Elasticsearch | Your existing 8.x, reachable from the gateway host; Kibana optional |
| LLM | URL / API key / model name of an OpenAI-compatible endpoint (ark-code-latest on the Volcengine Ark coding plan) |
| Hostname | A domain name (e.g. copilot.corp.local), not a bare IP (an IP is not a valid TLS SNI and some browsers refuse the handshake); without internal DNS, add a hosts entry on the analysts' machines |
Inbound: only 443 (80 for the redirect, optional). Outbound: the LLM endpoint on 443, your ES on 9200, license.reallysec.com on 443 (not needed for air-gapped installs, see Licensing).
Install
Install Docker (if missing)
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER # log out and back in
docker compose versionUnpack the delivery archive
The archive RST-Elastic-AI-Copilot-<version>.tar.gz carries the images; no registry access is needed.
sha256sum -c RST-Elastic-AI-Copilot-<version>.tar.gz.sha256
tar xzf RST-Elastic-AI-Copilot-<version>.tar.gz
cd RST-Elastic-AI-Copilot-<version>Run deploy.sh
./deploy.shIt checks Docker, generates state/machine-id and state/server_guid (the licence's hardware fingerprint - never regenerate them), docker loads the images, asks for the auth mode (1, built-in login) and ES source (1, existing ELK), then the LLM URL / key / model, timezone, ES / Kibana URLs, the site hostname and an admin password, writes the generated internal secrets to .env (mode 600), and runs docker compose up -d until everything is healthy.
It prints the URL at the end. About two minutes end to end.
Verify
curl -k https://copilot.corp.local/healthz # {"status":"ok"}
curl -k https://copilot.corp.local/readyz # es / es_write / timezonees_write in readyz must be ok. denied means the ES account lacks permissions on the .rst_copilot_* indices, see below.
Log in
Open https://copilot.corp.local/v2/, accept the self-signed certificate (swap in your own for production by editing Caddyfile), user admin, the password you just set.

You land on the Smart query home; the parts of the screen are explained in A tour of the UI.
ES account permissions
If your ES has security enabled, give ES_USER a role with at least:
- your log indices (e.g.
logs-*):read,view_index_metadata - the gateway's own indices
.rst_copilot_*:create_index,read,write,manage, with one wildcard - to pull live alerts, additionally
readandview_index_metadataon.alerts-security.alerts-*and.internal.alerts-security.alerts-*(hidden indices: the Kibana role page will not autocomplete them, type the pattern and press Enter)
Recommended: set RST_INDEX_WHITELIST=logs-*,filebeat-* in .env to limit which indices can be queried.
After install
- Activate a licence: the paid engines need one; trials are free.
/v2/settings: index whitelist, masking mode, audit.- Backups: copy the whole
./state/directory; export thegateway_statevolume with the bundledscripts/backup.sh(it covers the volume only, not./state/).
Upgrading
Unpack the new archive into the same directory and run ./deploy.sh again, choosing "keep existing .env" - it loads the new image, switches GATEWAY_IMAGE_TAG and restarts. To roll back, restart on the previous tag; licence state lives in state/ and the volume and survives.
Never regenerate state/machine-id or state/server_guid, and never docker compose down -v. Changing either is a new host to the licence, which then has to be re-activated.
Troubleshooting
| Symptom | Where to look |
|---|---|
/v2/ does not open | docker compose -f docker-compose.prod.yml logs caddy gateway; 443 open, CADDY_SITE_ADDRESS is a hostname |
| TLS handshake fails | CADDY_SITE_ADDRESS is a bare IP; use a hostname + hosts entry |
readyz says es_write=denied | ES account lacks create / write on .rst_copilot_* |
| Queries fail or come back empty | ES reachable? RST_INDEX_WHITELIST missing the target index? LLM key / endpoint correct? |
| Licence suddenly invalid | Was state/machine-id / state/server_guid regenerated? |