http://talon-analyst-api:3100. The images are published as ghcr.io/socfortress/talon-analyst-*; each release has a version (for example 0.1.2), and an install pins one.
talon-analyst is proprietary SOCFortress software under the SOCFortress EULA, which ships with every release. SOCFortress installs it on request for support clients, and this page describes what that install does. Contact SOCFortress to arrange one.
.env and secrets/ on the VM.
Prerequisites
CoPilot
- A running CoPilot, v0.1.99 or later, installed from its own Compose project. On v0.1.99, investigations, write-back and chat work; endpoint actions and automation need the release after it.
- A CoPilot admin account without 2FA, used only while the install runs. Its username and password are asked at a hidden prompt and never stored.
- CoPilot’s MySQL
rootpassword (from CoPilot’s.env), used once to create a read-only MySQL user for Talon, and again after each CoPilot upgrade to refresh its grants.
The VM
- linux/amd64 (x86-64) only. An arm64 host can’t run an install, including an Apple Silicon Mac, even under emulation: CoPilot’s images and the Wazuh and Velociraptor MCP server images are amd64 only.
- Docker Engine 24 or newer, and Docker Compose v2.24.4 or newer (
docker version,docker compose version). - Unprivileged user namespaces, for the sandbox that runs Talon’s shell. On Debian,
sysctl kernel.unprivileged_userns_clonemust be1(the default) andsysctl user.max_user_namespacesabove0. On an AppArmor host, only thesandboxservice runs unconfined. - Ubuntu 23.10 and later restrict user namespaces through AppArmor; this hasn’t been checked with the sandbox. Test the shell before going live, or use a Debian host.
Outbound access from the VM (HTTPS, 443, unless noted):
The public VirusTotal API is for non-commercial use, so a client install needs a commercial key or none. Check each other source’s terms before setting its key.
Read-only accounts
Talon’s MCP servers read your stack through read-only accounts:- Wazuh indexer: a user (
talon_readerby default) with a read-only role over the indices, plus read-only monitoring. - Wazuh manager API: a read-only RBAC user with the agent, syscollector, SCA and rules read permissions.
- Velociraptor: an API client config with the
readerandapiroles.
config api_client command to run on the Velociraptor server, then waits for the file.
The guided install
Work as root in a new install directory on the CoPilot VM. Replace<version> with the release to install, without the v (for example 0.1.2).
1
Create a Tavily API key (for web search)
Talon’s web search uses Tavily. Sign up at app.tavily.com and create an API key (the free plan has 1,000 credits a month; each search costs one). The installer asks for it and checks it with Tavily before writing it.It is optional: without a key, web search stays off. The model isn’t offered it, and everything else (including web fetch) works as before.
2
Copy the install files out of the image
install.sh and the LICENSE. It never overwrites a file you changed: it writes the release’s copy beside it as <file>.new.3
Run the installer
- A preflight: root, linux/amd64, Docker and Compose versions, user namespaces, CoPilot’s Docker network, free host ports (it says what holds
3100or6006, for example the earlier Talon, and offers the next free port), and the release. - The sandbox’s SSH keys.
- The configuration:
.env, with every secret no human needs generated; then the model provider key, the budgets, CoPilot, the read-only MySQL user, the indexer, Wazuh and Velociraptor accounts, threat intel, and the Tavily API key for web search (optional). Each answer that can be tested (the model key, CoPilot, MySQL, the backends) is tested before it is written. docker compose pullandup -d.- Customers: you pick CoPilot customers to onboard. Each is onboarded in shadow, and CoPilot’s AI trigger is offered per customer. Then the Talon Phoenix connector in CoPilot is set (for run timelines).
- A report: one PASS, WARN or FAIL line per connection, the stack checks, and the next steps.
- Air-gapped VM: load the images with
docker loadfirst, then runsh install.sh --no-pull. - Re-running
sh install.shkeeps what is set, sayskept, and asks only for what is missing. It is also the repair tool, and the way to onboard more customers later. - Adding or removing the Tavily key later (in
.env, or by re-runningsh install.sh) is done with the investigation queue empty, as for an upgrade: it changes the investigation workflow’s version, and a run in the queue across it can’t be recovered. Replacing a key with another one doesn’t. Thendocker compose up -d api. - URLs are prefilled from CoPilot’s own connectors (only the URL, never their credentials).
- TLS verification of the indexer and the Wazuh API is off by default, because their certificates are usually self-signed. The connections are still encrypted; turn verification on in
.envonce the MCP servers trust your CA. - The indexer reader may read every index (
INDEXER_ALLOWED_INDICES=*). Per-customer scoping is enforced by Talon itself: every query is bound to the customer’s verified indices.
scripts/backup.sh, which backs up Talon’s databases, memory and configuration (every secret included, so keep the copies encrypted and root-only).
Connect CoPilot
CoPilot finds Talon through its Talon connector (Connectors): a URL and an API key, sent asx-api-key.
The bootstrap’s
connector step sets both and runs CoPilot’s Verify. It first saves the connector’s previous URL and key in the install’s secrets/, so they can be put back. While another Talon serves the connector, it refuses unless every customer with its AI trigger on is live on talon-analyst, and names any customer that would otherwise get no AI report.
When to switch it:
- A CoPilot that no Talon serves yet (the connector isn’t verified): switch it right after the install, so the shadow phase can begin.
- A CoPilot served by the earlier Talon: switch it last, after every customer’s shadow comparison (below).
Roll out per customer: shadow first
Every customer goes through the same loop, one at a time: shadow, a comparison, then live.1
Onboard in shadow
The bootstrap’s
customer step (the installer runs it for the customers you pick):- writes the customer’s policy in Talon: anonymization on, the allowed model providers, automation level 0;
- keeps the customer out of the live list;
- adds the customer’s internal domains to the threat intel deny list;
- syncs and verifies the customer’s indices;
- reports (and can set) CoPilot’s AI trigger for the customer, and checks that CoPilot’s automation policy for it has every level off.
2
Let shadow reports build up
While a customer is in shadow, its reports stay in Talon and CoPilot gets nothing.
- On a CoPilot no Talon served before, the connector is switched and the AI trigger turned on, so every alert is investigated in shadow.
- On a CoPilot the earlier Talon still serves, SOCFortress sends tagged investigations by hand, which write nothing to CoPilot.
3
Compare
At least 7 days in shadow, and until 50 paired alerts or 14 days. Then SOCFortress spot-checks report pairs blind, and reviews the cost per alert and any failed jobs.
4
Go live
- The
customerstep with--liveassigns the customer to Talon’stalon-analystservice user in CoPilot first, and only then adds it to the live list. If CoPilot refuses the assignment, the list is unchanged. - For the first live customer, write-back is set to
livein.env. - With the investigation queue empty, the api is restarted.
- The startup log must show write-back live for the listed customers, all of them assigned to the service user.
.env change and an api restart with the queue empty, plus its CoPilot side:
The stricter setting always wins. Automation stays at level 0 unless SOCFortress and you agree on a level for a customer.
Rolling one customer back to shadow stops its write-back from the next job. Write-back off for the whole install is the kill switch: no write reaches CoPilot for any customer.
Moving from the earlier Talon
An existing Talon v1 install is replaced behind the same connector, so CoPilot needs no code change: only the connector’s URL and key change.1
Install side by side
Install talon-analyst in shadow on the same VM, as above. CoPilot’s connector keeps pointing at the earlier Talon throughout. If it holds host port 3100, the installer offers another (for example
3110); CoPilot still reaches talon-analyst as talon-analyst-api:3100 on its own network.2
Compare each customer
Onboard each customer in shadow, re-seed its review lessons, send tagged investigations by hand, and compare the reports with the earlier Talon’s for the same alerts.
3
Switch, for everyone at once
The connector is all or nothing: every customer with its AI trigger on moves at the switch, and a customer still in shadow would get no AI report at all. So, with the queue empty: put each of them live, set write-back to
live, restart the api, run the connector step as a dry run (it must name no customer), then apply it. Watch the first investigations complete in CoPilot.4
Keep the earlier Talon as the rollback
Leave it running, untouched, for 30 days. Rolling back puts the saved connector URL and key back and sets write-back to shadow. After 30 days with no rollback, stop it and archive its data.
- Memory. The earlier Talon’s memory stays where it is; talon-analyst starts empty, apart from the re-seeded review lessons.
- Chat sessions. Users start new conversations.
- The 15-minute sweep. The earlier Talon also investigated open alerts on a schedule. talon-analyst investigates only what CoPilot sends, so every customer that relied on the sweep needs its AI trigger on.
Upgrades
Upgrades follow the same pattern: empty the investigation queue (a run recovered by new code can fail), back up, refresh the install files from the new version’s image (the sameinstall-files command), set the new TALON_VERSION in .env, then docker compose pull and docker compose up -d. The api runs its database migrations on start. After a CoPilot upgrade, refresh the read-only MySQL user’s grants.